mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1967 字
6 分钟
Cgroup v2 深入
2026-04-11

当你执行 docker run --memory=512m --cpus=2 nginx 时,Docker 是怎么限制容器只能使用 512MB 内存和 2 个 CPU 的?答案是 Cgroup——Linux 内核的**控制组(Control Group)**机制。Cgroup 让你将进程分组,并对每个组施加资源限制、优先级分配和审计统计。

Cgroup 经历了从 v1 到 v2 的重大架构演进。Cgroup v1 的每个控制器有独立的层级树,导致进程可能属于不同控制器的不同 cgroup,管理混乱。Cgroup v2 采用统一层级设计——所有控制器共享同一棵 cgroup 树,一个进程只能属于一个 cgroup,所有控制器对同一组进程生效。

Cgroup 的历史可以追溯到 2007 年,Google 工程师 Paul Menage 和 Rohit Seth 向 Linux 内核提交了”Process Containers”补丁,后更名为 Control Groups(Cgroup)。Cgroup v1 的设计允许每个控制器(cpu、memory、blkio 等)拥有独立的层级树,进程可以同时属于不同控制器的不同 cgroup——这看似灵活,实则带来了管理混乱:一个进程在 cpu cgroup 中属于 /A,在 memory cgroup 中却属于 /B,运维人员难以追踪进程的资源归属。2016 年,内核开发者 Tejun Heo 主导了 Cgroup v2 的重构,采用统一层级设计——所有控制器共享同一棵 cgroup 树,一个进程只能属于一个 cgroup。这一”看似更不灵活”的设计,反而解决了 v1 的核心痛点。理解从 v1 到 v2 的演进动机,是理解 Cgroup v2 设计哲学的关键——v2 的每一个”限制”,都是对 v1 实际运维问题的回应。

前置知识#

  • Ch02 Linux Namespace 深入:Namespace 提供”视图隔离”,Cgroup 提供”资源限制”——两者是容器隔离的互补机制,理解它们的区别至关重要
  • Linux 文件系统操作:Cgroup v2 通过 /sys/fs/cgroup/ 文件系统暴露接口,所有操作都是文件读写
  • Linux 进程管理基础:进程树、信号、资源统计
Note

Cgroup 和 Namespace 经常被混淆:Namespace 决定进程”能看到什么”,Cgroup 决定进程”能用多少”。

本章将深入 Cgroup v2 的架构设计、三大核心控制器(CPU/内存/IO)的实现原理,以及容器运行时如何使用 Cgroup。

一、Cgroup v2 架构#

1.1 从 Cgroup v1 到 v2#

graph TB subgraph CgroupV1["Cgroup v1:多层级"] V1CPU["cpu 控制器<br/>/sys/fs/cgroup/cpu/"] V1MEM["memory 控制器<br/>/sys/fs/cgroup/memory/"] V1BLK["blkio 控制器<br/>/sys/fs/cgroup/blkio/"] V1PID["pids 控制器<br/>/sys/fs/cgroup/pids/"] end subgraph CgroupV2["Cgroup v2:统一层级"] V2ROOT["/sys/fs/cgroup/<br/>统一 cgroup 树"] V2CPU["cpu.max + cpu.weight"] V2MEM["memory.max + memory.min"] V2IO["io.max + io.weight"] V2PID["pids.max"] end V1CPU -.->|"问题:进程可属于<br/>不同层级的不同 cgroup"| V2ROOT V1MEM -.-> V2ROOT V1BLK -.-> V2ROOT V1PID -.-> V2ROOT V2ROOT --> V2CPU V2ROOT --> V2MEM V2ROOT --> V2IO V2ROOT --> V2PID style CgroupV1 fill:#ffcdd2,stroke:#c62828 style CgroupV2 fill:#c8e6c9,stroke:#2e7d32

1.2 Cgroup v1 vs v2 对比#

维度Cgroup v1Cgroup v2
层级结构每个控制器独立层级统一层级
进程归属可属于不同控制器的不同 cgroup只能属于一个 cgroup
控制器挂载各自挂载到 /sys/fs/cgroup/控制器名统一挂载到 /sys/fs/cgroup/
内存控制器memory + memswmemory(含 swap)
IO 控制器blkioio(基于 cgroup 写回)
压力通知PSI(Pressure Stall Information)
eBPF 扩展有限完整支持
内核版本2.6.24+4.5+(推荐 5.4+)

1.3 Cgroup v2 的核心文件#

# 查看 Cgroup v2 的根目录
ls /sys/fs/cgroup/
# 核心文件
cgroup.controllers # 当前 cgroup 可用的控制器
cgroup.subtree_control # 子 cgroup 启用的控制器
cgroup.procs # 属于当前 cgroup 的进程 PID
cgroup.type # cgroup 类型(domain/threaded)
cgroup.max.depth # 最大嵌套深度
cgroup.max.descendants # 最大后代数量
cgroup.stat # 统计信息
# PSI(Pressure Stall Information)
cpu.pressure # CPU 压力
memory.pressure # 内存压力
io.pressure # IO 压力

二、CPU 控制器#

2.1 cpu.max:硬限制#

cpu.max 设置 CPU 时间的硬限制,格式为 quota period(微秒):

# 限制容器最多使用 2 个 CPU 核心
# quota = 200000μs, period = 100000μs
echo "200000 100000" > /sys/fs/cgroup/docker/container1/cpu.max
# 查看当前设置
cat /sys/fs/cgroup/docker/container1/cpu.max
# 200000 100000
# 不限制(默认)
echo "max 100000" > /sys/fs/cgroup/docker/container1/cpu.max

CPU 配额计算公式:

可用 CPU 核数 = quota / period
例如:200000 / 100000 = 2 核

2.2 cpu.weight:软限制(权重)#

cpu.weight 设置 CPU 时间的权重分配(1-10000,默认 100):

# 设置权重为 200(相对于默认 100,获得 2 倍 CPU 时间)
echo "200" > /sys/fs/cgroup/docker/container1/cpu.weight
# 两个容器的 CPU 时间分配比例
# container1 (weight=200) : container2 (weight=100) = 2:1

2.3 cpu.max vs cpu.weight#

特性cpu.maxcpu.weight
类型硬限制软限制(权重)
超限行为进程被限流(throttled)按权重分配空闲 CPU
适用场景严格限制 CPU 使用相对优先级分配
Docker 参数--cpus=2--cpu-shares=2048
空闲 CPU不可使用空闲 CPU可以使用空闲 CPU

2.4 CPU 限流机制#

sequenceDiagram participant App as 容器进程 participant CFS as CFS 调度器 participant Cgroup as Cgroup CPU 控制器 Note over App,Cgroup: 一个调度周期(period = 100ms) App->>CFS: 请求 CPU 时间 CFS->>Cgroup: 检查剩余 quota Cgroup-->>CFS: quota 剩余 50ms App->>CFS: 继续执行 CFS->>Cgroup: 检查剩余 quota Cgroup-->>CFS: quota 用完! Note over App: 进程被限流(throttled)<br/>等待下一个周期 Note over App,Cgroup: 下一个周期开始 Cgroup->>CFS: quota 重置为 200ms App->>CFS: 恢复执行

2.5 cpuset:CPU 亲和性#

# 限制容器只能使用 CPU 0 和 CPU 2
echo "0,2" > /sys/fs/cgroup/docker/container1/cpuset.cpus
# 限制 NUMA 节点
echo "0" > /sys/fs/cgroup/docker/container1/cpuset.mems
# Docker 等价参数
docker run --cpuset-cpus=0,2 nginx

三、内存控制器#

3.1 memory.max:内存硬限制#

# 限制容器最多使用 512MB 内存
echo "536870912" > /sys/fs/cgroup/docker/container1/memory.max # 512 * 1024 * 1024
# 查看当前内存使用
cat /sys/fs/cgroup/docker/container1/memory.current
# 134217728 (128MB)
# 查看内存限制
cat /sys/fs/cgroup/docker/container1/memory.max
# 536870912
# 不限制
echo "max" > /sys/fs/cgroup/docker/container1/memory.max

3.2 memory.min / memory.low:内存保护#

Cgroup v2 引入了内存保护机制,防止重要容器的内存被 OOM 回收:

文件含义OOM 行为
memory.min最小内存保证(硬保护)低于此值绝不回收
memory.low最佳内存保证(软保护)低于此值尽量不回收
memory.max最大内存限制超过此值触发 OOM
# 设置内存保护
echo "134217728" > memory.min # 保证至少 128MB
echo "268435456" > memory.low # 尽量保留 256MB
echo "536870912" > memory.max # 最多使用 512MB

3.3 Swap 控制#

# Cgroup v2 的 swap 控制
# memory.swap.max = 最大 swap 使用量
echo "268435456" > memory.swap.max # 最多 256MB swap
# 查看当前 swap 使用
cat memory.swap.current
# 禁用 swap(Docker 默认)
echo "0" > memory.swap.max
# Docker 等价参数
docker run --memory=512m --memory-swap=1g nginx

3.4 OOM 控制与处理#

# OOM 控制组
echo "1" > memory.oom.group # 整个 cgroup 作为 OOM 受害者
# OOM 事件通知(通过 cgroup.events)
cat memory.events
# oom 5 # OOM 事件计数
# oom_kill 3 # OOM kill 计数
# oom_group_kill 2 # 组 OOM kill 计数
# 内存压力统计
cat memory.stat
# anon 134217728 # 匿名页
# file 67108864 # 文件缓存页
# slab 33554432 # Slab 缓存
# pgfault 12345 # 页错误
# pgmajfault 67 # 主要页错误

3.5 内存控制流程#

flowchart TB ALLOC["进程申请内存"] --> CHECK_MAX{memory.current<br/>> memory.max?} CHECK_MAX -->|否| ALLOC_OK["分配成功"] CHECK_MAX -->|是| RECLAIM["内核尝试回收内存"] RECLAIM --> RECLAIM_OK{回收成功?} RECLAIM_OK -->|是| ALLOC_OK RECLAIM_OK -->|否| CHECK_SWAP{swap 可用?} CHECK_SWAP -->|是| SWAP_OUT["换出到 swap"] CHECK_SWAP -->|否| OOM["触发 OOM Killer"] OOM --> KILL["杀死 cgroup 内的进程"] style ALLOC_OK fill:#c8e6c9,stroke:#2e7d32 style OOM fill:#ffcdd2,stroke:#c62828 style KILL fill:#ffcdd2,stroke:#c62828

四、IO 控制器#

4.1 io.max:IO 硬限制#

# 限制容器对 /dev/sda 的读写速率
# 格式:major:minor rbps wbps riops wiops
echo "8:0 rbps=104857600 wbps=52428800 riops=1000 wiops=500" > io.max
# 查看当前 IO 限制
cat io.max
# 8:0 rbps=104857600 wbps=52428800 riops=1000 wiops=500
# 查看当前 IO 统计
cat io.stat
# 8:0 rbytes=12345678 wbytes=87654321 rios=1234 wios=567 dbytes=0 dios=0

4.2 io.weight:IO 权重#

# 设置 IO 权重(1-10000,默认 100)
echo "200" > io.weight
# 按设备设置权重
echo "8:0 200" > io.weight

4.3 IO 控制器的工作原理#

Cgroup v2 的 IO 控制器基于比例-积分(PI)控制器实现限流:

  1. 每个 cgroup 维护一个 IO 预算(token bucket)
  2. 每次 IO 请求消耗预算
  3. 预算耗尽时,IO 请求被延迟(throttled)
  4. 下一个时间窗口预算恢复
# 查看 IO 限流统计
cat io.stat
# 8:0 rbytes=12345678 wbytes=87654321 rios=1234 wios=567
# dbytes=0 dios=0
# cost.wait=123456 cost.inflight=7890
# cost.wait: IO 限流导致的等待时间(纳秒)

五、PSI:压力失速信息#

5.1 PSI 原理#

PSI(Pressure Stall Information)是 Cgroup v2 的重要特性,它量化了资源竞争的严重程度:

# 查看 CPU 压力
cat /sys/fs/cgroup/docker/container1/cpu.pressure
# some avg10=0.00 avg60=0.10 avg300=0.05 total=1234567
# full avg10=0.00 avg60=0.00 avg300=0.00 total=0
# some: 至少一个任务等待资源
# full: 所有任务都在等待资源(更严重)
# avg10/60/300: 最近 10/60/300 秒的百分比

5.2 PSI 在容器中的应用#

# 监控容器的内存压力
watch -n 1 "cat /sys/fs/cgroup/docker/container1/memory.pressure"
# 基于 PSI 触发告警
# 当 avg10 > 50% 时,表示严重内存压力
# 可能需要增加内存限制或优化应用
PSI 指标含义告警阈值
some avg10 > 10%部分任务等待关注
some avg10 > 50%严重竞争告警
full avg10 > 0%所有任务等待严重告警

六、容器运行时与 Cgroup#

6.1 Docker 的 Cgroup 配置#

# Docker 的 Cgroup 参数映射
docker run \
--memory=512m \ # memory.max = 536870912
--memory-reservation=256m \ # memory.low = 268435456
--memory-swap=1g \ # memory.swap.max = 536870912
--cpus=2 \ # cpu.max = 200000 100000
--cpu-shares=2048 \ # cpu.weight = 2048
--cpuset-cpus=0,2 \ # cpuset.cpus = 0,2
--pids-limit=100 \ # pids.max = 100
--device-write-bps /dev/sda:50MB \ # io.max wbps
nginx
# 查看容器的 Cgroup 路径
docker inspect mycontainer --format '{{.CgroupPath}}'

6.2 Kubernetes 的 Cgroup 配置#

# Kubernetes Pod 的资源限制
apiVersion: v1
kind: Pod
spec:
containers:
- name: nginx
resources:
requests:
cpu: "1" # cpu.weight 权重分配
memory: "512Mi" # memory.min 保证
limits:
cpu: "2" # cpu.max 硬限制
memory: "1Gi" # memory.max 硬限制

6.3 containerd 的 Cgroup 管理#

// containerd 的 Cgroup 管理代码(简化)
package cgroups
import (
"fmt"
"os"
"path/filepath"
)
type CgroupConfig struct {
MemoryMax int64 // memory.max
MemoryMin int64 // memory.min
CPUMax string // cpu.max (quota period)
CPUWeight uint64 // cpu.weight
PidsMax int64 // pids.max
}
func ApplyCgroup(cgroupPath string, config *CgroupConfig) error {
root := "/sys/fs/cgroup"
// 创建 cgroup 目录
path := filepath.Join(root, cgroupPath)
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
// 设置 memory.max
if config.MemoryMax > 0 {
if err := os.WriteFile(
filepath.Join(path, "memory.max"),
[]byte(fmt.Sprintf("%d", config.MemoryMax)),
0644,
); err != nil {
return err
}
}
// 设置 cpu.max
if config.CPUMax != "" {
if err := os.WriteFile(
filepath.Join(path, "cpu.max"),
[]byte(config.CPUMax),
0644,
); err != nil {
return err
}
}
// 将进程加入 cgroup
if err := os.WriteFile(
filepath.Join(path, "cgroup.procs"),
[]byte(fmt.Sprintf("%d", os.Getpid())),
0644,
); err != nil {
return err
}
return nil
}

七、Cgroup 在容器运行时中的完整路径#

从 Docker CLI 到内核,Cgroup 配置经过多层转换:

flowchart LR subgraph 用户层["用户层"] CLI["docker run --memory=512m --cpus=2"] end subgraph Docker层["Docker 层"] SPEC["OCI Spec 生成<br/>linux.resources.memory.limit = 536870912<br/>linux.resources.cpu.quota = 200000<br/>linux.resources.cpu.period = 100000"] end subgraph containerd层["containerd 层"] SHIM["shim → runc create<br/>传递 Spec 给 runc init"] end subgraph runc层["runc 层"] CG_MGR["Cgroup Manager<br/>读取 Spec → 写入 cgroup 文件"] end subgraph 内核层["内核层"] FS["cgroup 文件系统<br/>/sys/fs/cgroup/docker/xxx/<br/>memory.max, cpu.max, cgroup.procs"] end CLI --> SPEC --> SHIM --> CG_MGR --> FS style 用户层 fill:#bbdefb,stroke:#1565c0 style Docker层 fill:#c8e6c9,stroke:#2e7d32 style containerd层 fill:#fff3e0,stroke:#e65100 style runc层 fill:#e1bee7,stroke:#6a1b9a style 内核层 fill:#ffcdd2,stroke:#c62828
Warning

Cgroup 的内存限制包含页面缓存(file cache)。当容器读取大量文件时,页面缓存会占用 memory.current,可能触发限流或 OOM。如果应用需要大量文件 IO,考虑适当放宽内存限制或使用 memory.low 设置软保护。

八、eBPF 与 Cgroup#

8.1 Cgroup eBPF 程序#

Cgroup v2 支持附加 eBPF 程序,实现更灵活的控制逻辑:

// eBPF 程序:限制网络连接
// 附加到 cgroup 的 BPF_CGROUP_INET_SOCK_CREATE hook
SEC("cgroup/sock")
int restrict_sockets(struct bpf_sock *ctx) {
// 只允许 TCP 和 UDP
if (ctx->protocol != IPPROTO_TCP &&
ctx->protocol != IPPROTO_UDP) {
return 0; // 拒绝
}
return 1; // 允许
}

8.2 常用的 Cgroup eBPF Hook#

Hook触发时机用途
cgroup/sock创建 socket限制网络协议
cgroup/connect发起连接限制出站连接
cgroup/sendmsg发送消息限制目标地址
cgroup/recvmsg接收消息限制来源地址
cgroup/post_bindbind 之后限制监听端口
cgroup/device设备访问限制设备操作

九、动手实践#

9.1 手动创建 Cgroup 并限制进程#

#!/bin/bash
# 手动创建 Cgroup v2 并限制进程
# 1. 创建 cgroup
CGROUP_PATH="/sys/fs/cgroup/mycontainer"
sudo mkdir -p $CGROUP_PATH
# 2. 启用控制器
echo "+cpu +memory +io +pids" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
# 3. 设置 CPU 限制(1 核)
echo "100000 100000" | sudo tee $CGROUP_PATH/cpu.max
# 4. 设置内存限制(256MB)
echo "268435456" | sudo tee $CGROUP_PATH/memory.max
# 5. 设置 PID 限制
echo "100" | sudo tee $CGROUP_PATH/pids.max
# 6. 启动进程并加入 cgroup
stress-ng --cpu 4 --timeout 60s &
PID=$!
echo $PID | sudo tee $CGROUP_PATH/cgroup.procs
# 7. 观察限流效果
watch -n 1 "cat $CGROUP_PATH/cpu.stat"
# nr_periods 10
# nr_throttled 8 ← 被限流 8 次
# throttled_usec 800000 ← 限流了 800ms
# 8. 清理
sudo rmdir $CGROUP_PATH

9.2 Cgroup 监控脚本#

#!/bin/bash
# 监控容器的 Cgroup 资源使用
CONTAINER=$1
CGROUP=$(docker inspect -f '{{.CgroupPath}}' $CONTAINER 2>/dev/null)
if [ -z "$CGROUP" ]; then
echo "Container not found"
exit 1
fi
CGROUP_FS="/sys/fs/cgroup${CGROUP}"
echo "=== CPU ==="
echo "Limit: $(cat $CGROUP_FS/cpu.max)"
echo "Usage: $(cat $CGROUP_FS/cpu.stat | grep usage_usec)"
echo "Throttled: $(cat $CGROUP_FS/cpu.stat | grep throttled)"
echo ""
echo "=== Memory ==="
echo "Limit: $(cat $CGROUP_FS/memory.max)"
echo "Current: $(cat $CGROUP_FS/memory.current)"
echo "Swap: $(cat $CGROUP_FS/memory.swap.current) / $(cat $CGROUP_FS/memory.swap.max)"
echo "OOM events: $(cat $CGROUP_FS/memory.events | grep oom)"
echo ""
echo "=== IO ==="
echo "Stats: $(cat $CGROUP_FS/io.stat)"
echo "Pressure: $(cat $CGROUP_FS/io.pressure)"
echo ""
echo "=== PSI ==="
echo "CPU: $(cat $CGROUP_FS/cpu.pressure)"
echo "Memory: $(cat $CGROUP_FS/memory.pressure)"

附、实践:用 Cgroup v2 限制进程资源#

本节用 Cgroup v2 的文件系统接口手工限制进程资源,观察限制效果。所有命令需要 root 权限。

附.1 确认 Cgroup v2 挂载#

mount | grep cgroup2
# cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cat /sys/fs/cgroup/cgroup.controllers
# cpuset cpu io memory hugetlb pids rdma

Cgroup v2 挂载在 /sys/fs/cgroup/,所有控制器共享同一棵 cgroup 树。

附.2 创建自定义 cgroup 并启用控制器#

# 创建 cgroup 目录
mkdir -p /sys/fs/cgroup/my-demo
# 启用 CPU 和 memory 控制器(从根 cgroup 委派)
echo "+cpu +memory" > /sys/fs/cgroup/cgroup.subtree_control
# 确认控制器已启用
cat /sys/fs/cgroup/my-demo/cgroup.controllers
# cpuset cpu io memory hugetlb pids rdma

附.3 设置内存限制#

# 设置内存上限为 512MB
echo "536870912" > /sys/fs/cgroup/my-demo/memory.max
# 确认限制生效
cat /sys/fs/cgroup/my-demo/memory.max
# 536870912

附.4 设置 CPU 限制#

# 限制 CPU 使用率为 50%(每 100000 微秒中最多使用 50000 微秒)
echo "50000 100000" > /sys/fs/cgroup/my-demo/cpu.max
# 确认限制生效
cat /sys/fs/cgroup/my-demo/cpu.max
# 50000 100000

cpu.max 的格式是 max quotamax 表示不限,50000 100000 表示每 100ms 周期内最多使用 50ms CPU 时间,即 50% CPU。

附.5 将进程移入 cgroup#

# 启动一个消耗 CPU 的进程
stress --cpu 1 --timeout 30 &
# 将进程 PID 写入 cgroup
echo $! > /sys/fs/cgroup/my-demo/cgroup.procs
# 观察 CPU 使用率被限制在 50%
top -bn1 | grep stress

附.6 观察 PSI 压力指标#

cat /sys/fs/cgroup/my-demo/cpu.pressure
# some avg10=0.00 avg60=0.00 avg300=0.00 total=0
# full avg10=0.00 avg60=0.00 avg300=0.00 total=0
cat /sys/fs/cgroup/my-demo/memory.pressure
# some avg10=0.00 avg60=0.00 avg300=0.00 total=0
# full avg10=0.00 avg60=0.00 avg300=0.00 total=0

PSI(Pressure Stall Information)是 Cgroup v2 的重要特性——some 表示”至少一个进程被延迟”,full 表示”所有进程被延迟”。当 CPU 或内存压力增大时,这些数值会上升,运维可以据此触发自动扩容。

注意:实验结束后清理 cgroup:rmdir /sys/fs/cgroup/my-demo。如果 cgroup 中仍有进程,需要先将它们移回根 cgroup。

十、本章小结#

上一章建立了Linux Namespace 的原理与实现的认知框架。

控制器关键文件功能Docker 参数
CPUcpu.max, cpu.weightCPU 时间限制与权重—cpus, —cpu-shares
内存memory.max, memory.min, memory.low内存限制与保护—memory, —memory-reservation
IOio.max, io.weight块设备 IO 限制—device-write-bps
PIDpids.max进程数限制—pids-limit
cpusetcpuset.cpus, cpuset.memsCPU 亲和性—cpuset-cpus
PSIcpu.pressure, memory.pressure, io.pressure压力监控
Note

Cgroup v2 的统一层级设计大大简化了容器运行时的资源管理逻辑。runc 和 containerd 都已完整支持 Cgroup v2。如果你的系统还在使用 Cgroup v1,建议升级到 v2 以获得更好的 PSI 支持和 eBPF 扩展能力。

支持与分享

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

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

部分信息可能已经过时

相关文章 智能推荐
1
容器存储
容器运行时 容器的可写层随容器删除而丢失,数据持久化需要 Volume。一网打尽容器存储的完整方案——Volume(绑定挂载/命名卷/tmpfs)、存储驱动(overlay2/devicemapper/btrfs)、CSI(容器存储接口)插件机制,以及 Kubernetes 的 PV/PVC/StorageClass 体系——从「docker run -v」到「理解容器存储的每一条挂载规则」。
2
Linux Namespace 深入
容器运行时 Namespace 是容器视图隔离的核心机制。全面剖析 8 种 Linux Namespace 的原理与实现——PID/Mount/Network/User/IPC/UTS/Cgroup/Time,剖析 unshare/clone/setns 三个系统调用的内核行为,理解 Namespace 的继承规则与嵌套关系,为理解 runc 源码和容器安全奠定基础。
3
综合实战:构建一个迷你容器运行时
容器运行时 综合实战——用 Go 从零构建一个迷你容器运行时——实现 Namespace 隔离(PID/Mount/UTS/IPC/Network)、Cgroup 资源限制(CPU/内存)、OverlayFS 分层文件系统、OCI Bundle 解析,最终实现一个能运行容器的 minirunc。将前 15 章的知识融会贯通,从「理解原理」到「动手实现」。
4
系列导读
容器运行时 本系列从 Linux 内核的 Namespace、Cgroup、OverlayFS 出发,深入 OCI 规范、runc 源码、containerd 架构,再到容器安全、沙箱运行时、网络、存储、镜像构建、Wasm 容器,最后综合实战构建一个迷你容器运行时——从「会用 Docker」到「理解容器运行时的每一行代码」,每章配有可运行的代码示例与架构图,让你从容器用户进阶到容器运行时工程师。
5
镜像构建:BuildKit
容器运行时 BuildKit 是 Docker 的新一代镜像构建引擎,支持并行构建、缓存导入导出、多阶段构建优化、secret 挂载等高级特性。从零讲透 BuildKit 的架构设计、Dockerfile 指令的执行原理、多阶段构建、缓存策略、以及如何编写高效的 Dockerfile——从「会写 Dockerfile」到「理解每一条指令的构建机制」。