探究 Linux 的 Namespace
# Linux 的 Namespace
# 什么是 Linux Namespace
Linux 手册中有一个介绍 Linux 命名空间的定义:
A namespace wraps a global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource. Changes to the global resource are visible to other processes that are members of the namespace, but are invisible to other processes.
namespace 将全局系统资源包装在一个抽象中,这使得 namespace 中的进程似乎具有自己的全局资源的独立实例。对全局资源的更改对作为 namespace 成员的其他进程可见,但对其他进程不可见。
Linux network namespaces 是 Linux 内核的一项功能,允许我们通过虚拟化隔离网络环境。例如,使用 network namespaces ,可以创建独立的网络接口和路由表,这些网络接口和表与系统的其余部分隔离并独立运行。
**Linux namespaces 是 Docker 和 Kubernetes 等容器技术的基础。**值得一提的是,Linux 还提供了 Cgroup,Cgroup 用于控制进程可以使用的系统资源(如 CPU、内存…)。
# Namespace 的类型
Linux 支持的8种 namespace:
namespace 名称 | 使用的标识 - Flag | 控制内容 |
---|---|---|
Cgroup | CLONE_NEWCGROUP | Controls the system resources (like CPU, Memory…) the process can use.(控制进程可以使用的系统资源) |
IPC | CLONE_NEWIPC | System V IPC, POSIX message queues(信号量,消息队列) |
Network | CLONE_NEWNET | Network devices, stacks, ports, etc. (网络设备,协议栈,端口等) |
Mount | CLONE_NEWNS | Mount points(挂载点) |
PID | CLONE_NEWPID | Process IDs(进程 ID) |
Time | CLONE_NEWTIME | Boot and monotonic clocks(启动和单调时钟) |
User | CLONE_NEWUSER | User and group IDs(用户和用户组) |
UTS | CLONE_NEWUTS | Hostname and NIS domain name(主机名与 NIS 域名) |
# Namespace 的发展历程
Linux namespace 的灵感来自贝尔实验室在整个 Plan 9中大量使用的更广泛的命名空间功能。
Linux namespace 起源于2002年的2.4.19内核中,其工作属于 Mount namespace 类型。从2006年开始添加了额外的 namespace ,并一直持续到未来。随着 User namespace 的引入,在内核3.8版本中完成了足够的容器支持功能。
自内核版本5.6以来,共有8种 namespace 。namespace 功能在所有类型中都是相同的:每个进程都与一个 namespace 相关联,并且只能查看或使用与该 namespace 相关联的资源,以及适用的子代 namespace 。通过这种方式,每个进程(或其进程组)可以具有关于资源的唯一视图。隔离哪个资源取决于为给定进程组创建的 namespace 的类型。
按时间线排序 namespace:
- Mount (mnt):Linux 2.4.19
- Inter-process Communication (IPC):inux 2.6.19
- UTS:Linux 2.6.19
- Process ID (pid):Linux 2.6.24
- Control group (cgroup) Namespace:Linux 2.6.24
- Network (net):Linux 2.6.24~2.6.29
- User ID (user):Linux 2.6.23~3.8
- Time Namespace:Linux 5.6
# Namespace 的作用
就如 Linux namespace 的定义一样,namespace 的作用是隔离资源。
Mount namespace
Mount namespaces provide isolation of the list of mounts seen by the processes in each namespace instance. Thus, the processes in each of the mount namespace instances will see distinct single directory hierarchies.
**隔离一组进程看到的一组文件系统装载点。**因此,不同 Mount namespaces 中的进程可以具有文件系统层次结构的不同视图。随着 Mount namespaces 的添加,
mount()
和umont()
系统调用停止了对系统上所有进程可见的全局装载点集的操作,而是执行仅影响与调用进程关联的 Mount namespaces 的操作。IPC namespace
IPC namespaces isolate certain IPC resources, namely, System V IPC objects (see sysvipc(7)) and (since Linux 2.6.30) POSIX message queues (see mq_overview(7)). The common characteristic of these IPC mechanisms is that IPC objects are identified by mechanisms other than filesystem pathnames.
Each IPC namespace has its own set of System V IPC identifiers and its own POSIX message queue filesystem. Objects created in an IPC namespace are visible to all other processes that are members of that namespace, but are not visible to processes in other IPC namespaces.
隔离某些进程间通信(IPC)资源。
UTS namespace
UTS namespaces provide isolation of two system identifiers: the hostname and the NIS domain name. These identifiers are set using sethostname(2) and setdomainname(2), and can be retrieved using uname(2), gethostname(2), and getdomainname(2). Changes made to these identifiers are visible to all other processes in the same UTS namespace, but are not visible to processes in other UTS namespaces.
隔离
uname()
系统调用返回的两个系统标识nodename
和domainname
;这些名称是使用sethostname()
和setdomainname()
系统调用设置的。在容器的上下文中,UTS namespaces 功能允许每个容器都有自己的主机名和 NIS 域名。这对于根据这些名称定制操作的初始化和配置脚本非常有用。PID namespace
PID namespaces isolate the process ID number space, meaning that processes in different PID namespaces can have the same PID. PID namespaces allow containers to provide functionality such as suspending/resuming the set of processes in the container and migrating the container to a new host while the processes inside the container maintain the same PIDs.
隔离进程 ID 编号空间。换句话说,不同 PID namespaces 中的进程可以具有相同的 PID。PID namespaces 的主要好处之一是,可以在主机之间迁移容器,同时保持容器内进程的相同进程ID。PID namespaces 还允许每个容器都有自己的
init
(PID 1)进程,这是“所有进程的祖先”,用于管理各种系统初始化任务,并在终止时获取孤立的子进程。CGroup namespace
Cgroup namespaces virtualize the view of a process's cgroups (see cgroups(7)) as seen via /proc/[pid]/cgroup and /proc/[pid]/mountinfo.
Each cgroup namespace has its own set of cgroup root directories. These root directories are the base points for the relative locations displayed in the corresponding records in the /proc/[pid]/cgroup file. When a process creates a new cgroup namespace using clone(2) or unshare(2) with the CLONE_NEWCGROUP flag, its current cgroups directories become the cgroup root directories of the new namespace. (This applies both for the cgroups version 1 hierarchies and the cgroups version 2 unified hierarchy.)
Cgroup 信息隔离。用于隐藏进程所属的控制组的身份,使命名空间中的 cgroup 视图始终以根形式来呈现,保障安全
Network namespace
Network namespaces provide isolation of the system resources associated with networking: network devices, IPv4 and IPv6 protocol stacks, IP routing tables, firewall rules, the /proc/net directory (which is a symbolic link to /proc/PID/net), the /sys/class/net directory, various files under /proc/sys/net, port numbers (sockets), and so on. In addition, network namespaces isolate the UNIX domain abstract socket namespace (see unix(7)).
提供了与网络相关的系统资源的隔离。因此,每个 Network namespace 都有自己的网络设备、IP地址、IP 路由表、
/proc/net
目录、端口号等等。从网络的角度来看,Network namespace 使容器变得有用:每个容器都可以有自己的(虚拟)网络设备和自己的应用程序,这些应用程序绑定到每个名称空间的端口号空间;主机系统中合适的路由规则可以将网络分组引导到与特定容器相关联的网络设备。例如,可以在同一主机系统上具有多个容器化的 web 服务器,每个服务器在其(每个容器)Network namespace 中绑定到端口80。
User namespace
User namespaces isolate security-related identifiers and attributes, in particular, user IDs and group IDs (see credentials(7)), the root directory, keys (see keyrings(7)), and capabilities (see capabilities(7)). A process's user and group IDs can be different inside and outside a user namespace. In particular, a process can have a normal unprivileged user ID outside a user namespace while at the same time having a user ID of 0 inside the namespace; in other words, the process has full privileges for operations inside the user namespace, but is unprivileged for operations outside the namespace.
隔离用户 ID 和组 ID。换句话说,进程的用户和组 ID 在 User namespace 内外可能不同。这里最有趣的情况是,一个进程可以在 User namespace 之外有一个普通的无特权用户 ID,同时在 User namespace 内部有一个 0 的用户 ID。这意味着进程对 User namespace 内的操作具有完全的根特权,但对 User namespace 外的操作没有特权。
从 Linux 3.8开始,无特权进程可以创建 User namespace,这为应用程序开辟了一系列有趣的新可能性:由于原本无特权的进程可以在 User namespace 内拥有 root 权限,因此无特权的应用程序现在可以访问以前仅限于 roo t的功能。
Time namespace
Time namespaces virtualize the values of two system clocks:
• CLOCK_MONOTONIC (and likewise CLOCK_MONOTONIC_COARSE and CLOCK_MONOTONIC_RAW), a nonsettable clock that represents monotonic time since—as described by POSIX—"some unspecified point in the past".
• CLOCK_BOOTTIME (and likewise CLOCK_BOOTTIME_ALARM), a nonsettable clock that is identical to CLOCK_MONOTONIC, except that it also includes any time that the system is suspended.
隔离启动和单调时钟。简单来说就是隔离系统时间,允许不同进程查看到不同的系统时间
# 参考
- Linux 手册:
- namespaces(7) — Linux manual page (opens new window)
- mount_namespaces(7) — Linux manual page (opens new window)
- pid_namespaces(7) — Linux manual page (opens new window)
- network_namespaces(7) — Linux manual page (opens new window)
- ipc_namespaces(7) — Linux manual page (opens new window)
- uts_namespaces(7) — Linux manual page (opens new window)
- user_namespaces(7) — Linux manual page (opens new window)
- cgroup_namespaces(7) — Linux manual page (opens new window)
- cgroups(7) — Linux manual page (opens new window)
- time_namespaces(7) — Linux manual page (opens new window)
- Namespaces in operation, part 1: namespaces overview (opens new window)
- https://en.wikipedia.org/wiki/Linux_namespace