命名空间是Linux操作系统内核的一种资源隔离方式,使不同的进程具有不同的系统视图。系统视图就是进程能够感知到的系统环境,如主机名、文件系统、网络协议栈、其他用户和进程等。使用命名空间后,每个进程都具备独立的系统环境,进程间彼此感觉不到对方的存在,进程之间相互隔离。目前,Linux中的命名空间共有6种,可以嵌套使用。
- Mount:隔离了文件系统的挂载点(mount points),处于不同“mount”命名空间中的进程可以看到不同的文件系统。
- Network:隔离进程网络方面的系统资源,包括网络设备、IPv4和IPv6的协议栈、路由表、防火墙等。
- IPC:进程间相互通信的命名空间,不同命名空间中的进程不能通信。
- PID:进程号在不同的命名空间中是独立编号的,不同的命名空间中的进程可以有相同的编号。当然,这些进程在操作系统中的全局(命名空间外)编号是唯一的。
- UTS:系统标识符命名空间,在每个命名空间中都可以有不同的主机名和NIS域名。
- User:命名空间中的用户可以有不同于全局的用户ID和组ID,从而具有不同的特权。
命名空间实现了在同一操作系统中隔离进程的方法,几乎没有额外的系统开销,所以是非常轻量的隔离方式,进程启动和运行的过程在命名空间中和外面几乎没有差别。
控制组
命名空间实现了进程隔离功能,但由于各个命名空间中的进程仍然共享同样的系统资源,如CPU、磁盘I/O、内存等,所以如果某个进程长时间占用某些资源,其他命名空间里的进程就会受到影响,这就是“吵闹的邻居(noisy neighbors)”现象。因此,命名空间并没有完全达到进程隔离的目的。为此,Linux内核提供了控制组(Control Groups,cgroups)功能来处理这个问题。
Linux把进程分成控制组,给每组里的进程都设定资源使用规则和限制。在发生资源竞争时,系统会根据每个组的定义,按照比例在控制组之间分配资源。控制组可设定规则的资源包括CPU、内存、磁盘I/O和网络等。通过这种方式,就不会出现某些进程无限度抢占其他进程资源的情况。
Linux系统通过命名空间设置进程的可见且可用资源,通过控制组规定进程对资源的使用量,这样隔离进程的虚拟环境(即容器)就建立起来了。
容器运行时
Linux 提供了命名空间和控制组两大系统功能,它们是容器的基础。但是,要把进程运行在容器中,还需要有便捷的SDK或命令来调用Linux的系统功能,从而创建出容器。容器的运行时(runtime)就是容器进程运行和管理的工具。
容器运行时分为低层运行时和高层运行时,功能各有侧重。低层运行时主要负责运行容器,可在给定的容器文件系统上运行容器的进程;高层运行时则主要为容器准备必要的运行环境,如容器镜像下载和解压并转化为容器所需的文件系统、创建容器的网络等,然后调用低层运行时启动容器。主要的容器运行时的关系如下图所示。