Linux 服务资源控制与 cgroups 深度运维:CPU、内存、IO 隔离最佳实践
一、cgroups 基础概念与 v1 vs v2 对比
cgroups(Control Groups)是 Linux 内核提供的资源限制、统计和隔离机制,主要用于进程分组管理。
主要子系统(Controllers):
cgroups v1 vs v2 核心差异(运维必须了解):
| | | |
|---|
| | | |
| | | |
| | 更强大(MemoryHigh、MemoryMax 等) | |
| | | |
| | | |
检查当前系统版本:
stat -fc %T /sys/fs/cgroup/
# 输出 cgroup2fs 即为 v2
cat /sys/fs/cgroup/cgroup.controllers
生产迁移建议:CentOS 8 / Rocky Linux / Ubuntu 20.04+ 默认推荐使用 cgroups v2。必要时可在 GRUB 中添加 systemd.unified_cgroup_hierarchy=1 参数启用。
二、Systemd 中的资源控制参数详解
Systemd 在 [Service] 段和 [Slice] 段中提供了直观的资源控制配置。
1. CPU 资源控制
[Service]
# CPU 权重(相对份额)
CPUShares=1024 # 默认 1024,值越大优先级越高
# 绝对 CPU 限制(百分比)
CPUQuota=60% # 限制最多使用 60% 单核
CPUQuotaPeriodSec=100ms
# CPU 核心亲和性
AllowedCPUs=0-3,8-11 # 只允许使用指定 CPU 核心
2. 内存资源控制(最重要)
[Service]
MemoryMax=4G # 硬限制,超过会被 OOM Kill
MemoryHigh=3G # 软限制,超过后开始回收(v2 推荐)
MemoryLow=512M # 保护最低内存
MemorySwapMax=2G # 允许 Swap 大小
# OOM 行为控制
OOMPolicy=continue # 推荐:不立即停止服务
3. IO 资源控制
[Service]
# v2 io 控制器
IOWeight=500 # 权重 1-10000
IOReadBandwidthMax=/dev/nvme0n1 50M
IOWriteBandwidthMax=/dev/nvme0n1 30M
# 旧版 blkio(v1)
BlockIOWeight=500
4. 其他关键限制
LimitNOFILE=1048576 # 打开文件数
LimitNPROC=4096 # 进程数
TasksMax=8192 # 任务(线程)最大数
MemoryAccounting=yes
CPUAccounting=yes
IOAccounting=yes
完整生产级示例(Nginx 服务):
[Service]
User=nginx
Type=forking
CPUQuota=80%
MemoryHigh=6G
MemoryMax=8G
IOWeight=600
TasksMax=4096
LimitNOFILE=524288
OOMPolicy=continue
Restart=always
三、Slice 单元:资源分组管理艺术
Slice 是 cgroups 的层次化分组工具,特别适合对同类服务进行统一管控。
1. 创建自定义 Slice 文件:/etc/systemd/system/webapps.slice
[Slice]
MemoryMax=24G
MemoryHigh=20G
CPUQuota=800% # 允许使用 8 核
IOWeight=700
2. 将服务绑定到 Slice
[Service]
Slice=webapps.slice
3. 层级结构设计推荐:
system.slice
├── database.slice # 数据库专用
│ ├── mysql.service
│ └── postgresql.service
├── webapps.slice # Web 服务
│ ├── nginx@.service
│ └── php-fpm@.service
├── cache.slice # Redis/Memcached
└── monitoring.slice # Prometheus 等监控
4. 动态调整 Slice
systemctl set-property webapps.slice MemoryMax=32G
systemctl set-property webapps.slice CPUQuota=1200%
四、生产环境资源控制最佳实践
1. 资源配额设计原则:
- 核心业务优先:数据库分配更高 CPUQuota 和 MemoryHigh。
- 缓冲设计:MemoryHigh 设置为 MemoryMax 的 70-80%,给内核回收空间。
- 容器化过渡:在 Kubernetes 中仍可通过 systemd 控制底层资源。
2. 防止 OOM 雪崩:
- 重要服务设置
OOMScoreAdjust=-500(降低被 Kill 优先级)。 - 配置
vm.overcommit_memory=1 + 合理 Swap。
3. IO 隔离策略:
- 日志写入服务使用低 IOWeight,避免影响业务 IO。
4. 监控指标体系:
systemd-cgtop # 实时 cgroups 监控
cat /sys/fs/cgroup/system.slice/nginx.service/memory.current
cat /sys/fs/cgroup/system.slice/nginx.service/cpu.stat
推荐结合 Prometheus + cAdvisor 或 node_exporter 采集以下指标:
- container_memory_usage_bytes
- container_cpu_usage_seconds_total
- container_blkio_io_service_bytes_total
五、资源控制高级调优技巧
1. CPU 实时调整:
# 临时提升某个服务 CPU 优先级
systemctl set-property nginx.service CPUShares=2048
2. 内存压力测试与调优: 使用 stress-ng 工具:
stress-ng --vm 8 --vm-bytes 80% -t 300s
3. 结合 systemd-run 临时资源限制:
systemd-run --slice=background.slice --property=CPUQuota=30% --property=MemoryMax=2G long-running-command
4. Drop-in 方式覆盖资源配置(推荐):
mkdir -p /etc/systemd/system/mysql.service.d/
cat > /etc/systemd/system/mysql.service.d/resource.conf << EOF
[Service]
MemoryMax=32G
CPUQuota=400%
IOWeight=900
EOF
systemctl daemon-reload
systemctl restart mysql.service
六、常见资源故障排查案例(实战)
案例1:服务被 OOM Killer 杀死 症状:服务突然退出,dmesg 显示 Out of memory。 排查:
journalctl -k | grep -i kill
cat /proc/$(pidof mysqld)/oom_score_adj
systemd-analyze security mysql.service
解决:提高 MemoryHigh,降低 OOMScoreAdjust,增加服务器内存或优化应用代码。
案例2:CPU 抢占严重,业务响应变慢 排查:
systemd-cgtop
top -c -o %CPU
ps -eo pid,ppid,cmd,%cpu --sort=-%cpu
解决:对非核心服务降低 CPUQuota,使用 CPUSet 绑定核心。
案例3:IO 风暴导致数据库卡顿 症状:磁盘 util 100%,数据库 QPS 暴跌。 解决:
- 为 MySQL 单独创建 highio.slice 并设置高 IOWeight。
案例4:cgroups v1/v2 切换后配置失效 解决:检查 /etc/systemd/system.conf 中的 DefaultCPUAccounting 等设置,执行 systemctl daemon-reload。
案例5:大规模容器主机资源超售 方案:设置全局默认限制 + 重要业务硬限 + 监控超限告警。
七、资源控制自动化与监控告警
Ansible 模板示例:
-name:配置服务资源限制
template:
src:resource.conf.j2
dest:"/etc/systemd/system/{{ service }}.service.d/resource.conf"
notify:reloadsystemd
Prometheus Alert 规则示例:
-alert:ServiceHighMemoryUsage
expr:container_memory_usage_bytes{container="nginx"}/container_spec_memory_limit_bytes>0.85
for:5m
labels:
severity:warning
Grafana 仪表盘建议:按 Slice 分组展示 CPU、内存、IO 使用趋势。