Docker容器技术与运维
上QQ阅读APP看书,第一时间看更新

1.4.1 名称空间

Linux的名称空间机制提供了一种资源隔离的解决方案。Docker通过名称空间机制为容器提供隔离的工作空间。运行容器时,Docker会为该容器创建一系列的名称空间。

1.什么是名称空间

名称空间又称命名空间,是对全局系统资源的一种封装隔离技术,使得处于不同名称空间的进程拥有彼此独立的全局系统资源,改变一个名称空间中的系统资源只会影响当前名称空间中的进程,而不会影响其他名称空间中的进程。采用名称空间机制,PID(进程ID)、IPC(进程间通信)、网络等系统资源不再是全局性的,而是属于特定的名称空间。

2.名称空间类型

Linux操作系统中的每个进程都有一个名为/proc/[pid]/ns的目录(pid为进程ID),其中包含该进程所属名称空间的信息。例如,执行以下操作可查看当前shell进程所属的名称空间($$代表当前shell的进程ID,ns代表名称空间):


[root@host-a ~]# ls -l /proc/$$/ns 
total 0 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 cgroup -> cgroup:[4026531835] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 ipc -> ipc:[4026531839] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 mnt -> mnt:[4026531840] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 net -> net:[4026531992] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 pid -> pid:[4026531836] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 pid_for_children -> pid:[4026531836] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 user -> user:[4026531837] 
lrwxrwxrwx. 1 root root 0 Mar 11 04:35 uts -> uts:[4026531838] 

从以上输出可知,Linux内核到目前为止实现了7种不同类型的名称空间(不同内核版本的Linux所支持的名称空间类型有所不同)。每种类型的每个名称空间都有一个ID(唯一编号),如“ipc:[4026531839]”中“ipc”表示名称空间类型,“4026531839”表示名称空间ID。如果两个进程的名称空间ID相同,则说明它们属于同一名称空间。

● Cgroup(控制组):用于隔离控制组根目录,从Linux 4.6版本开始,内核才提供此功能。

● IPC(进程间通信):用于隔离进程间通信所需的资源。PID名称空间和IPC名称空间可以组合起来使用,同一个IPC名称空间内的进程可以彼此看见,允许进行交互,不同名称空间的进程无法交互。

● Network(网络):为进程提供网络资源隔离能力。一个网络名称空间提供了一个独立的网络环境(包括网络设备接口、IPv4和IPv6协议栈、IP路由表、防火墙规则和套接字等),就跟一个独立的计算机系统一样。

● Mount(挂载):为进程提供磁盘挂载点和文件系统的隔离能力。每个进程都存在于一个挂载名称空间中。如果不使用挂载名称空间,子进程和父进程将共享一个挂载名称空间,子进程调用mount或umount命令将会影响到所有该名称空间内的进程。

● PID(进程ID):Linux通过名称空间管理进程ID,同一个进程在不同的名称空间中进程ID不同。进程名称空间是父子结构,子空间对于父空间是可见的。例中的pid和pid_for_children就属于同一名称空间。

● User(用户):用于隔离用户。

● UTS:用于隔离主机名和域名。UTS是UNIX Time-sharing System的缩写。

3.Docker使用名称空间

Linux名称空间具有更加精细的资源分配管理机制,为实现基于容器的虚拟化技术提供了很好的基础,Docker利用这一特性实现了资源的隔离。容器本质上就是进程,不同容器内的进程属于不同的名称空间,彼此透明,互不干扰。这些名称空间提供了一个隔离层。容器的每个方面都运行在独立的名称空间中,并且其访问权限也仅限于该名称空间。

Docker引擎使用下列几个类型的Linux名称空间来实现特定的资源隔离管理功能。

● PID名称空间:用于进程隔离。对于同一进程,在不同的名称空间中看到的进程ID不相同,每个进程命名空间有一套自己的进程ID管理方法。

● 网络名称空间:用于管理网络接口。有了PID名称空间,每个名称空间中的进程就可以相互隔离,但是网络端口还是共享本地系统的端口,这就需要通过网络名称空间实现网络隔离。网络名称空间为进程提供了一个完全独立的网络协议栈的视图。Docker采用虚拟网络设备的方式,将不同名称空间的网络设备连接到一起。默认情况下,容器中的虚拟网卡将同本地主机上的docker0网桥连接在一起。

● IPC名称空间:用于管理IPC资源的访问。容器中进程交互采用了Linux常见的进程间交互方法,包括信号量、消息队列和共享内存等。

● 挂载名称空间:用于管理文件系统挂载点。挂载名称空间类似于chroot功能,将一个进程放到一个特定的目录执行。挂载名称空间允许不同名称空间的进程看到不同的文件结构,这样每个名称空间中的进程所看到的文件目录会被彼此隔离。

● UTS名称空间:用于隔离内核和版本标识符。允许每个容器拥有独立的主机名和域名,从而可以虚拟出一个有独立主机名和网络空间的环境,就与网络上一台独立的主机一样。默认情况下,Docker容器的主机名就是返回的容器ID。

● 用户名称空间:每个容器可以有不同的用户和组ID,也就是说可以在容器内使用特定的内部用户执行程序,而不是使用本地系统上存在的用户来执行程序。每个容器内部都可以有自己的root账户,但与主机上的用户不在一个名称空间。通过使用隔离的用户名称空间可以提高安全性,避免容器内进程获取额外的权限。

目前Docker引擎除了用户名称空间不完全支持以外,其他5个名称空间都是默认开启的,并且可以通过clone系统调用进行创建。