Docker通過 Cgroup 來控制容器使用的資源配額,包括 CPU、內存、磁盤三大方面, 基本覆蓋了常見的資源配額和使用量控制。
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上的線程。
被 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 和內存---------------------------------
使用 Dockerfile 來創建一個基於 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資源。
但分配的結果取決於當時主機和其他容器的運行狀態, 實際上也無法保證容器 A一定能獲得CPU時間片。比如容器A的進程一直是空閑的,
那么容器B是可以獲取比容器A更多的CPU時間片的。極端情況下,例如主機上只運行了一個容器,即使它的 CPU 份額只有 50,它也可以獨占整個主機的CPU資源。
Cgroups 只在容器分配的資源緊缺時,即在需要對容器使用的資源進行限制時,才會生效。因此,無法單純根據某個容器的CPU份額來確定有多少CPU資源分配給它,
資源分配 結果取決於同時運行的其他容器的CPU分配和容器中進程運行情況。
可以通過 cpu share 可以設置容器使用 CPU 的優先級,比如啟動了兩個容器及運行查看 CPU 使用百分比。
資源分配 結果取決於同時運行的其他容器的CPU分配和容器中進程運行情況。
可以通過 cpu share 可以設置容器使用 CPU 的優先級,比如啟動了兩個容器及運行查看 CPU 使用百分比。
運行兩個容器
查看內存使用情況


---------------------------------CPU 周期限制---------------------------------
Docker 提供了--cpu-period、--cpu-quota 兩個參數控制容器可以分配到的 CPU 時鍾周期。
--cpu-period 是用來指定容器對 CPU 的使用要在多長時間內做一次重新分配。
--cpu-period 是用來指定容器對 CPU 的使用要在多長時間內做一次重新分配。
--cpu-quota 是用來指定在這個周期內,最多可以有多少時間用來跑這個容器。
與 --cpu-shares 不同的是,這種配置是指定一個絕對值,容器對 CPU 資源的使用絕對不會超過配置的值。
與 --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 參數一般聯合使用。
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 秒)
當然,在多核情況下,如果允許容器進程完全占用兩個 CPU,則可以將 cpu-period 設置為 100000(即 0.1 秒), cpu-quota 設置為 200000(0.2 秒)
---------------------------------CPU Core 控制---------------------------------
對多核 CPU 的服務器,Docker 還可以控制容器運行使用哪些 CPU 內核,即使用--cpuset-cpus 參數。
這對具有多 CPU 的服務器尤其有用,可以對需要高性能計算的容器進行性能最優的配置。
這對具有多 CPU 的服務器尤其有用,可以對需要高性能計算的容器進行性能最優的配置。
CPU內核綁定
看到容器中進程與 CPU 內核的綁定關系,達到綁定 CPU 內核的目的
---------------------------------CPU 配額控制參數的混合使用---------------------------------
通過 cpuset-cpus 參數指定容器 A 使用 CPU 內核 0,容器 B 只是用 CPU 內核 1。
在主機上只有這兩個容器使用對應 CPU 內核的情況,它們各自占用全部的內核資源,cpu-shares 沒有明顯效果。
在主機上只有這兩個容器使用對應 CPU 內核的情況,它們各自占用全部的內核資源,cpu-shares 沒有明顯效果。
cpuset-cpus、cpuset-mems 參數只在多核、多內存節點上的服務器上有效,並且必須與實際的物理配置匹配,否則也無法達到資源控制的目的。
在系統具有多個 CPU 內核的情況下,需要通過 cpuset-cpus 參數為設置容器 CPU 內核才能方便地進行測試。
上面的 centos:stress 鏡像安裝了 stress 工具,用來測試 CPU 和內存的負載。通過 在兩個容器上分別執行 stress -c 1 命令,
將會給系統一個隨機負載,產生 1 個進程。這 個進程都反復不停的計算由 rand() 產生隨機數的平方根,直到資源耗盡。
觀察到宿主機上的 CPU 使用率,第三個內核的使用率接近 100%, 並且一批進程的 CPU 使用率明顯存在 2:1 的使用比例的對比。
---------------------------------內存限額---------------------------------
與操作系統類似,容器可使用的內存包括兩部分:物理內存和 Swap。
Docker 通過下面兩組參數來控制容器內存的使用量。
Docker 通過下面兩組參數來控制容器內存的使用量。
-m 或 --memory:設置內存的使用限額,例如 100M、1024M。
--memory-swap:設置 內存+swap 的使用限額。
執行如下命令允許該容器最多使用 200M 的內存和 300M 的 swap。
--memory-swap:設置 內存+swap 的使用限額。
執行如下命令允許該容器最多使用 200M 的內存和 300M 的 swap。
--vm 1:啟動 1 個內存工作線程。
--vm-bytes 280M:每個線程分配 280M 內存。
默認情況下,容器可以使用主機上的所有空閑內存。
與 CPU 的 cgroups 配置類似, Docker 會自動為容器在目錄 /sys/fs/cgroup/memory/docker/<容器的完整長 ID>
中創建相應 cgroup 配置文件
默認情況下,容器可以使用主機上的所有空閑內存。
與 CPU 的 cgroups 配置類似, Docker 會自動為容器在目錄 /sys/fs/cgroup/memory/docker/<容器的完整長 ID>
中創建相應 cgroup 配置文件
如果讓工作線程分配的內存超過 300M,分配的內存超過限額,stress 線程報錯,容器 退出。
---------------------------------Block IO 的限制---------------------------------
默認情況下,所有容器能平等地讀寫磁盤,可以通過設置--blkio-weight 參數來改變 容器 block IO 的優先級。
--blkio-weight 與 --cpu-shares 類似,設置的是相對權重值,默認為 500。
在下面 的例子中,容器 A 讀寫磁盤的帶寬是容器 B 的兩倍。
--blkio-weight 與 --cpu-shares 類似,設置的是相對權重值,默認為 500。
在下面 的例子中,容器 A 讀寫磁盤的帶寬是容器 B 的兩倍。
---------------------------------bps 和 iops 的限制---------------------------------
bps 是 byte per second,每秒讀寫的數據量。
iops 是 io per second,每秒 IO 的次數。
可通過以下參數控制容器的 bps 和 iops:
iops 是 io per second,每秒 IO 的次數。
可通過以下參數控制容器的 bps 和 iops:
--device-read-bps,限制讀某個設備的 bps。
--device-write-bps,限制寫某個設備的 bps。
--device-read-iops,限制讀某個設備的 iops。
--device-write-iops,限制寫某個設備的 iops。
--device-write-bps,限制寫某個設備的 bps。
--device-read-iops,限制讀某個設備的 iops。
--device-write-iops,限制寫某個設備的 iops。
下面的示例是限制容器寫 /dev/sda 的速率為 5 MB/s。
通過 dd 命令測試在容器中寫磁盤的速度。因為容器的文件系統是在 host /dev/sda 上 的,
在容器中寫文件相當於對 host /dev/sda 進行寫操作。另外,oflag=direct 指定用 direct IO 方式寫文件,
這樣 --device-write-bps 才能生效。
這樣 --device-write-bps 才能生效。
結果表明限速 5MB/s 左右。作為對比測試,如果不限速,結果如下。
