gVisor 如何启用 systemd cgroup 驱动并映射 OCI 资源限制?
【免费下载链接】gvisorApplication Kernel for Containers项目地址: https://gitcode.com/GitHub_Trending/gv/gvisor
默认情况下,runsc自己创建 cgroup 并设置 cgroup 限制(这种模式称为 fs cgroup 驱动)。如果你希望容器的 cgroup 由宿主机的 systemd 管理——例如让容器资源出现在 systemd 的单元树中、由 systemd 负责记账——需要为runsc启用 systemd cgroup 驱动。该功能要求宿主机 systemd 版本至少为 244,并且启用统一 cgroups(cgroup v2)。本文基于 g3doc/user_guide/systemd.md 说明启用方式、单元命名规则,以及 OCI runtime spec 资源如何映射为 systemd 单元属性。
前提条件:systemd 版本与 cgroup v2
按 g3doc/user_guide/systemd.md 的说明,使用 systemd cgroup 驱动前需满足:
- 宿主机 systemd 版本 ≥ 244(可用
systemctl --version查看当前版本); - 宿主机启用统一 cgroups,即 cgroup v2。
这两条是硬性要求,不满足时该驱动不可用。
启用 systemd cgroup 驱动
--systemd-cgroup是runsc的全局选项,在命令前加上即可切换驱动,文档给出的示例形式是:
runsc --systemd-cgroup run ...需要说明的是,这个标志在 runsc/config/flags.go 中被标记为 EXPERIMENTAL("EXPERIMENTAL. Use systemd for cgroups."),属于实验性功能。
在 Docker 场景下,同样通过给 runsc 运行时附加该标志实现。快速入门指南 g3doc/user_guide/quick_start/docker.md 说明runsc install可以在--之后传递运行时参数,文档中的示例:
sudo runsc install --runtime runsc-debug -- \ --debug \ --debug-log=/tmp/runsc-debug.log \ --strace \ --log-packets仿照该形式,把--systemd-cgroup放在--之后,即可安装一个始终使用 systemd cgroup 驱动的运行时(runsc-systemd是示例运行时名,可自定)。仓库 Makefile 中也注册了一个带--systemd-cgroup标志的运行时(runsc-systemd-d),可作为参照。
runsc 如何决定单元名称和 slice
创建容器时,runsc 会通过 dbus 请求 systemd 为该容器创建一个 transient unit,并将其放入指定 slice。单元名和 slice 由 OCI runtime spec 中的Linux.CgroupsPath推导:
- 若
Linux.CgroupsPath已设置,期望其格式为[slice]:[prefix]:[name]:slice是容器所在的 systemd slice。为空时默认system.slice;但在 cgroup v2 下创建 rootless 容器时默认user.slice。slice可以用短横线表示子 slice(如user-1000.slice,表示user.slice的子 slice),但不能包含斜杠(user.slice/user-1000.slice是非法的)。-表示根 slice。prefix和name组成单元名<prefix>-<name>.scope;如果name以.slice结尾,则忽略prefix,name原样使用。
- 若
Linux.CgroupsPath未设置或为空,等价于设置为:runsc:<container-id>,最终得到system.slice下的runsc-<container-id>.scope。
创建出的单元是 systemd scope,runsc 通过Slice=属性指定父 slice,并设置Delegate=true。
OCI 资源限制到 systemd 属性的映射
runsc 会无条件启用所有控制器的记账,即为创建的 systemd 单元设置:
- CPUAccounting=true
- IOAccounting=true
- MemoryAccounting=true
- TasksAccounting=true
资源限制本身由 runsc 将 runtime spec 资源翻译为 systemd 单元属性来实现。需要注意:这种翻译并不完整,因为有些 cgroup 属性无法通过 systemd 设置——因此 systemd cgroup 驱动由 fs 驱动兜底(先通过 systemd 单元属性设置,再通过直接写 cgroupfs 文件设置)。
可翻译的资源取决于内核 cgroup 版本(v1/v2)和宿主机 systemd 版本;如果使用了较旧的系统d版本,runsc 不会设置它不支持的资源。g3doc/user_guide/systemd.md 给出的映射表如下:
| runtime spec resource | systemd property name | min systemd version |
|---|---|---|
| memory.limit | MemoryMax | |
| memory.reservation | MemoryLow | |
| memory.swap | MemorySwapMax | |
| cpu.shares | CPUWeight | |
| pids.limit | TasksMax | |
| cpu.cpus | AllowedCPUs | |
| cpu.mems | AllowedMemoryNodes | |
| unified.cpu.max | CPUQuota, CPUQuotaPeriodSec | |
| unified.cpu.weight | CPUWeight | |
| unified.cpu.idle | CPUWeight | v252 |
| unified.cpuset.cpus | AllowedCPUs | |
| unified.cpuset.mems | AllowedMemoryNodes | |
| unified.memory.high | MemoryHigh | |
| unified.memory.low | MemoryLow | |
| unified.memory.min | MemoryMin | |
| unified.memory.max | MemoryMax | |
| unified.memory.swap.max | MemorySwapMax | |
| unified.pids.max | TasksMax |
上表是文档原文的映射关系,其中仅unified.cpu.idle标注了最低 systemd 版本 v252。各属性的含义可参考systemd.resource-control(5)man page。
验证:检查 scope 单元与翻译后的属性
按上述规则,验证可以落在两点上(均为文档描述的行为,可据此核对):
- 单元放置位置:以默认
Linux.CgroupsPath(等价:runsc:<container-id>)为例,容器对应的单元应为system.slice下的runsc-<container-id>.scope;若你设置了自定义CgroupsPath,则按 slice/前缀规则推导出预期单元名,确认 transient scope 出现在对应 slice 中。 - 属性翻译:检查该 scope 的记账属性(
CPUAccounting、IOAccounting、MemoryAccounting、TasksAccounting均为 true,Delegate=true),以及资源属性是否反映了 OCI spec 中的设置,例如 OCI 的unified.memory.max对应MemoryMax、cpu.shares对应CPUWeight。
在带资源参数的场景下,g3doc/user_guide/quick_start/docker.md 展示了docker run --runtime=runsc ... --cpus=0.5这类用法;这些参数进入 runtime spec 后即按上表翻译。
限制与边界
- 标志本身标记为 EXPERIMENTAL,行为以 g3doc/user_guide/systemd.md 描述为准。
- 翻译不完整:无法通过 systemd 设置的 cgroup 属性会回退到直接写 cgroupfs(fs 驱动兜底),而不是报错。
- 较旧版本的 systemd 会静默跳过它不支持的资源,而不是报错。
- 资源限制的生效范围:按 g3doc/user_guide/compatibility.md 的说明,sandbox 内部的 cgroup(CPU、内存)只用于资源记账,限制不在 sandbox 内部强制执行;把 gVisor 放入宿主机的 cgroup 可以限制整个 sandbox 的资源,但 gVisor 目前无法在同一 sandbox 内竞争进程之间强制资源限制。
【免费下载链接】gvisorApplication Kernel for Containers项目地址: https://gitcode.com/GitHub_Trending/gv/gvisor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考