在 Linux 中通过 cgroups 限制 Nginx、MySQL 等服务的资源使用,核心思路是为服务创建专属 cgroup,配置资源限制,并将服务进程关联到该组。以下是具体配置方法和步骤,涵盖 CPU、内存、磁盘 I/O 等关键资源:
⚙️ 一、通用配置流程(适用于所有服务)
-
安装 cgroup 工具
若未安装cgroup-tools
,需先执行:sudo apt-get update && sudo apt-get install cgroup-tools # Debian/Ubuntu sudo yum install libcgroup-tools -y # CentOS/RHEL
-
创建 cgroup 并设置资源限制
# 创建名为 nginx_limit 的 cgroup(限制 CPU 和内存) sudo cgcreate -g cpu,memory:/nginx_limit # 设置 CPU 限制(示例:限制为 50%) sudo cgset -r cpu.cfs_period_us=100000 /nginx_limit # 周期 100ms sudo cgset -r cpu.cfs_quota_us=50000 /nginx_limit # 配额 50ms(即 50%) # 设置内存限制(示例:限制为 1GB) sudo cgset -r memory.limit_in_bytes=1G /nginx_limit
-
将服务进程关联到 cgroup
- 方法 1:启动时直接绑定(推荐)
# 使用 cgexec 启动服务 sudo cgexec -g cpu,memory:nginx_limit systemctl start nginx
- 方法 2:对运行中进程绑定
# 获取 PID(如 MySQL 主进程) sudo systemctl status mysql | grep "Main PID" # 绑定到 cgroup sudo cgclassify -g cpu,memory:mysql_limit <PID>
- 方法 1:启动时直接绑定(推荐)
🖥️ 二、针对 Nginx 的配置示例
-
限制 CPU 和内存
参考上述通用流程创建 cgroup(如nginx_limit
),并设置参数:- CPU 限制:
cpu.cfs_quota_us
与cpu.cfs_period_us
比例控制。 - 内存限制:
memory.limit_in_bytes
防止内存溢出。
- CPU 限制:
-
补充:文件描述符限制
Nginx 需处理大量连接,需单独调整(非 cgroup):# 修改 /etc/security/limits.conf nginx soft nofile 65535 nginx hard nofile 65535 # 在 Nginx 配置中同步 worker_rlimit_nofile 65535; # 位于 nginx.conf
🗄️ 三、针对 MySQL 的配置示例
-
限制 CPU 和内存
# 创建 cgroup sudo cgcreate -g cpu,memory:/mysql_limit # 限制 CPU 为 4 核等效(400%) sudo cgset -r cpu.cfs_quota_us=400000 /mysql_limit sudo cgset -r cpu.cfs_period_us=100000 /mysql_limit # 限制内存为 4GB sudo cgset -r memory.limit_in_bytes=4G /mysql_limit
-
磁盘 I/O 限制(需额外配置)
# 创建 blkio cgroup sudo cgcreate -g blkio:/mysql_io # 限制读写带宽(示例:限制写带宽 50MB/s) sudo cgset -r blkio.throttle.write_bps_device="MAJ:MIN 52428800" /mysql_io # 查看设备号:`lsblk -o NAME,MAJ:MIN`
⚠️ 注意:需同时限制带宽和 IOPS 以避免单维度失效。
🔄 四、持久化配置(重启后生效)
临时配置重启后会丢失,需通过 systemd 或 启动脚本 实现持久化:
-
Systemd 服务集成(推荐)
修改服务的 systemd 单元文件(如/etc/systemd/system/mysql.service
):[Service] ... CPUQuota=50% # 限制 CPU 使用率 MemoryHigh=1G # 软内存限制 MemoryMax=1.5G # 硬内存限制 IOWeight=500 # 相对 I/O 权重
执行
sudo systemctl daemon-reload && sudo systemctl restart mysql
生效。 -
通过脚本自动绑定
创建/etc/rc.local
脚本(示例为 MySQL):# 获取 PID 并绑定到 cgroup PID=$(systemctl show mysql --value -p MainPID) cgclassify -g cpu,memory:mysql_limit $PID
⚠️ 五、注意事项
-
子进程继承:确保 cgroup 设置支持继承(默认开启),否则需手动绑定子进程。
-
Swap 影响:内存限制在开启 Swap 时可能失效,建议禁用 Swap。
-
监控验证:
- 使用
top
或htop
观察%CPU
和%MEM
。 - 检查 cgroup 状态:
cat /sys/fs/cgroup/memory/mysql_limit/memory.usage_in_bytes
。
- 使用
-
多服务隔离:若同一主机运行多个 MySQL/Nginx 实例,需为每个实例创建独立 cgroup 避免资源竞争。
📊 配置参数参考表
资源类型 | cgroup参数 | Nginx示例值 | MySQL示例值 | 作用 |
---|---|---|---|---|
CPU | cpu.cfs_quota_us |
50000 (50%) | 400000 (4核) | 周期内可使用的 CPU 时间 |
cpu.cfs_period_us |
100000 | 100000 | CPU 周期长度(微秒) | |
内存 | memory.limit_in_bytes |
1G | 4G | 最大内存使用量 |
磁盘 I/O | blkio.throttle.write_bps_device |
未设置 | 50MB/s | 限制写入带宽 |
通过以上配置,可有效隔离 Nginx、MySQL 等服务的资源使用,避免单个应用耗尽系统资源导致整体服务不可用。建议先在测试环境验证参数,再应用于生产环境。