Files
docker_practice/18_security/18.2_control_group.md
2026-02-25 21:06:21 -08:00

103 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 18.2 控制组
控制组 (Cgroups) Linux 容器机制的另外一个关键组件如果说命名空间 (Namespace) 决定了容器能**看到**什么那么控制组就决定了容器能**使用**多少资源
在安全领域中资源的不可用性本身就是一种安全威胁控制组负责实现资源的审计和限制这对于抵御资源耗尽型攻击如拒绝服务攻击 DoS至关重要
### 18.2.1 为什么资源限制关乎安全
默认情况下Docker 容器对系统资源的使用是没有限制的一个容器理论上可以使用宿主机所有的 CPU 计算能力吃光所有的内存耗尽所有的系统 PID
想象一下以下场景
- 一个恶意用户向你暴露在公网的应用发起海量并发请求
- 应用程序逻辑中存在内存泄漏漏洞
- 黑客在入侵容器后在里面运行了挖矿木马程序
如果没有 Cgroups 的限制某个容器内的异常行为或恶意攻击将会榨干宿主机的资源导致宿主机上其他健康的容器甚至 Docker 守护进程自身因为 OOMOut Of Memory崩溃或 CPU 饥饿而停止响应
### 18.2.2 核心资源限制实战
为了确保多租户平台如公有或私有的 PaaS 平台的稳定性或者在生产环境防止服务级联故障我们要养成在启动容器时**显式声明资源上限**的习惯
#### 1. 内存限制
限制内存可以防止应用程序因内存泄漏或恶意载荷导致宿主机 OOM
**关键参数**
- `-m, --memory=""`硬限制容器可使用的最大内存量
- `--memory-swap=""`限制容器可使用的内存与 Swap 总量
**实战示例**
限制容器最多只能使用 512MB 内存并且禁用 Swap memory memory-swap 设置成一样的值即可
```bash
$ docker run -d \
--name web_app \
--memory="512m" \
--memory-swap="512m" \
nginx:alpine
```
如果该容器内的应用尝试分配超过 512MB 的内存该进程将会被内核的 OOM Killer 杀掉但绝不会波及到宿主机的其他部分
#### 2. CPU 限制
限制 CPU 可以防止个别计算密集型的容器垄断 CPU 时间片保证系统的调度公平性
**关键参数**
- `--cpus=<value>`指定容器可以使用的 CPU 核心数量可以是小数
- `-c, --cpu-shares=0`软限制设置容器使用 CPU 的相对权重默认是 1024
**实战示例**
限制容器最多使用 1.5 CPU 核心的算力
```bash
$ docker run -d \
--name worker_app \
--cpus="1.5" \
busybox \
md5sum /dev/urandom
```
即使上面的命令是一个死循环的哈希计算进程容器也永远无法吃满双核 CPU 系统的全部算力
#### 3. 进程数限制
进程炸弹Fork Bomb是一种典型的拒绝服务攻击方式它通过不断 `fork()` 新进程来耗尽系统的进程表条目导致系统无法创建任何新任务
**关键参数**
- `--pids-limit=<number>`限制容器内允许创建的最大进程数
**实战示例**
一个常规的 Web 服务进程数通常在几十到上百之间我们可以设定一个合理的上限来防范 Fork 炸弹
```bash
$ docker run -d \
--name app_service \
--pids-limit=100 \
python:alpine python app.py
```
当容器内的进程总数达到 100 任何尝试派生新进程的操作都会失败并返回 `Resource temporarily unavailable`从而挫败相关的攻击行为
### 18.2.3 最佳实践建议
在生产环境中不仅要在单机使用 Docker 命令时设置这些参数更应当在集群编排工具中将资源配额制度化
例如 Kubernetes 强烈建议为每个 Pod 设置 `requests` `limits`
```yaml
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
```
通过 Cgroups 的资源边界控制你可以从根本上切断一条导致整个系统雪崩的脆弱链路这也进一步使得 Docker 以及容器技术成为了现代高可用服务的基础设施首选