在本文中,笔者将介绍一些特殊的Linux技术(包括命名空间和控制组)是如何使容器成为可能的。

Linux的一些技术构成了在系统上构建和运行容器进程的基础,包括:命名空间、控制组(cgroup)、seccomp、SELinux。
命名空间
命名空间为容器提供了一个隔离层,它为容器提供了它自己的Linux文件系统的视图。这限制了进程可以看到的内容,因此限制了可用的资源。
Linux内核中有几个命名空间,Docker或Podman和其他人在创建容器时使用这些名称空间:
$ docker container run alpine ping 8.8.8.8
$ sudo lsns -p 29413
NS TYPE NPROCS PID USER COMMAND
4026531835 cgroup 299 1 root /usr/lib/systemd/systemd --
switched...
4026533105 mnt 1 29413 root ping 8.8.8.8
4026533106 uts 1 29413 root ping 8.8.8.8
4026533105 ipc 1 29413 root ping 8.8.8.8
[...]
用户
用户命名空间隔离容器中的用户和组。这是通过允许容器具有与主机系统不同的UID和GID范围视图来实现的。用户命名空间使软件能够作为根用户在容器内运行。如果入侵者攻击容器,然后逃逸到主机,则它们仅限于非根身份。
mnt
mnt命名空间允许容器拥有自己的系统文件系统层次结构视图。你可以在Linux系统的/proc/<PID>/mounts位置找到每个容器进程的挂载点。
UTS
Unix分时系统(UTS)命名空间允许容器具有唯一的主机名和域名。运行容器时,即使使用-name标记,也会使用随机ID作为主机名。你可以使用unshare命令了解其工作原理。
$ docker container run -it --name nived alpine sh
/ # hostname
9c9a5edabdd6
/ #
$ sudo unshare -u sh
# hostname isolated.hostname
# hostname
# exit
$ hostname
homelab.redhat.com
IPC
进程间通信(IPC)命名空间允许不同的容器进程通过访问共享内存范围或使用共享消息队列进行通信。
# ipcmk -M 10M
Shared memory id: 0
# ipcmk -M 20M
Shared memory id: 1
# ipcs
---- Message Queues ----
key msqid owner perms used-bytes messages
---- Shared Memory Segments
key shmid owner perms bytes nattch status
0xd1df416a 0 root 644 10485760 0
0xbd487a9d 1 root 644 20971520 0
[...]
PID
进程ID(PID)命名空间确保容器内运行的进程与外部世界隔离。在容器内运行ps命令时,由于此命名空间,你只能看到在容器内运行的进程,而不能看到在主机上运行的进程。
net
网络命名空间允许容器拥有自己的网络接口、IP地址、路由表、端口号等视图。容器如何能够与外部世界通信?你创建的所有容器都连接到一个特殊的虚拟网络接口以进行通信。
控制组(cgroup)
cgroup是制作容器的基本模块。cgroup分配和限制容器使用的资源,如CPU、内存、网络I/O。容器引擎自动创建每种类型的cgroup文件系统,并在容器运行时为每个容器设置值。
Seccomp
Seccomp基本上代表安全计算。它是一种Linux功能,用于限制允许应用程序进行的一组系统调用。例如,Docker的默认seccomp配置文件禁用了大约44个系统调用(总共超过300个可用)。
这里的想法是为容器提供对可能需要的资源的访问。例如,如果你不需要容器来更改主机上的时钟时间,则可能不需要使用clock_adjtime和clock_settime系统调用,因此将它们屏蔽是有意义的。类似地,你不希望容器更改内核模块,因此它们不需要进行create_module、delete_module系统调用。
SELinux
SELinux代表安全增强型Linux。如果你在主机上运行Red Hat发行版,则默认情况下会启用SELinux。SELinux允许你限制应用程序只能访问自己的文件,并阻止任何其他进程访问它们。因此,如果应用程序被破坏,将限制它可以影响或控制的文件数量。通过为文件和进程设置上下文,并通过定义策略来实现这一点,这些策略将强制执行进程可以看到的内容并对其进行更改。
容器的SELinux策略由container-selinux包定义。默认情况下,容器使用container_t标签运行,允许在/usr目录下读取(r)和执行(x),并从/etc目录中读取大部分内容。标签container_var_lib_t 对于与容器相关的文件是通用的。
小结
容器是当今IT基础设施的重要组成部分,也是一项非常有趣的技术。即使你的角色不直接涉及容器化,了解一些基本的容器概念和方法也会让你了解它们如何帮助组织。容器是基于开源Linux技术构建的,这让它们变得更好。
原文链接:
https://opensource.com/article/21/8/container-linux-technology






