2. Docker 资源限制基础:CPU、内存、磁盘IO、网络带宽限制的核心概念与cgroup原理
2.1 为什么需要资源限制?
在 Docker 容器化部署中,多个容器共享宿主机的操作系统内核与硬件资源。如果没有资源限制,一个异常容器(如内存泄漏、CPU 死循环)可能耗尽宿主机资源,导致其他业务容器甚至宿主机本身不可用。资源限制是保障多租户隔离、服务稳定性与可预测性的第一道防线。
核心目标: 通过 cgroup(Control Group)机制,对每个容器的 CPU、内存、磁盘 I/O、网络带宽进行配额控制,实现“有限资源下的公平调度与故障隔离”。
2.2 cgroup 原理概述
cgroup 是 Linux 内核提供的一种资源管理机制,Docker 通过它实现资源限制。cgroup 将进程(容器内的所有进程)组织成层级化的控制组,并为每个组设置资源配额。Docker 在创建容器时,会在 /sys/fs/cgroup/ 下为容器创建对应的子目录,写入限制参数。
2.3 CPU 资源限制
Docker 通过 --cpus、--cpu-shares、--cpuset-cpus 等参数控制容器 CPU 使用。底层对应 cgroup 的 cpu 子系统。
| 参数 | cgroup 文件 | 说明 | 典型场景 |
|---|---|---|---|
--cpus |
cpu.cfs_quota_us / cpu.cfs_period_us |
限制容器最多使用多少个 CPU 核心(支持小数,如 1.5) | 精确控制 CPU 上限,防止单容器占满所有核心 |
--cpu-shares |
cpu.shares |
设置 CPU 权重(相对值,默认 1024),仅在 CPU 竞争时生效 | 保证高优先级容器获得更多 CPU 时间片 |
--cpuset-cpus |
cpuset.cpus |
将容器绑定到指定的物理 CPU 核心(如 0-3) | NUMA 优化、低延迟应用、避免 CPU 缓存抖动 |
实践建议: 生产环境优先使用
--cpus 进行硬限制,配合 --cpu-shares 做软优先级。避免单独使用 --cpu-shares 作为唯一限制手段,因为它在 CPU 空闲时允许容器突破权重。
CPU 限制示例
# 限制容器最多使用 2.5 个 CPU 核心
docker run --cpus="2.5" nginx
# 设置 CPU 权重为 2048(默认 1024),竞争时获得更多时间片
docker run --cpu-shares=2048 nginx
# 绑定到 CPU 核心 0 和 1
docker run --cpuset-cpus="0,1" nginx
2.4 内存资源限制
内存限制通过 --memory(硬限制)和 --memory-swap(交换分区限制)实现,对应 cgroup 的 memory 子系统。当容器内存使用超过硬限制时,内核会触发 OOM Killer 终止容器进程。
| 参数 | cgroup 文件 | 说明 | 注意事项 |
|---|---|---|---|
--memory / -m |
memory.limit_in_bytes |
容器最大可用物理内存(如 512m、2g) | 超过此值触发 OOM |
--memory-swap |
memory.memsw.limit_in_bytes |
物理内存 + 交换分区的总量上限 | 默认与 --memory 相同(禁用 swap) |
--memory-reservation |
memory.soft_limit_in_bytes |
内存软限制,当宿主机内存紧张时尽力保证 | 不保证严格限制,仅作为调度提示 |
--oom-kill-disable |
memory.oom_control |
禁止 OOM Killer 杀死容器进程 | 需配合 --memory 使用,否则可能耗尽宿主机内存 |
OOM 风险: 设置
--memory 但不设置 --memory-swap 时,Docker 默认禁用 swap,容器内存达到硬限制后立即 OOM。对于 Java、Node.js 等内存密集型应用,建议预留 20%-30% 的缓冲空间。
内存限制示例
# 限制物理内存 512MB,禁用 swap
docker run -m 512m nginx
# 限制物理内存 1GB,swap 上限 512MB(总计 1.5GB)
docker run -m 1g --memory-swap 1.5g nginx
# 设置软限制 2GB,硬限制 4GB
docker run -m 4g --memory-reservation 2g nginx
2.5 磁盘 I/O 资源限制
磁盘 I/O 限制通过 --blkio-weight、--device-read-bps、--device-write-iops 等参数实现,对应 cgroup 的 blkio 子系统。支持按设备(如 /dev/sda)分别限制读写速率。
| 参数 | cgroup 文件 | 说明 | 单位 |
|---|---|---|---|
--blkio-weight |
blkio.weight |
块设备 I/O 权重(10-1000,默认 500) | 相对值 |
--device-read-bps |
blkio.throttle.read_bps_device |
限制设备读取速率(字节/秒) | kb、mb、gb |
--device-write-bps |
blkio.throttle.write_bps_device |
限制设备写入速率(字节/秒) | kb、mb、gb |
--device-read-iops |
blkio.throttle.read_iops_device |
限制设备读取 IOPS | 次/秒 |
--device-write-iops |
blkio.throttle.write_iops_device |
限制设备写入 IOPS | 次/秒 |
磁盘 I/O 限制示例
# 设置 blkio 权重为 800(高优先级)
docker run --blkio-weight 800 nginx
# 限制 /dev/sda 读取速率 50MB/s,写入速率 30MB/s
docker run --device-read-bps /dev/sda:50mb --device-write-bps /dev/sda:30mb nginx
# 限制 /dev/sda 读取 IOPS 为 1000,写入 IOPS 为 500
docker run --device-read-iops /dev/sda:1000 --device-write-iops /dev/sda:500 nginx
2.6 网络带宽限制
Docker 原生未提供直接的网络带宽限制参数,但可通过以下方式实现:
- tc(Traffic Control): 在容器 veth 接口上配置 HTB 或 TBF 队列规则,限制带宽。
- --net QoS 插件: 使用第三方面网络插件(如 Calico、Weave)的 QoS 策略。
- cgroup net_prio 子系统: 设置网络优先级,间接影响带宽分配。
| 方法 | 粒度 | 复杂度 | 适用场景 |
|---|---|---|---|
| tc 直接限速 | 容器级别 | 中 | 单机部署,需要精确控制带宽 |
| 网络插件 QoS | 容器/命名空间 | 低 | Kubernetes 集群,声明式管理 |
| cgroup net_prio | 优先级 | 低 | 仅需区分优先级,不要求精确速率 |
tc 限速示例
# 获取容器网络命名空间 PID
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' container_name)
# 在容器网络命名空间中配置 tc 限速(限制出口带宽 10Mbps)
nsenter -t $CONTAINER_PID -n tc qdisc add dev eth0 root tbf rate 10mbit burst 32kbit latency 400ms
生产建议: 在 Kubernetes 环境中,优先使用 NetworkPolicy 配合 CNI 插件的带宽注解(如
kubernetes.io/ingress-bandwidth)进行限制。在纯 Docker 环境中,建议将 tc 限速封装为启动脚本或使用 docker-compose 的 ulimits 配合自定义网络驱动。
2.7 资源限制综合配置清单
以下是一个企业级 Nginx 容器的资源限制示例,涵盖 CPU、内存、磁盘 I/O 和网络带宽:
docker run -d \
--name web-nginx \
--cpus="2" \
--memory="1g" \
--memory-swap="1.5g" \
--memory-reservation="768m" \
--blkio-weight=600 \
--device-read-bps /dev/sda:100mb \
--device-write-bps /dev/sda:50mb \
--device-read-iops /dev/sda:5000 \
--device-write-iops /dev/sda:2000 \
--restart=always \
nginx:1.25-alpine
验证命令: 使用
docker stats web-nginx 实时查看资源使用情况;使用 cat /sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes 确认 cgroup 配置生效。
2.8 常见资源限制异常与排查方向
| 异常现象 | 可能原因 | 排查命令/方法 |
|---|---|---|
| 容器频繁 OOM 重启 | 内存硬限制过低,或应用内存泄漏 | docker logs --tail 50 查看 OOM 日志;dmesg | grep -i oom |
| 容器 CPU 使用率被截断 | --cpus 设置过小,或 cpuset 绑定核心不足 |
docker stats 观察 CPU%;cat /sys/fs/cgroup/cpu/docker/<id>/cpu.cfs_quota_us |
| 磁盘写入缓慢 | blkio 写入速率限制过低,或磁盘本身瓶颈 | iotop 查看进程 I/O;cat /sys/fs/cgroup/blkio/docker/<id>/blkio.throttle.write_bps_device |
| 网络延迟高、吞吐低 | tc 限速策略过于严格,或网络插件 QoS 冲突 | tc -s qdisc show dev eth0 查看队列统计;iperf3 测试带宽 |