Linux 中的 namespace

基本介绍

namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。

Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响。

namespace 的作用

从前面介绍我们基本明确了 namespace 的作用,那就是“隔离”。Linux 内核实现 namespace 的一个主要目的就是实现轻量级虚拟化(容器)服务;在同一个 namespace 下的进程可以感知彼此的变化,而对外界的进程一无所知。这样就可以让容器中的进程产生错觉,认为自己置身于一个独立的系统中,从而达到隔离的目的。也就是说 linux 内核提供的 namespace 技术为 docker 等容器技术的出现和发展提供了基础条件。

从 docker 实现者的角度考虑该如何实现一个资源隔离的容器。比如是不是可以

  • 通过 chroot 命令切换根目录的挂载点,从而隔离文件系统。
  • 为了在分布式的环境下进行通信和定位,容器必须要有独立的 IP、端口和路由等,这就需要对网络进行隔离。
  • 容器需要一个独立的主机名以便在网络中标识自己
  • 进程间的通信隔离。
  • 用户权限隔离
  • 运行在容器中的应用需要有进程号(PID),需要与宿主机中的 PID 进行隔离。

也就是说这六种隔离能力是实现一个容器的基础,下面就看下 linux 内核的 namespace 特性提供了什么样的隔离能力:

|名称| Flag| 隔离的资源|
| ———— | ———— |
|Cgroup |CLONE_NEWCGROUP |Cgroup root directory(cgroup 的根目录)|
|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 domian name(主机名和 NIS 域名)|

Cgroup namespace 是后面才增加的,本篇不做过多介绍,将另起篇幅。

namespace 的基本操作

查看进程所属的 namespace

/proc/[pid]/ns 目录下会包含进程所属的 namespace 信息,使用下面的命令可以查看当前进程所属的 namespace 信息:

1
2
3
4
5
6
7
8
9
10
11
$ ll /proc/$$/ns
总用量 0
dr-x--x--x 2 admin admin 0 12月 12 11:19 ./
dr-xr-xr-x 9 admin admin 0 12月 12 11:18 ../
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 cgroup -> cgroup:[4026537386]
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 ipc -> ipc:[4026536810]
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 mnt -> mnt:[4026537383]
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 net -> net:[4026536400]
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 pid -> pid:[4026537385]
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 user -> user:[4026531837]
lrwxrwxrwx 1 admin admin 0 12月 12 11:19 uts -> uts:[4026537384]

或者

1
2
3
4
5
6
7
8
9
10
11
$ ll /proc/7370/ns
总用量 0
dr-x--x--x 2 admin admin 0 12月 12 11:20 ./
dr-xr-xr-x 9 admin admin 0 12月 9 18:43 ../
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 cgroup -> cgroup:[4026537386]
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 ipc -> ipc:[4026536810]
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 mnt -> mnt:[4026537383]
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 net -> net:[4026536400]
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 pid -> pid:[4026537385]
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 user -> user:[4026531837]
lrwxrwxrwx 1 admin admin 0 12月 12 11:20 uts -> uts:[4026537384]

从输出的 namespace 信息可以看到,namespace 文件都是链接文件; 以 cgroup:[4026537386] 为例:

  • cgroup 是 namespace 的类型
  • 数字(inode number )标识一个 namespace,可以理解为 namespace 的 ID
    如果两个进程的某个 namespace 文件指向同一个链接文件,说明其相关资源在同一个 namespace 中。

参考

作者

卫恒

发布于

2020-12-12

更新于

2022-04-23

许可协议

评论