Docker实战:使用CGroups控制资源

文章目录

  • [1. 实战概述](#1. 实战概述)
  • [2. 实战步骤](#2. 实战步骤)
    • [2.1 构建带stress-ng的alpine镜像](#2.1 构建带stress-ng的alpine镜像)
    • [2.2 设置CPU周期与配额](#2.2 设置CPU周期与配额)
      • [2.2.1 提出任务](#2.2.1 提出任务)
      • [2.2.2 完成任务](#2.2.2 完成任务)
      • [2.2.3 压力测试](#2.2.3 压力测试)
    • [2.3 设置容器CPU使用率](#2.3 设置容器CPU使用率)
      • [2.3.1 提出任务](#2.3.1 提出任务)
      • [2.3.2 完成任务](#2.3.2 完成任务)
    • [2.4 设置容器内存配额](#2.4 设置容器内存配额)
      • [2.4.1 提出任务](#2.4.1 提出任务)
      • [2.4.2 完成任务](#2.4.2 完成任务)
      • [2.4.3 压力测试](#2.4.3 压力测试)
    • [2.5 设置容器写磁盘的带宽](#2.5 设置容器写磁盘的带宽)
      • [2.5.1 提出任务](#2.5.1 提出任务)
      • [2.5.2 完成任务](#2.5.2 完成任务)
  • [3. 实战总结](#3. 实战总结)

1. 实战概述

  • 本次实战基于 EulerOS 系统,使用自建 alpine-stress 镜像,依次完成 CPU 周期配额、CPU 权重分配、内存限制及磁盘 I/O 带宽控制等容器资源管理实验。通过 docker run 参数结合 stress-ng 压测工具,验证了 CGroups 对计算与存储资源的调度能力,同时揭示了在 cgroup v2 环境下磁盘限速的局限性。

2. 实战步骤

2.1 构建带stress-ng的alpine镜像

  • 执行命令:vim Dockerfile

  • 执行命令:docker build -t alpine-stress .

  • 执行命令:docker run --rm alpine-stress stress-ng --cpu 1 --timeout 10s

  • 结果说明 :执行成功,stress-ng 在 10 秒内对 1 个 CPU 核心施加压力,系统内存充足未触发 OOM,验证了容器资源压测工具正常工作。

2.2 设置CPU周期与配额

2.2.1 提出任务

  • 利用alpine-stress镜像生成容器,设置容器调度的周期为50000,将容器在每个周期内的CPU配额设置为25000

2.2.2 完成任务

  • 执行命令:docker run -it --cpu-period=50000 --cpu-quota=25000 alpine-stress sh
  • 结果说明 :容器以 --cpu-period=50000--cpu-quota=25000 启动,限制其最多使用 50% 的 CPU 时间(即 0.5 核),成功实现 CPU 资源控制,验证了 CGroups 对容器 CPU 占用的精细化管理。
  • 参数说明--cpu-period--cpu-quota 是基于 Linux 内核 CFS(Completely Fair Scheduler) 的机制;默认情况下,--cpu-period=100000(100ms), --cpu-quota=-1(不限制);本任务中, CPU \text{CPU} CPU限制 = quota period = 25000 50000 = 0.5 = \displaystyle\frac{\text{quota}}{\text{period}} = \frac{25000}{50000} = 0.5 =periodquota=5000025000=0.5核

2.2.3 压力测试

  1. 在容器内启动 CPU 压力负载
    • 执行命令:stress-ng --cpu 4 --timeout 30s --metrics-brief
    • 结果说明 :在 CPU 配额限制为 0.5 核的容器中运行 stress-ng --cpu 4,成功完成 30 秒压测,bogo ops 达 988.64/s,验证了多线程负载下 CGroups 对 CPU 使用率的有效控制,实际占用未突破配额限制。
  2. 在宿主机监控 CPU 使用情况
    • 在压力负载测试期间新开Eluer终端,执行命令:docker stats
    • 结果说明 :容器 thirsty_sammet 的 CPU 使用率稳定在 49.56%,接近设定的 50% 配额上限,验证了 --cpu-period=50000 --cpu-quota=25000 对 CPU 资源的精确限制,成功实现 CGroups 的精细化调度控制。

2.3 设置容器CPU使用率

2.3.1 提出任务

  • 利用alpine-stress镜像生成两个容器,设置第二个容器的CPU使用率是第一个容器的两倍

2.3.2 完成任务

  1. 终端1:启动第一个容器(CPU 权重 1024,绑定到CPU 0)

    • 执行命令:docker run -it --name cpu-test-1 --cpuset-cpus=0 --cpu-shares=1024 alpine-stress stress-ng --cpu 1 --timeout 60s
    • 结果说明 :容器 cpu-test-1 成功在 CPU 0 上运行,执行了 60 秒的单线程压力测试,验证了其被绑定至指定 CPU 核心并正常工作,为后续多容器 CPU 资源竞争实验奠定了基础。
  2. 终端2:启动第二个容器(CPU 权重 2048,绑定到CPU 0)

    • 执行命令:docker run -it --name cpu-test-2 --cpuset-cpus=0 --cpu-shares=2048 alpine-stress stress-ng --cpu 1 --timeout 60s
    • 结果说明 :容器 cpu-test-2 成功绑定至 CPU 0 并执行 60 秒单线程压测,验证其在指定核心上运行正常,为后续与同核容器进行 CPU 权重对比实验做好准备。
  3. 终端3:在两个容器运行期间查看容器状态

    • 执行命令:docker stats
    • 结果说明 :在 CPU 0 上运行的两个容器中,cpu-test-2 的 CPU 使用率为 66.82%,cpu-test-1 为 33.36%,比例接近 2:1,验证了 --cpu-shares=20481024 在资源竞争下实现 CPU 时间按权重分配的有效性。

2.4 设置容器内存配额

2.4.1 提出任务

  • 利用alpine-stress镜像生成容器,设置容器使用的最大内存为256MB

2.4.2 完成任务

  • 执行命令:docker run -it --name test-memory --memory="256m" --memory-swap="256m" alpine-stress sh

  • 结果说明 :容器 test-memory 成功以 256MB 内存和 256MB 总虚拟内存(禁用 swap)启动,验证了 --memory-swap 参数配置生效,为后续触发 OOM 的内存压测实验做好准备。

2.4.3 压力测试

  • 在容器内执行命令:stress-ng --vm 1 --vm-bytes 300M --timeout 30s,超过256M内存限制
  • 在终端2上执行命令:docker ps -a --filter "name=test-memory",获取容器ID:ca3845b91025
  • 执行命令:docker inspect ca3845b91025 | grep -i oom
  • 结果说明 :容器 ca3845b91025OOMKilled 字段为 true,表明其因内存超限被内核 OOM Killer 强制终止,验证了在严格内存限制(如 --memory=256m --memory-swap=256m)下,容器无法分配超过配额的内存,成功触发资源保护机制。

2.5 设置容器写磁盘的带宽

2.5.1 提出任务

  • 利用alpine-stress镜像生成两个容器,设置第二个容器写磁盘的带宽是第一个容器的两倍

2.5.2 完成任务

  1. 获取根文件系统设备
    • 执行命令:ROOT_DEV=$(readlink -f /dev/mapper/openeuler-root)
    • 执行命令:echo $ROOT_DEV
  2. 启动第一个容器(写带宽限制为 10 MB/s)
    • 执行命令:docker run -d --name io-test-1 --device-write-bps /dev/dm-0:10mb alpine-stress sh -c "dd if=/dev/zero of=/tmp/test1 bs=1M count=100 oflag=direct"
  3. 启动第二个容器(写带宽限制为 20 MB/s)
    • 执行命令:docker run -d --name io-test-2 --device-write-bps /dev/dm-0:20mb alpine-stress sh -c "dd if=/dev/zero of=/tmp/test2 bs=1M count=100 oflag=direct"
  4. 验证是否生效
    • 执行命令:docker logs io-test-1docker logs io-test-2
    • 结果说明 :尽管设置了 --device-write-bps /dev/dm-0:10mb20mb 的写带宽限制,但容器实际写入速度分别达到 1.2GB/s 和 2.1GB/s,远超设定值。这表明在 cgroup v2 环境下,Docker 的 --device-write-bps 参数未生效,无法实现对磁盘 I/O 带宽的精确控制,需改用其他方式(如 ionice)进行相对优先级管理。

3. 实战总结

  • 本次实战系统验证了 Docker 容器在 CPU、内存和磁盘 I/O 三个维度的资源控制机制。CPU 方面,通过 --cpu-period/--cpu-quota 精确限制核数,--cpu-shares 实现多容器按权重分配 CPU 时间,docker stats 显示比例接近理论值;内存方面,设置 --memory=256m 并禁用 swap 后,超限进程被 OOM Killer 正确终止,证明内存隔离有效;磁盘 I/O 方面,尽管配置 --device-write-bps,但因系统启用 cgroup v2,该参数失效,实际写速达 GB/s 级。最终改用 ionice 可实现相对优先级控制。实验表明:CPU 与内存限制可靠,而磁盘带宽精确限速在现代 Linux 发行版中需依赖替代方案
相关推荐
Fortune_yangyang2 小时前
docker 搭建lnmp
运维·docker·容器
峰顶听歌的鲸鱼2 小时前
16.docker:存储
运维·笔记·docker·容器·云计算
无双@2 小时前
Github BettaFish 微舆docker部署教程 —— 打造你的八卦天团!
docker·容器·开源·github·微舆·bettafish
2301_8000509912 小时前
docker
运维·docker·容器
查尔斯-BUG万象集14 小时前
解决 OceanBase CE 启动失败:OBD-2002: Failed to start 0.0.0.0 observer
docker·k8s·oceanbase
好奇的菜鸟15 小时前
Docker 一键启动:打造高效的 Java 微服务开发环境
java·docker·微服务
汪碧康15 小时前
【k8s-1.34.2安装部署】五.worker端containerd2.2.1、kubelet-1.34.2安装
docker·云原生·容器·kubernetes·jenkins·kubelet·xkube
小趴菜不能喝16 小时前
Docker 网络
网络·docker·容器
忙里偷闲学python17 小时前
docker
运维·docker·容器