容器基礎(二)之程序的資源限制

2022-07-06 22:30:20 字數 4085 閱讀 4873

結論:對於 docker 等大多數 linux 容器來說,cgroups 技術是用來製造約束的主要手段,而 namespace 技術則是用來修改程序檢視的主要方法。

在介紹完容器的」隔離「技術之後,我們再來說說容器的」限制「問題。

我還是以pid namespace為例,來給你解釋這個問題。

雖然容器內的1號程序在」障眼法「的干擾下只能看到容器裡的情況,但是宿主機上,它作為第100號程序與其他程序之間依然是平等的競爭關係。這就意味著,雖然第100號程序表面上被隔離起來了, 但是它能夠使用到的資源(比如cpu、記憶體),卻是可以隨便被宿主機上的其他程序(或容器)占用。

當然,這個100號程序自己也可能把所有資源都吃光。這些情況,顯然都不是乙個」沙盒「應用該表現出來的合理行為。

而linux cgroup就是linux核心中用來為程序設定資源限制的乙個重要功能。

linux cgroup的全稱是linux control group。它最主要的作用,就是限制乙個程序組能夠使用的資源上限,包括cpu、記憶體、磁碟、網路頻寬等。

此外,cgroup還能夠對程序進行優先順序設定、審計,以及將程序掛起和恢復等操作。

在 linux 中,cgroups 給使用者暴露出來的操作介面是檔案系統,即它以檔案和目錄的方式組織在作業系統的 /sys/fs/cgroup 路徑下。在 ubuntu 16.04 機器裡,我可以用 mount 指令把它們展示出來,這條命令是:

$ mount -t cgroup 

cpuset on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)

cpu on /sys/fs/cgroup/cpu type cgroup (rw,nosuid,nodev,noexec,relatime,cpu)

cpuacct on /sys/fs/cgroup/cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct)

blkio on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)

memory on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)

...

可以看到,在 /sys/fs/cgroup 下面有很多諸如 cpuset、cpu、 memory 這樣的子目錄,也叫子系統。這些都是我這台機器當前可以被 cgroups 進行限制的資源種類。而在子系統對應的資源種類下,你就可以看到該類資源具體可以被限制的方法。比如,對 cpu 子系統來說,我們就可以看到如下幾個配置檔案,這個指令是:

$ ls /sys/fs/cgroup/cpu

cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release

cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks

而這樣的配置檔案又如何使用呢?

你需要在對應的子系統下面建立乙個目錄,比如,我們現在進入 /sys/fs/cgroup/cpu 目錄下:

root@ubuntu:/sys/fs/cgroup/cpu$ mkdir container

root@ubuntu:/sys/fs/cgroup/cpu$ ls container/

cgroup.clone_children cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release

cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks

這個目錄就稱為乙個「控制組」。你會發現,作業系統會在你新建立的 container 目錄下,自動生成該子系統對應的資源限制檔案。

現在,我們在後台執行這樣一條指令碼:

$ while : ; do : ; done &

[1] 226

顯然,它執行了乙個死迴圈,可以把計算機的 cpu 吃到 100%,根據它的輸出,我們可以看到這個指令碼在後台執行的程序號(pid)是 226。

這樣,我們可以用 top 指令來確認一下 cpu 有沒有被打滿:

$ top

%cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

在輸出裡可以看到,cpu 的使用率已經 100% 了(%cpu0 :100.0 us)。

而此時,我們可以通過檢視 container 目錄下的檔案,看到 container 控制組裡的 cpu quota 還沒有任何限制(即:-1),cpu period 則是預設的 100  ms(100000  us):

$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us 

-1$ cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us

100000

接下來,我們可以通過修改這些檔案的內容來設定限制。

比如,向 container 組裡的 cfs_quota 檔案寫入 20  ms(20000  us):

$ echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

結合前面的介紹,你應該能明白這個操作的含義,它意味著在每 100  ms 的時間裡,被該控制組限制的程序只能使用 20  ms 的 cpu 時間,也就是說這個程序只能使用到 20% 的 cpu 頻寬。

接下來,我們把被限制的程序的 pid 寫入 container 組裡的 tasks 檔案,上面的設定就會對該程序生效了:

$ echo 226 > /sys/fs/cgroup/cpu/container/tasks

我們可以用 top 指令檢視一下:

$ top

%cpu0 : 20.3 us, 0.0 sy, 0.0 ni, 79.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

可以看到,計算機的 cpu 使用率立刻降到了 20%(%cpu0 : 20.3 us)。

除 cpu 子系統外,cgroups 的每乙個子系統都有其獨有的資源限制能力,比如:

blkio,為​​​塊​​​設​​​備​​​設​​​定​​​i/o 限​​​制,一般用於磁碟等裝置;

cpuset,為程序分配單獨的 cpu 核和對應的記憶體節點;

memory,為程序設定記憶體使用的限制。

linux cgroups 的設計還是比較易用的,簡單粗暴地理解呢,它就是乙個子系統目錄加上一組資源限制檔案的組合。而對於 docker 等 linux 容器專案來說,它們只需要在每個子系統下面,為每個容器建立乙個控制組(即建立乙個新目錄),然後在啟動容器程序之後,把這個程序的 pid 填寫到對應控制組的 tasks 檔案中就可以了。而至於在這些控制組下面的資源檔案裡填上什麼值,就靠使用者執行 docker run 時的引數指定了,比如這樣一條命令:

$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash

在啟動這個容器後,我們可以通過檢視 cgroups 檔案系統下,cpu 子系統中,「docker」這個控制組裡的資源限制檔案的內容來確認:

$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us 

100000

$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us

20000

這就意味著這個 docker 容器,只能使用到 20% 的 cpu 頻寬。

容器的資源限制

我們在建立虛擬機器時,會根據物理機的硬碟 cpu等資源對虛擬機器的資源進行限制,同樣的容器也可以對其進行資源限制,我們先看看docke runr中的命令 root localhost vagrant docker run help 其中,有關於對memory做限制的 m,memory bytes m...

容器的資源限制實戰

目錄 一 虛擬化技術如何限制資源?二 為容器執行限定記憶體 三 為容器執行限定cpu vmvare 安裝的虛擬機器可以通過介面設定cpu 記憶體.的資源限制,如下圖。docer 容器也同樣可以通過指定引數來達到這個目的。其原理為何?請參見 我的環境是一台阿里雲伺服器。通過docker run hel...

限制程序使用的資源

getrlimit和setrlimit函式 每個程序都有一組資源限制,其中某一些可以用getrlimit和setrlimit函式查詢和更改。include include int getrlimit int resource,struct rlimit rlptr int setrlimit int...