實操:docker資源控制——cgroup


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

Cgroup概述

Cgroup是control groups的縮寫,是linux內核提供的一種可以限制、記錄、隔離進程組所使用的物理資源的機制
物理資源如CPU、內存、磁盤IO等等
Cgroup被LXC、docker等很多項目用於實現進程資源控制。cgroup本身是提供將進程進行分組化管理的功能和接口的基礎結構,IO或內存的分配控制等具體的資源管理是通過該方式

這些具體的資源管理功能成爲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和內存使用狀況

一: docker資源控制——CPU

CPU使用率控制

1.1 查看當前容器CPU限制狀態

cat /sys/fs/cgroup/cpu/docker/容器ID/cpu.cfs_quota_us

-1代表cpu資源使用是不受限制的,上限是硬件

[root@kibana ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
dd5782cde89d        centos:7            "/bin/bash"         48 minutes ago      Up 48 minutes                           test3
de37ff32e2c4        centos:7            "/bin/bash"         2 hours ago         Up 2 hours                              test1
[root@kibana docker]# cd /sys/
[root@kibana sys]# ls
block  bus  class  dev  devices  firmware  fs  hypervisor  kernel  module  power
[root@kibana sys]# cd fs
[root@kibana fs]# ls
cgroup  pstore  selinux  xfs
[root@kibana fs]# cd cgroup/
[root@kibana cgroup]# ls
blkio  cpu  cpuacct  cpu,cpuacct  cpuset  devices  freezer  hugetlb  memory  net_cls  net_cls,net_prio  net_prio  perf_event  pids  systemd
[root@kibana cgroup]# ll cpu
lrwxrwxrwx. 1 root root 11 Apr 16 09:27 cpu -> cpu,cpuacct
[root@kibana cgroup]# cd cpu
[root@kibana cpu]# ls
cgroup.clone_children  cgroup.sane_behavior  cpuacct.usage_percpu  cpu.rt_period_us   cpu.stat       notify_on_release  tasks
cgroup.event_control   cpuacct.stat          cpu.cfs_period_us     cpu.rt_runtime_us  docker         release_agent      user.slice
cgroup.procs           cpuacct.usage         cpu.cfs_quota_us      cpu.shares         machine.slice  system.slice
[root@kibana cpu]# cat cpu.cfs_quota_us 
-1
[root@kibana cpu]# cd docker/
[root@kibana docker]# ls
cgroup.clone_children  cpuacct.usage         cpu.rt_period_us   dd5782cde89d7084de43e8c343f6cbbe99e5b12226e037b7e5529a35d05bce55
cgroup.event_control   cpuacct.usage_percpu  cpu.rt_runtime_us  de37ff32e2c45188a4fd5d87c20dbbb0db8eeea13583e515b89a90a66ad3e7b1
cgroup.procs           cpu.cfs_period_us     cpu.shares         notify_on_release
cpuacct.stat           cpu.cfs_quota_us      cpu.stat           tasks
[root@kibana docker]# cat cpu.cfs_quota_us 
-1
[root@kibana docker]# cd dd5782cde89d7084de43e8c343f6cbbe99e5b12226e037b7e5529a35d05bce55/
[root@kibana dd5782cde89d7084de43e8c343f6cbbe99e5b12226e037b7e5529a35d05bce55]# ls
cgroup.clone_children  cgroup.procs  cpuacct.usage         cpu.cfs_period_us  cpu.rt_period_us   cpu.shares  notify_on_release
cgroup.event_control   cpuacct.stat  cpuacct.usage_percpu  cpu.cfs_quota_us   cpu.rt_runtime_us  cpu.stat    tasks
[root@kibana dd5782cde89d7084de43e8c343f6cbbe99e5b12226e037b7e5529a35d05bce55]# cat cpu.cfs_quota_us 
-1

備註:

cpu週期 1s 100000

按照cpu時間週期分配

cpu在一個時刻,只能給一個進程佔用

cpu的衡量單位是秒

1.2 對容器cpu的限制方法

以20%爲例

1.2.1 創建時指定限制

[root@kibana ~]# docker run -itd --name tese13 --net net172.18/16 --ip 172.18.0.11 --cpu-quota 20000 centos:7 /bin/bash
7bee273b367147dd9ef7946229ad316f12b095be268ef2c1e8a5078ba47f7ed6
[root@kibana ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7bee273b3671        centos:7            "/bin/bash"         3 seconds ago       Up 2 seconds                            tese13
dd5782cde89d        centos:7            "/bin/bash"         About an hour ago   Up About an hour                        test3
de37ff32e2c4        centos:7            "/bin/bash"         2 hours ago         Up 2 hours                              test1

或者

1.2.2 修改文件參數

[root@kibana ~]# echo 20000 > /sys/fs/cgroup/cpu/docker/7bee273b367147dd9ef7946229ad316f12b095be268ef2c1e8a5078ba47f7ed6/cpu.cfs_quota_us 
[root@kibana ~]#echo 20000 》

可以使用–help查看命令

[root@kibana ~]# docker run --help

對容器CPU進行BC壓力測試,測試之前新開一臺終端,top,然後按1

[root@kibana ~]# docker exec -it tese13 /bin/bash
[root@7bee273b3671 /]# yum install bc -y 

在這裏插入圖片描述

[root@7bee273b3671 /]# echo "scale=5000;4*a(1)" | bc -l -q

解釋:a是bc的一個內置函數,代表反正切arctan,由於 tan(pi/4)=1,於是4*arctan(1) = pi

在這裏插入圖片描述

bc的cpu佔用率被限制在20
備註:
種方法是絕對限制

Docker 提供了–cpu-period、–cpu-quota兩個參數控制容器可以分配到的cpu時鐘週期

–cpu-period是用來指定容器對CPU的使用要在多長時間內做一次重新分配

–cpu-quota是用來指定在這個週期內,最多可以有多少時間用來跑這個容器

與–cpu-shares不同的是,這種配置是指定一個絕對值,容器對CPU資源的使用絕對不會超過配置的值

–cpu-period和–cpu-quota的單位爲微秒(1秒=1的六次方微秒),cpu-period的最小值爲1000微秒,最大值爲1000000微秒(1秒),默認值是0.1秒

–cpu-quota的默認值爲-1,代表不做控制。

–cpu-period和–cpu-quota參數一般聯合使用

例如:容器進程需要每一秒使用單個CPU的0.2秒時間,可以將–cpu-period設置爲1秒,cpu-quota值設爲0.2秒

當然,在多核情況下,如果允許容器進程完全佔用兩個cpu,可以將cpu-period設爲0.1秒,cpu-quota設置0.2秒

[root@localhost stress]# docker ru  -itd --cpu-period 100000 --cpu-quota 200000 centos:stress
[root@localhost stress]# docker exec -it 容器ID
[root@localhost stress]# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us
[root@localhost stress]# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us

1.2.3 創建時按比例分配CPU資源

創建兩個容器爲C1和C2,若只有這兩個容器,設置容器的權重,使得C1和C2的CPU資源佔比爲33.3%和66.7%

[root@kibana ~]# docker run -itd --name c1 --network net172.18/16 --ip 172.18.0.21 --cpu-shares 512 centos:7 /bin/bash
9128e8cb60893a90eaf6575e7b36f104574bf22282311553a19b7dc56cf77045
[root@kibana ~]# docker run -itd --name c2 --network net172.18/16 --ip 172.18.0.22 --cpu-shares 512 centos:7 /bin/bash
b85c3fd567e8d30c4888243ee5f05167bf89e4cbb43a5b6d5499b81914775751
docker run -itd --name c1 --cpu-shares 512 centos:7

docker run -itd --name c2 --cpu-shares 1024 centos:7
[root@kibana ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
b85c3fd567e8        centos:7            "/bin/bash"         48 seconds ago       Up 47 seconds                           c2
9128e8cb6089        centos:7            "/bin/bash"         About a minute ago   Up About a minute                       c1
7bee273b3671        centos:7            "/bin/bash"         59 minutes ago       Up 59 minutes                           tese13
dd5782cde89d        centos:7            "/bin/bash"         2 hours ago          Up 2 hours                              test3
de37ff32e2c4        centos:7            "/bin/bash"         3 hours ago          Up 3 hours                              test1

分別進容器測試,在top查看,或者docker stats 查看狀態

[root@kibana ~]# docker stats
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
b85c3fd567e8        c2                  0.00%               392KiB / 1.781GiB   0.02%               648B / 0B           0B / 0B             1
9128e8cb6089        c1                  0.00%               392KiB / 1.781GiB   0.02%               648B / 0B           0B / 0B             1
7bee273b3671        tese13              0.00%               272KiB / 1.781GiB   0.01%               14.9MB / 123kB      0B / 0B             1
dd5782cde89d        test3               0.00%               944KiB / 1.781GiB   0.05%               15.1MB / 175kB      0B / 0B             3
de37ff32e2c4        test1               0.00%               80KiB / 1.781GiB    0.00%               15.1MB / 158kB      0B / 0B             1

進入c1,c2,安裝壓力測試軟件stress

[root@kibana ~]# docker exec -it c1 /bin/bash
[root@9128e8cb6089 /]# yum install epel-release -y
[root@9128e8cb6089 /]# yum install stress -y
[root@kibana ~]# docker exec -it c2 /bin/bash
[root@b85c3fd567e8 /]# yum install epel-release -y
[root@b85c3fd567e8 /]# yum install stress -y

c1,c2測試

[root@b85c3fd567e8 /]# stress -c 4
[root@9128e8cb6089 /]# stress -c 4

在這裏插入圖片描述

在這裏插入圖片描述
備註:命令中的–cpu-shares參數值不能保證可以獲得一個vcpu或者多少GHz的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 share設置使用CPU的優先級,比如啓動了兩個容器及運行查看CPU使用百分比

[root@localhost stress]# docker run -itd --name cpu512 --cpu-shares 512 centos:stress -c 10
#容器產生10個子函數進程
[root@localhost stress]# docker exec -it cpu512 bash
#進入容器使用top查看cpu使用情況

再開一個容器做比較

[root@localhost stress]# docker run -itd --name cpu1024 --cpu-shares 1024 centos:stress -c 10
[root@localhost stress]# docker exec -it cpu1024 bash
#進入容器使用top對比兩個容器的%CPU,比例是1:2

1.2.4 限制容器使用指定的CPU core

對多核CPU的服務器,Docker還可以控制容器運行使用哪些CPU內核,即使用–cpuset-cpus參數

這對具有多cpu的服務器尤爲有用,可以對需要高性能計算的容器進行性能優化的配置
當前cpu核數爲4核

驗證方法:top 然後按1檢查

在這裏插入圖片描述

[root@kibana ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
b85c3fd567e8        centos:7            "/bin/bash"         About an hour ago   Exited (137) 37 minutes ago                       c2
9128e8cb6089        centos:7            "/bin/bash"         About an hour ago   Exited (137) 37 minutes ago                       c1
7bee273b3671        centos:7            "/bin/bash"         2 hours ago         Exited (137) 37 minutes ago                       tese13
dd5782cde89d        centos:7            "/bin/bash"         4 hours ago         Exited (137) 37 minutes ago                       test3
de37ff32e2c4        centos:7            "/bin/bash"         4 hours ago         Exited (137) 37 minutes ago                       test1

批量刪除容器

[root@kibana ~]# docker ps -a | awk '{print "docker rm "$1}' | bash
Error: No such container: CONTAINER
b85c3fd567e8
9128e8cb6089
7bee273b3671
dd5782cde89d
de37ff32e2c4
[root@kibana ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

創建容器,指定cpuID給容器test02

[root@kibana ~]# docker run -idt --name test02 --cpuset-cpus 1,3 centos:7 /bin/bash
ad53ee764486d1b26ff664b62dc6b2056269d605967e45799f1b369d08cb4c4b
[root@kibana ~]# 

進入容器,壓測檢查

[root@ad53ee764486 /]# yum install stress epel-release -y
[root@ad53ee764486 /]# stress -c 4

在這裏插入圖片描述

top 然後按1檢查

只有指定的內核在運轉
備註:

[root@localhost stress]# docker run -itd --name cpu1 --cpuset-cpus 0-1 centos:stress

執行以上命令需要宿主機爲雙核,表示創建的容器只能用0、1兩個內核,最終生成的cgroup的cpu內核配置如下

[root@localhost stress]# docker exec -it cpu1 bash
[root@localhost stress]# cat /sys/fs/cgroup/cpuset/cpuset.cpus
0-1

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

[root@localhost stress]# docker exec cpu1 taskset -c -p 1
#容器內部第一個進程號pid爲1的被綁定到指定CPU上運行
pid 1's current affinity list: 0,1

1.2.5 cpu配額控制參數的混合使用

通過 cpuset-cpus參數指定容器A使用cpu內核0,容器B用cpu內核1

在主機上只有這兩個容器使用相對應cpu內核的情況下,它們各自佔用全部的內核資源,cpu-shares沒有明顯效果

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

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

宿主系統爲4核心地情況下

[root@localhost stress]# docker run -itd --name cpu3 --cpuset-cpus 1 --cpu-shares 512 centos:stress stress -c 1
[root@localhost stress]# docker exec it cpu3 bash
[root@localhost 容器ID]# top
[root@localhost 容器ID]#exit
[root@localhost stress]# top #記住按1查看每個核心地佔用

再創建一個

[root@localhost stress]# docker run -itd --name cpu4 --cpuset-cpus 2 --cpu-shares 1024 centos:stress stress -c 1

總結:上面地centos:stress鏡像安裝了stress工具,用來測試cpu和內存地負載,通過在兩個容器上分別執行stress -c 1命令,將會給系統一個隨機負載,產生一個進程,這一個進程都反覆不停地計算由rand()產生隨機數地平方根,直到資源耗盡

觀察到宿主機地cpu使用率,創建容器時指定地cpu使用率接近100%,並且一批進程地cpu使用率明顯存在2:1地使用比例地對比

二: docker資源控制——Mem

限制內存使用

docker run -itd --name testm -m 512m centos:7 /bin/bash

[root@kibana ~]# docker run -itd --name testm -m 512m centos:7 /bin/bash
[root@kibana ~]# docker stats

在這裏插入圖片描述

進入容器驗證

[root@fc4e53fcf5c9 /]# yum install epel* -y
[root@fc4e53fcf5c9 /]# yum install stress -y
[root@fc4e53fcf5c9 /]# stress -m 512m --vm 2

備註:
與操作系統類似,容器可使用地內存包括兩部分:物理內存和swap

docker通過下面兩組參數來控制容器內存地使用量

-m或–memory:設置內存地使用限額,例如100m或者1024m

–memory-swap:設置內存+swap地使用限額

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

[root@localhost stress]# docker run -itd --name memswap1 -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M

–vm 1:啓動一個內存工作線程

–vm-bytes 280M:每個線程分配280M內存

默認情況下,容器可以使用主機上的所有空閒內存,與cpu的cgroups配置類似,docker會自動爲容器在宿主目錄/sys/fs/group/memory/docker/容器完整ID/中創建相應的cgroup配置文件

如果讓工作線程分配的內存超過300M,分配的內存超過限額,tress線程報錯,容器異常退出

[root@localhost stress]# docker run -itd -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M

三:docker資源控制——IOps和bps

bps是byte per seconds,每秒讀寫的數據量
iops是 io per seconds,每秒IO的次數
對block的IO進行限制

控制數據量用的多

控制IO次數用的不太多

–device-read-bps:限制讀某個設備的bps(數據量)

例:docker run -d --device-read-bps /dev/sda:30M centos:7

–device-write-bps:限制某個寫入設備的bs(數據量)

例:docker run -d --device-write-bps /dev/sda:30 centos:7

–device-read-iops:限制讀某個設備的iops(次數)

–device-write-iops:限制寫入某個設備的iops(次數)
限制容器流量在30M每秒

[root@kibana ~]# docker run -tid --name testi --device-read-bps /dev/sda:30M centos:7 /bin/bash
[root@kibana ~]# docker stats
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章