如果通过POD的形式来启动多个容器那么它们的名称空间会是共享的么,所以我这里讨论是在默认情况下同一个POD的不同容器的哪些名称空间是打通的。这里先说一下结论,共享的是UTS、IPC、NET、USER。
UTS名称空间主机名名称空间,保存内核名称、版本以及主机名和域名。默认情况下同一个POD的不同容器是共享UTS的,看下面的配置:
apiVersion: apps/v1 kind: Deployment metadata: name: centos-dep labels: app: centos spec: replicas: 1 selector: matchLabels: app: centos template: metadata: labels: app: centos spec: containers: - name: app1 image: centos imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c"] args: - sleep 3600 - name: app2 image: centos imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c"] args: - sleep 3600运行这个POD,然后分别登陆到不同容器去查看主机名,你会发现主机名一样,而且就是POD的名字,如下图:
另外你通过uname -a如果查看到的内容是一致的也说明是共享UTS名称空间的。
实验证明,默认情况下同一个POD中的不同容器的UTS名称空间是共享的。
IPC名称空间进程间通信名称空间,IPC的隔离就是阻断进程间通信,主要是信号量、队列和共享内存。运行主机进程通过上面的机制进行通信。
下面通过一个实验来看看同一个POD的IPC名称空间是否是共享的,在app2中通过命令ipcmk --queue来创建一个队列,然后在app1中通过命令ipcs来查看,如果有这个队列就说明是共享的,如下图:
实验证明,默认情况下同一个POD中的不同容器的IPC名称空间是共享的。
MNT名称空间Mount名称空间,提供对磁盘挂载点和文件系统的隔离能力。同一主机上的不同进程访问相同的路径会得到相同的内容,因为它们共享本地主机的磁盘和文件系统。
在同一POD内容器之间挂载点名称空间是隔离的,如果该POD的多个容器挂载一个POD级别的Volume,那么它们就可以实现挂载点的共享,但共享的也仅仅是这一个Volume并不是整个文件系统。
实验证明,默认情况下同一个POD中的不同容器的MNT名称空间不是共享的。
NET名称空间网络名称空间,同一主机上的不同进程可以进行localhost或者本地unix socket通信。在单独启动容器的时候不同容器是隔离的,但是在POD中不同容器通过一个Infra容器来进行共享网络名称空间,其原理是其他用户自己定义的容器都Join这个Infra容器的网络。这里我启动的就是一个Cetnos镜像,无法做本地通信验证。不过它的确是通过Infra容器来共享的。
PID名称空间进程ID名称空间,同一主机上的不同进程在同一PID空间内可以看到其他进程的ID,并且同一PID空间的进程的ID不会重复。另外PID名称空间有层级关系,子空间看不到父空间的内容,但是父空间可以管理子空间,比如发送信号。
在POD中则对应为同一POD内的不同容器可以看到对方的进程ID。默认不是共享的,可以设置POD的shareProcessNamespace这个值为true来进行共享,默认为false。我在App2中启动一个top命令,然后在App1中通过ps命令查看,看下面的测试:
实验证明,默认情况下同一个POD中的不同容器的PID名称空间不是共享的。
USER名称空间隔离用户、组以及相关用户能力的。也就是在不同的User Namespace中,相同的用户可以有不同的UID或者不同的权限。另外还可以通过映射的方式把某个User Namespace的用户映射到另外一个User Namespace的用户上,这样这两个名称可能不同的用户就具有相同的权限。如果想要在本机进行验证需要查看一下这个文件:
cat /proc/sys/user/max_user_namespaces如果是0则表示没有开启,需要给它一个值echo "15000" > /proc/sys/user/max_user_namespaces,然后你再运行unshare -U或者unshare --user就不会报错了。
在Docker中默认并没有开启user namespace。