mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
2433 字
7 分钟
Linux Namespace 深入
2026-04-10

当你在一个容器里执行 ps aux,只看到自己的进程;执行 ifconfig,只看到自己的网卡;执行 hostname,只看到自己的主机名——这不是魔法,而是 Linux Namespace 在工作。Namespace 让每个进程拥有独立的系统资源视图,仿佛运行在专属的操作系统中。

Namespace 的概念并非 Linux 首创。1992 年,Bell Labs 的 Plan 9 操作系统率先提出了”per-process namespace”的理念——每个进程可以拥有独立的文件系统命名空间。这一思想深刻影响了后来的 Linux 内核设计。2002 年,Linux 2.4.19 引入了第一个 Namespace——Mount Namespace,允许进程拥有独立的文件系统挂载视图。此后十余年间,内核逐步添加了 PID(2006,2.6.24)、Network(2009,2.6.29)、IPC(2006,2.6.19)、UTS(2006,2.6.19)、User(2013,3.8)、Cgroup(2016,4.6)、Time(2020,5.6)等 Namespace。2013 年 Docker 诞生后,Namespace 从”内核开发者的小众特性”一跃成为容器技术的基石——容器的”视图隔离”全部由 Namespace 实现。理解 Namespace 的演进脉络,有助于理解为什么不同 Namespace 的行为差异如此之大(例如 User Namespace 支持”非特权创建”,而 Network Namespace 需要 CAP_NET_ADMIN),因为这些差异根植于它们各自的历史背景和设计目标。

前置知识#

  • Linux 系统编程基础:clone()unshare()setns() 三个系统调用是操作 Namespace 的核心接口
  • Ch01 容器全景:从 chroot 到 OCI:建立容器技术的全景认知,理解 Namespace 在容器架构中的位置
  • Linux /proc 文件系统:Namespace 的信息通过 /proc/[pid]/ns/ 目录暴露
Note

如果你对 Linux 进程和文件系统的基础概念还不熟悉,推荐先阅读姊妹系列「从零剖析 Linux 操作系统」中的 Cgroups 与 NamespacesVFS 与文件系统 章节。

本章将深入 8 种 Linux Namespace 的原理与实现。不仅要知道”Namespace 能隔离什么”,更要理解”Namespace 怎么隔离”、“隔离的边界在哪里”、“哪些场景可以逃逸”。

一、Namespace 核心概念#

1.1 什么是 Namespace?#

Namespace 的核心思想是资源隔离:将全局资源包装为一个抽象,让 Namespace 内的进程看起来拥有独立的资源实例。内核为每种资源维护了一个映射表,将 Namespace 内的虚拟 ID 映射到全局的实际 ID。

// Linux 内核中 Namespace 的核心数据结构(简化)
struct nsproxy {
struct uts_namespace *uts_ns; // UTS: 主机名
struct ipc_namespace *ipc_ns; // IPC: 进程间通信
struct mnt_namespace *mnt_ns; // Mount: 挂载点
struct pid_namespace *pid_ns; // PID: 进程 ID
struct net *net_ns; // Network: 网络栈
struct cgroup_namespace *cgroup_ns; // Cgroup: Cgroup 视图
struct user_namespace *user_ns; // User: 用户 ID
struct time_namespace *time_ns; // Time: 时钟
};
// 每个进程的 task_struct 包含 nsproxy 指针
struct task_struct {
struct nsproxy *nsproxy;
// ...
};

1.2 三个系统调用#

Linux 提供了三个系统调用来操作 Namespace:

系统调用功能关键参数
clone()创建新进程并指定新 NamespaceCLONE_NEWPID, CLONE_NEWNET, …
unshare()将当前进程移入新 Namespace同上
setns()将当前进程加入已有 Namespacefd(指向 /proc/PID/ns/ 的文件描述符)
// clone: 创建新进程并加入新 Namespace
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
static int child_func(void *arg) {
printf("Child PID: %d\n", getpid()); // 在新 PID Namespace 中,PID 为 1
return 0;
}
int main() {
// 分配子进程栈
char *stack = malloc(1024 * 1024);
char *stack_top = stack + 1024 * 1024;
// 创建子进程,同时创建新的 PID 和 Mount Namespace
pid_t pid = clone(child_func, stack_top,
CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);
if (pid == -1) {
perror("clone");
return 1;
}
printf("Parent PID: %d, Child PID: %d\n", getpid(), pid);
wait(NULL);
free(stack);
return 0;
}
# unshare: 将当前进程移入新 Namespace
# 创建新的 Mount Namespace 并挂载 proc
sudo unshare --mount --pid --fork --mount-proc /bin/bash
# setns: 加入已有的 Namespace
# 进入 Docker 容器的 Network Namespace
sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' mycontainer) -n ip addr

1.3 Namespace 的继承与嵌套#

Namespace 支持嵌套——一个 Namespace 可以是另一个 Namespace 的子 Namespace。子 Namespace 中的资源对父 Namespace 可见(反之不一定),这取决于具体的 Namespace 类型。

graph TB subgraph 宿主Namespace["宿主 Namespace (init_ns)"] INIT["PID 1 (systemd)"] A["PID 100 (dockerd)"] B["PID 200 (containerd)"] end subgraph 容器NS1["容器 Namespace 1"] C1["PID 1 (nginx master)"] C2["PID 10 (nginx worker)"] end subgraph 容器NS2["容器 Namespace 2"] D1["PID 1 (redis-server)"] D2["PID 15 (redis-cli)"] end subgraph 嵌套NS["嵌套 Namespace (DinD)"] E1["PID 1 (dockerd)"] E2["PID 50 (containerd)"] end A -->|"clone(CLONE_NEWPID)"| C1 B -->|"clone(CLONE_NEWPID)"| D1 C1 -->|"clone(CLONE_NEWPID)"| E1 style 宿主Namespace fill:#e8eaf6,stroke:#283593 style 容器NS1 fill:#e0f2f1,stroke:#00695c style 容器NS2 fill:#fff3e0,stroke:#e65100 style 嵌套NS fill:#fce4ec,stroke:#c62828

二、PID Namespace#

2.1 原理#

PID Namespace 隔离进程 ID 号空间。在新的 PID Namespace 中,第一个进程的 PID 为 1,后续进程依次递增。宿主机上,这些进程仍然有全局唯一的 PID。

# 在容器中看到的 PID
docker exec mycontainer ps aux
# PID USER COMMAND
# 1 root nginx: master process
# 10 nginx nginx: worker process
# 在宿主机上看到的同一进程
ps aux | grep nginx
# root 12345 ... nginx: master process
# 101 12346 ... nginx: worker process

2.2 PID 1 的特殊性#

PID 1 在 Linux 中有特殊地位:

特性说明
信号处理PID 1 默认忽略 SIGINT 和 SIGTERM,除非显式注册处理函数
僵尸回收PID 1 负责回收所有子进程的退出状态(wait)
优雅退出容器停止时,PID 1 收到 SIGTERM,应优雅关闭子进程
Warning

很多容器因为 PID 1 进程选择不当(如使用 shell 脚本启动应用),导致无法优雅退出或僵尸进程堆积。推荐使用 tini 或 dumb-init 作为 PID 1 进程。

2.3 PID Namespace 的限制#

  • PID Namespace 嵌套最多 32 层
  • 从父 Namespace 可以看到子 Namespace 的进程(但 PID 不同)
  • 从子 Namespace 无法看到父 Namespace 的进程
  • kill 系统调用只能发送信号给同一 Namespace 内的进程(除非有 CAP_KILL)

三、Mount Namespace#

3.1 原理#

Mount Namespace 隔离文件系统挂载点视图。不同 Mount Namespace 中的进程可以看到不同的挂载点列表。

# 创建新的 Mount Namespace
sudo unshare --mount /bin/bash
# 在新 Namespace 中挂载 tmpfs
mount -t tmpfs tmpfs /mnt
mount | grep /mnt
# tmpfs on /mnt type tmpfs
# 在另一个终端(宿主 Namespace)查看
mount | grep /mnt
# 看不到 /mnt 的挂载——因为 Mount Namespace 隔离了挂载点视图

3.2 共享子树(Shared Subtrees)#

Mount Namespace 的关键特性是共享子树传播类型,它决定了挂载事件如何在 Namespace 之间传播:

传播类型说明典型用途
shared挂载/卸载事件传播到对等组系统默认,USB 热插拔
slave只接收对等组的传播,不反向传播容器只读共享宿主挂载
private不传播也不接收容器独立挂载
unbindable不能被 bind mount防止递归挂载
# 查看挂载点的传播类型
findmnt -o TARGET,PROPAGATION
# 将挂载点设为 private(容器常用)
mount --make-private /
# 将挂载点设为 slave
mount --make-slave /sys

3.3 容器中的 Mount 操作#

runc 在创建容器时,会执行一系列 mount 操作:

# runc 的典型 mount 操作(简化)
mount -t proc proc /proc # 挂载 procfs
mount -t sysfs sysfs /sys # 挂载 sysfs
mount -t devtmpfs devtmpfs /dev # 挂载 devtmpfs
mount -t tmpfs tmpfs /dev/shm # 挂载共享内存
mount -t tmpfs tmpfs /run # 挂载运行时目录
mount -t cgroup2 cgroup2 /sys/fs/cgroup # 挂载 Cgroup v2

四、Network Namespace#

4.1 原理#

Network Namespace 隔离网络栈——包括网络设备、IP 地址、路由表、端口号、iptables 规则等。

# 创建 Network Namespace
sudo ip netns add ns1
sudo ip netns add ns2
# 查看 Namespace 中的网络设备
sudo ip netns exec ns1 ip link
# 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN
# 只有 loopback 设备,且处于 DOWN 状态
# 创建 veth pair 连接两个 Namespace
sudo ip link add veth1 type veth peer name veth2
sudo ip link set veth1 netns ns1
sudo ip link set veth2 netns ns2
# 配置 IP 地址
sudo ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth1
sudo ip netns exec ns1 ip link set veth1 up
sudo ip netns exec ns1 ip link set lo up
sudo ip netns exec ns2 ip addr add 10.0.0.2/24 dev veth2
sudo ip netns exec ns2 ip link set veth2 up
sudo ip netns exec ns2 ip link set lo up
# 测试连通性
sudo ip netns exec ns1 ping -c 3 10.0.0.2

4.2 容器网络模式#

Docker 支持多种网络模式,每种模式对 Network Namespace 的使用不同:

网络模式Namespace 策略特点
bridge独立 Network NS + veth pair默认模式,容器有独立 IP
host共享宿主 Network NS性能最好,无网络隔离
none独立 Network NS,仅 loopback无网络,用于安全隔离
container共享另一容器的 Network NSPod 内容器共享网络栈

4.3 Network Namespace 与 CNI#

Kubernetes 通过 CNI(Container Network Interface)插件配置 Pod 的网络:

{
"cniVersion": "0.4.0",
"name": "bridge-network",
"type": "bridge",
"bridge": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/16",
"routes": [{"dst": "0.0.0.0/0"}]
}
}
Note

Network Namespace 是容器网络的基础,但 CNI 插件负责了 veth pair 创建、bridge 连接、IP 分配、路由配置等复杂工作。详见 Ch12 容器网络

五、User Namespace#

5.1 原理#

User Namespace 隔离用户和组 ID。最强大的特性是UID 映射:容器内的 root(UID 0)可以映射到宿主机上的普通用户(UID 100000),实现 rootless 容器。

# 创建 User Namespace,映射 UID
sudo unshare --user --map-root-user /bin/bash
# 在新 User Namespace 中
id
# uid=0(root) gid=0(root)
# 但在宿主机上,这个进程的实际 UID 是普通用户
# 从另一个终端查看
ps -o pid,uid,ruid,comm -p $(pgrep -f "unshare")

5.2 UID/GID 映射#

User Namespace 通过 /proc/PID/uid_map/proc/PID/gid_map 定义映射关系:

# 查看 Docker 容器的 UID 映射
cat /proc/$(docker inspect -f '{{.State.Pid}}' mycontainer)/uid_map
# 0 100000 65536
# 含义:容器内 UID 0-65535 → 宿主机 UID 100000-165535
# 手动配置 UID 映射
echo "0 100000 65536" > /proc/$PID/uid_map
echo "0 100000 65536" > /proc/$PID/gid_map

5.3 User Namespace 与 Capability#

User Namespace 的一个关键特性:在新的 User Namespace 中,进程拥有全部 Capability,但这些 Capability 只在该 Namespace 内有效。

graph LR subgraph 宿主UserNS["宿主 User Namespace"] ROOT["UID 0 (root)<br/>全部 Capability"] USER["UID 1000<br/>无 Capability"] end subgraph 容器UserNS["容器 User Namespace"] CROOT["UID 0 (容器内 root)<br/>容器内全部 Capability<br/>映射到宿主 UID 100000"] CUSER["UID 1000 (容器内)<br/>映射到宿主 UID 101000"] end ROOT -->|"创建 User NS"| CROOT CROOT -.->|"UID 映射"| USER style 宿主UserNS fill:#e8eaf6,stroke:#283593 style 容器UserNS fill:#e0f2f1,stroke:#00695c

六、IPC / UTS / Cgroup / Time Namespace#

6.1 IPC Namespace#

IPC Namespace 隔离 System V IPC 对象和 POSIX 消息队列:

# 查看 System V IPC 对象
ipcs -q # 消息队列
ipcs -m # 共享内存
ipcs -s # 信号量
# 在新 IPC Namespace 中,看不到宿主的 IPC 对象
sudo unshare --ipc /bin/bash
ipcs -q # 空的

6.2 UTS Namespace#

UTS Namespace 隔离主机名和域名(源自 UNIX Time-Sharing System):

# 创建新 UTS Namespace 并设置主机名
sudo unshare --uts /bin/bash
hostname mycontainer
hostname
# mycontainer
# 宿主机的主机名不受影响

6.3 Cgroup Namespace#

Cgroup Namespace 隔离 Cgroup 根目录视图。在容器内,进程只能看到自己的 Cgroup 子树:

# 不使用 Cgroup Namespace
cat /proc/self/cgroup
# 0::/system.slice/docker-abc123.scope → 看到完整路径
# 使用 Cgroup Namespace
sudo unshare --cgroup /bin/bash
cat /proc/self/cgroup
# 0::/ → 看到的是根目录,不知道自己在子树中

6.4 Time Namespace#

Time Namespace(Linux 5.6+)隔离 CLOCK_BOOTTIMECLOCK_MONOTONIC 时钟,主要用于容器迁移场景(如 checkpoint/restore):

# 创建 Time Namespace
sudo unshare --time /bin/bash
# 修改 Time Namespace 的偏移
# /proc/PID/timens_offsets

七、Namespace 组合与容器配置#

7.1 runc 的默认 Namespace 配置#

runc 创建容器时,默认配置 6 种 Namespace:

{
"linux": {
"namespaces": [
{ "type": "pid" },
{ "type": "mount" },
{ "type": "ipc" },
{ "type": "uts" },
{ "type": "network" },
{ "type": "cgroup" }
]
}
}

7.2 Namespace 组合对比#

组合方式用途示例
全部独立标准容器docker run
共享 Network NSPod 内容器Kubernetes Pod
共享 IPC NS进程间通信System V 共享内存
共享 PID NS进程可见调试 sidecar
User NS + 其他 NSRootless 容器Podman rootless
flowchart LR subgraph Pod["Kubernetes Pod"] PAUSE["pause 容器<br/>持有 Network NS"] APP1["应用容器 A<br/>共享 Network NS"] APP2["应用容器 B<br/>共享 Network NS"] end PAUSE -->|"创建 Network NS"| NET_NS["Network Namespace<br/>共享 IP / 端口 / 路由"] APP1 -->|"join Network NS"| NET_NS APP2 -->|"join Network NS"| NET_NS APP1 -.->|"localhost 通信"| APP2 style Pod fill:#e8eaf6,stroke:#283593 style NET_NS fill:#e0f2f1,stroke:#00695c
Tip

Kubernetes Pod 中多个容器共享 Network Namespace 时,应用之间可以通过 localhost 直接通信,但端口不能冲突。设计 Pod 时要为每个容器规划好监听端口,避免端口抢占导致启动失败。

7.3 Namespace 与安全#

flowchart TB subgraph 安全层级["容器安全层级"] NS["Namespace<br/>视图隔离"] CG["Cgroup<br/>资源限制"] CAP["Capabilities<br/>权限控制"] SEC["seccomp<br/>系统调用过滤"] AA["AppArmor<br/>文件访问控制"] end NS -->|"隔离不等于安全"| CAP CAP -->|"限制特权操作"| SEC SEC -->|"限制系统调用"| AA subgraph 逃逸风险["已知逃逸路径"] E1["/proc/sysrq-trigger"] E2["内核漏洞(CVE)"] E3["特权容器 + 挂载"] E4["共享 PID Namespace"] end NS -.->|"无法阻止"| E1 CAP -.->|"可以阻止"| E1 SEC -.->|"可以阻止"| E2 AA -.->|"可以阻止"| E3 style 安全层级 fill:#e8f5e9,stroke:#2e7d32 style 逃逸风险 fill:#ffcdd2,stroke:#c62828

八、动手实践#

8.1 用 Go 创建隔离进程#

package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
func main() {
switch os.Args[1] {
case "run":
run()
case "child":
child()
default:
panic("invalid command")
}
}
func run() {
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// 创建新的 Namespace
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS |
syscall.CLONE_NEWPID |
syscall.CLONE_NEWNS |
syscall.CLONE_NEWNET |
syscall.CLONE_NEWIPC,
}
must(cmd.Run())
}
func child() {
fmt.Printf("Running %v as PID %d\n", os.Args[2:], os.Getpid())
// 挂载 proc(在新 Mount Namespace 中)
must(syscall.Mount("proc", "/proc", "proc", 0, ""))
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
must(cmd.Run())
}
func must(err error) {
if err != nil {
panic(err)
}
}

8.2 Namespace 可视化脚本#

#!/bin/bash
# 可视化进程的 Namespace 关系
echo "=== 容器进程的 Namespace ==="
for pid in $(docker top mycontainer -o pid | tail -n +2); do
echo "PID $pid:"
ls -la /proc/$pid/ns/ 2>/dev/null | awk '{print " " $NF}'
done
echo ""
echo "=== 宿主进程的 Namespace ==="
echo "PID 1 (systemd):"
ls -la /proc/1/ns/ | awk '{print " " $NF}'
echo ""
echo "=== Namespace 差异 ==="
echo "容器进程与宿主进程的 Namespace 不同 = 隔离生效"

附、实践:用 unshare 手工创建隔离环境#

本节用 unshare 命令手工创建各种 Namespace,观察隔离效果。所有命令在 Linux 系统上以 root 权限运行。

附.1 观察宿主进程的 Namespace#

每个进程的 Namespace 信息通过 /proc/[pid]/ns/ 目录暴露:

ls -la /proc/self/ns/
cgroup:[4026531835]
ipc:[4026532213]
mnt:[4026532224]
net:[4026531840]
pid:[4026532226]
time:[4026531834]
user:[4026531837]
uts:[4026532225]

方括号中的数字是 Namespace 的 inode 号。同一 inode 号表示同一 Namespace。

附.2 UTS Namespace:独立主机名#

# 在新 UTS Namespace 中设置主机名
unshare --uts sh -c 'hostname isolated-host && hostname'
# isolated-host
# 宿主主机名未变
hostname
# LAPTOP-NMOAUL8E

UTS Namespace 让每个隔离环境拥有独立的主机名,容器中的 hostname 命令只影响自己的 Namespace。

附.3 PID Namespace:独立进程树#

# 创建新的 PID Namespace,--fork 必须,--mount-proc 让 ps 只看到新 Namespace 的进程
unshare --pid --fork --mount-proc sh -c 'echo "容器内 PID: $$" && ps aux'
容器内 PID: 1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 2800 1664 ? S 01:32 0:00 sh -c echo "容器内 PID: $$" && ps aux
root 2 0.0 0.0 11320 4352 ? R 01:32 0:00 ps aux

关键观察:在新 PID Namespace 中,进程的 PID 从 1 开始,ps aux 只显示同一 Namespace 中的进程。宿主进程的 PID 完全不同:

echo "宿主 PID: $$"
# 宿主 PID: 3361650

注意--mount-proc 会重新挂载 /proc,这是 ps 命令能正确显示新 PID Namespace 进程的前提。如果不加 --mount-procps 仍会读取宿主的 /proc,显示所有进程。

附.4 Network Namespace:独立网络栈#

# 创建新的 Network Namespace
unshare --net sh -c 'ip link show'
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

新 Network Namespace 只有 loopback 接口,且状态为 DOWN——没有 eth0、没有 IP 地址、无法通信。这正是容器网络需要 CNI 插件配置的原因(详见 Ch12 容器网络)。

附.5 用 setns 加入已有 Namespace#

nsenter 命令可以进入一个正在运行的容器的 Namespace:

# 找到容器的 PID
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' mycontainer)
# 进入容器的 Namespace
nsenter -t $CONTAINER_PID -m -p -u -i -n -- /bin/sh

这等价于 docker exec,但 nsenter 更底层——它直接调用 setns() 系统调用,不经过 Docker API。

九、本章小结#

上一章从全景视角介绍了容器全景与三大内核基石。

Namespace隔离内容容器默认启用关键特性
PID进程 IDPID 1 特殊性、嵌套限制 32 层
Mount挂载点共享子树传播、pivot_root
Network网络栈veth pair、bridge、CNI
User用户/组 ID(可选)UID 映射、rootless 容器
IPC进程间通信System V IPC、POSIX MQ
UTS主机名简单但重要
CgroupCgroup 视图隐藏 Cgroup 路径
Time系统时钟容器迁移场景

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Linux Namespace 深入
https://blog.souloss.com/posts/container-runtime/namespace-deep-dive/
作者
Souloss
发布于
2026-04-10
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐
1
Cgroup v2 深入
容器运行时 Cgroup 是容器资源限制的核心机制。逐层拆解 Cgroup v2 的统一层级设计、CPU/内存/IO 三大控制器的实现原理、eBPF 扩展机制,以及容器运行时如何通过 Cgroup 实现资源隔离——从「docker run --memory=512m」到内核的 cgroup 文件系统,理解每一步的资源控制逻辑。
2
综合实战:构建一个迷你容器运行时
容器运行时 综合实战——用 Go 从零构建一个迷你容器运行时——实现 Namespace 隔离(PID/Mount/UTS/IPC/Network)、Cgroup 资源限制(CPU/内存)、OverlayFS 分层文件系统、OCI Bundle 解析,最终实现一个能运行容器的 minirunc。将前 15 章的知识融会贯通,从「理解原理」到「动手实现」。
3
系列导读
容器运行时 本系列从 Linux 内核的 Namespace、Cgroup、OverlayFS 出发,深入 OCI 规范、runc 源码、containerd 架构,再到容器安全、沙箱运行时、网络、存储、镜像构建、Wasm 容器,最后综合实战构建一个迷你容器运行时——从「会用 Docker」到「理解容器运行时的每一行代码」,每章配有可运行的代码示例与架构图,让你从容器用户进阶到容器运行时工程师。
4
沙箱运行时:gVisor/Kata
容器运行时 runc 的 Namespace+Cgroup 隔离依赖共享内核,内核漏洞可导致容器逃逸。gVisor 用用户态内核(Sentry)拦截所有系统调用,Kata Containers 用轻量级虚拟机实现硬件级隔离。深入探讨两种沙箱运行时的架构、实现原理、与 runc 的对比选型,以及它们在 Kubernetes 中的集成方式。
5
容器网络
容器运行时 容器网络的核心问题是——隔离的 Network Namespace 如何与外部通信?详细解读 veth pair(虚拟网卡对)、bridge(虚拟网桥)、iptables/NAT(地址转换)、CNI(容器网络接口)的完整链路,以及 Docker 的四种网络模式和 Kubernetes 的 Pod 网络模型——从「容器能 ping 通外网」到「理解每一条网络规则」。