2.3 cgroups (资源限制)

机制原理

cgroups(control groups)是 Linux 内核的资源计数与限制机制。把同一个 hierarchy 下的进程归到一个 cgroup,该 cgroup 的所有进程共享一套配额。典型可限制的资源:

子系统限制的字段
cpu / cpuacctCPU 时间 / accountingcpu.sharescpu.cfs_quota_us
memory内存 + swapmemory.limit_in_bytes
pidsPID 数量pids.max
devicesdevice node 访问devices.allow / deny
blkioblock IO 权重blkio.weight
freezerfreeze / thawfreezer.state
net_cls / net_prio网络 classnet_cls.classid

Cgroup 有 v1(各子系统独立 hierarchy)与 v2(统一 hierarchy)两代。CubeSandbox:

  • guest kernel: 同时支持 v1 与 v2(configs/kernel-oc9.configCONFIG_CGROUPS=yCONFIG_CGROUP_PIDS=yCONFIG_CGROUP_SCHED=yCONFIG_CGROUP_DEVICE=yCONFIG_CGROUP_CPUACCT=y)
  • host grub 引导启用 v2 兼容:systemd.unified_cgroup_hierarchy=1

host 侧落地在 agent/rustjail/src/cgroups/(mod.rsnotifier.rssystemd.rsmock.rs)以及 Cubelet/plugins/cube/internals/cgroup/cgroup.goSetCubeboxCgroupLimit

为什么 CubeSandbox 使用它

  • CPU/内存强约束 —— 比 KVM 的 vCPU / 内存隔离更接近 OS 层
  • counter-based DoS —— pids.max 直接限制进程数,防止 forkbomb
  • oom triggers 区分优先级 —— cgroup 内 OOM 与 host OOM 隔离,sandbox 内 OOM 不应"挤"死 kubelet
  • device deny 是 DAC 之外的二次防线 —— 恶意进程即使跑成 0:0,devices.deny 仍能阻止它写 /dev/kvm 等敏感节点
  • 与 KVM 隔离正交 —— KVM 防"内核逃逸",cgroup 防"内核内资源滥用",两层一起才完整

如何使用 / 配置

OCI spec(用户提交)

{
  "linux": {
    "resources": {
      "memory": { "limit": 268435456, "reservation": 134217728 },   // 256 MiB
      "cpu":    { "shares": 512, "quota": 50000, "period": 100000 } // 0.5 vCPU
    }
  }
}

agent 端转换(简化流程)

// agent/rustjail/src/cgroups/mod.rs
let path = format!("/sys/fs/cgroup/memory/cube/box-{}", box_id);
fs::write(format!("{}/memory.limit_in_bytes", path), 268_435_456u64.to_string())?;
fs::write(format!("{}/memory.swappiness", path), "0")?;

// CPU
fs::write(format!("{}/cpu.shares", path), 512u64.to_string())?;
fs::write(format!("{}/cpu.cfs_quota_us", path), 50000u64.to_string())?;
fs::write(format!("{}/cpu.cfs_period_us", path), 100000u64.to_string())?;

// pids
fs::write(format!("/sys/fs/cgroup/pids/cube/box-{}/pids.max", box_id), 1024u64.to_string())?;

Cubelet 侧显式调用(也供 host 上 host-cgroup 限制)

// Cubelet/services/cubebox/cube_container_create.go:107-118
cgroupp.SetCubeboxCgroupLimit(ctx, cgInfo.CgroupID,
    /* memory */ 268435456,
    /* cpuShares */ 512,
    /* pidsMax */ 1024,
)

注意:

  • 不要让 cgroup 路径穿透 —— 在 systemd.unified_cgroup_hierarchy=0 的 host 上,agent 走 /sys/fs/cgroup/cpu,cpuacct/<id> 而不是各自分离,改 cgroup 路径规划会引发限制失效
  • memory.swap 必须设置为 0 或有限制,否则 malware 可靠 swap 隐蔽占内存
  • pids.max 别设太大(>1k 在 forkbomb 时已经足够打爆 host)
  • devices.allow 只放过确实需要的设备,如 c 1:3 /dev/null rwm,其它一律保持 deny