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