ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Namespace 详解

Namespace 详解 在 Linux 系统中namespace 是在内核级别以一种抽象的形式来封装系统资源的通过将系统资源放在不同的 namespace 中来实现资源隔离的目的。设置了不同 namespace 的程序就可以享有彼此独立的一份系统资源。Linux 中当前可用的命名空间如下rootdocker-host:~# ls -l /proc/$$/ns total 0 lrwxrwxrwx 1 root root 0 Jul 6 10:44 cgroup - cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Jul 6 10:44 ipc - ipc:[4026531839] lrwxrwxrwx 1 root root 0 Jul 6 10:44 mnt - mnt:[4026531840] lrwxrwxrwx 1 root root 0 Jul 6 10:44 net - net:[4026531992] lrwxrwxrwx 1 root root 0 Jul 6 10:44 pid - pid:[4026531836] lrwxrwxrwx 1 root root 0 Jul 6 10:44 pid_for_children - pid:[4026531836] lrwxrwxrwx 1 root root 0 Jul 6 10:44 user - user:[4026531837] lrwxrwxrwx 1 root root 0 Jul 6 10:44 uts - uts:[4026531838] rootdocker-host:~#当前系统使用到的命名空间有cgroup ns隔离 CGroup 视图。ipc ns隔离进程间通信资源。mnt ns隔离文件系统挂载点。net ns隔离网络资源。pid ns隔离进程 ID。user ns隔离用户和用户组 ID。uts ns隔离主机名和域名。pid_for_children: 当前进程的子进程将继承的 PID ns。下面通过从非管理账户 user1 的视角来具体理解命名空间的工作原理。首先配置 user1 用户的 sudo 免密并添加 dockers 组这组操作请自行完成。以 user1 用户登录新的会话运行一个名字 conns 的 alpine 容器user1docker-host:~$ docker run --name conns --rm -id alpine ash e2b6aac529d8181064b1ad29a7f28cce84307ef11badbc1aa6701188f73b0b35 user1docker-host:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e2b6aac529d8 alpine ash 4 seconds ago Up 3 seconds conns user1docker-host:~$我们知道conns 容器包含有一个精简但完整的 rootfs 文件系统user1docker-host:~$ docker exec -it conns ash / # ls -l total 56 drwxr-xr-x 2 root root 4096 Jun 13 16:38 bin drwxr-xr-x 5 root root 340 Jul 6 10:51 dev drwxr-xr-x 1 root root 4096 Jul 6 10:51 etc drwxr-xr-x 2 root root 4096 Jun 13 16:38 home drwxr-xr-x 6 root root 4096 Jun 13 16:38 lib drwxr-xr-x 5 root root 4096 Jun 13 16:38 media drwxr-xr-x 2 root root 4096 Jun 13 16:38 mntdrwxr-xr-x 2 root root 4096 Jun 13 16:38 opt dr-xr-xr-x 277 root root 0 Jul 6 10:51 proc drwx------ 1 root root 4096 Jul 6 10:54 root drwxr-xr-x 3 root root 4096 Jun 13 16:38 run drwxr-xr-x 2 root root 4096 Jun 13 16:38 sbin drwxr-xr-x 2 root root 4096 Jun 13 16:38 srv dr-xr-xr-x 13 root root 0 Jul 6 10:51 sys drwxrwxrwt 2 root root 4096 Jun 13 16:38 tmp drwxr-xr-x 7 root root 4096 Jun 13 16:38 usr drwxr-xr-x 11 root root 4096 Jun 13 16:38 var / #将 conns 容器的文件系统导出user1docker-host:~$ mkdir mancontainer user1docker-host:~$ cd mancontainer user1docker-host:~/mancontainer$ docker export conns -o dockercontainer.tar user1docker-host:~/mancontainer$ ls -l total 8500 -rw------- 1 user1 user1 8700416 Jul 6 10:59 dockercontainer.tar user1docker-host:~/mancontainer$在当前目录创建一个 rootfs 目录并将导出的 conns 文件系统解压到这个目录这么做的目的就是要手工创建一个资源隔离的类似容器对象。好了新的文件系统好像是独立的 root 文件系统但是看 ip link 命令显示的网络信息可以发现除了挂载点之外的网络、进程等资源在“模拟容器”中都能看到这些资源没有隔离。 回到 user1 用户使用 unshare 命令隔离出一组新的命名空间集合。unshare 命令用于创建一个新 ns 集合并在其 中启动一个 Bash shell实现资源隔离这是 Linux 容器技术的基础之一。重点如果此时我们在其他终端上检查主机中的进程时会看到即使上面的用户 root在进程之外也是在普通用 户 user1 的凭据下执行的rootdocker-host:~# ps -ef | grep 2640 user1 2640 2625 0 10:50 pts/0 00:00:00 -bash user1 4066 2640 0 11:34 pts/0 00:00:00 unshare --mount --uts --ipc --net --pid --fork --user --map-root-user /bin/bash root 4341 3429 0 11:44 pts/1 00:00:00 grep --colorauto 2640 rootdocker-host:~#这就是 PID 命名空间的神奇之处它使得一个进程具有不同的 PID 号例如 K8s pod 场景。回到 “模拟容器” 环境如果想要显示当前正在运行的进程结果先显示的是主机中的所有进程rootdocker-host:~/mancontainer# ps -ef UID PID PPID C STIME TTY TIME CMD nobody 1 0 0 10:41 ? 00:00:01 /sbin/init maybe‑ubiquity nobody 2 0 0 10:41 ? 00:00:00 [kthreadd] nobody 3 2 0 10:41 ? 00:00:00 [rcu_gp] nobody 4 2 0 10:41 ? 00:00:00 [rcu_par_gp] ......回到“模拟容器”环境会看到有一个新的网络设备出现了rootdocker-host:~/mancontainer# ip link 1: lo: LOOPBACK mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 10: vethContainerif11: BROADCAST,MULTICAST mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether ea:b5:ca:8c:db:f8 brd ff:ff:ff:ff:ff:ff link‑netnsid 0 rootdocker-host:~/mancontainer#
返回列表