Docker核心原理:Cgroups
Cgroups 是 Linux 内核提供的一种强大的机制,用于对一组进程(process groups)进行资源管理、和限制。
对于 Docker 来说,Cgroups 是实现容器资源隔离和管理的关键基石。
没有 Cgroups,Docker 就无法有效地限制容器的资源使用,也就无法保证多容器环境下的稳定性和性能。
为什么需要Cgroups?
因为:所有的应用程序都运行在同一个操作系统内核之上,共享所有的系统资源(CPU、内存、磁盘 I/O、网络带宽等)。
如果某个应用程序出现资源消耗过高的情况(例如,一个死循环占用了大量 CPU,或者一个内存泄漏导致内存耗尽)。
它可能会无限制地吞噬系统资源,导致其他应用程序运行缓慢甚至崩溃,最终可能拖垮整个宿主机。
虽然 Namespaces 提供了进程、网络等方面的隔离,但如果没有 Cgroups 的资源限制。
一个恶意、或有缺陷的容器,仍然可能通过过度消耗资源来影响其他容器甚至宿主机。
因此,需要Cgroups来限制资源。
Cgroups的工作原理
Cgroups 的核心思想:是将任务(进程)组织成层级的树状结构。
并在树的每个节点上附加各种子系统,从而实现对该节点下所有任务的资源控制和监控。
对应的控制组结构如下:
/sys/fs/cgroup/ ├── memory/docker/<container-id>/ ├── cpu/docker/<container-id>/ ├── blkio/docker/<container-id>/ └── ...
每个子系统下都有一份以容器 ID 命名的目录,用来记录资源配额与使用情况。
Cgroups 将系统资源划分为不同的子系统(Subsystem),每个子系统控制一种资源,例如:
子系统名称 | 控制资源 | 功能举例 |
---|---|---|
cpu |
CPU 时间分配 | 限制容器最大 CPU 使用量 |
cpuset |
指定 CPU 核 | 指定容器只能运行在哪些 CPU 上 |
memory |
内存使用限制 | 限制容器内存上限、防止 OOM |
blkio |
磁盘 IO 限制 | 控制容器读写磁盘的带宽和速度 |
net_cls |
网络带宽管理 | 给容器打网络流量标签,用于限速 |
devices |
设备访问控制 | 限制容器访问特定硬件设备 |
举几个例子:
CPU 限制
通过 cpu.shares
设置容器进程的 CPU 时间片权重,或使用 cpu.cfs_quota_us
设置使用配额。
# 只允许使用一个核 docker run --cpus=1 ...
表示:只允许使用一个核。
内存 限制
通过 memory.limit_in_bytes
设置容器可用的最大内存,超过后触发 OOM。
docker run --memory=256m ...
总之,Docker 之所以能做到“限制谁、限制多少、怎么限制”。
核心依赖的就是 Linux Cgroups,它是实现资源隔离与弹性伸缩的基石技术。