Docker資源控制的Cgroup參數使用

一、Cgroup簡介

  • Cgroup 是Control Groups的縮寫,是Linux 內核提供的一種可以限制、記錄、隔離進程組所使用的物理資源(如CPU、 內存、磁盤IO等等)的機制,被LXC、docker等很多項目用於實現進程資源控制。

  • Cgroups提供了以下功能:

1、限制進程組可以使用的資源數量(Resource limiting )。比如:memory子系統可以爲進程組設定一個memory使用上限,一旦進程組使用的內存達到限額再申請內存,就會觸發OOM(out of memory)。

2、進程組的優先級控制(Prioritization )。比如:可以使用cpu子系統爲某個進程組分配特定cpu share。

3、記錄進程組使用的資源數量(Accounting )。比如:可以使用cpuacct子系統記錄某個進程組使用的cpu時間

4、進程組隔離(Isolation)。比如:使用ns子系統可以使不同的進程組使用不同的namespace,以達到隔離的目的,不同的進程組有各自的進程、網絡、文件系統掛載空間。

5、進程組控制(Control)。比如:使用freezer子系統可以將進程組掛起和恢復。

[root@master tls]# cat /proc/cgroups 
#subsys_name    hierarchy       num_cgroups     enabled
cpuset  4       1       1
cpu     6       85      1
cpuacct 6       85      1
memory  7       85      1
devices 10      85      1
freezer 9       1       1
net_cls 5       1       1
blkio   3       85      1     
perf_event      8       1       1
hugetlb 11      1       1
pids    2       1       1
net_prio        5       1       1

cpuset:如果是多核心的CPU, 這個子系統會爲cgroup 任務分配單獨的CPU和內存。
CPU:使用調度程序爲cgroup任務提供CPU的訪問。
cpuacct:產生cgroup, 任務的CPU資源報告
memory: 設置每個cgroup 的內存限制以及產生內存資源報告。
devices:允許或拒絕cgroup任務對設備的訪問。
freezer:暫停和恢復cgroup任務。
net_cls: 標記每個網絡包以供cgroup 方便使用。
blkio:設置限制每個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb 等等。
ns:命名空間子系統。
perf_event: 增加了對每個group 的監測跟蹤的能力,可以監測屬於某個特定的group 的所有線程以及運行在特定CPU上的線程。

二、基於Dockerfile創建安裝stress鏡像

stress是用來測試cpu內存的負載,通過在兩個容器分別執行stress -c 1,這將會給系統一個隨機負載,產生一個進程,這個進程會反覆不停地計算由rand()產生地隨機數的平方根,直到資源耗盡。

首先使用Dockerfile創建一個基於centos的stress的工具鏡像

[root@master tls]# mkdir /stress
[root@master tls]# cd /stress/
[root@master stress]# vi Dockerfile   #文件內容在下圖中

在這裏插入圖片描述

//安裝鏡像
[root@master stress]# docker build -t centos:stress .  
[root@master stress]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              stress              d5b03b3a7589        2 minutes ago       466MB
nginx               latest              602e111c06b6        2 days ago          127MB
centos              7                   5e35e350aded        5 months ago        203MB    

三、創建容器的CPU權重控制

  • 默認情況下,每個docker容器的cpu份額都是1024,單獨一個容器的份額是沒有意義的,只有在同時運行多個容器時,容器cpu的加權效果才能體現出現。

  • 例如,兩個容器A、B的cpu份額分別爲1000和500,在cpu進行時間片分配的時候,容器A比容器B多一倍的機會獲得cpu的時間片,但是分配的結果取決於當時主機和其他容器的運行狀態,實際上也無法保證容器A一定能夠獲得cpu的時間片。比如容器A的進程一直是空閒的,那麼容器B是可以獲取比容器A更多的cpu時間片的,極端情況下,例如主機上只運行的一個容器,即使它的cpu份額只有50,它也可以獨佔整個主機的cpu資源

  • cgroups只在容器分配的資源緊缺時,即需要對容器使用的資源進行限制時,纔會生效。因此,無法單純的根據某個容器的份額的cpu份額來確定有多少cpu資源分配給它,可以通過cpu share參數可以設置容器使用cpu的優先級,比如啓動了兩個容器及運行查看cpu的cpu的使用百分比

  • 創建兩個容器,分別制定不同的權重比

// --cpu-shares 指定使用cpu的權重
// stress -c 指定產生子進程的個數
[root@master ~]# docker run -itd --name cpu512 --cpu-shares 512 centos:stress stress -c 10
[root@master ~]# docker run -itd --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10

[root@master ~]# docker ps -a    #查看容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f68bc1d06b72        centos:stress       "stress -c 10"      10 seconds ago      Up 8 seconds                            cpu1024
ab0e0020144b        centos:stress       "stress -c 10"      6 minutes ago       Up 6 minutes                            cpu512

##進入容器使用top命令查看cpu的使用率
[root@master ~]# docker exec -it cpu512 bash
[root@ab0e0020144b /]# top

在這裏插入圖片描述

[root@master ~]# docker exec -it cpu1024 bash
[root@f68bc1d06b72 /]# top

在這裏插入圖片描述
分別進入cpu512和cpu1024之後可以看到,%cpu的比例差不多是1:2,符合我們設置的–cpu-shares參數。

四、cpu週期限制

  • Docker提供了 --cpu-period、–cpu-quota兩個參數控制容器可以分配到cpu的時鐘週期。
// --cpu-period是用來指定容器對於cpu的使用要在多長時間內重新分配一次
// --cpu-quota是用來指定在這個週期內,最多可以有多少時間跑這個容器,
   與--cpu-shares(權重)不同的是,這種配置指定一個絕對值,容器對cpu資源使用絕對不會超過配置的值。
  • cpu-peiod和cpu-quota參數一般聯合使用。
  • 例如:容器進程需要每一秒鐘使用單個cpu的0.2時間,可以將 --cpu-period設置爲1000000(1秒),–cpu-quota設置爲200000(0.2秒)。
    當然,在多核情況下,如果允許容器進程完全佔用兩個cpu,則可以將cpu-period設置爲100000(0.1秒),cpu-quota設置爲200000(0.2秒)
//設置 --cpu-period爲0.1秒,--cpu-quota爲0.2秒
[root@master ~]# docker run -itd --cpu-period 100000 --cpu-quota 200000 centos:stress 
7fc4d48428fa3fc7527e7ece2f504307f13d83414e3714aa187d86356ba596d2

[root@master ~]# docker ps -a    #查看容器ID號
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
7fc4d48428fa        centos:stress       "/bin/bash"         12 seconds ago      Up 11 seconds                                     priceless_bell
f68bc1d06b72        centos:stress       "stress -c 10"      28 minutes ago      Exited (137) 18 minutes ago                       cpu1024
ab0e0020144b        centos:stress       "stress -c 10"      35 minutes ago      Exited (137) 18 minutes ago                       cpu512

[root@master ~]# docker exec -it 7fc4d48428fa bash        #使用ID號進入容器

//查看容器cgroup參數
[root@7fc4d48428fa /]# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us    
100000
[root@7fc4d48428fa /]# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us  
200000

在這裏插入圖片描述

五、cpu core控制

  • 對於多核cpu的服務器,docker還可以控制容器運行使用那些cpu內核,以及使用–cpuset-cpus參數,這對於具有多cpu服務器尤其有用,可以對需要高性能計算的容器進行性能最優的配置。
//執行以下命令需要宿主機爲雙核,表示創建的容器只能使用0、1兩個內核,最終生成cgroup的cpu內核配置如下:

[root@master ~]# docker run -itd --name cpu1 --cpuset-cpus 0-1 centos:stress 
1c2e16cd9d63cf4e429b91cb41a357a91b03287234b9e123966e3871113d5ce2
[root@master ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
1c2e16cd9d63        centos:stress       "/bin/bash"         9 seconds ago       Up 9 seconds                                      cpu1
 
[root@master ~]# docker exec -it cpu1 bash
[root@1c2e16cd9d63 /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus
0-1
 
//通過下列指令可以看到容器中進程與cpu內核的綁定關係,達到綁定cpu內核的目的
[root@master ~]# docker exec -it 1c2e16cd9d63 taskset -c -p 1    #容器內部的第一個進程號pid爲1,被綁定到指定到的cpu上運行
pid 1's current affinity list: 0,1

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

  • 通過cpuset-cpus參數指定容器A使用cpu內核0,容器B使用cpu內核1。
    在主機上只有這個兩個容器使用對應的cpu內核情況,它們各自佔用全部的內核資源,cpu-shares沒有明顯的效果。
  • cpuset-cpus、cpuset-mems參數只在多核、內存節點上服務器有效,並且必須與實際的物理配置匹配,否則也無法達到資源控制的目的。
  • 在系統具有多個cpu內核的情況下,需要通過cpuset-cpus參數爲設置容器cpu內核才能方便進行測試
//宿主機系統修改爲4核心
[root@master ~]# docker run -itd --name cpu2 --cpuset-cpus 1 --cpu-shares 512 centos:stress stress -c 1
[root@master ~]# docker run -itd --name cpu3 --cpuset-cpus 3 --cpu-shares 1024 centos:stress stress -c 1

 ##分別進入cpu2和cpu3查看cpu使用率,有下面數據可知,cpu1和3使用率達到了100%,權重對它們沒有影響
[root@master ~]# docker exec -it cpu2 bash
[root@be8bf29e69a8 /]# top

在這裏插入圖片描述

[root@master ~]# docker exec -it cpu3 bash
[root@152fde97b135 /]# top

在這裏插入圖片描述

七、內存限制

  • 與操作系統類似,容器可使用的內存包括兩部分:物理內存和swap
    容器通過 -m或–memory設置內存的使用限額,例如:-m 300M;通過–memory-swap設置內存+swap的使用限額

  • 實例如下,允許容器最多使用200M的內存和300M的swap

[root@master ~]#  docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
// --vm 1 ,代表啓動一個內存工作線程
// --vm-bytes 280 M ,代表每個線程可以分配280M內存
  • 默認情況下,容器可以使用主機上的所有空閒內存。
    上述配置與cpu的cgroup的配置類似,Docker會自動爲容器目錄/sys/fs/cgroup/memory/docker/<容器ID> 中創建相應的cgroup的配置文件
    在這裏插入圖片描述
    注:如果分配的內存超過限額,stress線程就會報錯,容器會自動退出
    在這裏插入圖片描述

八、Block IO的限制

默認情況下,所有容器能平等地讀寫磁盤,可以通過設置–blkio-weight參數來改變容器block IO的優先級。

//--blkio-weight 與--cpu-shares 類似,設置的是相對權重值,默認爲500。

[root@master ~]# docker run -it --name container_A --blkio-weight 600 centos:stress   #指定權重600
[root@c21c48529aed /]# cat /sys/fs/cgroup/blkio/blkio.weight
600
[root@c21c48529aed /]# exit
exit
[root@master ~]# docker run -it --name container_B --blkio-weight 300 centos:stress   #指定權重值300
[root@a2a8cb6ddecc /]# cat /sys/fs/cgroup/blkio/blkio.weight
300

九、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 的速率爲5 MB/s

[root@master ~]# docker run -it --device-write-bps /dev/sda:5MB centos:stress 
[root@da0e26f19149 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct 
//按ctrl+c中斷查看

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

結果表明限速5MB/s 左右。作爲對比測試,創建一個普通容器,沒有做限速,查看其寫速度。

[root@master ~]# docker run -it centos:stress 
[root@c157255f82d9 /]# dd if=/dev/zero of=test2 bs=1M count=1024 oflag=direct   

在這裏插入圖片描述
在多個容器運行時,必須使用上述的參數設置優化,不能把所有的資源給其中一個容器,會造成資源浪費,容器不穩定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章