一次由于cgroups限制错误导致的香港服务器资源调度异常

一次由于cgroups限制错误导致的香港服务器资源调度异常

我们在香港数据中心部署了一批用于高并发访问场景的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

故障恢复与验证

资源限制配置更新后,重启容器服务并观察业务表现。通过对比变更前后的指标数据:

一次由于cgroups限制错误导致的香港服务器资源调度异常

同时通过 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 配置差异对比工具,及时发现未生效配置。

通过本次实践,我们建立了更加完善的资源控制机制,为多租户、高并发环境下的稳定运行打下坚实基础。希望这篇文章能为读者在类似问题排查中提供实战参考。

未经允许不得转载:A5数据 » 一次由于cgroups限制错误导致的香港服务器资源调度异常

相关文章

contact