Linux内核中的Namespace技术

对应到容器技术,为了隔离不同类型的资源,Linux 内核里面实现了以下几种不同类型的 namespace。

  • UTS,对应的宏为 CLONE_NEWUTS,表示不同的 namespace 可以配置不同的 hostname。
  • User,对应的宏为 CLONE_NEWUSER,表示不同的 namespace 可以配置不同的用户和组。
  • Mount,对应的宏为 CLONE_NEWNS,表示不同的 namespace 的文件系统挂载点是隔离的
  • PID,对应的宏为 CLONE_NEWPID,表示不同的 namespace 有完全独立的 pid,也即一个 namespace 的进程和另一个 namespace 的进程,pid 可以是一样的,但是代表不同的进程。
  • Network,对应的宏为 CLONE_NEWNET,表示不同的 namespace 有独立的网络协议栈。

操作 namespace 的常用指令 nsenter,可以用来运行一个进程,进入指定的 namespace。例如,通过下面的命令,我们可以运行 /bin/bash,并且进入 nginx 所在容器的 namespace。

# nsenter --target 58212 --mount --uts --ipc --net --pid -- env --ignore-environment -- /bin/bash

root@f604f0e34bc2:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

另一个命令是 unshare,它会离开当前的 namespace,创建且加入新的 namespace,然后执行参数中指定的命令。运行下面这行命令之后,pid 和 net 都进入了新的 namespace。

unshare --mount --ipc --pid --net --mount-proc=/proc --fork /bin/bash

在内核里面,对于任何一个进程 task_struct 来讲,里面都会有一个成员 struct nsproxy,用于保存 namespace 相关信息,里面有 struct uts_namespace、struct ipc_namespace、struct mnt_namespace、struct pid_namespace、struct net *net_ns 和 struct cgroup_namespace *cgroup_ns。

创建 namespace 的时候,我们在内核中会调用 copy_namespaces,调用顺序依次是 copy_mnt_ns、copy_utsname、copy_ipcs、copy_pid_ns、copy_cgroup_ns 和 copy_net_ns,来复制 namespace。

此文章为4月Day4 学习笔记,内容来源于极客时间《趣谈 Linux 操作系统》,推荐该课程。

猜你喜欢

转载自blog.csdn.net/key_3_feng/article/details/129942638