前言
我们都知道,
linux
中的进程树其实只有1棵, 根是pid
为1
的进程, 然而我们进入一个docker容器
中, 进程树的根也是pid
为1
, 可是这个根进程
与宿主机里的根进程
并不是同一进程, 事实上, 这个进程在宿主机中有真正对应的进程, 可pid
并不是1
, 而是其他值, 这是怎么做到的呢? 就是使用Linux 内核
提供的namespace
技术, 就像这样在整棵树中, 从
pid
为8
开始, 存在一棵子树, 这棵子树有两个pid, 前者是相对于整棵树的, 而后者是相对于单独的进程命名空间
namespace 有什么用
namespace
可以将一组进程隔离在特定的命名空间中, 让这一组进程无法看到其他命名空间的进程, 那么创建这样的隔离环境有什么好处呢? 为了安全和稳定, 这样可以防止入侵者通过某个服务进程来破坏其他进程, 而且我们可以在一个机器上创建出多个安全的隔离环境
namespace 小栗子
首先我们在宿主机中查看一下进程树
, 使用命令 pstree -p
-
查看宿主机中的进程树
walkerjun@walkerjun:~$ pstree -p systemd(1)─┬─ModemManager(871)─┬─{ModemManager}(904) │ ├─{ModemManager}(912) │ └─{ModemManager}(916) ├─NetworkManager(867)─┬─{NetworkManager}(905) │ ├─{NetworkManager}(907) │ └─{NetworkManager}(911) ├─accounts-daemon(749)─┬─{accounts-daemon}(750) │ ├─{accounts-daemon}(751) │ └─{accounts-daemon}(818) ├─atop(884) ├─atopacctd(875) ├─avahi-daemon(755)───avahi-daemon(862) ├─bluetoothd(757) ├─boltd(874)─┬─{boltd}(890) │ ├─{boltd}(894) │ └─{boltd}(897) ├─clash(2057)─┬─{clash}(2070) │ ├─{clash}(2071) │ ├─{clash}(2073) │ ├─{clash}(2084)
正如我们上面说的, 进程树是以
pid
为1
的进程为根节点的树, 往下开支散叶下去, 有非常多的进程, 这些进程都是在默认进程空间中
, 下面我们尝试创建一个新的进程命名空间
, 在新的命名空间中查看进程树, 我们希望看到不一样的结果 -
创建新的进程命名空间
使用命令
sudo unshare -ipf --mount-proc
, 可以创建一个新的进程命名空间
, 在这之后查看进程树pstree -p
walkerjun@walkerjun:~$ sudo unshare -ipf --mount-proc [sudo] walkerjun 的密码: root@walkerjun:/home/walkerjun# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 17:51 pts/1 00:00:00 -bash root 6 1 0 17:51 pts/1 00:00:00 ps -ef root@walkerjun:/home/walkerjun# pstree -p bash(1)───pstree(7)
我们可以看到, 在新的
进程命名空间
下只有两个进程,pid
为1
和pid
为7
, 因为这是新创建的, 所以这个命名空间下没有其他进程了, 这样我们就完成了一个进程命名空间
的创建, 拥有了一个进程隔离环境, 那么怎么往这个空间里面加入新程序呢? 这个命名空间的根进程
就是bash
, 即当前终端bash进程, 因此接下来在这个窗口创建的程序, 都会在这个进程命名空间
下, 我们来实验下 -
往新进程命名空间中加入新程序
直接执行
python -m http.server
开启一个 http下载服务器, 然后用ps -ef
验证root@walkerjun:/home/walkerjun# python -m http.server & [1] 8 root@walkerjun:/home/walkerjun# Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... root@walkerjun:/home/walkerjun# root@walkerjun:/home/walkerjun# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 17:51 pts/1 00:00:00 -bash root 8 1 0 18:05 pts/1 00:00:00 python -m http.server root 9 1 0 18:05 pts/1 00:00:00 ps -ef root@walkerjun:/home/walkerjun# 127.0.0.1 - - [23/Jun/2023 18:07:03] "GET / HTTP/1.1"
我们可以看到, 我们新启动的程序, 出现在新
进程命名空间
中了
namespace 的种类
上面谈论的namespace
是 PID
(进程命名空间), 除了这个还有 Cgroup
, IPC
, Network
, Mount
, Time
, User
, UTS