结论:cgroup(control group)把进程组织成层级组,对各组的 CPU、内存、块 I/O、PIDs 数等资源做限制、记账和优先级控制;namespace 负责"看不见别人"(隔离视图),cgroup 负责"用不超配"(资源配额),两者共同构成容器的技术底座。
展开:主要子系统(v2 为统一层级):1)cpu——cpu.max 设带宽上限(周期内配额,如 50000/100000 = 半核),cpu.weight 设相对权重;超限的任务被限流(throttle)而非杀死。2)memory——memory.max 硬上限,触顶触发 cgroup 级 OOM 杀组内进程;memory.high 软上限做节流回压;页缓存也计入内存记账(v1 时代常被忽视的坑)。3)io——按设备设 IOPS/BPS 上限。4)pids——pids.max 防 fork 炸弹。容器落地:Docker/K8s 为每个容器创建 cgroup,resources.limits/requests 翻译成对应的 cpu.max/memory.max;监控指标(cAdvisor)也来自 cgroup 记账。易错点:1)JVM/Go 早期版本按宿主机核数设置并行度,容器内要配合 -XX:ActiveProcessorCount/GOMAXPROCS 或新版自动识别 cgroup;2)内存 limit 触顶是 cgroup OOM,日志在宿主机 dmesg 里,表现为容器内进程被杀但无应用日志。
# 手动体验:限 0.5 核
mkdir /sys/fs/cgroup/demo
echo "50000 100000" > /sys/fs/cgroup/demo/cpu.max
echo $PID > /sys/fs/cgroup/demo/cgroup.procs
追问方向:cgroup v1 与 v2 的差异、K8s 的 QoS(Guaranteed/Burstable/BestEffort)如何映射到 oom_score_adj 与 cgroup 参数。