作为开源Container技术代表的Docker,它跟Linux内核的Namespace和Cgroup两大特性密不可分。物有本末,事有终始。知所先后,则近道矣。理解Linux的这两大特性将有助于我们更深入的理解Docker。在前面的文章中,我们曾经体验过如何使用chroot和LXC,在本文中我们将会使用unshare命令来演示Linux内核的MNT Namespace是如何动作的。
Namespace并不是Linux才推出的东西,早在很久之前,Unix上就有类似的东西,而HPUX和Solaris商用的Conatiner更是以前就有推出。而在Linux的2.6之后的版本Namespace就逐步的被加了进来。
项番 | 类型 | 功能说明 |
---|---|---|
No.1 | MNT Namespace | 提供磁盘挂载点和文件系统的隔离能力 |
No.2 | IPC Namespace | 提供进程间通信的隔离能力 |
No.3 | Net Namespace | 提供网络隔离能力 |
No.4 | UTS Namespace | 提供主机名隔离能力 |
No.5 | PID Namespace | 提供进程隔离能力 |
No.6 | User Namespace | 提供用户隔离能力 |
root@ubuntu:~# uname -a
Linux ubuntu 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
root@ubuntu:~#
确认当前进程PID
root@ubuntu:~# echo $$
32968
root@ubuntu:~#
确认当前进程的各个namespace
root@ubuntu:~# ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Sep 15 10:23 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Sep 15 10:23 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Sep 15 10:23 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Sep 15 10:23 net -> net:[4026531957]
lrwxrwxrwx 1 root root 0 Sep 15 10:23 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Sep 15 10:23 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Sep 15 10:23 uts -> uts:[4026531838]
root@ubuntu:~#
内容说明
项番 | 内容说明 |
---|---|
No.1 | linux会在/proc下创建所对应的进程相关的信息,ns则为Namespace的信息 |
No.2 | $$为当前进程PID,/proc/$$/ns下的Namespace的个数回随着Linux内核的高低不同显示的个数不同,因为Linux所支持的Namespace不是一次到位的 |
No.3 | mnt:[4026531840],不同的Namespace都有不同的编号,比如32968的mnt的namespace的编号就是4026531840 |
No.4 | 关于Cgroup会单独在后面进行说明 |
首先我们来看一下没有隔离的mount是怎样动作的,为了简单起见使用tmpfs这种基于内存的文件系统来模拟。
root@ubuntu:~# mkdir /tmp/testnoisolation
root@ubuntu:~# mount -t tmpfs tmpfs /tmp/testnoisolation
root@ubuntu:~# cd /tmp/testnoisolation
root@ubuntu:/tmp/testnoisolation#
root@ubuntu:/tmp/testnoisolation# touch aaa bbb ccc ddd
root@ubuntu:/tmp/testnoisolation# ll
total 4
drwxrwxrwt 2 root root 120 Sep 15 10:56 ./
drwxrwxrwt 13 root root 4096 Sep 15 10:55 ../
-rw-r--r-- 1 root root 0 Sep 15 10:56 aaa
-rw-r--r-- 1 root root 0 Sep 15 10:56 bbb
-rw-r--r-- 1 root root 0 Sep 15 10:56 ccc
-rw-r--r-- 1 root root 0 Sep 15 10:56 ddd
root@ubuntu:/tmp/testnoisolation#
在新起一个终端来确认目录/tmp/testnoisolation的信息
admin01@ubuntu:~$ echo $$
33414
admin01@ubuntu:~$ ls -l /tmp/testnoisolation
total 0
-rw-r--r-- 1 root root 0 Sep 15 10:56 aaa
-rw-r--r-- 1 root root 0 Sep 15 10:56 bbb
-rw-r--r-- 1 root root 0 Sep 15 10:56 ccc
-rw-r--r-- 1 root root 0 Sep 15 10:56 ddd
admin01@ubuntu:~$
root@ubuntu:~# mkdir /tmp/testisolation
虽然也可以使用Linux内核提供的系统函数写简单的程序来实现,但是多少有点喧宾夺主的感觉。linux已经提供了非常贴心的unshare命令,只需要下面一行语句我们就能重新启动一个bash的进程,而在其中的mnt namespace是被隔离的。
root@ubuntu:~# echo $$
32968
root@ubuntu:~# unshare --mount /bin/bash
root@ubuntu:~#
好像没有任何变化,其实这个已经不是刚才我们的32968进程了,而是一个新的进程,通过确认$$就能确认
root@ubuntu:~# echo $$
33447
root@ubuntu:~#
再来确认一下,33447和32968两个进程的关系,我们能清楚地看到这是父子关系的两个进程,虽然都是bash
admin01@ubuntu:~$ ps -ef |grep 32968 |grep -v grep
root 32968 32967 0 10:16 pts/0 00:00:00 -su
root 33447 32968 0 11:09 pts/0 00:00:00 /bin/bash
admin01@ubuntu:~$ pstree 32968
bashqqqbash
admin01@ubuntu:~$
root@ubuntu:~# echo $$
33447
root@ubuntu:~# mount -t tmpfs tmpfs /tmp/testisolation
root@ubuntu:~# cd /tmp/testisolation
root@ubuntu:/tmp/testisolation#
root@ubuntu:/tmp/testisolation# touch aaa bbb ccc ddd
root@ubuntu:/tmp/testisolation# ll
total 4
drwxrwxrwt 2 root root 120 Sep 15 11:15 ./
drwxrwxrwt 14 root root 4096 Sep 15 11:02 ../
-rw-r--r-- 1 root root 0 Sep 15 11:15 aaa
-rw-r--r-- 1 root root 0 Sep 15 11:15 bbb
-rw-r--r-- 1 root root 0 Sep 15 11:15 ccc
-rw-r--r-- 1 root root 0 Sep 15 11:15 ddd
root@ubuntu:/tmp/testisolation#
在新起一个终端来确认目录/tmp/testisolation的信息,没有任何信息。
admin01@ubuntu:~$ ll /tmp/testisolation
total 8
drwxr-xr-x 2 root root 4096 Sep 15 11:02 ./
drwxrwxrwt 14 root root 4096 Sep 15 11:02 ../
admin01@ubuntu:~$
/proc/$$/ns下面会列出当前的namespace信息,我们来看看一下这个使用unshare隔离了mnt namespace的信息
root@ubuntu:~# ls -l /proc/33447/ns
total 0
lrwxrwxrwx 1 root root 0 Sep 15 11:25 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 mnt -> mnt:[4026532506]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 net -> net:[4026531957]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Sep 15 11:11 uts -> uts:[4026531838]
root@ubuntu:~#
与之前进行比较,我们可以清晰地发现,除了mnt的namespace编号从4026531840变为4026532506之外,其余都没有改变。这也是使用unshare -m或者unshare –mnt所实现的隔离,创建了新的namespace。
在比较原始的chroot中,画地为牢之后,是无法挣脱其所指定的根的,虽然有效但是略显粗暴。而namespace则自由的多,起码可以自由的动作,当然不只是这一点区别,但是这一点是最为直观能看出来的
root@ubuntu:/tmp/testisolation# pwd
/tmp/testisolation
root@ubuntu:/tmp/testisolation# cd ../testnoisolation/
root@ubuntu:/tmp/testnoisolation# ll
total 4
drwxrwxrwt 2 root root 120 Sep 15 10:56 ./
drwxrwxrwt 14 root root 4096 Sep 15 11:17 ../
-rw-r--r-- 1 root root 0 Sep 15 10:56 aaa
-rw-r--r-- 1 root root 0 Sep 15 10:56 bbb
-rw-r--r-- 1 root root 0 Sep 15 10:56 ccc
-rw-r--r-- 1 root root 0 Sep 15 10:56 ddd
root@ubuntu:/tmp/testnoisolation#
内容 | URL |
---|---|
docker基础:从chroot理解namespace的隔离 | http://blog.csdn.net/liumiaocn/article/details/52388793 |
在CentOS7上使用LXC管理容器 | http://blog.csdn.net/liumiaocn/article/details/52348219 |
如何使用RHEL/CentOS 7安装创建和管理LXC (Linux Containers) | http://blog.csdn.net/liumiaocn/article/details/52337479 |