
我们在香港数据中心部署了一批用于高并发访问场景的Web服务节点,支撑着数百万级别的日活用户访问。为了保障系统资源的高效利用和服务之间的资源隔离,我们在所有节点上采用了cgroups (control groups) 进行资源限制与调度,主要针对 CPU 和内存进行细粒度控制。
近期,我们收到监控告警,提示有一台服务器(节点编号:HK-WEB-03)在业务低峰期 CPU 使用率持续100%,导致容器内业务响应时间异常升高。初步排查发现该服务器上仅部署了3个轻量级服务容器,理论资源占用应远低于实际消耗。本文将详细还原这次故障的排查过程、技术细节、根因分析与解决方案。
一、香港服务器环境信息
香港服务器型号:Dell PowerEdge R740
- CPU:Intel Xeon Gold 6338 × 2(32核64线程)
- 内存:512 GB DDR4 ECC
- 操作系统:Ubuntu 20.04 LTS
- 容器运行时:containerd 1.6
- cgroups版本:cgroups v2
- 调度策略:基于 systemd 统一资源分配,采用 slice 单元控制
二、故障初步排查
1. CPU占用确认
通过 htop 工具查看整体CPU使用情况:
htop
观察到内核进程 kworker/* 占用大量 CPU,而用户空间容器进程占比反而较低。
进一步执行:
top -H -p <PID>
发现部分线程占用接近 100%,但并不归属于我们的业务容器。
2. 容器资源限制审查
使用 systemd-cgls 查看资源控制层级:
systemd-cgls
发现所有容器都在 user.slice 下运行,而 user.slice 本身未设置 CPU 限制。这意味着即使容器在自己 namespace 中设置了限制,父级资源组未加控制,调度器仍然会依据全局资源调度规则分配 CPU 时间片。
进一步验证每个容器的 cgroup 设置:
cat /sys/fs/cgroup/user.slice/user-1000.slice/cgroup.controllers
cat /sys/fs/cgroup/user.slice/user-1000.slice/cgroup.max
发现配置项 cpu.max 显示为 max max,即没有限制。
根因分析
由于我们在迁移至 cgroups v2 过程中,仅对容器 runtime 层配置了限制参数(如 –cpus=1.0),但未同步配置 systemd 上层 slice 的 CPU 限制,导致实际调度中该 slice 仍被视为“无限制资源池”。
此外,cgroups v2 中 CPU 调度采用基于 weight 的公平调度机制,而非 v1 的 quota/period。我们的运行时配置未对 cpu.weight 做合理设置(默认为 100),所有容器在竞争 CPU 时调度器以默认权重调度,极易导致资源倾斜。
解决方案
1. 为 systemd 的 slice 设置明确资源限制
我们将所有业务容器统一划入 custom.slice,并为其配置如下参数:
# /etc/systemd/system/custom.slice.d/10-Resources.conf
[Slice]
CPUQuota=80%
CPUWeight=200
MemoryMax=256G
重载 systemd 配置:
systemctl daemon-reexec
systemctl daemon-reload
systemctl restart systemd-logind
并确保容器服务统一纳入此 slice:
systemctl set-property containerd.service Slice=custom.slice
2. 在容器运行时明确指定 cgroups 配置
更新 containerd 的 default_runtime 设置,加入资源权重:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
在 Pod 或容器 YAML 中添加:
resources:
limits:
cpu: "2"
memory: "4Gi"
requests:
cpu: "1"
memory: "2Gi"
3. 实时监控 cgroups 状态
部署自研 cgroup 状态采集脚本,定期读取以下路径:
/sys/fs/cgroup/<slice>/cpu.stat
/sys/fs/cgroup/<slice>/cpu.max
/sys/fs/cgroup/<slice>/cpu.weight
并将其接入 Prometheus 监控体系,设置告警规则:
avg_over_time(container_cpu_usage_seconds_total[5m]) > 0.8
故障恢复与验证
资源限制配置更新后,重启容器服务并观察业务表现。通过对比变更前后的指标数据:

同时通过 Linux pressure stall information (PSI) 进一步验证资源瓶颈情况改善。
三、本次故障维护带来的启示
本次故障表面看似资源不够用,实则源于 cgroups 配置失误,尤其是在 cgroups v2 下,系统级 slice 的调度行为对最终效果有决定性影响。
教训总结:
- cgroups v2 不再兼容 v1 的配置语义,尤其是 CPU 配额参数,必须采用新方式设置;
- systemd slice 配置优先级高于容器运行时配置,需要全局审查;
- 监控粒度需深入至调度器视角,如 PSI、cgroup metrics 等;
- 资源限制要配合调度权重使用,确保业务优先级得以体现。
建议实践:
- 所有生产环境节点统一使用 systemd slice 进行资源分类;
- 容器平台配置默认 cpu.weight 与 memory.high,并强制上线审计;
- 引入 cgroup 配置差异对比工具,及时发现未生效配置。
通过本次实践,我们建立了更加完善的资源控制机制,为多租户、高并发环境下的稳定运行打下坚实基础。希望这篇文章能为读者在类似问题排查中提供实战参考。











