Docker虚拟化关键技术(一)---Namespace

一、Linux虚拟化的资源隔离(namespace)

 

试想一下,如果想在一个系统中虚拟出一个主机或隔离出一个进程,应该从哪些方面下手呢?
也许你第一反应可能就是 chroot 命令,这条命令给用户最直观的感觉就是使用后根目录 / 的挂载点切换了,即文件系统被隔离了。然后,为了在分布式的环境下进行通信和定位,容器必然需要一个独立的 IP、端口、路由等等,自然就想到了网络的隔离。同时,你的容器还需要一个独立的主机名以便在网络中标识自己。想到网络,顺其自然就想到通信,也就想到了进程间通信的隔离。可能你也想到了权限的问题,对用户和用户组的隔离就实现了用户权限的隔离。最后,运行在容器中的应用需要有自己的 PID, 自然也需要与宿主机中的 PID 进行隔离。
由此,我们基本上完成了一个容器所需要做的六项隔离,Linux 内核中就提供了这六种 namespace 隔离的系统调用。

 

二、命名空间

1.pid 命名空间
我们通过fork来创建进程时可以为每个进程指定命名空间。linux下的进程关系是一棵树,所以有了父命名空间和子名字空间之分。
不同用户的进程就是通过 pid 命名空间隔离开的,且不同命名空间中可以有相同 pid。
在同一个Namespace中只能看到当前命名空间的进程。
所有的 LXC 进程(Linux container)在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的命名空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。

在namespace2创建的P2进程有两个pid。第一个是在父命名空间的下的它的PID号,一个是在自己空间下的PID号。之所以有父pid号是因为P2最终还是在父命名空间下运行的,而为进程指定命名空间是为了让P2和P3实现隔离。


宿主机上:
[root@STAG-DOCKER-01 ~]# ps -ef|grep nginx|grep iag
root     196048 192819  0 Mar27 ?        00:00:02 nginx: master process /home/root/iag/nginx/sbin/nginx
root     222565 217594  0 Mar29 pts/33   00:00:00 vi /home/root/iag/nginx/conf/module/imp-http.conf

容器内:
[root@STAG-DOCKER-01 /]# ps -ef|grep nginx|grep iag
root        344      1  0 Mar27 ?        00:00:02 nginx: master process /home/root/iag/nginx/sbin/nginx
root     103781 103582  0 Mar29 ?        00:00:00 vi /home/root/iag/nginx/conf/module/imp-http.conf

 

2.net 命名空间
有了 pid 命名空间, 每个命名空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 命名空间实现的, 每个 net 命名空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker 网桥 docker0 连接在一起。NET NAMESPACE实现网络协议栈上的隔离,在自己的namespace中对网络的设置只能在本namespace中生效。


3.ipc 命名空间
容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication – IPC), 包括信号量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 命名空间中的进程间交互,因此需要在 IPC 资源申请时加入命名空间信息,每个 IPC 资源有一个唯一的 32 位 id。
同一个命名空间下的进程才可以通信。IPC Namespace针对的是SystemV IPC和Posix消息队列。这些IPC机制都会用到标识符,例如用标识符来区别不同的消息队列,然后两个进程通过标识符找到对应的消息队列进行通信等。
IPC Namespace能做到的事情是,使相同的标识符在两个Namespace中代表不同的消息队列,这样也就使得两个Namespace中的进程不能通过IPC进程通信了。


4.mnt 命名空间
类似 chroot,将一个进程放到一个特定的目录执行。mnt 命名空间允许不同命名空间的进程看到的文件结构不同,这样每个命名空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个命名空间中的容器在 /proc/mounts 的信息只包含所在命名空间的 mount point。
你可以通过/proc/[pid]/mounts查看到所有挂载在当前namespace中的文件系统,还可以通过/proc/[pid]/mountstats看到mount namespace中文件设备的统计信息,包括挂载文件的名字、文件系统类型、挂载位置等等。
进程在创建mount namespace时,会把当前的文件结构复制给新的namespace。新namespace中的所有mount操作都只影响自身的文件系统,而对外界不会产生任何影响。


5.uts 命名空间(隔离主机)
UTS(“UNIX Time-sharing System”) 命名空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 主机上的一个进程。
User namespace中使用到了map转换(uid_map),由于container并不是真正的虚拟化,所以在Guest-OS中创建的root用户会被映射到Host-OS中的普通用户中去。
为什么要使用UTS Namespace做隔离?
这是因为主机名可以用来代替IP地址,因此,也就可以使用主机名在网络上访问某台机器了,如果不做隔离,这个机制在容器里就会出问题。


6.User Namespace(隔离用户ID和组ID)
User Namespace用来隔离用户和组ID,也就是说一个进程在Namespace里的用户和组ID与它在host里的ID可以不一样,这样说可能读者还不理解有什么实际的用处。User Namespace最有用的地方在于,host的普通用户进程在容器里可以是0号用户,也就是root用户。这样,进程在容器内可以做各种特权操作,但是它的特权被限定在容器内,离开了这个容器它就只有普通用户的权限了。

 

 

三、应用实例

针对某个进程,ns下的
[root@STAG-DOCKER-01 92962]# pwd
/proc/92962
[root@STAG-DOCKER-01 92962]# tree ns
ns
|-- ipc -> ipc:[4026531839]
|-- mnt -> mnt:[4026531840]
|-- net -> net:[4026532004]
|-- pid -> pid:[4026531836]
|-- user -> user:[4026531837]
`-- uts -> uts:[4026531838]
0 directories, 6 files

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值