编辑
2020-02-19
计算机基础科学
00
请注意,本文编写于 1321 天前,最后修改于 113 天前,其中某些信息可能已经过时。

目录

IPC Namespace
PID Namespace
Mount Namespace
User Namespace
Network Namespace

mark

在上次的文章《虚拟化的基石——Namespace》 中主要讲述了Namespace的作用,却没有详细的拿代码举证,上次仅仅证明了UTS Namespace,剩下五个命名空间全在这篇文章了,主要是IPC Namespace、PID Namespace、Mount Namespace、User Namespace、Network Namespace的概念的理解以及使用代码证明!

IPC Namespace

IPC Namespace用来隔离System V IPC和POSIX message queues。每一个 IPC Namespace,都有自己的System V IPC和POSIX message queue。所谓System V IPC即系统IPC资源,其实主要是共享内存、信号量( System V信号量 )、消息队列;POSIX message queues其实就是随文件系统的消息队列

  • 随进程持续的(Process-Persistent IPC) IPC对象一直存在,直到最后拥有他的进程被关闭为止,典型的IPC有pipes(管道)和FIFOs(先进先出对象)

  • 随内核持续的(Kernel-persistent IPC) IPC对象一直存在直到内核被重启或者对象被显式关闭为止,在Unix中这种对象有System v 消息队列,信号量,共享内存。(注意Posix消息队列,信号量和共享内存被要求为至少是内核持续的,但是也有可能是文件持续的,这样看系统的具体实现)。

  • 随文件系统持续的(FileSystem-persistent IPC) 除非IPC对象被显式删除,否则IPC对象会一直保持(即使内核才重启了也是会留着的)。如果Posix消息队列,信号量,和共享内存都是用内存映射文件的方法,那么这些IPC都有着这样的属性。

还是昨天的UTS Namespace代码稍做修改

mark

现在go run IPNamespace.go

mark

通过以上实验,可以发现在新创建的Namespace里,看不到宿主机上已经创建的message queue,说明IPC Namespace创建成功,IPC 已经被隔离。

PID Namespace

PID Namespace是用来隔离进程ID的。同样一个进程在不同的PID Namespace里可以拥有不同的PID。这样就可以理解,在docker container里面,使用ps -ef经常会发现,在容器内,前台运行的那个进程PID是1,但是在容器外,使用ps -ef会发现同样的进程却有不同的PID,这就是PID Namespace做的事情。

mark

mark

Mount Namespace

Mount Namespace用来隔离各个进程看到的挂载点视图。在不同Namespace的进程中到的文件系统层次是不一样的。在Mount Namespace中调用mount()和umount()仅仅只会影当前Namespace内的文件系统,而对全局的文件系统是没有影响的。

看到这里,也许就会想到chroot()。它也是将某一个子目录变成根节点。但是,MountNamespace不仅能实现这个功能,而且能以更加灵活和安全的方式实现。MountNamespace是Linux第一个实现的Namespace类型,因此,它的系统调用参是NEWNS (New Namespace的缩写)。当时人们貌似没有意识到,以后还会有很多类型Namespace加入Linux大家庭。代码做了一点改动,增加了NEWNS标识,如下。

mark

运行代码,然后查看一下/proc 的文件内容。proc 是一个文件系统,提供额外的机制,可以通过内核和内核模块将信息发送给进程。这里的/proc 还是宿主机的, 所以看到里面会比较乱,下面将/proc mount 到我们自己的Namespace 下面来。

mark

Mount Namespace 中的mount 和外部空间是隔离的, mount 操作并没有影响到外部。Docker volume 也是利用了这个特性。

User Namespace

User Namespace主要是隔离用户的用户组ID。也就是说,一个进程的UserID和GroupID在User Namespace内外可以是不同的。比较常用的是,在宿主机上以一个非root用户运行创建一个User Namespace,然后在User Namespace里面却映射成root用户。

这意味着,这个进程在User Namespace里面有root权限,但是在User Namespace外面却没有root的权限。从LinuxKernel3.8开始,非root进程也可以创建UserNamespace,并且此用户在Namespace里面可以被映射成root,且在Namespace内有root权限。

mark

mark

Network Namespace

Network Namespace是用来隔离网络设备、IP 地址端口等网络栈的Namespace。Network Namespace可以让每个容器拥有自己独立的(虚拟的)网络设备,而且容器内的应用可以绑定到自己的端口,每个Namespace内的端口都不会互相冲突。在宿主机上搭建网桥后,就能很方便地实现容器之间的通信,而且不同容器上的应用可以使用相同的端口。

mark

mark

在Namespace 里面什么网络设备都没有。这样就能断定Network Namespace 与宿主机之间的网络是处于隔离状态了,是不是离Docker的实现更进一步了呢?

本文作者:Tim

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!