天天看點

阿裡PouchContainer資源管理探秘:PouchContainer底層的核心技術

PouchContainer

是阿裡巴巴集團開源的高效、企業級容器引擎技術,擁有隔離性強、可移植性高、資源占用少等特點。可以幫助企業快速實作存量業務容器化,同時提高超大規模下資料中心的實體資源使用率。

資源管理是容器運作時的一個重要的部分,本文将給大家介紹PouchContainer資源管理的常用接口和其對應的底層核心接口,為了讓讀者加深了解,本文為部分接口提供了測試用例。

1. PouchContainer資源管理常用接口

接口 描述
--blkio-weight 塊裝置IO相對權重,取值範圍為0到100之間的整數。
--blkio-weight-device 指定的塊裝置的IO相對權重
--cpu-period 完全公平算法中的period值
--cpu-quota 完全公平算法中的quota值
--cpu-share CPU份額 (相對權重)
--cpuset-cpus 限制容器使用的cpu核
--cpuset-mems 限制容器使用的記憶體節點,該限制僅僅在NUMA系統中生效。
--device-read-bps 限制對某個裝置的讀取速率 ,數字需要使用正整數,機關是kb, mb, or gb中的一個。
--device-read-iops 限制對某個裝置每秒IO的讀取速率,數字需要使用正整數。
--device-write-bps 限制對某個裝置的寫速率 ,數字需要使用正整數,機關是kb, mb, or gb中的一個。
--device-write-iops 限制對某個裝置每秒IO的寫速率,數字需要使用正整數。
-m, --memory 記憶體使用限制。 數字需要使用整數,對應的機關是b, k, m, g中的一個。
--memory-swap 總記憶體使用限制 (實體記憶體 + 交換分區,數字需要使用整數,對應的機關是b, k, m, g中的一個。
--memory-swappiness 調節容器記憶體使用交換分區的選項,取值為0和100之間的整數(含0和100)。
--memory-wmark-ratio

用于計算low_wmark,取值範圍:0到100之間的整數(包含0和100)。

--oom-kill-disable 記憶體耗盡時是否殺掉容器
--oom-score-adj 設定容器程序觸發OOM的可能性,值越大時越容易觸發容器程序的OOM。
--pids-limit 用于限制容器内部的pid數量。

2. PouchContainer資源管理底層的核心技術

2.1 Memory資管管理

對應的核心接口 核心接口描述

cgroup/memory/memory.limit_in_bytes

設定記憶體上限,機關是位元組,也可以使用k/K、m/M或者g/G表示要設定數值的機關。

cgroup/memory/memory.memsw.limit_in_bytes

設定記憶體加上交換分區的使用總量。通過設定這個值,可以防止程序把交換分區用光。
cgroup/memory/memory.swappiness 控制核心使用交換分區的傾向。取值範圍是0至100之間的整數(包含0和100)。值越小,越傾向使用實體記憶體。

cgroup/memory/memory.wmark_ratio

用于計算low_wmark,low_wmark = memory.limit_in_bytes * MemoryWmarkRatio。當memory.usage_in_bytes大于low_wmark時,觸發核心線程進行記憶體回收,當回收到memory.usage_in_bytes小于high_wmark時停止回收。

cgroup/memory/memory.oom_control

如果設定為0,那麼在記憶體使用量超過上限時,系統不會殺死程序,而是阻塞程序直到有記憶體被釋放可供使用時,另一方面,系統會向使用者态發送事件通知,使用者态的監控程式可以根據該事件來做相應的處理,例如提高記憶體上限等。

/proc/$pid/oom_score_adj

設定程序觸發OOM的可能性,值越大時越容易觸發容器程序的OOM。

2.2 cpu資管管理

對應的cgroup接口 cgroup接口描述

cgroup/cpu/cpu.cfs_period_us

負責CPU帶寬限制,需要與

cpu.cfs_quota_us

搭配使用。我們可以将period設定為1秒,将quota設定為0.5秒,那麼cgroup中的程序在1秒内最多隻能運作0.5秒,然後就會被強制睡眠,直到下一個1秒才能繼續運作。

cgroup/cpu/cpu.cfs_quota_us

cpu.cfs_period_us

搭配使用。
cgroup/cpu/cpu.shares 負責CPU比重配置設定的接口。假設我們在cgroupfs的根目錄下建立了兩個cgroup(C1和C2),并且将cpu.shares分别配置為512和1024,那麼當C1和C2争用CPU時,C2将會比C1得到多一倍的CPU占用率。要注意的是,隻有當它們争用CPU時CPU share才會起作用,如果C2是空閑的,那麼C1可以得到全部的CPU資源。
cgroup/cpuset/cpuset.cpus 允許程序使用的CPU清單(例如:0-4,9)。
cgroup/cpuset/cpuset.mems 允許程序使用的記憶體節點清單(例如:0-1)。

2.3 io資管管理

cgroup/blkio/blkio.weight 設定權重值,取值範圍是10至1000之間的整數(包含10和1000)。這跟cpu.shares類似,是比重配置設定,而不是絕對帶寬的限制,是以隻有當不同的cgroup在争用同一個塊裝置的帶寬時,才會起作用。
cgroup/blkio/blkio.weight_device 對具體的裝置設定權重值,這個值會覆寫上述的blkio.weight。

cgroup/blkio/blkio.throttle.read_bps_device

對具體的裝置,設定每秒讀塊裝置的帶寬上限。

cgroup/blkio/blkio.throttle.write_bps_device

設定每秒寫塊裝置的帶寬上限。同樣需要指定裝置。

cgroup/blkio/blkio.throttle.read_iops_device

設定每秒讀塊裝置的IO次數的上限。同樣需要指定裝置。

cgroup/blkio/blkio.throttle.write_iops_device

設定每秒寫塊裝置的IO次數的上限。同樣需要指定裝置。

2.4 其他資源管理接口

cgroup/pids/pids.max 限制程序數

3. PouchContainer資源管理接口詳解與測試方法

以下内容針對各資源管理接口做了詳盡的說明。為了加深讀者了解,部分接口提供有測試用例。用例中的PouchContainer版本為0.4.0。如果在你的鏡像中stress指令不可用,你可以通過sudo apt-get install stress來安裝stress工具。

3.1 Memory資管管理

3.1.1 -m, --memory

可以限制容器使用的記憶體量,對應的cgroup檔案是

cgroup/memory/memory.limit_in_bytes

機關:b,k,m,g

在預設情況下,容器可以占用無限量的記憶體,直至主機記憶體資源耗盡。

運作如下指令來确認容器記憶體的資源管理對應的cgroup檔案。

# pouch run -ti --memory 100M reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/memory/memory.limit_in_bytes"
104857600           

可以看到,當記憶體限定為100M時,對應的cgroup檔案數值為104857600,該數值的機關為位元組,即104857600位元組等于100M。

本機記憶體環境為:

# free -m
              total        used        free      shared  buff/cache   available
Mem:         257755        2557      254234           1         963      254903
Swap:          2047           0        2047           

我們使用stress工具來驗證記憶體限定是否生效。stress是一個壓力工具,如下指令将要在容器内建立一個程序,在該程序中不斷的執行占用記憶體(malloc)和釋放記憶體(free)的操作。在理論上如果占用的記憶體少于限定值,容器會工作正常。注意,如果試圖使用邊界值,即試圖在容器中使用stress工具占用100M記憶體,這個操作通常會失敗,因為容器中還有其他程序在運作。

下面嘗試對一個限制記憶體使用為100M的容器執行一個占用150M記憶體的操作,但容器運作是正常的,沒有出現OOM。

# pouch run -ti --memory 100M reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress stress --vm 1 --vm-bytes 150M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd           

通過以下指令看一下系統的記憶體使用量,你會發現Swap的記憶體占用量有所增加,說明--memory選項沒有限制Swap記憶體的使用量。

#free -m
              total        used        free      shared  buff/cache   available
Mem:         257755        2676      254114           1         965      254783
Swap:          2047          41        2006           

嘗試使用

swapoff -a

指令關閉Swap時我們再次執行早先的指令。從以下log中可以看到,當容器使用記憶體超過限制時會觸發錯誤。

# pouch run -ti --memory 100M reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress stress --vm 1 --vm-bytes 150M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [1](422) kill error: No such process
stress: FAIL: [1](452) failed run completed in 0s
esses
stress: FAIL: [1](422) kill error: No such process
stress: FAIL: [1](452) failed run completed in 0s           

3.1.2 --memory-swap

可以限制容器使用交換分區和記憶體的總和,對應的cgroup檔案是

cgroup/memory/memory.memsw.limit_in_bytes

取值範圍:大于記憶體限定值

運作如下指令來确認容器交換分區的資源管理對應的cgroup檔案。可以看到,當memory-swap限定為1G時,對應的cgroup檔案數值為1073741824,該數值的機關為位元組,即1073741824B等于1G。

# pouch run -ti -m 300M --memory-swap 1G reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"
1073741824           

如下所示,當嘗試占用的記憶體數量超過memory-swap值時,容器出現異常。

# pouch run -ti -m 100M --memory-swap 200M reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress bash -c "stress --vm 1 --vm-bytes 300M"
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [1](416) <-- worker 10 got signal 9
stress: WARN: [1](418) now reaping child worker processes
stress: FAIL: [1](422) kill error: No such process
stress: FAIL: [1](452) failed run completed in 0s           

3.1.3 --memory-swappiness

該接口可以設定容器使用交換分區的趨勢,取值範圍為0至100的整數(包含0和100)。0表示容器不使用交換分區,100表示容器盡可能多的使用交換分區。對應的cgroup檔案是cgroup/memory/memory.swappiness。

# pouch run -ti --memory-swappiness=100 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c 'cat /sys/fs/cgroup/memory/memory.swappiness'
100           

3.1.4 --memory-wmark-ratio

用于計算low_wmark,

low_wmark = memory.limit_in_bytes * MemoryWmarkRatio

。當

memory.usage_in_bytes

大于low_wmark時,觸發核心線程進行記憶體回收,當回收到

memory.usage_in_bytes

小于high_wmark時停止。對應的cgroup接口是

cgroup/memory/memory.wmark_ratio

# pouch run -ti --memory-wmark-ratio=60 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c 'cat /sys/fs/cgroup/memory/memory.wmark_ratio'
60           

3.1.5 --oom-kill-disable

當out-of-memory (OOM)發生時,系統會預設殺掉容器程序,如果你不想讓容器程序被殺掉,可以使用該接口。接口對應的cgroup檔案是

cgroup/memory/memory.oom_control

當容器試圖使用超過限定大小的記憶體值時,就會觸發OOM。此時會有兩種情況,第一種情況是當接口--oom-kill-disable=false的時候,容器會被殺掉;第二種情況是當接口--oom-kill-disable=true的時候,容器會被挂起。

以下指令設定了容器的的記憶體使用限制為20M,将--oom-kill-disable接口的值設定為true。檢視該接口對應的cgroup檔案,

oom_kill_disable

的值為1。

# pouch run -m 20m --oom-kill-disable=true reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c 'cat /sys/fs/cgroup/memory/memory.oom_control'
oom_kill_disable 1
under_oom 0           

oom_kill_disable

:取值為0或1,當值為1的時候表示當容器試圖使用超出記憶體限制時(即20M),容器會挂起。

under_oom:取值為0或1,當值為1的時候,OOM已經出現在容器中。

通過

x=a; while true; do x=$x$x$x$x; done

指令來耗盡記憶體并強制觸發OOM,log如下所示。

# pouch run -m 20m --oom-kill-disable=false reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c 'x=a; while true; do x=$x$x$x$x; done'

[[email protected] /root]
#echo $?
137           

通過上面的log可以看出,當容器的記憶體耗盡的時候,容器退出,退出碼為137。因為容器試圖使用超出限定的記憶體量,系統會觸發OOM,容器會被殺掉,此時under_oom的值為1。我們可以通過系統中cgroup檔案(

/sys/fs/cgroup/memory/docker/${container_id}/memory.oom_control

)檢視

under_oom

的值(

oom_kill_disable

1,under_oom 1)。

當--oom-kill-disable=true的時候,容器不會被殺掉,而是被系統挂起。

3.1.6 --oom-score-adj

參數--oom-score-adj可以設定容器程序觸發OOM的可能性,值越大時越容易觸發容器程序的OOM。當值為-1000時,容器程序完全不會觸發OOM。該選項對應着底層的

/proc/$pid/oom_score_adj

接口。

# pouch run -ti --oom-score-adj=300 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress bash -c "cat /proc/self/oom_score_adj"
300           

3.2 cpu資源管理

3.2.1 --cpu-period

核心預設的Linux 排程CFS(完全公平排程器)周期為100ms,我們通過--cpu-period來設定容器對CPU的使用周期,同時--cpu-period接口需要和--cpu-quota接口一起來使用。--cpu-quota接口設定了CPU的使用值。CFS(完全公平排程器) 是核心預設使用的排程方式,為運作的程序配置設定CPU資源。對于多核CPU,根據需要調整--cpu-quota的值。

對應的cgroup檔案是

cgroup/cpu/cpu.cfs_period_us

。以下指令建立了一個容器,同時設定了該容器對CPU的使用時間為50000(機關為微秒),并驗證了該接口對應的cgroup檔案對應的值。

# pouch run -ti --cpu-period 50000 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/cpu/cpu.cfs_period_us"
50000           

以下指令将--cpu-period的值設定為50000,--cpu-quota的值設定為25000。該容器在運作時可以擷取50%的cpu資源。

# pouch run -ti --cpu-period=50000 --cpu-quota=25000 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress stress -c 1
stress: info: [1] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd           

從log的最後一行中可以看出,該容器的cpu使用率約為50.0%,與預期相符。

# top -n1
top - 17:22:40 up 1 day, 57 min,  3 users,  load average: 0.68, 0.16, 0.05
Tasks: 431 total,   2 running, 429 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 26354243+total, 25960588+free,  1697108 used,  2239424 buff/cache
KiB Swap:  2096636 total,        0 free,  2096636 used. 25957392+avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 53256 root      20   0    7324    100      0 R  50.0  0.0   0:12.95 stress           

3.2.2 --cpu-quota

cgroup/cpu/cpu.cfs_quota_us

# pouch run -ti --cpu-quota 1600 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us"
1600           

--cpu-quota接口設定了CPU的使用值,通常情況下它需要和--cpu-period接口一起來使用。具體使用方法請參考--cpu-period選項。

3.2.3 --cpu-share

對應的cgroup檔案是cgroup/cpu/cpu.shares。

# pouch run -ti --cpu-quota 1600 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/cpu/cpu.shares"
1600           

通過--cpu-shares可以設定容器使用CPU的權重,這個權重設定是針對CPU密集型的程序的。如果某個容器中的程序是空閑狀态,那麼其它容器就能夠使用本該由空閑容器占用的CPU資源。也就是說,隻有當兩個或多個容器都試圖占用整個CPU資源時,--cpu-shares設定才會有效。

我們使用如下指令來建立兩個容器,它們的權重分别為1024和512。

# pouch run -d --cpuset-cpus=0 --cpu-share 1024 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress stress -c 1
c7b99f3bc4cf1af94da35025c66913d4b42fa763e7a0905fc72dce66c359c258

[[email protected] /root]
# pouch run -d --cpuset-cpus=0 --cpu-share 512 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress stress -c 1
1ade73df0dd9939cc65e05117e3b0950b78079fb36f6cc548eff8b20e8f5ecb9           

從如下top指令的log可以看到,第一個容器産生的程序PID為10513,CPU占用率為65.1%,第二個容器産生程序PID為10687,CPU占用率為34.9%。兩個容器CPU占用率約為2:1的關系,測試結果與預期相符。

#top
top - 09:38:24 up 3 min,  2 users,  load average: 1.20, 0.34, 0.12
Tasks: 447 total,   3 running, 444 sleeping,   0 stopped,   0 zombie
%Cpu(s):  3.1 us,  0.0 sy,  0.0 ni, 96.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 26354243+total, 26187224+free,   964068 used,   706120 buff/cache
KiB Swap:  2096636 total,  2096636 free,        0 used. 26052548+avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 10513 root      20   0    7324    100      0 R  65.1  0.0   0:48.22 stress
 10687 root      20   0    7324     96      0 R  34.9  0.0   0:20.32 stress           

3.2.4 --cpuset-cpus

該接口對應的cgroup檔案是cgroup/cpuset/cpuset.cpus。

在多核CPU的虛拟機中,啟動一個容器,設定容器隻使用CPU核1,并檢視該接口對應的cgroup檔案會被修改為1,log如下所示。

# pouch run -ti --cpuset-cpus 1 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/cpuset/cpuset.cpus"
1           

通過以下指令指定容器使用cpu核1,并通過stress指令加壓。

# pouch run -ti --cpuset-cpus 1 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 stress -c 1           

檢視CPU資源的top指令的log如下所示。需要注意的是,輸入top指令并按Enter鍵後,再按數字鍵1,終端才能顯示每個CPU的狀态。

#top
top - 17:58:38 up 1 day,  1:33,  3 users,  load average: 0.51, 0.11, 0.04
Tasks: 427 total,   2 running, 425 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :100.0 us,  0.0 sy,  0.0 ni,  0.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.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st           

從以上log得知,隻有CPU核1的負載為100%,而其它CPU核處于空閑狀态,結果與預期結果相符。

3.2.5 --cpuset-mems

該接口對應的cgroup檔案是cgroup/cpuset/cpuset.mems。

# pouch run -ti --cpuset-mems=0 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/cpuset/cpuset.mems"
0           

以下指令将限制容器程序使用記憶體節點1、3的記憶體。

# pouch run -ti --cpuset-mems="1,3" reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash           

以下指令将限制容器程序使用記憶體節點0、1、2的記憶體。

# pouch run -ti --cpuset-mems="0-2" reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash           

3.3 io資管管理

3.3.1 --blkio-weight

通過--blkio-weight接口可以設定容器塊裝置IO的權重,有效值範圍為10至1000的整數(包含10和1000)。預設情況下,所有容器都會得到相同的權重值(500)。對應的cgroup檔案為cgroup/blkio/blkio.weight。以下指令設定了容器塊裝置IO權重為10,在log中可以看到對應的cgroup檔案的值為10。

# pouch run -ti --rm --blkio-weight 10 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.weight"
10           

通過以下兩個指令來建立不同塊裝置IO權重值的容器。

# pouch run -it --name c1 --blkio-weight 300 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 /bin/bash
# pouch run -it --name c2 --blkio-weight 600 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 /bin/bash           

如果在兩個容器中同時進行塊裝置操作(例如以下指令)的話,你會發現所花費的時間和容器所擁有的塊裝置IO權重成反比。

# time dd if=/mnt/zerofile of=test.out bs=1M count=1024 oflag=direct           

3.3.2 --blkio-weight-device

通過--blkio-weight-device="裝置名:權重"接口可以設定容器對特定塊裝置IO的權重,有效值範圍為10至1000的整數(包含10和1000)。

對應的cgroup檔案為cgroup/blkio/blkio.weight_device。

# pouch run --blkio-weight-device "/dev/sda:1000" reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.weight_device"
8:0 1000           

以上log中的"8:0"表示sda的裝置号,可以通過stat指令來擷取某個裝置的裝置号。從以下log中可以檢視到/dev/sda對應的主裝置号為8,次裝置号為0。

#stat -c %t:%T /dev/sda
8:0           

如果--blkio-weight-device接口和--blkio-weight接口一起使用,那麼Docker會使用--blkio-weight值作為預設的權重值,然後使用--blkio-weight-device值來設定指定裝置的權重值,而早先設定的預設權重值将不在這個特定裝置中生效。

# pouch run --blkio-weight 300 --blkio-weight-device "/dev/sda:500" reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.weight_device"
8:0 500           

通過以上log可以看出,當--blkio-weight接口和--blkio-weight-device接口一起使用的時候,/dev/sda裝置的權重值由--blkio-weight-device設定的值來決定。

3.3.3 --device-read-bps

該接口用來限制指定裝置的讀取速率,機關可以是kb、mb或者gb。對應的cgroup檔案是

cgroup/blkio/blkio.throttle.read_bps_device

# pouch run -it --device /dev/sda:/dev/sda --device-read-bps /dev/sda:1mb reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"
8:0 1048576           

以上log中顯示8:0 1000,8:0表示/dev/sda, 該接口對應的cgroup檔案的值為1048576,是1MB所對應的位元組數,即1024的平方。

建立容器時通過--device-read-bps接口設定裝置讀取速度為500KB/s。從以下log中可以看出,讀取速度被限定為498KB/s,與預期結果相符合。

# pouch run -it --device /dev/sda:/dev/sda --device-read-bps /dev/sda:500k reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash
root@r10f10195:/# dd iflag=direct,nonblock if=/dev/sda of=/dev/null bs=5000k coun
1+0 records in
1+0 records out
5120000 bytes (5.1 MB) copied, 10.2738 s, 498 kB/s           

3.3.4 --device-write-bps

該接口用來限制指定裝置的寫速率,機關可以是kb、mb或者gb。對應的cgroup檔案是

cgroup/blkio/blkio.throttle.write_bps_device

# pouch run -it --device /dev/sda:/dev/sda --device-write-bps /dev/sda:1mB reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"
8:0 1048576           

以上log中顯示8:0 1000,8:0表示/dev/sda, 該接口對應的cgroup檔案的值為1048576,是1MB所對應的位元組數,即1024的平方。

建立容器時通過--device-write-bps接口設定裝置寫速度為1MB/s。從以下log中可以看出,讀取速度被限定為1.0MB/s,與預期結果相符合。

限速操作:

# pouch run -it --device /dev/sdb:/dev/sdb --device-write-bps /dev/sdb:1mB reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash
root@r10d08216:/# dd oflag=direct,nonblock of=/dev/sdb if=/dev/urandom bs=10K count=1000
1024+0 records in
1024+0 records out
10485760 bytes (10 MB) copied, 10.0022 s, 1.0 MB/s           

3.3.5 --device-read-iops

該接口設定了裝置的IO讀取速率,對應的cgroup檔案是

cgroup/blkio/blkio.throttle.read_iops_device

# pouch run -it --device /dev/sda:/dev/sda --device-read-iops /dev/sda:400 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"
8:0 400           

可以通過"--device-read-iops /dev/sda:400"來限定sda的IO讀取速率(400次/秒),log如下所示。

# pouch run -it --device /dev/sda:/dev/sda --device-read-iops /dev/sda:400 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash
root@r10d08216:/# dd iflag=direct,nonblock if=/dev/sda of=/dev/null bs=1k count=1024
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 2.51044 s, 418 kB/s
root@r10d08216:/#           

通過上面的log資訊可以看出,容器每秒IO的讀取次數為400,共需要讀取1024次(log第二行:count=1024),測試結果顯示執行時間為2.51044秒,與預期值2.56(1024/400)秒接近,符合預期。

3.3.6 --device-write-iops

該接口設定了裝置的IO寫速率,對應的cgroup檔案是

cgroup/blkio/blkio.throttle.write_iops_device

# pouch run -it --device /dev/sda:/dev/sda --device-write-iops /dev/sda:400 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash -c "cat /sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"
8:0 400           

可以通過"--device-write-iops /dev/sda:400"來限定sda的IO寫速率(400次/秒),log如下所示。

# pouch run -it --device /dev/sdb:/dev/sdb --device-write-iops /dev/sdb:400 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04 bash
root@r10d08216:/# dd oflag=direct,nonblock of=/dev/sdb if=/dev/urandom bs=1K count=1024
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 2.50754 s, 418 kB/s           

通過上面的log資訊可以看出,容器每秒IO的寫入次數為400,共需要寫1024次(log第二行:count=1024),測試結果顯示執行時間為2.50754秒,與預期值2.56(1024/400)秒接近,符合預期。

3.4 其他資源管理接口

--pids-limit用于限制容器内部的pid數量,對應的cgroup接口是cgroup/pids/pids.max。

# pouch run -ti --pids-limit 100 reg.docker.alibaba-inc.com/sunyuan/ubuntu:14.04stress bash -c "cat /sys/fs/cgroup/pids/pids.max"
100           

如果在容器内部不斷建立新的程序,系統會提示如下錯誤。

bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable           

4. 總結

PouchContainer的資源管理依賴于Linux底層的核心技術,感興趣的讀者可以根據自己興趣補充一些有針對性的測試。關于其依賴的核心技術的實作已經遠超本文的範疇。感興趣的讀者可以自行閱讀核心手冊。

參考資料

PouchContainer社群文檔 Linux Programmer's Manual