systemd 和 runc 之间的关系
有关系,而且关系非常清晰,但层级一定要分清。
内容:结论 -> 架构关系 -> 典型交互路径 -> 常见误区澄清。
systemd 和 runc 不在同一层,但它们通过“进程模型”和“cgroups”产生了间接联系。
- systemd:通用的 系统与服务管理器
- runc:符合 OCI 规范的 容器进程启动器
👉 它们不是互相调用关系,而是“可以协作,但互不依赖”
systemd 是 PID 1,负责整个系统的:
- 进程生命周期管理
- 服务启动 / 停止 / 重启
- cgroups 管理
- 资源限制(CPU / Memory / IO)
- socket / timer / mount 管理
本质一句话:
systemd 是“进程控制平面”。
runc 是一个 一次性工具,负责:
- 创建 Linux namespaces
- 设置 cgroups
- 挂载 rootfs
- 执行容器的
init进程 - 启动完成后 立刻退出
本质一句话:
runc 是“容器进程引导器”。
这是它们发生关系的地方。
-
systemd 是 cgroup 的总管理者
-
所有进程最终都在某个 systemd 管理的 cgroup 下
-
systemd 负责:
- 创建
- 层级划分
- 回收
- 资源限制
-
runc 不会创建顶层 cgroup
-
它只是:
- 被告知“你该用哪个 cgroup”
- 把容器进程放进去
-
runc 本身不负责长期管理
systemd (PID 1)
└─ dockerd.service
└─ dockerd
└─ containerd
└─ runc
└─ 容器 init 进程 (PID N)
-
systemd:
- 管理
dockerd.service - 创建并维护 cgroup 树
- 管理
-
runc:
- 在 systemd 已划好的 cgroup 空间中
- 启动容器进程
- 启动完成即退出
👉 runc 从不“接管系统”,它只是启动一个进程
这是理解它们关系的关键类比:
| 项目 | systemd-run | runc |
|---|---|---|
| 作用 | 启动一个受控进程 | 启动一个受控进程 |
| 是否一次性 | 是 | 是 |
| 是否管理生命周期 | 否 | 否 |
| 使用 cgroups | 是 | 是 |
| 隔离维度 | 资源 | 资源 + namespace |
👉 runc = systemd-run + namespace + rootfs
systemd 有:
systemd-nspawnsystemd-run --property=...- 原生 cgroups v2 支持
但 systemd 不等同于 OCI runtime:
| 能力 | systemd | runc |
|---|---|---|
| OCI 规范 | ❌ | ✅ |
| Namespace 组合 | 有 | 完整 |
| rootfs 管理 | 有 | 标准化 |
| 容器生态兼容 | 低 | 高 |
- systemd 管理 cgroups
- 容器运行在 systemd slice 中
- runc 只负责启动
例如:
# /etc/systemd/system/docker.service
[Service]
Slice=docker.slice
- 容器内 PID 1 是 systemd
- 外部仍然是 runc 启动
- systemd 管理容器内部服务
👉 这是“systemd 在容器里”,不是 systemd 管 runc
不对。 systemd 管的是 调用 runc 的服务进程,不是 runc 本身。
不对。 runc 是 fork + exec 后立即退出 的工具。
不对。 容器生命周期由上层(Docker / containerd / CRI)管理。
systemd 是“系统级进程与资源管理者”,runc 是“容器级进程启动器”。它们通过 cgroups 间接协作,但不互相依赖、不互相替代。