Cgroup--資源限額

Cgroup--資源限額

1、Cgroup簡介
#爲何要作資源分配  Cgroup cpu ; 內存 ;I/0
    容器共享內核資源的 ,甚至有可能一個容器能把宿主機硬件資源耗盡\
    虛擬機在建立的時候以及作了
#Cgroup 是Control Groups的縮寫,是Linux 內核提供的一種能夠限制、記錄、隔離進程組
    所使用的物理資源(如CPU、 內存、磁盤IO等等)的機制,被LXC、docker等不少項目用於實現進程資源控制。
    Cgroup自己是提供將進程進行分組化管理的功能和接口的基礎結構,I/O或內存的分配控制等具體的資源
    這些具體的資源 管理功能稱爲Cgroup子系統,有如下幾大子系統

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

#Cgroups提供瞭如下功能:

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

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

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

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

五、進程組控制(Control)。好比:使用freezer子系統能夠將進程組掛起和恢復。

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

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

-首先使用Dockerfile建立一個基於centos的stress的工具鏡像
mkdir /opt/stress && cd /opt/stress/
cat > Dockerfile <<EOF
FROM centos:7
MAINTAINER li "li@suning.com"
RUN yum install -y wget
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install -y stress
EOF
docker build -t centos:stress .

#三: 建立容器的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的使用百分比

-建立兩個容器,分別制定不一樣的權重比
-下面利用stress壓力測試工具來測試CPU和內存使用狀況
// --cpu-shares 指定使用cpu的權重
// stress -c 指定產生子進程的個數
docker run -itd --name cpu512 --cpu-shares 512 centos:stress stress -c 10
docker ps -a
docker exec -it ead0f498113f bash
top
docker run -itd --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10
docker ps -a
docker exec -it 9c92d6cfcb82 bash
top
"分別進入cpu512和cpu1024以後能夠看到,%cpu的比例差很少是1:2,符合咱們設置的–cpu-shares參數。"

#4、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秒
docker run -itd --cpu-period 100000 --cpu-quota 200000 centos:stress
docker exec -it a818387b1ab9  bash
cat /sys/fs/cgroup/cpu/cpu.cfs_period_us 
100000
cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us 
200000
"能夠看到剛剛設置的週期限制"

#5、cpu core控制
-對於多核cpu的服務器,docker還能夠控制容器運行使用那些cpu內核,以及使用–cpuset-cpus參數,
 這對於具備多cpu服務器尤爲有用,能夠對須要高性能計算的容器進行性能最優的配置
-執行如下命令須要宿主機爲雙核,表示建立的容器只能使用0、1兩個內核,最終生成cgroup的cpu內核配置以下:
docker run -itd --name cpu1 --cpuset-cpus 0-1 centos:stress 
docker exec -it 0e2b322279d0 bash
cat /sys/fs/cgroup/cpuset/cpuset.cpus
0-1
//經過下列指令能夠看到容器中進程與cpu內核的綁定關係,達到綁定cpu內核的目的
docker exec 0e2b322279d0 taskset -c -p 1     "容器內部的第一個進程號pid爲1,被綁定到指定到的cpu上運行"
pid 1's current affinity list: 0,1'
stress -c 10
"另一個端口top查看只有0-1個核心的cpu資源利用率是100%,其餘核心不受影響"

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

- 經過cpuset-cpus參數指定容器A使用cpu內核0,容器B使用cpu內核1。
  在主機上只有這個兩個容器使用對應的cpu內核狀況,它們各自佔用所有的內核資源,cpu-shares沒有明顯的效果。
- cpuset-cpus、cpuset-mems參數只在多核、內存節點上服務器有效,而且必須與實際的物理配置匹配,不然也沒法達到資源控制的目的。
docker run -itd --name cpu2 --cpuset-cpus 1 --cpu-shares 512 centos:stress stress -c 1

docker run -itd --name cpu3 --cpuset-cpus 3 --cpu-shares 1024 centos:stress stress -c 1

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

## 7、內存限額

- 與操做系統相似,容器可以使用的內存包括兩部分:物理內存和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內存
123
默認狀況下,容器可使用主機上的全部空閒內存。
上述配置與cpu的cgroup的配置相似,Docker會自動爲容器目錄`/sys/fs/cgroup/memory/docker/<容器ID>` 中建立相應的cgroup的配置文件
docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280Mdocker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M

## 8、Block IO的限制

默認狀況下,全部容器能平等地讀寫磁盤,能夠經過設置–blkio-weight參數來改變容器block IO的優先級。
//--blkio-weight 與--cpu-shares 相似,設置的是相對權重值,默認爲500。
//下面的例子中,容器A肚子餓磁盤的帶寬是容器B的兩倍
[root@localhost ~]# docker run -it --name container_A --blkio-weight 600 centos:stress 
[root@58df16aba958 /]# cat /sys/fs/cgroup/blkio/blkio.weight
600

[root@localhost ~]# docker run -it --name container_B --blkio-weight 300 centos:stress 
[root@f27372eaf22a /]# cat /sys/fs/cgroup/blkio/blkio.weight
300

## 9、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。
[root@localhost ~]# docker run -it --device-write-bps /dev/sda:5MB centos:stress 
[root@549a4728c2ac /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct
76+0 records in
76+0 records out
79691776 bytes (80 MB) copied, 15.2013 s, 5.2 MB/s
"ctrl+c中斷查看速率,使用dd命令測試在容器中的讀寫磁盤的速度.由於容器的文件系統是在host/dev/sda上的,在容器中寫文件至關於對host/dev/sda進行寫操做.另外,oflag=direct 指定用direct IO方式寫文件,這樣 --device-write-bps 才能生效"

//結果代表IO讀寫限速5MB左右.做爲對比測試,若是不限速,執行如下命令
[root@localhost ~]# docker run  -it centos:stress 
[root@65d5e313bbe6 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 1.04922 s, 1.0 GB/s
在多個容器運行時,必須使用上述的參數設置優化,不能把全部的資源給其中一個容器,會形成資源浪費,容器不穩定。
相關文章
相關標籤/搜索