Docker中的Cgroup資源配置方法


摘要

Docker通過Cgroup來控制容器使用的資源配額,包括CPU、內存、磁盤三大方面,基本覆蓋了常見的資源配額和使用量控制。

一、Cgroup簡介

Cgroup是Control Groups的縮寫,是Linux內核提供的一種可以限制、記錄、隔離進程組所使用的物理資源(如CPU、內存、磁盤IO等待)的機制,被LXC、docker等很多項目用於實現進程資源控制。Cgroup本身是提供將進程進行分組化管理的功能和接口的基礎結構,I/O或內存的分配控制等具體的資源管理是通過該功能來實現的。這些具體的資源管理功能稱為Cgroup子系統,有以下幾大子系統實現:

blkio:設置限制每個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb等等

CPU:使用調度程序為cgroup任務提供CPU的訪問

cpuacct:產生cgroup任務的CPU資源報告

cpuset:如果是多核心的CPU,這個子系統會為cgroup任務分配單獨的CPU和內存

devices:允許或拒絕cgroup任務對設備的訪問

freezer:暫停和恢復cgroup任務

memory:設置每個cgroup的內存限制以及產生內存資源報告

net_cls:標記每個網絡包以供cgroup方便使用

ns:命名空間子系統

perf_event:增加了對每個group的監測跟蹤的能力,可以監測屬於某個特定的group的所有線程以及運行在特定CPU上的線程

下面開始使用stress壓力測試工具來測試CPU和內存使用狀況

二、安裝stress工具

 1 創建stress目錄  2 [root@server1 ~]# mkdir /opt/stress  3 [root@server1 ~]# cd /opt/stress/
 4 
 5 編寫Dockerfile文件  6 [root@server1 stress]# vim DockerfileFROM centos:7
 7 MAINTAINER xu  8 RUN yum -y install wget
 9 RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/rep
10 o/epel-7.repo 11 RUN yum -y install stress 12 
13 構建鏡像 14 [root@server1 stress]# docker build -t centos:stress . 15 
16 查看鏡像 17 [root@server1 stress]# docker images 18 REPOSITORY TAG IMAGE ID CREATED SIZE 19 centos              stress              821b4e4b3972        5 seconds ago       417MB

三、CPU資源分配

默認情況下,每個Docker容器的CPU份額都是1024。單獨一個容器的份額是沒有意義的。只有在同時運行多個容器時,容器的CPU加權的效果才能體現出來。例如,兩個容器A、B的CPU份額分別為1000和500,在CPU進行時間片分配的時候,容器A比容器B多一倍的機會獲得CPU的時間片。但分配的結果取決於當時主機和其他容器的運行狀態,實際上也無法保證容器A一定能獲得CPU時間片。比如容器A的進程一直時空閑的,那么容器B是可以獲取比容器A更多的CPU時間片的,極端情況下,例如主機上只運行了一個容器,即使它的CPU份額只有50,它也可以獨占整個主機的CPU資源

Cgroup只在容器分配的資源緊缺時,即在需要對容器使用的資源進行限制時,才會生效。因此,無法單純根據某個容器的CPU份額來確定有多少CPU資源分配給它,資源分配結果取決於同時運行的其他容器的CPU分配和容器中進程運行情況。

可以通過cpu share可以設置容器使用CPU的優先級,比如,啟動了兩個容器及運行查看CPU使用百分比

3.1、運行兩個容器

 

1 [root@server1 stress]# docker run -dit --name cpu500 --cpu-shares 500 centos:stress stress -c 10
2 c0083744c59f24ca4ff008b2e5fa25dbd7e3363c7b81362d5f4f87c0ac486c7b 3 [root@server1 stress]# docker run -dit --name cpu1000 --cpu-shares 1000 centos:stress stress -c 10
4 b84cc76469bc7264b26a3c9db846b2e07918a25e425b1bf62bc9688e501dc82f

 

3.2、查看內存使用情況

 1 進入cpu1000容器  2 [root@server1 stress]# docker exec -it b84cc76469bc /bin/bash  3 
 4 查看cpu使用情況  5 [root@b84cc76469bc /]# top  6 
 7 進入cpu500容器  8 [root@server1 stress]# docker exec -it c0083744c59f /bin/bash  9 
10 查看cpu使用情況 11 [root@c0083744c59f /]# top

容器1000cpu使用情況如下

 

 

 容器500cpu使用情況如下

 

 

 

對比后可以得出cpu1000的容器cpu使用率大概是另一個的兩倍

四、CPU周期限制

Docker提供了--cpu-period、--cpu-quota兩個參數控制容器可以分配到的CPU時鍾周期。

  • --cpu-period是用來指定容器對CPU的使用要在多長時間內做一次重新分配。
  • --cpu-quota是用來指定在這個周期內,最多可以有多少時間用來跑這個容器。
  • 與--cpu-shares不同的是,這種配置是指定一個絕對值,容器對CPU資源的使用絕對不會超過配置的值
  • cpu-period和cpu-quota的單位為微秒(μs)。cpu-period的最小值為1000微秒,最大值為1秒(10^6 μs),默認值為 0.1 秒(100000 μs)。
  • cpu-quota的值默認為-1,表示不做控制。cpu-period和cpu-quota參數一般聯合使用

例如:容器進程需要每1秒使用單個CPU的0.2秒時間,可以將cpu-period設置為1000000(即1秒),cpu-quota 設置為 200000(0.2 秒)。當然,在多核情況下,如果允許容器進程完全占用兩個CPU,則可以將cpu-period設置為100000(即0.1秒),cpu-quota設置為200000(0.2秒)。

 1 運行容器並設置周期  2 [root@server1 stress]# docker run -dit --cpu-period 100000 --cpu-quota 200000 centos:stress  3 9449396fc3b0b8a99b1fb8fb211998032bc91933df831b5c3341e435a64beda5  4 [root@server1 stress]# docker ps -a  5 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES  6 9449396fc3b0        centos:stress       "/bin/bash"         5 seconds ago       Up 4 seconds goofy_mclean  7 
 8 進入容器  9 [root@server1 stress]# docker exec -it 9449396fc3b0 /bin/bash 10 
11 查看周期 12 [root@9449396fc3b0 /]# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us 13 100000
14 [root@9449396fc3b0 /]# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us 15 200000

五、CPU Core控制

對多核 CPU 的服務器,Docker 還可以控制容器運行使用哪些 CPU 內核,即使用--cpuset-cpus 參數。這對具有多 CPU 的服務器尤其有用,可以對需要高性能計算的容器進行性能最優的配置。

5.1、進行CPU Core控制配置

 1 表示創建的容器只能用 0、1兩個內核  2 [root@server1 ~]# docker run -dit --name cpu1 --cpuset-cpus 0-1 centos:stress  3 3266be3c50ebfe8e4e34bc3c202e7ad419314aedccdea1b09c941baf029569d1  4 
 5 查看容器運行狀態  6 [root@server1 ~]# docker ps -a  7 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES  8 3266be3c50eb        centos:stress       "/bin/bash"         6 seconds ago       Up 5 seconds cpu1  9 
10 進入容器 11 [root@server1 ~]# docker exec -it 3266be3c50eb /bin/bash 12 
13 生成 的 cgroup 的 CPU 內核配置如下 14 [root@3266be3c50eb /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus 15 0-1

5.2、CPU內核綁定

通過下面指令可以看到容器中進程與 CPU 內核的綁定關系,達到綁定 CPU 內核的目的

1 [root@server1 ~]# docker exec 3266be3c50eb taskset -c -p 1
2 pid 1's current affinity list: 0,1

5.3、壓力測試

六、CPU配額參數的混合使用

通過 cpuset-cpus 參數指定容器 A 使用 CPU 內核 1,容器 B 只是用 CPU 內核 3。在主機上只有這兩個容器使用對應 CPU 內核的情況,它們各自占用全部的內核資源,cpu-shares 沒有明顯效果。

cpuset-cpus、cpuset-mems 參數只在多核、多內存節點上的服務器上有效,並且必須與實際的物理配置匹配,否則也無法達到資源控制的目的。

在系統具有多個 CPU 內核的情況下,需要通過 cpuset-cpus 參數為設置容器 CPU 內核才能方便地進行測試

 1 CPU配置  2 [root@server1 ~]# docker run -dit --name cpu3 --cpuset-cpus 1 --cpu-shares 500 centos:stress stress -c 1
 3 275bc9803463abd9098c632d836f605d76bab74467cff2cd57f956762f6fed24  4 [root@server1 ~]# docker run -dit --name cpu4 --cpuset-cpus 3 --cpu-shares 1000 centos:stress stress -c 1
 5 be61e954017eb398701c9c17440cdf3c72450e4ebb1b76fb2022afeadee277fd  6 
 7 查看容器運行情況  8 [root@server1 ~]# docker ps -a  9 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10 be61e954017e        centos:stress       "stress -c 1"       48 seconds ago       Up 48 seconds cpu4 11 275bc9803463        centos:stress       "stress -c 1" About a minute ago Up About a minute cpu3 12 
13 分別進入兩個容器 14 [root@server1 ~]# docker exec -it 275bc9803463 /bin/bash 15 [root@server1 ~]# docker exec -it be61e954017e /bin/bash 16 
17 分別查看CPU使用情況 18 [root@be61e954017e /]# top        #記住按1查看每個核心的占用

cpu3容器cpu使用情況

 

cpu4容器cpu使用情況

 

 

 

總結:上面的 centos:stress 鏡像安裝了 stress 工具,用來測試 CPU 和內存的負載。通過 在兩個容器上分別執行 stress -c 1 命令,將會給系統一個隨機負載,產生 1 個進程。這 個進程都反復不停的計算由 rand() 產生隨機數的平方根,直到資源耗盡。觀察到宿主機上的 CPU 使用率,第三個內核的使用率接近 100%, 並且一批進程的 CPU 使用率明顯存在 2:1 的使用比例的對比。

七、內存限額

與操作系統類似,容器可使用的內存包括兩部分:物理內存和Swap,Docker通過下面兩組參數來控制容器內存的使用量

  • -m或--memory:設置內存的使用限額,例如100M、1024M。
  • --memory-swap:設置內存+swap的使用限額

執行如下命令允許該容器最多使用200M的內存和300M的內存+swap

 1 內存限額配置  2 [root@server1 ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M  3 stress: dbug: [1] using backoff sleep of 3000us  4 stress: dbug: [1] --> hogvm worker 1 [6] forked  5 stress: dbug: [6] allocating 293601280 bytes ...  6 stress: dbug: [6] touching bytes in strides of 4096 bytes ...  7 會一直運行  8 
 9 --vm 1:啟動 1 個內存工作線程。 10 --vm-bytes 280M:每個線程分配 280M 內存。 11 默認情況下,容器可以使用主機上的所有空閑內存。 12 
13 如果讓工作線程分配的內存超過300M,分配的內存超過限額,stress線程報錯,容器退出 14 [root@server1 ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M 15 stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd 16 stress: dbug: [1] using backoff sleep of 3000us 17 stress: dbug: [1] --> hogvm worker 1 [6] forked 18 stress: dbug: [6] allocating 325058560 bytes ... 19 stress: dbug: [6] touching bytes in strides of 4096 bytes ... 20 stress: FAIL: [1] (416) <-- worker 6 got signal 9
21 stress: WARN: [1] (418) now reaping child worker processes 22 stress: FAIL: [1] (422) kill error: No such process #沒有進程退出 23 stress: FAIL: [1] (452) failed run completed in 1s

八、Block IO的限制

默認情況下,所有容器能平等地讀寫磁盤,可以通過設置--blkio-weight參數來改變容器block IO的優先級。--blkio-weight與--cpu-shares類似,設置的是相對權重值,默認為500。

在下面的例子中,容器A讀寫磁盤的帶寬是容器B的兩倍

 1 Block IO 的限制配置  2 [root@server1 ~]# docker run -dit --name container_A --blkio-weight 400 centos:stress  3 6cfcf6a595b729cf77267ad939e70a1e30f973b3197d4aec2903ec3429a78b3b  4 [root@server1 ~]# docker run -dit --name container_B --blkio-weight 200 centos:stress  5 e680d986196c36c4910c7e91fe798c2389e0d298c0c4e5bc7b76d99e288fdf82  6 
 7 查看容器運行情況  8 [root@server1 ~]# docker ps -a  9 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10 e680d986196c        centos:stress       "/bin/bash"              46 seconds ago       Up 46 seconds container_B 11 6cfcf6a595b7        centos:stress       "/bin/bash" About a minute ago Up About a minute container_A 12 
13 進入容器分別查看 14 [root@server1 ~]# docker exec -it 6cfcf6a595b7 /bin/bash 15 [root@6cfcf6a595b7 /]# cat /sys/fs/cgroup/blkio/blkio.weight 16 400
17 
18 [root@server1 ~]# docker exec -it e680d986196c /bin/bash 19 [root@e680d986196c /]# cat /sys/fs/cgroup/blkio/blkio.weight 20 200

九、bps和iops的限制

bps是byte per second,每秒讀寫的數據量

iops是io per second,每秒IO的次數

可通過以下參數控制容器的bps和iops:

  • --device-read-bps,限制讀某個設備的bps
  • --device-write-bps,限制寫某個設備的bps
  • --device-read-iops,限制讀某個設備的iops
  • --device-write-iops,限制寫某個設備的iops 

下面的示例是限制容器寫/dev/sda的速率為5MB/s

 1 bps 和 iops 的限制配置  2 [root@server1 ~]# docker run -dit --device-write-bps /dev/sda:5MB centos:stress  3 88fa4e4ca86fa3f17ed829d91a597d7b7f6645ca0c11d23af3441406203291f2  4 
 5 查看容器運行情況  6 [root@server1 ~]# docker ps -a  7 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES  8 88fa4e4ca86f        centos:stress       "/bin/bash"         5 seconds ago       Up 4 seconds interesting_mclaren  9 
10 進入容器 11 [root@server1 ~]# docker exec -it 88fa4e4ca86f /bin/bash 12 
13 進行測試 14 [root@88fa4e4ca86f /]# dd if=/dev/zero of=text bs=1M count=1024 oflag=direct # 15 可以按ctrl+c中斷查看 16 ^C14+0 records in
17 14+0 records out 18 14680064 bytes (15 MB) copied, 2.80506 s, 5.2 MB/s #限速5MB/s

通過dd命令測試在容器中寫磁盤的速度。因為容器的文件系統是在host /dev/sda上的,在容器中寫文件相當於對host /dev/sda進行寫操作。另外,oflag=direct指定用direct IO方式寫文件,這樣 --device-write-bps才能生效

結果表明限速5MB/s左右。作為對比測試,如果不限速,結果如下:

1 運行另一個容器 2 [root@server1 ~]# docker run -it centos:stress 3 
4 [root@ffd2062aa3a4 /]# dd if=/dev/zero of=text bs=1M count=1024 oflag=direct 5 1024+0 records in
6 1024+0 records out 7 1073741824 bytes (1.1 GB) copied, 0.465947 s, 2.3 GB/s #不限速,2.3GB/s

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM