概述

在平时本地运行一些资源消耗比较高的容器的时候,你可能有时会不爽一个容器就把机器搞得卡地不行,这个时候你就想将这个容器关掉了,但是有不能关,不知道你有没有这个困扰,至少我是有的,所以这里就介绍一下 Docker 怎么限制容器的资源消耗。

CPU

Docker 限制 CPU 有几个维度:

  • 简单:限制 CPU 核数,这个很好理解
    • 使用方式:[root@liqiang.io]# docker run --cpus=4 表示允许使用 4 个核心
  • 复杂:基于 CPU 时间片的限制,docker 是基于 CFS 的调度实现,这是老版本使用的,新版本都推荐使用简单的方式
    • 使用方式:[root@liqiang.io]# docker run --cpu-period=100000 --cpu-quota=200000 表示每个 CPU 使用的时间是 100 ms,这个容器最多使用 200ms(相当于限制了 2 个核,但是不是绝对)

但是上面这两个在 Go 程序中有问题,当用 Go 代码获取 CPU Number 的时候,会获取到宿主机上的所有 core,这对于 Go 来说不合理。

除此之外,docker 还提供了其他的 cpu 选项,不细说了,简单描述一下:

  • cpuset-cpus:绑定容器只能使用哪些核
  • cpu-shares:当多个容器抢 CPU 时间时,可以通过这个值按比例分配 CPU 时间

Docker container 有个问题,那就是在 VM 里面运行 Container,当你扩容了 VM 之后,Container 的 CPU 核数并不会增加,解决方式是手动修改 container 的 cgroup 配置:

内存

内存的限制选项也好几个,我挑 4 个有意义的说一下吧:

  • 限制内存大小:[root@liqiang.io]# docker run -m 200m 只能使用 200M 的内存,多了就 OOM
  • 限制内存软大小:[root@liqiang.io]# docker run --memory-reservation 200m 在系统内存紧张的时候限制使用 200M 的内存,多了也没什么,这其实比较鸡肋
  • 内核内存使用限制:[root@liqiang.io]# docker run --kernel-memory 200m 只能使用 200m 的内核内存,多了就 OOM
  • OOM 设置:[root@liqiang.io]# docker run --oom-kill-disable 进程超内存了不要 OOM,那怎么办,就申请不到内存咯

磁盘

限制磁盘大小

默认 Docker 只能使用 10 G 的 Volume,如果想要更大一些,需要修改启动参数:

  1. [root@liqiang.io]# cat /etc/docker/daemon.json
  2. {
  3. "storage-driver": "devicemapper",
  4. "storage-opts": [
  5. "dm.basesize=40G"
  6. ]
  7. }

限制磁盘 IO

这个选项就比较多了,直接看下列表吧:

  1. --blkio-weight uint16 Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
  2. --blkio-weight-device list Block IO weight (relative device weight) (default [])
  3. --device-read-bps list Limit read rate (bytes per second) from a device (default [])
  4. --device-read-iops list Limit read rate (IO per second) from a device (default [])
  5. --device-write-bps list Limit write rate (bytes per second) to a device (default [])
  6. --device-write-iops list Limit write rate (IO per second) to a device (default [])

使用示例:

  1. # 这是限制磁盘的
  2. [root@liqiang.io]# docker run -it --rm --device-write-bps /dev/sda:50kb ubuntu /bin/bash
  3. root@9eab6510cccf:/# time dd if=/dev/zero of=test.out bs=1M count=1024 oflag=direct
  4. 1048576 bytes (1.0 MB, 1.0 MiB) copied, 20.4818 s, 51.2 kB/s
  5. # 这是限制文件的
  6. [root@liqiang.io]# docker run -it --rm --device-write-bps /dev/dm-x:50mb centos /bin/bash

网络

网络的需求就太常见了,但是根据我查找资料,Docker 官方似乎还没有支持这个功能,但是,有网友简单地用 tc 命令直接在容器内部实现了,操作方式为:

  1. [root@liqiang.io]# docker run --rm -it centos:7 /bin/sh
  2. tc qdisc add dev eth0 handle 1: ingress
  3. tc filter add dev eth0 parent 1: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate 1mbit burst 10k drop flowid :1
  4. tc qdisc add dev eth0 root tbf rate 1mbit latency 25ms burst 10k`

这个可以用来限制 eth0 interface 的速度为 1M,具体可以参照:How can I rate limit network traffic on a docker container

Ref