2、Docker资源限制核心参数:CPU、内存与磁盘I/O
资源限制这件事,说白了就是给容器戴上「紧箍咒」。
我见过太多线上事故了——某个容器把宿主机CPU吃满,其他服务全部瘫痪。嗯,这就是没做资源限制的后果。今天咱们就把Docker资源限制的三个核心维度讲透:CPU、内存、磁盘I/O。
2.1 CPU限制:别让一个容器吃掉所有核
CPU限制有三个关键参数,我习惯把它们分成「硬限制」和「软限制」两类。
2.1.1 --cpus:最直观的硬限制
这个参数直接限制容器能使用多少个CPU核心。比如:
docker run --cpus="1.5" nginx
意思是这个容器最多用1.5个核。你想想看,如果宿主机是4核,那它最多占37.5%的CPU时间。
2.1.2 --cpu-shares:相对权重,不是绝对限制
这个参数很多人理解错了。它不是限制CPU上限,而是设置权重。
docker run --cpu-shares=512 service-a
docker run --cpu-shares=1024 service-b
当CPU资源充足时,两个容器都能跑满。只有CPU争抢时,service-b会得到两倍于service-a的时间片。
2.1.3 --cpuset-cpus:绑定到特定核心
这个参数把容器绑定到指定的CPU核心上运行。
docker run --cpuset-cpus="0,2" nginx
为什么需要这个?
我遇到过一种情况:某些CPU核心因为NUMA架构,访问特定内存更快。把容器绑定到这些核心上,性能能提升10%~20%。
实战建议:
- 普通Web服务:用--cpus就够了
- 数据库类:考虑--cpuset-cpus绑定到物理核心
- 批处理任务:用--cpu-shares做优先级区分
2.2 内存限制:OOM Killer的最后一刀
内存限制比CPU更严格。CPU可以超卖,内存不行。一旦超了,系统会直接杀掉进程。
2.2.1 -m / --memory:硬性上限
docker run -m 512m nginx
容器最多用512MB内存。超了怎么办?会被OOM Killer干掉。
我记得有一次,一个Node.js应用因为内存泄漏,连续被杀了三次。后来我加了--memory-swap限制,才把问题暴露出来。
2.2.2 --memory-swap:内存+交换分区的总上限
这个参数很多人搞混。它控制的是「内存+交换分区」的总量。
docker run -m 512m --memory-swap=1g nginx
意思是:内存最多512MB,交换分区最多512MB,总共1GB。
2.2.3 --memory-reservation:软限制
这个参数是「建议值」,不是硬限制。
docker run -m 1g --memory-reservation=512m nginx
当宿主机内存充足时,容器可以用到1GB。当内存紧张时,Docker会尝试把容器内存压缩到512MB以内。
嗯,这个参数我一般用在混部场景。比如把离线任务和在线任务混在一起,离线任务设一个较低的reservation,在线任务设高一些。
2.3 磁盘I/O限制:别让日志把磁盘打满
磁盘I/O限制是最容易被忽略的。我见过一个容器疯狂写日志,把整个宿主机的磁盘IOPS打满,其他容器全部卡死。
2.3.1 --blkio-weight:I/O优先级
和--cpu-shares类似,这是相对权重。
docker run --blkio-weight=500 service-a
docker run --blkio-weight=1000 service-b
当磁盘I/O争抢时,service-b得到两倍于service-a的I/O时间。
2.3.2 --device-read-bps / --device-write-bps:读写速率限制
这个参数直接限制每秒读写多少字节。
docker run --device-write-bps /dev/sda:10mb nginx
意思是:往/dev/sda写数据时,速度不超过10MB/s。
为什么要限制?
我曾经有个日志采集容器,每秒写200MB日志到磁盘。结果数据库容器因为磁盘带宽被抢,查询延迟从2ms飙升到500ms。后来我加了--device-write-bps=50mb,问题解决。
2.3.3 --device-read-iops / --device-write-iops:IOPS限制
除了带宽,还可以限制每秒I/O操作次数。
docker run --device-write-iops /dev/sda:1000 nginx
这个参数对SSD特别有用。因为SSD虽然带宽大,但IOPS有限。限制IOPS可以防止小文件读写把磁盘打满。
总结一下我的资源规划公式:
| 资源类型 | 硬限制 | 软限制 | 适用场景 |
|---|---|---|---|
| CPU | --cpus | --cpu-shares | 在线服务用硬限制,离线任务用软限制 |
| 内存 | -m | --memory-reservation | 核心服务用硬限制,混部用软限制 |
| 磁盘I/O | --device-*-bps | --blkio-weight | 日志类用bps限制,数据库用weight |
最后说一句:资源限制不是设了就完事了。我建议每个容器都加上Prometheus监控,观察实际使用量。如果发现某个容器长期接近上限,就该考虑扩容了。
嗯,下一章咱们聊聊如何用这些参数做成本优化。说白了,资源限制做得好,云账单能省30%以上。