Docker 和 K8s 是如何把进程“关”进容器里的?当你执行 

ls -l /proc/self/ns 时看到的那些神秘文件又代表什么?本文带你通过生动的比喻和实例,彻底搞懂 Linux Namespaces。

作为一名云原生工程师,我们每天都在和容器打交道。但你是否好奇过,所谓的“容器”在 Linux 内核层面到底长什么样?

当你登录到一台 Linux 服务器,执行 ls -l /proc/$$/ns,你会看到下面这些“天书”:

lrwxrwxrwx ... cgroup -> cgroup:[4026531835]lrwxrwxrwx ... ipc -> ipc:[4026531839]lrwxrwxrwx ... mnt -> mnt:[4026531840]lrwxrwxrwx ... net -> net:[4026531993]lrwxrwxrwx ... pid -> pid:[4026531836]lrwxrwxrwx ... user -> user:[4026531837]lrwxrwxrwx ... uts -> uts:[4026531838]

这些文件,就是容器技术的基石——Linux Namespaces。今天我们就来逐一拆解它们。

什么是 Namespace

如果把 Linux 操作系统比作一栋大楼,所有的进程原本都住在大厅里,共享所有的资源(水、电、厕所)。而 Namespace 就是在大楼里隔出的独立房间。

  • 隔离:房间里的人以为自己拥有整个大楼,看不到房间外面的人。

  • 共享:虽然住在房间里,但大家其实还是在同一栋大楼(同一个内核)里。

七大 Namespace 详解

1. mnt (Mount Namespace) —— 独立的“视界”

  • 作用:隔离文件系统挂载点。

  • 比喻:给房间装了单向玻璃。

  • 实例:

    • 你在容器里执行 mount -t tmpfs tmpfs /tmp,只有容器里的人能看到这个挂载,宿主机和其他容器完全无感。

    • 这就是为什么 Docker 容器里有独立的 /proc、/sys,而不会和宿主机混淆。

2. net (Network Namespace) —— 独立的“网线”

  • 作用:隔离网络栈(网卡、IP、路由表、端口)。

  • 比喻:房间里单独拉了一根网线,有独立的路由器。

  • 实例:

    • 容器里的 eth0 IP 是 10.244.1.2,而宿主机是 192.168.1.100。

    • 容器里监听 80 端口,宿主机上也可以监听 80 端口,互不冲突。

3. pid (PID Namespace) —— 独立的“户口本”

  • 作用:隔离进程编号。

  • 比喻:在房间里,你是“1号人物”(老大);但在大楼管理处,你只是个普通住户(编号 10086)。

  • 实例:

    • 容器内:ps -ef 看到主进程 PID 是 1。

    • 宿主机:ps -ef 看到同一个进程,PID 可能是 45678。

    • 这让容器内的进程以为自己是系统的初始化进程,拥有至高无上的地位。

4. uts (UTS Namespace) —— 独立的“门牌号”

  • 作用:隔离主机名 (Hostname) 和域名。

  • 比喻:你可以给自己的房间起名叫“总统套房”,不影响大楼叫“希尔顿”。

  • 实例:

    • 容器里 hostname my-web-app,宿主机的 hostname 依然是 node-01。

5. ipc (IPC Namespace) —— 独立的“电话线”

  • 作用:隔离进程间通信(共享内存、信号量、消息队列)。

  • 比喻:房间里的内线电话,打不到隔壁房间去。

  • 实例:

    • 防止不同容器的进程因为使用了相同的共享内存 Key 而发生冲突或数据泄露。

6. user (User Namespace) —— 独立的“身份”

  • 作用:隔离用户 ID (UID) 和组 ID (GID)。

  • 比喻:你在房间里穿着“皇帝的新衣”(Root),但走出房间你就是个平民。

  • 实例:

    • 容器内:你是 root (UID 0),可以为所欲为。

    • 宿主机:你只是个普通用户 (UID 1000),没有破坏系统的权限。

    • 这是容器安全的重要特性(Rootless Container)。

7. cgroup (Cgroup Namespace) —— 独立的“电表”

  • 作用:隔离 Cgroup 根目录视图。

  • 比喻:你只能看到自己房间的电表读数,看不到整栋楼的电表。

  • 实例:

    • 在容器里查看 /proc/self/cgroup,路径会变短,隐藏了宿主机复杂的层级结构。

那些数字代表什么

回到开头的文件列表: lrwxrwxrwx ... net -> net:[4026531993]

中括号里的数字 4026531993 是 Namespace 的 Inode 编号(身份证号)。

  • 如何判断两个进程是否在同一个容器里? 看它们的 Namespace Inode 是否一样!如果 net:[...] 的数字一样,说明它们共享同一个网络栈(比如 K8s Pod 里的 Pause 容器和业务容器)。

  • 常用命令:

    • lsns:列出系统所有 Namespace。

    • nsenter -t <PID> -n:穿越到目标进程的 Network Namespace 里去(修网络神器)。

举例:

下面是一个pod的两个容器,在node节点上分别查看这两个容器的进程:

pod的信息:sysops                        sysops-788dfd5f5c-8lmdm                                     2/2     Running             0                  10d两个容器进程:.....containers:  - args:    - -c    - python3 manage.py migrate && gunicorn -c sysops/config/gunicorn_conf.py sysops.asgi:application    command:    - sh    image: x.com/ops/sysops:v5.4.25    imagePullPolicy: IfNotPresent    name: sysops    ports:    - containerPort: 8000      name: sysops      protocol: TCP    resources:      limits:        cpu: "4"        memory: 4Gi      requests:        cpu: "2"        memory: 2Gi    terminationMessagePath: /dev/termination-log    terminationMessagePolicy: File    ......  - args:    - -c    - cd ./golang-k8s;./k8s_informer    command:    - sh    image: x.com/ops/sysops:v5.4.25    imagePullPolicy: IfNotPresent    name: go-informer    resources:      limits:        cpu: "2"        memory: 2Gi      requests:        cpu: "2"        memory: 2Gi.....查看两个进程对应在/prod/pid/ns/net的inode值,结果一样,再查看一个非相同pod的容器进程,发现net inode值不同# ps -ef|grep k8s_informerroot     38881 36852  0 22:20 pts/0    00:00:00 grep --color=auto k8s_informerroot     50299 13547  0 Nov19 ?        00:00:00 sh -c cd ./golang-k8s;./k8s_informerroot     50312 50299  0 Nov19 ?        00:46:34 ./k8s_informer(root@k8n1-k8n1 2025-11-29 22:20:02 ~)# ls /proc/50299/ns/ipc  mnt  net  pid  user  uts(root@k8n1-k8n1 2025-11-29 22:20:17 ~)# ls /proc/50299/ns/ -ltotal 0lrwxrwxrwx 1 root root 0 Nov 29 22:20 net -> net:[4026532784](root@k8n1-k8n1 2025-11-29 22:20:21 ~)# ps -ef|grep gunicorn_conf.pyroot     43142 36852  0 22:20 pts/0    00:00:00 grep --color=auto gunicorn_conf.pyroot     50266 13547  0 Nov19 ?        00:00:00 sh -c python3 manage.py migrate && gunicorn -c sysops/config/gunicorn_conf.py sysops.asgi:applicationroot     52904 50266  0 Nov19 ?        00:03:25 /usr/local/bin/python3.11 /usr/local/bin/gunicorn -c sysops/config/gunicorn_conf.py sysops.asgi:application# ls -l /proc/50266/ns/total 0lrwxrwxrwx 1 root root 0 Nov 29 22:20 net -> net:[4026532784](root@k8n1-k8n1 2025-11-29 22:20:57 ~)第三个进程-非相同pod的容器进程# ps -ef|grep argocd-root     40761 36852  0 22:31 pts/0    00:00:00 grep --color=auto argocd-1001     46942 43638  0 Nov13 ?        00:13:17 /shared/argocd-dex rundexpolkitd  59513 59098  0 Nov13 ?        00:01:30 /usr/bin/tini -- /usr/local/bin/argocd-applicationset-controllerpolkitd  59526 59513  0 Nov13 ?        00:38:52 /usr/local/bin/argocd-applicationset-controllerpolkitd  61684 61459  0 Nov13 ?        00:01:30 /usr/bin/tini -- /usr/local/bin/argocd-application-controllerpolkitd  61697 61684  1 Nov13 ?        07:11:29 /usr/local/bin/argocd-application-controller(root@k8n1-k8n1 2025-11-29 22:31:09 ~)# ls /proc/59513/ns/net -llrwxrwxrwx 1 polkitd input 0 Nov 29 22:31 /proc/59513/ns/net -> net:[4026532962]

结尾

Linux Namespaces 通过这 7 种隔离机制,为进程编织了一个完美的“楚门的世界”。理解了它们,你就理解了容器技术的灵魂。如果你觉得这篇文章有用,欢迎点赞、在看、转发! ❤️

小知识

使用 nsenter 进入容器网络空间执行-查看网络相关内容nsenter  -t  659030(容器服务进程)  -n ss -xl|grep phpnsenter 是 Linux 容器调试的“瑞士军刀”。容器本质上就是利用 Linux 的 Namespace(命名空间) 技术做隔离的。nsenter (Namespace Enter) 的作用就是进入这些隔离的空间。只要你知道容器进程的 PID,你就可以用 nsenter 进入它的任何维度:网络 (-n / --net):用途:看 IP、端口、防火墙规则、抓包。命令:nsenter -t <PID> -n ip addr 或 nsenter -t <PID> -n tcpdump ...
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐