docker 资源限制
1 容器底层技术
容器底层技术
Docker底层技术包括:namespace主要是隔离作用,cgroups主要是资源限制,联合文件主要用于
镜像分层存储和管理。

namespace
namespace是将内核的全局资源做封装,使得每个namespace都有一份独立的资源,因此不同的进程在各自的namespace内对
同一种资源的使用不会互相干扰。
-- 1、UTS namespace提供了主机名和域名的隔离,这样每个容器就拥有独立的主机名和域名了,在网络上就可以被视为一个独
立的节点,在容器中对hostname的命名不会对宿主机造成任何影响。
-- 2、IPC namespace实现了进程间通信的隔离,包括常见的几种进程间通信机制,如信号量,消息队列和共享内存。
-- 3、PID namespace完成的是进程号的隔离,同样的一个进程在不同的PID Namespace里面可以拥有不同的PID。
-- 4、Mount namespace是用来隔离各个进程看到的挂载点视图。在不同namespace中的进程看到的文件系统层次是不一样
的。
-- 5、User namespace主要是隔离用户的用户组ID。也就是说,一个进程的User ID和Group ID在User namespace内外可以是
不同的。
-- 6、Network namespace是用来隔离网络设备,IP地址端口等网络栈的namespace。Network namespace可以让每个容器
拥有自己独立的网络设备(虚拟的),而且容器内的应用可以绑定到自己的端口,每个namesapce内的端口都不会互相冲
突。
cgroups
cgroups是control groups的缩写,最初由google的工程师提出,后来被整合进Linux内核。cgroups是Linux内核提供的一种可以
限制、记录、隔离进程组(process groups)所使用的物理资源(如:CPU、内存、IO等)的机制。在默认情况下,Docker容器并不
会对容器内部进程使用的内存大小进行任何限制。对于直接使用Docker的用户而言,这非常危险。如果哪个业务容器,出现了内存泄
漏;那么它可能会危害到整个主机系统,导致业务应用容器所在的主机出现OOM。
cgroups到底长什么样子呢?我们可以在/sys/fs/cgroup中找到它,创建一个新容器,并使用-m限制容器能够使用的内存大小。
[root@ws ~]# docker run -itd --name ws1 -m 200M busybox:latest
564a17b39ae7428d04a751304bdaa37718363936de9a373506cbee010ad1b72b
随着容器的创建启动,在/sys/fs/cgroup/memory/docker/目录中,Linux会创建该容器的cgroup目录,目录中包含了对容器所使
用资源的限制。
[root@ws ~]# cd /sys/fs/cgroup/
[root@ws cgroup]# ls
blkio cpuacct cpuset freezer memory net_cls,net_prio perf_event systemd
cpu cpu,cpuacct devices hugetlb net_cls net_prio pids
[root@ws cgroup]# cd memory/
[root@ws memory]# ls
cgroup.clone_children memory.kmem.max_usage_in_bytes memory.memsw.limit_in_bytes memory.usage_in_bytes
cgroup.event_control memory.kmem.slabinfo memory.memsw.max_usage_in_bytes memory.use_hierarchy
cgroup.procs memory.kmem.tcp.failcnt memory.memsw.usage_in_bytes notify_on_release
cgroup.sane_behavior memory.kmem.tcp.limit_in_bytes memory.move_charge_at_immigrate release_agent
docker memory.kmem.tcp.max_usage_in_bytes memory.numa_stat system.slice
machine.slice memory.kmem.tcp.usage_in_bytes memory.oom_control tasks
memory.failcnt memory.kmem.usage_in_bytes memory.pressure_level user.slice
memory.force_empty memory.limit_in_bytes memory.soft_limit_in_bytes
memory.kmem.failcnt memory.max_usage_in_bytes memory.stat
memory.kmem.limit_in_bytes memory.memsw.failcnt memory.swappiness
[root@ws memory]# cd docker/
[root@ws docker]# ls
564a17b39ae7428d04a751304bdaa37718363936de9a373506cbee010ad1b72b memory.kmem.tcp.limit_in_bytes memory.numa_stat
cgroup.clone_children memory.kmem.tcp.max_usage_in_bytes memory.oom_control
cgroup.event_control memory.kmem.tcp.usage_in_bytes memory.pressure_level
cgroup.procs memory.kmem.usage_in_bytes memory.soft_limit_in_bytes
memory.failcnt memory.limit_in_bytes memory.stat
memory.force_empty memory.max_usage_in_bytes memory.swappiness
memory.kmem.failcnt memory.memsw.failcnt memory.usage_in_bytes
memory.kmem.limit_in_bytes memory.memsw.limit_in_bytes memory.use_hierarchy
memory.kmem.max_usage_in_bytes memory.memsw.max_usage_in_bytes notify_on_release
memory.kmem.slabinfo memory.memsw.usage_in_bytes tasks
memory.kmem.tcp.failcnt memory.move_charge_at_immigrate
[root@ws docker]# cd 564a17b39ae7428d04a751304bdaa37718363936de9a373506cbee010ad1b72b/
[root@ws 564a17b39ae7428d04a751304bdaa37718363936de9a373506cbee010ad1b72b]# ls
cgroup.clone_children memory.kmem.slabinfo memory.memsw.failcnt memory.soft_limit_in_bytes
cgroup.event_control memory.kmem.tcp.failcnt memory.memsw.limit_in_bytes memory.stat
cgroup.procs memory.kmem.tcp.limit_in_bytes memory.memsw.max_usage_in_bytes memory.swappiness
memory.failcnt memory.kmem.tcp.max_usage_in_bytes memory.memsw.usage_in_bytes memory.usage_in_bytes
memory.force_empty memory.kmem.tcp.usage_in_bytes memory.move_charge_at_immigrate memory.use_hierarchy
memory.kmem.failcnt memory.kmem.usage_in_bytes memory.numa_stat notify_on_release
memory.kmem.limit_in_bytes memory.limit_in_bytes memory.oom_control tasks
memory.kmem.max_usage_in_bytes memory.max_usage_in_bytes memory.pressure_level
[root@ws 564a17b39ae7428d04a751304bdaa37718363936de9a373506cbee010ad1b72b]# cat memory.limit_in_bytes
209715200
[root@ws 564a17b39ae7428d04a751304bdaa37718363936de9a373506cbee010ad1b72b]#
2 容器资源限制
资源管理
每个容器在运行时,都需要内存、CPU、IO等资源,用户可以根据需求为容器分配资源。对于容器而言,容器中的资源大小与Docker host资源大小是一致的,因为它们都共享同一个内核。如果运行多个容器,某个容器在运过程中异常占用大量的资源,那么势必会对其他容器造成影响
构建stress镜像,stress是一个容器压力测试工具,也能帮助我们学习docker的资源限制
[root@ws ~]# cat Dockerfile
FROM ubuntu:trusty
RUN apt-get update && apt-get install -y stress
ENTRYPOINT ["/usr/bin/stress", "--verbose"]
[root@ws ~]# docker build -t stress .
[+] Building 47.0s (6/6) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 149B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:trusty 0.9s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/2] FROM docker.io/library/ubuntu:trusty@sha256:64483f3496c1373bfd55348e88694d1c4d0c9b660dee6bfef5e12f43b9933b30 27.3s
=> => resolve docker.io/library/ubuntu:trusty@sha256:64483f3496c1373bfd55348e88694d1c4d0c9b660dee6bfef5e12f43b9933b30 0.0s
=> => sha256:512123a864da5e2a62949e65b67106292c5c704eff90cac2b949fc8d7ac1e58e 189B / 189B 0.2s
=> => sha256:64483f3496c1373bfd55348e88694d1c4d0c9b660dee6bfef5e12f43b9933b30 1.20kB / 1.20kB 0.0s
=> => sha256:881afbae521c910f764f7187dbfbca3cc10c26f8bafa458c76dda009a901c29d 945B / 945B 0.0s
=> => sha256:13b66b487594a1f2b75396013bc05d29d9f527852d96c5577cc4f187559875d0 3.31kB / 3.31kB 0.0s
=> => sha256:2e6e20c8e2e69fa5c3fcc310f419975cef5fbeb6f7f2fe1374071141281b6a06 70.69MB / 70.69MB 4.8s
=> => sha256:0551a797c01db074ab0233ceb567e66b8ebdcb9de9a2e7baa36d57dfbca463a3 72.66kB / 72.66kB 0.2s
=> => extracting sha256:2e6e20c8e2e69fa5c3fcc310f419975cef5fbeb6f7f2fe1374071141281b6a06 21.9s
=> => extracting sha256:0551a797c01db074ab0233ceb567e66b8ebdcb9de9a2e7baa36d57dfbca463a3 0.1s
=> => extracting sha256:512123a864da5e2a62949e65b67106292c5c704eff90cac2b949fc8d7ac1e58e 0.1s
=> [2/2] RUN apt-get update && apt-get install -y stress 18.2s
=> exporting to image 0.2s
=> => exporting layers 0.1s
=> => writing image sha256:8f14107fe51fd7aff04f355ca4c7e6a488a57f991efedb83978bb3f6a1d5190e 0.0s
=> => naming to docker.io/library/stress 0.0s
内存限制
容器资源限制参数说明

1、容器对内存的使用限制一般会使用-m或者--memory,这个参数仅限制对物理内存的使用
[root@ws ~]# docker run -it --name a1 --rm -m 50M stress --vm 1 --vm-bytes 30M
2、在容器中也可以使用swap,这就需要用到--memory-swap参数,--memory-swap是指容器所用的
物理内存加sawp的总和,需要配合-m使用。
[root@ws ~]# docker run -it --name a1 --rm -m 50M --memory-swap=100M stress --vm 1 --vm-bytes 70M
cpu限制
常用的容器CPU限制参数如表:

1、创建两个容器a1和a2,a1的cpu权重为512,a2的cpu权重为1024,,同时将Docker host上的cpu全部占满。
[root@ws ~]# docker run -it --name a1 --rm -c 512 stress --cpu 4
[root@ws ~]# top
top - 10:51:09 up 1 day, 1:21, 2 users, load average: 3.05, 1.06, 0.46
Tasks: 196 total, 5 running, 191 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.7 us, 0.1 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 4026372 total, 247976 free, 561468 used, 3216928 buff/cache
KiB Swap: 4194300 total, 4193276 free, 1024 used. 2988236 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
30596 root 20 0 7312 96 0 R 100.0 0.0 1:17.63 stress
30597 root 20 0 7312 96 0 R 100.0 0.0 1:17.42 stress
30598 root 20 0 7312 96 0 R 100.0 0.0 1:17.68 stress
30595 root 20 0 7312 96 0 R 99.7 0.0 1:17.60 stress
8632 root 20 0 320216 6884 5380 S 0.3 0.2 2:22.79 vmtoolsd
30516 root 20 0 0 0 0 S 0.3 0.0 0:00.07 kworker/0
[root@ws ~]# docker run -it --name a2 --rm -c 1024 stress --cpu 4
[root@ws ~]# top
top - 10:56:17 up 1 day, 1:26, 2 users, load average: 3.99, 2.89, 1.42
Tasks: 198 total, 6 running, 192 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.9 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 4026372 total, 246348 free, 562960 used, 3217064 buff/cache
KiB Swap: 4194300 total, 4193276 free, 1024 used. 2986620 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
30769 root 20 0 7312 92 0 R 100.0 0.0 4:33.90 stress
30768 root 20 0 7312 92 0 R 99.7 0.0 4:34.11 stress
30770 root 20 0 7312 92 0 R 99.7 0.0 4:33.57 stress
30767 root 20 0 7312 92 0 R 99.3 0.0 4:34.05 stress
9042 root 20 0 1783508 43876 15564 S 0.3 1.1 5:57.94 containerd
1 root 20 0 191544 4576 2640 S 0.0 0.1 0:21.95 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.11 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:03.75 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/
2、参数-cpuset-cpus用于设置容器可以使用的CPU核数,示例如下,将容器中的工作进程运行在cpu1和cpu3上面。
[root@ws ~]# docker run -it --name a1 --rm --cpuset-cpus="1,3" stress --vm 2 --vm-bytes 100M
[root@ws ~]# top
top - 10:59:29 up 1 day, 1:30, 2 users, load average: 1.66, 2.59, 1.59
Tasks: 193 total, 1 running, 191 sleeping, 1 stopped, 0 zombie
%Cpu0 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 4026372 total, 360488 free, 552136 used, 3113748 buff/cache
KiB Swap: 4194300 total, 4193276 free, 1024 used. 2997640 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9 root 20 0 0 0 0 S 0.3 0.0 1:16.60 rcu_sched
Block IO限制
Block IO限制常用参数如表:

1、blkio IO权重,默认情况下,所有的容器都是平级的读写磁盘,可以通过--blkio-weight参数设置容器读写磁盘的
优先级。
示例如下,使用下面的命令创建两个--blkio-weight值不同的容器。:
[root@ws ~]# docker run --name cy1 -it --rm --blkio-weight 100 centos:7
[root@2ddb228322ff /]# time dd if=/dev/zero of=test.out bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 3.71316 s, 289 MB/s
real 0m3.721s
user 0m0.012s
sys 0m3.168s
[root@ws ~]# docker run --name cy2 -it --rm --blkio-weight 1000 centos:7
[root@35c4f43588a0 /]# time dd if=/dev/zero of=test.out bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 3.07043 s, 350 MB/s
real 0m3.076s
user 0m0.003s
sys 0m2.711s
在容器中同时执行下面的dd命令,进行测试,第一个是a1的执行结果,第二个是a2的执行结果,两个结果对比并不明
显,因为Docker host不是那么的繁忙。
2、device-write-bps,默认情况下,Docker对容器的写速度是没有限制的,我们可以使用--device-write-bps参数限
制容器对硬盘些速度的限制。
示例如下,使用下面的命令创建容器,并执行命令验证写速度的限制。通过直接结果可以得知,容器向硬盘写入20M
的数据,以1.0 MB/s的速度写入。
[root@ws ~]# docker run --name cy3 -it --rm --device-write-bps /dev/sda:1mb centos:7
[root@8d977a2c3738 /]# time dd if=/dev/zero of=test.out bs=1M count=20 oflag=direct
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied, 0.0540759 s, 388 MB/s
real 0m0.057s
user 0m0.000s
sys 0m0.048s