Linux系统资源动态调度容器服务防止抢占

为什么容器会互相抢占资源?

当多个容器运行在同一台 Linux 服务器时,如果没有明确的资源限制,它们会像争抢公共食堂的饭菜一样,争着使用 CPU 和内存。
如果其中一个容器突然需要大量计算,其他容器就会响应变慢甚至超时。
这就是 容器资源抢占 问题。
本文用最简单的方式,教你通过 Linux系统资源动态调度容器服务防止抢占 的完整方法,零基础也能照做。

准备工作:确认系统和工具

先检查你的 Linux 发行版和内核版本。
推荐使用 cgroup v2(新版控制组),它比旧版更简洁、调度更精准。

# 查看 cgroup 当前版本
mount | grep cgroup
# 如果输出包含 cgroup2,说明已启用 v2

如果系统默认是 cgroup v1(常见于 CentOS 7),可以升级到 v2:

  1. 在 GRUB 内核参数中添加 systemd.unified_cgroup_hierarchy=1
  2. 重启生效

同时确保已安装 Docker(或 Podman),本文以 Docker 为例。

核心操作一:使用 Docker 参数静态限制

最直接的方式是在启动容器时指定 CPU 和内存限额。

docker run -d --name web1 \
  --cpus="1.5" \
  --memory="512m" \
  --memory-reservation="256m" \
  nginx:alpine
  • --cpus:限制容器最多使用 1.5 个核(核数可以是小数)
  • --memory:硬限制,容器最多用 512MB 内存,超限会被 OOM kill
  • --memory-reservation:软限制,当宿主机内存紧张时,系统会优先回收超过此值的部分

这种静态方式已经能防止大部分抢占,但不够“动态”。

核心操作二:利用 cgroup v2 实现动态调度

动态调度指的是根据实时负载自动调整容器所占资源比例。
cgroup v2 支持 CPU 权重(weight)和内存保护(memory.min)。

  1. 创建两个容器的 cgroup 目录(Docker 会自动创建,我们手动微调):
mkdir -p /sys/fs/cgroup/system.slice/docker-web1
mkdir -p /sys/fs/cgroup/system.slice/docker-web2
  1. 设置 CPU 权重(默认值为 100,越高越优先):
echo 200 > /sys/fs/cgroup/system.slice/docker-web1/cpu.weight
echo 50 > /sys/fs/cgroup/system.slice/docker-web2/cpu.weight

这样当两个容器同时跑满 CPU 时,web1 获得约 80% 的资源,web2 约 20%。
如果 web2 空闲,web1 可以多用。
这就是动态调度的基础。

  1. 设置内存最低保障:
echo 256M > /sys/fs/cgroup/system.slice/docker-web1/memory.min
echo 128M > /sys/fs/cgroup/system.slice/docker-web2/memory.min

即使内存紧张,每个容器也能保证至少得到设定量的内存,不会被对方完全抢走。

注意:直接修改 cgroup 文件后,重启容器或 Docker 服务会导致配置丢失。建议将配置写入 systemd service 的 Slice 中,或使用 Docker Compose 的 cgroup_parent 参数持久化。

核心操作三:使用 systemd slice 持久化方案

对于生产环境,推荐通过 systemd 的 slice 资源控制实现持久化:

  1. 创建 slice 文件 /etc/systemd/system/container.slice
[Slice]
CPUWeight=200
MemoryMin=2G
MemoryMax=4G
  1. 在容器启动时指定 cgroup 父级:
docker run -d --name app1 --cgroup-parent=/container.slice nginx

这样所有加入 container.slice 的容器共享 slice 的资源池,再配合 cpu.weightmemory.min 实现动态分配。

避坑说明

  • 不要给 CPU 权重过大的差距:比如一个设 1000,另一个设 1,会导致前者几乎完全压制后者,失去“动态”意义。
  • cgroup v1 不支持 memory.min:如果你必须用 CentOS 7,请使用 memory.limit_in_bytes 硬限制,软限制用 memory.soft_limit_in_bytes
  • 动态调度不等于无限弹性:如果所有容器同时请求的总资源超过宿主机物理上限,依然可能触发 OOM。建议配合 swappiness 和 swap 限制使用。

效果验证方法

启动两个测试容器,一个跑压力测试,一个跑轻量服务:

# 容器 A 跑满 CPU
docker run --rm --cpus=2 busybox sh -c "while true; do :; done" &
# 容器 B 模拟服务
docker run --rm --cpus=2 nginx

然后用 docker stats 观察实时 CPU 占用:

docker stats --no-stream

正常配置下,两个容器应该根据权重分配资源,不会出现一个吃掉 100% 另一个挂起的情况。

如果发现容器频繁 OOM,请检查 memory.min 是否设置过低,或者宿主机总内存不足。

常见高频问题

Q:cgroup v2 下如何临时调整正在运行的容器?
A:找到对应容器的 cgroup 路径(docker inspect | grep Cgroup),直接修改该目录下的 cpu.weightmemory.min 即可。

Q:我只有 Docker Compose,如何设置资源动态调度?
A:在 docker-compose.yml 中使用 cpus: '1.5'mem_limit: 512m 以及 cgroup_parent: /container.slice 字段。

Q:本文的方法能否防止“内存泄露型”容器抢占?
A:可以兜底。硬限制 memory.max 会直接杀掉内存泄露的容器,保护宿主和其他服务。

---

如果你正在处理 Linux系统资源动态调度容器服务防止抢占,建议先按本文步骤完整执行,再根据自己的环境微调权重值。
遇到异常时优先回看避坑和高频问题部分,也可以对照 dmesg | grep -i oom 检查是否触发了内存溢出。

(全文完)

分享到:
上一篇
宝塔面板对接企业微信钉钉告警推送故障
下一篇
OpenTelemetry分布式链路追踪服务器集群
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意