linux namespaces是Linux提供的一种内核级别环境隔离的方法,也是Container环境隔离的底层技术,Linux Namespaces共有如下种类
分类 | 系统调用参数 | 相关内核版本 |
---|---|---|
Mount namespaces | CLONE_NEWNS | Linux 2.4.19 |
UTS namespaces | CLONE_NEWUTS | Linux 2.6.19 |
IPC namespaces | CLONE_NEWIPC | Linux 2.6.19 |
PID namespaces | CLONE_NEWPID | Linux 2.6.24 |
Network namespaces | CLONE_NEWNET | Linux 2.6.29 |
User namespaces | CLONE_NEWUSER | Linux 3.8 |
Mount
: mount表空间隔离,配合chroot系统调用,使程序有自己的文件系统UTS
: hostname(本地主机名)和doaminname隔离,使应用有自己独立的主机名IPC
: 隔离进程间通讯PID
: 使程序包括子程序构造一个独立的程序集,最先创建的程序为1号pidNetwork
: 网络空间隔离,支行在此空间的程序拥有独立的网络栈。User
: 此空间下有独立的uid/gid系统因此,一个容器拥有一组命名空间,即Mount1、UTS1、IPC1、PID1、Network1、User1组合。
Namespaces操作的可以通过三个系统调用完成clone(),unshare(),setns(),默认情况下子进程继承新父进程的namespaces
❯ sudo lsns
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 317 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531837 user 318 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531838 uts 317 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531839 ipc 317 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531840 mnt 312 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026531856 mnt 1 91 root kdevtmpfs
4026531956 net 317 1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 22
4026532215 mnt 1 5127 chrony /usr/sbin/chronyd
4026532216 mnt 2 5120 root /usr/sbin/NetworkManager --no-daemon
4026532219 mnt 1 6264 root /usr/bin/simple
4026532220 uts 1 6264 root /usr/bin/simple
4026532221 ipc 1 6264 root /usr/bin/simple
4026532222 pid 1 6264 root /usr/bin/simple
4026532224 net 1 6264 root /usr/bin/simple
4026532281 mnt 1 5438 root /usr/sbin/cupsd -f
❯ sudo ls -l /proc/*/ns/ |awk '{print $11}' |sort -u
ipc:[4026531839]
ipc:[4026532221]
mnt:[4026531840]
mnt:[4026531856]
mnt:[4026532215]
mnt:[4026532216]
mnt:[4026532219]
mnt:[4026532281]
net:[4026531956]
net:[4026532224]
pid:[4026531836]
pid:[4026532222]
user:[4026531837]
uts:[4026531838]
uts:[4026532220]
>sudo docker inspect -f "{{.State.Pid}}" 34b48c1d3093 //34b48c1d3093是容器id
>10427 //查询容器对应在主机上的pid
> sudo ls -l /proc/10427/ns
lrwxrwxrwx 1 root root 0 Dec 11 16:21 ipc -> ipc:[4026533018]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 mnt -> mnt:[4026533016]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 pid -> pid:[4026533019]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Dec 11 16:21 uts -> uts:[4026533017]
从结果看,一个容器对应6个命名空间,类型不重复,正好验证了我们之前的结论 “一个容器拥有一组命名空间,即Mount1、UTS1、IPC1、PID1、Network1、User1组合”。
nsenter作用是查看某个命令空间内的信息。
nsenter的使用帮忙如下:
Usage:
nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.
Options:
-t, --target <pid> target process to get namespaces from
-m, --mount[=<file>] enter mount namespace
-u, --uts[=<file>] enter UTS namespace (hostname etc)
-i, --ipc[=<file>] enter System V IPC namespace
-n, --net[=<file>] enter network namespace
-p, --pid[=<file>] enter pid namespace
-U, --user[=<file>] enter user namespace
-S, --setuid <uid> set uid in entered namespace
-G, --setgid <gid> set gid in entered namespace
<span> </span>--preserve-credentials do not touch uids or gids
-r, --root[=<*dir*>] set the root directory
-w, --wd[=<*dir*>] set the working directory
-F, --no-fork do not fork before exec'ing <program>
-Z, --follow-context set SELinux context according to --target PID
-h, --help display this help and exit
-V, --version output version information and exit
For more details see nsenter(1).
操作特定进程命名空间中的信息,容器就是一个命名空间
查看容器内的网卡信息:
❯ sudo nsenter -t 10427 -n ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
66: eth0@if67: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
也可以通过 nsenter -t 10427 -n bash 进入命名空间,单独执行ip addr命令
查看容器的Host信息(主机名)
❯ sudo nsenter -t 10427 -u hostname
d911aa5d1a1c //hostname
等价于进入容器后,执行hostname命令
>docker exec -it 34b48c1d3093 sh //进入容器
>/home/zenap # hostname
d911aa5d1a1c //hostname