docker 資源限制

1 容器底層技術

容器底層技術

Docker底層技術包括:namespace主要是隔離作用,cgroups主要是資源限制,聯合文件主要用於
鏡像分層存儲和管理。

8. Docker的資源限制_Docker

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
內存限制

容器資源限制參數説明

8. Docker的資源限制_5e_02

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限制參數如表:

8. Docker的資源限制_Docker_03

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限制常用參數如表:

8. Docker的資源限制_5e_04

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