2-7-Docker的系统资源限制及验证
默认情况下 , Docker容器是没有资源限制的 , 它会尽可能地使用宿主机能够分配给它的资源。如果不对容器资源进行限制 , 容器之间就会相互影响 , 一些占用硬件资源较高的容器会吞噬掉所有的硬件资源 , 从而导致其它容器无硬件资源可用 , 发生停服状态。 Docker提供了限制内存 , CPU或磁盘IO的方法 , 可以对容器所占用的硬件资源大小以及多少进行限制 , 我们在使用docker create创建一个容器或者docker run运行一个容器的时候就可以来对此容器的硬件资源做限制。
Docker通过cgroup来控制容器使用的资源配额 , 包括 CPU、内存、磁盘三大方面 , 基本覆盖了常见的资源配额和使用量控制。
1. 内存限制
1.1 OOM(Out of Memory Exception)
对于Linux主机 , 如果没有足够的内容来执行其他重要的系统任务 , 将会抛出OOM (Out of Memory Exception, 内存溢出、内存泄漏、内存异常 ) , 随后系统会开始杀死进程以释放内存 , 凡是运行在宿主机的进程都有可能被kill , 包括Dockerd和其它的应用程序 , 如果重要的系统进程被Kill , 会导致和该进程相关的服务全部宕机。通常越消耗内存比较大的应用越容易被kill , 比如 : mysql数据库 , java程序等
产生OOM异常时 , Dockerd尝试通过调整Docker守护程序上的OOM优先级来减轻这些风险 , 以便它比系统上的其他进程更不可能被杀死但是容器 的OOM优先级未调整 , 这使得单个容器被杀死的可能性比Docker守护程序或其他系统进程被杀死的可能性更大 , 不推荐通过在守护程序或容器上手动设置--oom -score-adj为极端负数 , 或通过在容器上设置 --oom-kill-disable来绕过这些安全措施
OOM 优先级机制 :
linux会为每个进程算一个分数 , 最终将分数最高的kill
/proc/PID/oom_score_adj: 范围为-1000到1000, 值越高容易被宿主机kill掉。如果将该值设置为-1000, 则进程永远不会被宿主机kernel kill/proc/PID/oom_adj: 范围为-17到+15, 取值越高越容易被干掉。如果是-17, 则表示不能被kill, 该设置参数的存在是为了和旧版本的Linux内核兼容。/proc/PID/oom_score: 这个值是系统综合进程的内存消耗量、CPU时间 [utime +、存活时间 (uptime – start time) ]和oom_adj计算出的进程得分 , 消耗内存越多得分越高 , 容易被宿主机kernel强制杀死
[root@harbor ~]# cat /proc/`pidof dockerd`/oom_score
0
[root@harbor ~]# cat /proc/`pidof dockerd`/oom_score_adj
-500
[root@harbor ~]# cat /proc/`pidof dockerd`/oom_adj
-81.2 容器内存限制
Docker可以强制执行硬性内存限制 , 即只允许容器使用给定的内存大小。Docker也可以执行非硬性内存限制 , 即容器可以使用尽可能多的内存 , 除非内核检测到主机上的内存不够用了。当单独使用或设置了多个选项时 , 其中一些选项会产生不同的效果。
大部分的选项取正整数 , 跟着一个后缀b , k , m , g , 表示字节 , 千字节 , 兆字节或千兆字节。
1.2.1 --memory-swap 设置
介绍
--memory-swap是一个修饰符标志 , 只有在--memory设置时才有意义。使用swap允许容器在容器耗尽可用的所有RAM时将多余的内存需求写入磁盘。对于经常将内存交换到磁盘的应用程序 , 性能会受到影响。它的设置会产生复杂的效果 :
如果
--memory-swap设置为正整数 , 那么这两个--memory和--memory-swap必须设置。--memory-swap表示可以使用的memory and swap, 并--memory控制非交换内存(物理内存)使用的量。所以如果--memory="300m"和--memory-swap="1g", 容器可以使用300m的内存和700m(1g - 300m)swap。如果
--memory-swap设置为0, 则忽略该设置 , 并将该值视为未设置。如果
--memory-swap设置为与值相同的值--memory , 并且--memory设置为正整数 , 则容器无权访问swap。请参考下面阻止容器使用交换。如果
--memory-swap未设置并--memory设置 , 则容器可以使用两倍于--memory设置的swap, 主机容器需要配置有swap。例如 , 如果设置--memory="300m"和--memory-swap未设置 , 容器可以使用300m的内存和600m的swap。如果
--memory-swap明确设置为-1, 则允许容器使用无限制swap, 最多可达宿主机系统上可用的数量。在容器内部 , 工具如
free报告主机的swap, 而不是容器内真正可用的内存。不要依赖free或类似工具来确定是否存在swap。
防止容器使用交换分区
如果
--memory和--memory-swap设置为相同的值 , 则可以防止容器使用swap。这是因为--memory-swap可以使用的memory and swap , 而--memory只是可以使用的物理内存量。
1.2.2 --memory-swappiness 设置
值为
0将关闭匿名页面交换。值
100将所有匿名页面设置为可交换。默认情况下 , 如果未设置
--memory-swappiness, 则值将从主机继承。
1.2.3 --kernel-memory 设置
内核内存限制以分配给容器的总内存表示。请考虑以下方案 :
无限内存 , 无限内核内存 : 这是默认设置。
无限内存 , 有限的内核内存 : 当所有
cgroup所需的内存量大于主机上实际存在的内存量时 , 这是合适的。您可以将内核内存配置为永远不会覆盖主机上可用的内容 , 而需要更多内存的容器需要等待它。有限的内存 , 无限的内核内存 : 整体内存有限 , 但内核内存不受限制。
有限的内存 , 有限的内核内存 : 限制用户和内核内存对于调试与内存相关的问题非常有用。如果容器使用意外数量的任一类型的内存 , 则内存不足而不会影响其他容器或主机。在此设置中 , 如果内核内存限制低于用户内存限制 , 则内核内存不足会导致容器遇到
OOM错误。如果内核内存限制高于用户内存限制 , 则内核限制不会导致容器遇到OOM。
当您打开任何内核内存限制时 , 主机会根据每个进程跟踪“高水位线”统计信息 , 因此您可以跟踪哪些进程 ( 在本例中为容器)正在使用多余的内存。通过/proc/<PID>/status在主机上查看 , 可以在每个过程中看到这一点。
2. CPU限制
一个宿主机 , 有几十个核心的CPU , 但是宿主机上可以同时运行成百上千个不同的进程用以处理不同的任务 , 多进程共用一个CPU的核心依赖计数就是为可压缩资源 , 即一个核心的CPU可以通过调度而运行多个进程 , 但是同一个单位时间内只能有一个进程在CPU上运行 , 那么这么多的进程怎么在CPU上执行和调度的呢?
实时优先级 :
0-99非实时优先级(
nice):-20-19, 对应100-139的进程优先级Linux kernel进程的调度基于CFS(Completely Fair Scheduler) , 完全公平调度
服务器资源密集型
CPU密集型的场景: 优先级越低越好 , 计算密集型任务的特点是要进行大量的计算 , 消耗CPU资源 , 比如计算圆周率、数据处理、对视频进行高清解码等等 , 全靠CPU的运算能力。IO密集型的场景: 优先级值高点 , 涉及到网络、磁盘IO的任务都是IO密集型任务 , 这类任务的特点是CPU消耗很少 , 任务的大部分时间都在等待IO操作完成 ( 因为IO的速度远远低于 CPU 和内存的速度) , 比如 Web 应用 , 高并发 , 数据量大的动态网站来说 , 数据库应该为IO密集型
2.1 CFS原理
cfs定义了进程调度的新模型 , 它给cfs_rq ( cfs的run queue)中的每一个进程安排一个虚拟时钟(vruntime)。如果一个进程得以执行 , 随着时间的增长 , 其vruntime将不断增大。没有得到执行的进程vruntime不变, 而调度器总是选择vruntime跑得最慢的那个进程来执行。这就是所谓的“完全公平”。为了区别不同优先级的进程 , 优先级高的进程vruntime增长得慢 , 以至于它可能得到更多的运行机会。 CFS的意义在于 , 在一个混杂着大量计算型进程和IO交互进程的系统中 , CFS调度器相对其它调度器在对待IO交互进程要更加友善和公平。
示例: 查看硬盘调度算法
[root@ubuntu1804 ~]#cat /sys/block/sda/queue/scheduler
noop deadline [cfq] 2.2 配置默认CFS调度程序
默认情况下 , 每个容器对主机的CPU周期的访问都是不受限制的。您可以设置各种约束 , 以限制给定容器对主机CPU周期的访问。大多数用户使用并配置 默认的CFS调度程序。在Docker 1.13及更高版本中 , 还可以配置 realtime scheduler。
3. IO 限制
Block IO是另一种可以限制容器使用的资源。Block IO指的是磁盘的读写 , docker可通过设置权重、限制bps和iops的方式控制容器读写磁盘的带宽
注:目前Block IO限额只对direct IO(不使用文件缓存)有效。
如何进行Block IO的限制?
默认情况下 , 所有容器能平等地读写磁盘 , 可以通过设置 --blkio-weight 参数来改变容器block IO的优先级。--blkio-weight 与 --cpu-shares 类似 , 设置的是相对权重值 , 默认为 500。在下面的例子中 , container_A 读写磁盘的带宽是container_B的两倍。
docker run -it --name container_A --blkio-weight 600 ubuntu
docker run -it --name container_B --blkio-weight 300 ubuntu如何对bps和iops进行限制?
bps是byte per second , 表示每秒读写的数据量。
iops 是io per second , 表示每秒的输入输出量(或读写次数)。
可通过以下参数控制容器的 bps 和 iops:
--device-read-bps, 限制读某个设备的 bps。--device-write-bps, 限制写某个设备的 bps。--device-read-iops, 限制读某个设备的 iops。--device-write-iops, 限制写某个设备的 iops。
对写bps进行限制的测试
限制容器写 /dev/sda 的速率为 30 MB/s。
docker run -it --device-write-bps /dev/sda:30MB centos:latest通过dd测试在容器中写磁盘的速度。因为容器的文件系统是在宿主机的/dev/sda上的 , 在容器中写文件相当于对宿主机/dev/sda进行写操作。另外 , oflag=direct 指定用 direct IO 方式写文件 , 这样 --device-write-bps 才能生效。
time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct参数说明如下:
if=file:输入文件名 , 缺省为标准输入of=file:输出文件名 , 缺省为标准输出ibs=bytes:一次读入 bytes 个字节(即一个块大小为 bytes 个字节)obs=bytes:一次写 bytes 个字节(即一个块大小为 bytes 个字节)bs=bytes:同时设置读写块的大小为 bytes , 可代替 ibs 和 obscount=blocks:仅拷贝blocks个块 , 每个块大小等于 ibs 指定的字节数
4. 压力测试
4.1 测试准备
stress-ng是一个压力测试工具 , 可以通过软件仓库进行安装 , 也提供了docker版本的容器
软件包安装, 安装源为
epel源[root@centos7 ~]#yum -y install stress-ng [root@ubuntu1804 ~]#apt -y install stress-ng容器安装
[root@centos7 ~]# docker pull lorel/docker-stress-ng Using default tag: latest latest: Pulling from lorel/docker-stress-ng [DEPRECATION NOTICE] Docker Image Format v1, and Docker Image manifest version 2, schema 1 support will be removed in an upcoming release. Suggest the author of docker.io/lorel/docker-stress-ng:latest to upgrade the image to the OCI Format, or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/ c52e3ed763ff: Pull complete a3ed95caeb02: Pull complete 7f831269c70e: Pull complete Digest: sha256:c8776b750869e274b340f8e8eb9a7d8fb2472edd5b25ff5b7d55728bca681322 Status: Downloaded newer image for lorel/docker-stress-ng:latest docker.io/lorel/docker-stress-ng:latest [root@centos7 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE lorel/docker-stress-ng latest 3a248aa42b59 8 years ago 8.1MB 查看帮助
[root@centos7 ~]# docker run -it lorel/docker-stress-ng stress-ng, version 0.03.11 Usage: stress-ng [OPTION [ARG]] --h, --help show help --affinity N start N workers that rapidly change CPU affinity --affinity-ops N stop when N affinity bogo operations completed --affinity-rand change affinity randomly rather than sequentially --aio N start N workers that issue async I/O requests --aio-ops N stop when N bogo async I/O requests completed --aio-requests N number of async I/O requests per worker -a N, --all N start N workers of each stress test -b N, --backoff N wait of N microseconds before work starts -B N, --bigheap N start N workers that grow the heap using calloc() --bigheap-ops N stop when N bogo bigheap operations completed --bigheap-growth N grow heap by N bytes per iteration --brk N start N workers performing rapid brk calls --brk-ops N stop when N brk bogo operations completed --brk-notouch don't touch (page in) new data segment page --bsearch start N workers that exercise a binary search --bsearch-ops stop when N binary search bogo operations completed --bsearch-size number of 32 bit integers to bsearch -C N, --cache N start N CPU cache thrashing workers --cache-ops N stop when N cache bogo operations completed (x86 only) .... Example: stress-ng --cpu 8 --io 4 --vm 2 --vm-bytes 128M --fork 4 --timeout 10s Note: Sizes can be suffixed with B,K,M,G and times with s,m,h,d,y
使用示例
假如一个容器未做内存使用限制 , 则该容器可以利用到系统内存最大空间 , 默认创建的容器没有做内存资源限制。
范例:默认一个works分配256M内存 , 2个即占512M内存
[root@centos7 ~]# docker run --name c1 -it --rm lorel/docker-stress-ng --vm 2
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
##因上一个命令是前台执行 , 下面在另一个终端窗口中执行 , 可以看到占用512M左右内存
[root@centos7 ~]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
951086dbb9c2 c1 198.14% 514.2MiB / 1.777GiB 28.26% 656B / 0B 0B / 0B 54.2 内存测试
指定内存最大值
[root@centos7 ~]# docker run --name c1 -it --rm -m 300m lorel/docker-stress-ng --vm 2 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm [root@centos7 ~]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 9f1d1e82710f c1 116.29% 299.9MiB / 300MiB 99.98% 656B / 0B 6.09GB / 6.55GB 5设置4个进程同时测试 , 每个进程占用内存为256M左右
[root@centos7 ~]# docker run --name c2 -it --rm lorel/docker-stress-ng --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 vm [root@centos7 ~]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 3184ab62361e c2 198.88% 1.002GiB / 1.777GiB 56.41% 656B / 0B 0B / 0B 9查看内存限制
#启动两个工作进程 , 每个工作进程最大允许使用内存 256M , 且宿主机不限制当前容器最大内存 [root@centos ~]# ls /sys/fs/cgroup/memory/docker/ 98963c88d9970017f330514dc4bdae5a6bde578fa6b376c30c38107556e1ac2a memory.kmem.limit_in_bytes memory.kmem.usage_in_bytes memory.move_charge_at_immigrate memory.usage_in_bytes cgroup.clone_children memory.kmem.max_usage_in_bytes memory.limit_in_bytes memory.numa_stat memory.use_hierarchy cgroup.event_control memory.kmem.slabinfo memory.max_usage_in_bytes memory.oom_control notify_on_release cgroup.procs memory.kmem.tcp.failcnt memory.memsw.failcnt memory.pressure_level tasks memory.failcnt memory.kmem.tcp.limit_in_bytes memory.memsw.limit_in_bytes memory.soft_limit_in_bytes memory.force_empty memory.kmem.tcp.max_usage_in_bytes memory.memsw.max_usage_in_bytes memory.stat memory.kmem.failcnt memory.kmem.tcp.usage_in_bytes memory.memsw.usage_in_bytes memory.swappiness [root@centos7 ~]# ls /sys/fs/cgroup/memory/docker/98963c88d9970017f330514dc4bdae5a6bde578fa6b376c30c38107556e1ac2a/ cgroup.clone_children memory.kmem.failcnt memory.kmem.tcp.limit_in_bytes memory.max_usage_in_bytes memory.move_charge_at_immigrate memory.stat tasks cgroup.event_control memory.kmem.limit_in_bytes memory.kmem.tcp.max_usage_in_bytes memory.memsw.failcnt memory.numa_stat memory.swappiness cgroup.procs memory.kmem.max_usage_in_bytes memory.kmem.tcp.usage_in_bytes memory.memsw.limit_in_bytes memory.oom_control memory.usage_in_bytes memory.failcnt memory.kmem.slabinfo memory.kmem.usage_in_bytes memory.memsw.max_usage_in_bytes memory.pressure_level memory.use_hierarchy memory.force_empty memory.kmem.tcp.failcnt memory.limit_in_bytes memory.memsw.usage_in_bytes memory.soft_limit_in_bytes notify_on_release [root@centos7 ~]# cat /sys/fs/cgroup/memory/docker/98963c88d9970017f330514dc4bdae5a6bde578fa6b376c30c38107556e1ac2a/memory.limit_in_bytes 9223372036854771712 [root@centos7 ~]# echo 2^63 | bc 9223372036854775808内存限制
200M,并且动态调整内存限制[root@centos7 ~]# docker run -it --rm -m 200M lorel/docker-stress-ng --vm 2 --vm-bytes 256M stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm [root@centos7 ~]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS cc1b51627e62 fervent_feynman 88.86% 199.9MiB / 200MiB 99.94% 516B / 0B 36.8MB / 1.26GB 5 #查看宿主机基于 cgroup 对容器进行内存资源的大小限制 [root@centos7 ~]# cat /sys/fs/cgroup/memory/docker/cc1b51627e62ac83daf3c5ae2cb13965423667e43a8d49c105aa91f72972f2a5/memory.limit_in_bytes 209715200 [root@centos7 ~]# echo 200*1024*1024 | bc 209715200 #动态修改内存限制 [root@centos7 ~]# echo 300*1024*1024 | bc 314572800 #通过echo 命令可以改内存限制的值 , 但是可以在原基础之上增大内存限制 , 缩小内存限制会报错write error: Device or resource busy [root@centos7 ~]# echo 314572800 > /sys/fs/cgroup/memory/docker/cc1b51627e62ac83daf3c5ae2cb13965423667e43a8d49c105aa91f72972f2a5/memory.limit_in_bytes [root@centos7 ~]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS cc1b51627e62 clever_torvalds 183.34% 299.9MiB / 300MiB 99.96% 656B / 0B 3.97GB / 45.3GB 5内存大小软限制
[root@centos7 ~]# docker run -it --rm -m 256m --memory-reservation 128m --name c1 lorel/docker-stress-ng --vm 2 --vm-bytes 256M stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm [root@centos7 ~]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 2ca1e4934433 c1 170.18% 256MiB / 256MiB 99.99% 656B / 0B 886MB / 4.5GB 5 #查看内存硬限制 [root@centos7 ~]# cat /sys/fs/cgroup/memory/docker/2ca1e4934433c0e0498b1dd5db379acaaec13724500ef770b7dc2e6c4f14e375/memory.limit_in_bytes 268435456 #查看内存软限制 [root@centos7 ~]# cat /sys/fs/cgroup/memory/docker/2ca1e4934433c0e0498b1dd5db379acaaec13724500ef770b7dc2e6c4f14e375/memory.soft_limit_in_bytes 134217728 #软限制不能高于硬限制 [root@centos7 ~]# docker run -it --rm -m 256m --memory-reservation 257m --name c1 lorel/docker-stress-ng --vm 2 --vm-bytes 256M docker: Error response from daemon: Minimum memory limit can not be less than memory reservation limit, see usage. See 'docker run --help'.关闭oom机制
#查看docker OOM机制默认值 [root@centos7 ~]# cat /sys/fs/cgroup/memory/docker/memory.oom_control oom_kill_disable 0 under_oom 0 #启动容器时关闭OOM机制 [root@centos7 ~]# docker run -it --rm -m 256m --oom-kill-disable --name c1 lorel/docker-stress-ng --vm 2 --vm-bytes 256M stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 2 vm [root@centos7 ~]# docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS bce0f3557209 c1 0.00% 255.8MiB / 256MiB 99.92% 656B / 0B 24.4MB / 578MB 5 [root@centos7 ~]# cat /sys/fs/cgroup/memory/docker/bce0f3557209c6d1012be525c1d65dfae2062f5c81648a9178b35d7e4dd83a00/memory.oom_control oom_kill_disable 1 under_oom 1交换分区限制
# docker run -it --rm -m 256m --memory-swap 512m --name c1 centos bash #宿主机cgroup验证: # cat /sys/fs/cgroup/memory/docker/容器 ID/memory.memsw.limit_in_bytes 536870912
4.3 CPU测试
查看
stress-ng测试cpu配置[root@centos7 ~]# docker run -it --rm -m 256m --oom-kill-disable lorel/docker-stress-ng | grep cpu -c N, --cpu N start N workers spinning on sqrt(rand()) --cpu-ops N stop when N cpu bogo operations completed -l P, --cpu-load P load CPU by P %%, 0=sleep, 100=full load (see -c) --cpu-method m specify stress cpu method m, default is all Example: stress-ng --cpu 8 --io 4 --vm 2 --vm-bytes 128M --fork 4 --timeout 10s不限制容器的
CPU[root@ubuntu1804 ~]#lscpu |grep CPU CPU op-mode(s): 32-bit, 64-bit CPU(s): 6 On-line CPU(s) list: 0-5 CPU family: 6 Model name: Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz CPU MHz: 2494.236 NUMA node0 CPU(s): 0-5 [root@ubuntu1804 ~]#docker run -it --rm lorel/docker-stress-ng --cpu 4 --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 818a85e1da2f frosty_taussig 595.57% 1.037GiB / 2.908GiB 35.64% 1.12kB / 0B 0B / 0B 13 [root@ubuntu1804 ~]#cat /sys/fs/cgroup/cpuset/docker/818a85e1da2f9a4ef297178a9dc09b338b2308108195ad8d4197a1c47febcbff/cpuset.cpus 0-5 [root@ubuntu1804 ~]#top
限制使用
CPU[root@ubuntu1804 ~]#docker run -it --rm --cpus 1.5 lorel/docker-stress-ng --cpu 4 --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 9f8b2e693113 busy_hodgkin 147.71% 786.8MiB / 2.908GiB 26.42% 836B / 0B 0B / 0B 13 [root@ubuntu1804 ~]#top
限制
CPU[root@ubuntu1804 ~]#docker run -it --rm --cpu-quota 2000 --cpu-period 1000 lorel/docker-stress-ng --cpu 4 --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS bd949bb6698e affectionate_chebyshev 185.03% 1.037GiB / 2.908GiB 35.64% 836B / 0B 0B / 0B 13 [root@ubuntu1804 ~]#绑定
CPU#一般不建议绑在0号CPU上 , 因0号CPU一般会较忙 [root@ubuntu1804 ~]#docker run -it --rm --cpus 1.5 --cpuset-cpus 2,4-5 lorel/docker-stress-ng --cpu 4 --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 585879094e73 hungry_albattani 154.35% 1.099GiB / 2.908GiB 37.79% 906B / 0B 0B / 0B 13 [root@ubuntu1804 ~]#cat /sys/fs/cgroup/cpuset/docker/585879094e7382d2ef700947b4454426eee7f943f8d1438fe42ce34df789227b/cpuset.cpus 2,4-5 [root@ubuntu1804 ~]#top
多个容器的
CPU利用率比例#同时开两个容器 [root@ubuntu1804 ~]#docker run -it --rm --name c1 --cpu-shares 1000 lorel/docker-stress-ng --cpu 4 --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm [root@ubuntu1804 ~]#docker run -it --rm --name c2 --cpu-shares 500 lorel/docker-stress-ng --cpu 4 --vm 4 stress-ng: info: [1] defaulting to a 86400 second run per stressor stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS a1d4c6e6802d c2 195.88% 925.3MiB / 2.908GiB 31.07% 726B / 0B 0B / 0B 13 d5944104aff4 c1 398.20% 1.036GiB / 2.908GiB 35.64% 906B / 0B 0B / 0B 13 [root@ubuntu1804 ~]# #查看c1容器的cpu利用比例 [root@ubuntu1804 ~]#cat /sys/fs/cgroup/cpu,cpuacct/docker/d5944104aff40b7b76f536c45a68cd4b98ce466a73416b68819b9643e3f49da7/cpu.shares 1000 #查看c2容器的cpu利用比例 [root@ubuntu1804 ~]#cat /sys/fs/cgroup/cpu,cpuacct/docker/a1d4c6e6802d1b846b33075f3c1e1696376009e85d9ff8756f9a8d93d3da3ca6/cpu.shares 500 #再打开新的容器 , cpu分配比例会动态调整 [root@ubuntu1804 ~]#docker run -it --rm --name c3 --cpu-shares 2000 lorel/docker-stress-ng --cpu 4 --vm 4 [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS c2d54818e1fe c3 360.15% 664.5MiB / 2.908GiB 22.31% 726B / 0B 1.64GB / 150MB 13 a1d4c6e6802d c2 82.94% 845.2MiB / 2.908GiB 28.38% 936B / 0B 103MB / 4.54MB 13 d5944104aff4 c1 181.18% 930.1MiB / 2.908GiB 31.23% 1.12kB / 0B 303MB / 19.8MB 13动态调整
cpu shares值[root@ubuntu1804 ~]#echo 2000 > /sys/fs/cgroup/cpu,cpuacct/docker/a1d4c6e6802d1b846b33075f3c1e1696376009e85d9ff8756f9a8d93d3da3ca6/cpu.shares [root@ubuntu1804 ~]#docker stats --no-stream CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS a1d4c6e6802d c2 389.31% 1.037GiB / 2.908GiB 35.64% 1.01kB / 0B 1.16GB / 14MB 13 d5944104aff4 c1 200.28% 1.036GiB / 2.908GiB 35.63% 1.19kB / 0B 2.66GB / 26.7MB 13 [root@ubuntu1804 ~]#
5. docker 使用gpu
Docker中针对GPU资源与CPU、内存和磁盘IO资源不同。如果Docker要使用GPU,需要docker支持GPU,在docker19以前都需要单独下载nvidia-docker1或nvidia-docker2来启动容器,但是docker19中后需要GPU的Docker只需要加个参数-–gpus即可(-–gpus all表示使用所有的gpu ; 要使用`2个gpu:–-gpus 2即可 ; 也可直接指定使用哪几个卡:--gpus '"device=1,2"'),Docker里面想读取nvidia显卡再也不需要额外的安装nvidia-docker了。
查看是否具备--gpus参数
docker run --help | grep -i gpus查看nvidia界面是否能够启动
运行nvidia官网提供的镜像,并输入nvidia-smi命令,查看nvidia界面是否能够启动。
docker run --gpus all nvidia/cuda:9.0-base nvidia-smi在Docker容器中使用GPU
# 使用所有GPU
docker run --gpus all nvidia/cuda:9.0-base nvidia-smi
# 使用两个GPU
docker run --gpus 2 nvidia/cuda:9.0-base nvidia-smi
# 指定GPU运行
docker run --gpus '"device=2"' nvidia/cuda:9.0-base nvidia-smi
docker run --gpus '"device=1,2"' nvidia/cuda:9.0-base nvidia-smi
docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:9.0-base nvidia-smi参考链接
docker-容器资源限制 - 运维派 (yunweipai.com)
Docker之五--Docker的系统资源限制及验证 - 一叶知秋~~ - 博客园 (cnblogs.com)
Docker资源(CPU/内存/磁盘IO/GPU)限制与分配指南-阿里云开发者社区 (aliyun.com)