Docker cgroup

Docker 利用 cgroup 来限制容器的 CPU、内存、I/O、网络等资源。你可以手动用 cgroup 创建一个 类似 Docker 的受限进程,来理解 Docker 的底层封装。


最简单的 cgroup + namespace 实现容器

Docker 不仅仅是 cgroup,还用到了 namespace(名字空间),所以我们用 unshare + cgroup 手写一个最小的 "容器"。


Demo 1:用 cgroup 限制进程

步骤 1:创建 cgroup


bash

复制编辑

mkdir /sys/fs/cgroup/demo_container

步骤 2:限制资源

(1) 限制 CPU 只能用 50%

bash

复制编辑

echo "50000 100000" > /sys/fs/cgroup/demo_container/cpu.max

(2) 限制内存最多 100MB

bash

复制编辑

echo "100000000" > /sys/fs/cgroup/demo_container/memory.max

(3) 限制进程数最多 5 个

bash

复制编辑

echo "5" > /sys/fs/cgroup/demo_container/pids.max


步骤 3:启动进程,并加入 cgroup


bash

复制编辑

sleep 99999 & echo $! > /sys/fs/cgroup/demo_container/cgroup.procs

这个进程 只能用 50% CPU、100MB 内存,最多开 5 个子进程,跟 Docker 容器的资源限制类似!


Demo 2:用 namespace 实现隔离

Docker 还用 namespace 实现进程隔离,我们可以手写一个最小容器。

步骤 1:启动隔离的进程


bash

复制编辑

unshare -m -u -i -n -p -f --mount-proc bash

解释:

  • -m → 隔离 挂载点(类似 chroot
  • -u → 隔离 主机名
  • -i → 隔离 进程 ID
  • -n → 隔离 网络
  • -p → 隔离 PID
  • -f → 让 bash 变成新 namespace 的第一个进程
  • --mount-proc → 挂载新的 /proc

步骤 2:修改 hostname


bash

复制编辑

hostname my-container

现在 hostname 在这个进程里变了,外面不受影响!

步骤 3:查看进程


bash

复制编辑

ps aux

你会发现进程 ID 跟主机不一样,说明它在自己的 PID namespace 里,和 Docker 容器行为一致!


Docker 是怎么用 cgroup 和 namespace 的?

当你运行:


bash

复制编辑

docker run -it --memory=100m --cpus=0.5 ubuntu bash

Docker 其实做了三件事:

  1. 创建 cgroup
    • memory.max=100m
    • cpu.max=50%
    • pids.max=无限制
  2. 创建 namespace
    • mount namespace(隔离文件系统)
    • network namespace(隔离网络)
    • pid namespace(隔离进程)
  3. 运行进程
    • /bin/bash 作为容器的第一个进程

你可以用 docker inspect <容器 ID> 看到 cgroup 具体路径,比如:


bash

复制编辑

cat /sys/fs/cgroup/memory/docker/<容器ID>/memory.max

会发现它和 docker run --memory=100m 对应上了。


总结

  • cgroup:Docker 用它 限制 CPU、内存、I/O
  • namespace:Docker 用它 隔离进程、网络、文件系统
  • unionfs:Docker 用它 提供分层镜像

unshare + cgroup 手写一个最小的容器,感受 Docker 的底层封装

### 修改 DockerCGroup 配置 Docker 通过 Cgroup(Control Groups)来实现对容器资源的配额和控制,包括 CPU、内存、磁盘 I/O 等资源的限制和度量。用户可以通过修改 DockerCgroup 设置,调整容器的资源使用策略。 要更改 DockerCGroup 设置,通常涉及两个层面的配置:一是系统级的 Cgroup 版本选择(如切换 cgroup v1 或 v2),二是 Docker 服务对 Cgroup 的具体资源限制配置。 #### 更改 Cgroup 版本 Linux 系统支持两种版本的 Cgroup:v1 和 v2。Docker 默认支持两种版本,但某些功能在 v2 下可能受限。如果需要切换为 cgroup v1,需修改 GRUB 配置: ```bash sudo vim /etc/default/grub ``` 将以下参数添加到 `GRUB_CMDLINE_LINUX` 中: ``` systemd.unified_cgroup_hierarchy=0 ``` 更新 GRUB 配置并重启系统: ```bash sudo update-grub sudo reboot ``` 该配置会禁用统一的 cgroup v2 层级,启用传统的 cgroup v1 模式 [^1]。 #### 配置 Docker 使用的 Cgroup 资源限制 Docker 默认使用 `cgroupfs` 驱动来管理容器的资源限制。可以通过修改 Docker 的守护进程配置文件 `/etc/docker/daemon.json` 来指定 Cgroup 相关的资源限制策略。例如,限制容器的内存使用: ```json { "default-ulimits": { "memlock": { "Name": "memlock", "Hard": -1, "Soft": -1 } }, "exec-opts": ["native.cgroupdriver=cgroupfs"] } ``` 还可以为特定容器设置资源限制。例如,启动一个容器时限制其内存为 20MB: ```bash docker run -d --name test-mem --memory="20m" stress --vm 1 --vm-bytes 50M --vm-keep ``` 该命令启动一个容器,并限制其最大内存为 20MB,即使尝试分配 50MB 内存,也会受到 Cgroup 的限制 [^3]。 #### 手动操作 Cgroup 策略 如果需要更细粒度地控制资源,可以直接操作 Cgroup 文件系统。例如,创建一个 cgroup 并设置内存限制: ```bash sudo mkdir /sys/fs/cgroup/memory/mygroup echo 20971520 > /sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes ``` 将某个进程加入该组: ```bash echo <pid> > /sys/fs/cgroup/memory/mygroup/tasks ``` 这样可以实现对特定进程的资源控制,适用于调试或高级用例 [^3]。 #### 注意事项 - 修改 Cgroup 设置后,必须重启 Docker 服务以使配置生效: ```bash sudo systemctl restart docker ``` - 如果使用 systemd 作为 Cgroup 驱动(推荐),需确保 Docker 配置中包含: ```json { "exec-opts": ["native.cgroupdriver=systemd"] } ``` 这可以避免与系统管理工具之间的冲突 [^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值