Docker资源限制详解

Docker资源限制详解

1. cgroups 控制组机制

1.1 什么是cgroups

cgroups(control groups)是Linux内核提供的一种机制,用于:

  • 限制进程组使用的物理资源(CPU、内存、IO等)
  • 记录进程组的资源使用情况
  • 隔离不同进程组的资源访问

重要性:默认情况下Docker容器不对资源使用进行限制,存在内存泄漏等风险

1.2 cgroups目录结构

bash 复制代码
[root@hrz3 ~]# docker run --name mycentos1 -itd -m 200M centos:7 
# 查看cgroups的目录结构
[root@hrz3 ~]# ls /sys/fs/cgroup/
blkio  cpuacct      cpuset   freezer  memory   net_cls,net_prio  perf_event  systemd
cpu    cpu,cpuacct  devices  hugetlb  net_cls  net_prio          pids

# 查看具体容器的内存限制
[root@hrz3 ~]# cat /sys/fs/cgroup/memory/docker/2e4ed7eeef4bdc6cafcdb234049479b6bd6aa6ed6253f38b25f06fd3ea844cb6/memory.limit_in_bytes

说明:每个资源类型都有对应的cgroup目录,容器创建时会在这些目录下生成对应的资源限制文件

2. 构建stress测试镜像

2.1 完整的stress镜像构建过程

bash 复制代码
# 1. 拉取Ubuntu基础镜像
[root@hrz3 ~]# docker pull ubuntu:jammy

# 2. 创建Dockerfile
[root@hrz3 ~]# vim Dockerfile

Dockerfile内容

dockerfile 复制代码
# 使用Ubuntu基础镜像
FROM ubuntu:jammy

# 更新软件源并安装stress工具
RUN apt-get update && apt-get install -y stress

# 设置容器的默认启动命令
ENTRYPOINT ["/usr/bin/stress", "--verbose"]
bash 复制代码
# 3. 构建stress镜像
[root@hrz3 ~]# docker build -t stress .

# 4. 验证镜像构建成功
[root@hrz3 ~]# docker images | grep stress
[root@hrz3 ~]# docker run --rm stress --help

3. 内存资源限制

3.1 核心内存限制参数

参数 功能 示例 说明
-m, --memory 容器最大内存使用量 -m 512m 硬限制,超过会被OOM Killer终止
--memory-swap 内存+交换分区总限制 -m 512m --memory-swap=1g 控制交换空间使用
--memory-reservation 内存软限制 --memory-reservation 50M 系统紧张时的目标限制
--kernel-memory 内核内存限制 --kernel-memory=128m 限制内核数据结构使用
--oom-kill-disable 禁用OOM Killer --oom-kill-disable 保护关键容器不被杀死
--memory-swappiness 交换分区倾向 --memory-swappiness=0 0-100,越低越避免使用swap
--oom-score-adj OOM优先级调整 --oom-score-adj=-500 -1000到1000,调整被杀优先级

3.2 内存限制实践示例

示例1:限制容器物理内存为50MB

用途:测试内存限制的基本功能

bash 复制代码
[root@hrz3 ~]# docker run -it --name a1 --rm -m 50M stress --vm 1 --vm-bytes 30M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 31457280 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 31457280 bytes
......

示例2:限制物理内存50MB,总内存(物理+交换)100MB

用途:允许容器使用交换空间扩展内存

bash 复制代码
[root@hrz3 ~]# docker run -it --name a1 --rm -m 50M --memory-swap=100M stress --vm 1 --vm-bytes 70M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [7] forked
stress: dbug: [7] allocating 73400320 bytes ...
stress: dbug: [7] touching bytes in strides of 4096 bytes ...
stress: dbug: [7] freed 73400320 bytes
......

示例3:设置内存软限制

用途:为容器设置内存使用目标,系统紧张时尽量保持在此范围内

bash 复制代码
[root@hrz3 ~]# docker run -it -m 100M --memory-reservation 50M centos:7

示例4:禁用OOM Killer

用途:保护关键容器进程不被自动杀死

bash 复制代码
[root@hrz3 ~]# docker run -it -m 100M --oom-kill-disable centos:7

4. CPU资源限制

4.1 核心CPU限制参数

参数 功能 示例 说明
--cpu-shares, -c CPU相对权重 -c 512 默认1024,按比例分配CPU时间
--cpus CPU核心数量限制 --cpus=1.5 限制使用的CPU核心数
--cpuset-cpus CPU核心绑定 --cpuset-cpus="0,2" 指定使用的物理CPU核心
--cpu-period CPU调度周期 --cpu-period=100000 CFS调度周期,默认100ms
--cpu-quota CPU时间配额 --cpu-quota=50000 周期内可用的CPU时间
--cpuset-mems NUMA节点绑定 --cpuset-mems="0" 在多NUMA节点系统中优化内存访问

4.2 CPU限制实践示例

示例1:CPU权重对比测试

用途:演示CPU时间按权重分配的原理

终端1:启动权重为512的容器

bash 复制代码
[root@hrz3 ~]# docker run -it --name a1 --rm -c 512 stress --cpu 4

终端2:启动权重为1024的容器(默认值)

bash 复制代码
[root@hrz3 ~]# docker run -it --name a2 --rm -c 1024 stress --cpu 4

终端3:监控CPU使用情况

bash 复制代码
[root@hrz3 ~]# top

top命令输出分析

bash 复制代码
top - 20:07:09 up  3:28,  3 users,  load average: 7.24, 3.52, 1.62
Tasks: 200 total,   9 running, 191 sleeping,   0 stopped,   0 zombie
%Cpu(s): 99.9 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st

可以看到系统CPU几乎被完全占用,多个stress进程在竞争CPU资源

示例2:CPU核心绑定

用途:将容器进程绑定到特定CPU核心,提高缓存命中率

bash 复制代码
[root@hrz3 ~]# docker run -it --name a1 --rm --cpuset-cpus="1,3" stress --vm 2 --vm-bytes 100M

CPU绑定效果验证

在另一个终端查看CPU使用情况,按数字1显示各CPU核心使用率

bash 复制代码
[root@hrz3 ~]# top
top - 20:14:13 up  3:36,  3 users,  load average: 4.76, 3.13, 2.02
Tasks: 193 total,   4 running, 189 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.3 us,  6.2 sy,  0.0 ni, 93.1 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu1  : 12.5 us, 87.5 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st  # CPU1被占用
%Cpu2  :  0.3 us,  4.7 sy,  0.0 ni, 94.6 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu3  : 16.0 us, 84.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st  # CPU3被占用

说明:可以看到只有CPU1和CPU3被占用,证明CPU绑定生效

5. Block IO限制

5.1 核心Block IO参数

参数 功能 示例 说明
--blkio-weight IO相对权重 --blkio-weight 100 10-1000,默认500
--blkio-weight-device 设备特定权重 --blkio-weight-device="/dev/sda:200" 针对特定设备的权重
--device-read-bps 读取带宽限制 --device-read-bps="/dev/sda:1mb" 限制读取速度
--device-write-bps 写入带宽限制 --device-write-bps="/dev/sda:1mb" 限制写入速度
--device-read-iops 读取IOPS限制 --device-read-iops="/dev/sda:100" 限制读取操作次数
--device-write-iops 写入IOPS限制 --device-write-iops="/dev/sda:100" 限制写入操作次数

5.2 Block IO限制实践示例

示例1:IO权重对比测试

用途:演示不同IO权重容器的磁盘访问优先级

终端1:启动权重为100的容器

bash 复制代码
[root@hrz3 ~]# docker run --name a1 -it --rm --blkio-weight 100 centos:7

终端2:启动权重为1000的容器

bash 复制代码
[root@hrz3 ~]# docker run --name a2 -it --rm --blkio-weight 1000 centos:7

在两个容器中分别执行磁盘测试

在a1容器中执行

bash 复制代码
[root@4365499baaba /]# time dd if=/dev/zero of=test.out bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.891708 s, 1.2 GB/s

real    0m0.908s
user    0m0.000s
sys     0m0.765s

在a2容器中执行

bash 复制代码
[root@c30c3c7f1cc2 /]# time dd if=/dev/zero of=test.out bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.877454 s, 1.2 GB/s

real    0m0.878s
user    0m0.000s
sys     0m0.781s

说明oflag=direct参数绕过缓存直接写入磁盘,测试真实磁盘IO性能

示例2:写入带宽限制

用途:限制容器对磁盘的写入速度,防止IO密集型应用影响其他服务

bash 复制代码
[root@hrz3 ~]# docker run --name a3 -it --rm --device-write-bps /dev/sda:1mb centos:7

在容器内测试写入速度

bash 复制代码
[root@867b0d653cfb /]# time dd if=/dev/zero of=test.out bs=1M count=20 oflag=direct
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied, 0.0141288 s, 1.5 GB/s

real    0m0.015s
user    0m0.000s
sys     0m0.014s

注意:实际测试结果显示速度很快,这可能是因为:

  1. 系统缓存的影响
  2. 测试数据量较小
  3. 需要更长时间的测试才能看到限制效果

6. 关键概念总结

6.1 Linux Namespace类型

Linux内核实现了6种Namespace用于资源隔离:

  • UTS: 主机名和域名隔离
  • IPC: 进程间通信隔离
  • PID: 进程ID隔离
  • Mount: 文件系统挂载点隔离
  • User: 用户和用户组隔离
  • Network: 网络设备、端口等隔离

6.2 资源限制重要说明

重要理解

  1. Docker容器资源限制只是对容器实际使用资源进行限制
  2. 从容器内部视角看,它认为自己的资源与宿主机相同
  3. 资源限制通过cgroups机制在宿主机层面实现
  4. 合理设置资源限制可以防止"吵闹的邻居"问题,保证系统稳定性

6.3 最佳实践建议

生产环境资源限制建议

  • 所有容器都应该设置适当的内存限制
  • 关键业务容器应设置CPU权重保障性能
  • IO密集型应用应设置磁盘IO限制
  • 使用资源监控工具定期检查资源使用情况
  • 根据实际业务需求动态调整资源限制

通过合理配置这些资源限制参数,可以确保Docker容器在共享的宿主机环境中稳定运行,避免单个容器过度消耗资源影响其他服务。

相关推荐
yalipf4 小时前
忘记密码更改ubuntu18.08的密码--前提是要知道用户名work
linux·运维·ubuntu
雲帝5 小时前
1panel docker开启swap内存
运维·docker·容器
web安全工具库6 小时前
Makefile 模式规则精讲:从 %.o: %.c 到静态模式规则的终极自动化
linux·运维·c语言·开发语言·数据库·自动化
qq_264220896 小时前
k8s-Pod详解
云原生·容器·kubernetes
小诸葛的博客7 小时前
k8s localpath csi原理
云原生·容器·kubernetes
Do_GH12 小时前
【Linux】07.Ubuntu开发环境部署
linux·运维·ubuntu
勤源科技13 小时前
全链路智能运维中的实时流处理架构与状态管理技术
运维·架构
tryCbest13 小时前
Linux使用Docker部署项目后期更新
linux·运维·docker
忧郁的橙子.14 小时前
十六、kubernetes 1.29 之 集群安全机制
安全·容器·kubernetes