控制群組(control groups)
/ see-groups /
命名空間決定一群行程能「看見」什麼;控制群組——簡稱 cgroups——決定它能「用」多少。一個 cgroup 是一個 Linux 核心機制,把一組行程聚在一起,對它們的資源消耗施加限制與計量:能拿多少 CPU 時間、多少記憶體、多少磁碟與網路頻寬。如果命名空間是容器的牆,那 cgroups 就是計量錶與斷路器——打造容器不可或缺的第二半。
你透過一個掛載在 /sys/fs/cgroup 的特殊檔案系統來使用 cgroups,它組織成一棵目錄樹。每個目錄是一個群組;你把某行程的 PID 寫進該群組的 cgroup.procs 檔案,就把它放進群組裡,再透過把數字寫進控制檔來設定限制。例如,寫入 memory.max 就為該群組能用的記憶體設上限——超過了,核心便回收分頁,若回收不來,就對「該群組裡」的某個行程動用記憶體不足殺手(OOM killer),而不是動到系統其餘部分。CPU 控制器讓你給一個群組一個權重(忙碌時的公平份額)或一個硬上限(比方說,不得超過一個核心的 30%)。核心也持續記帳——一個群組消耗了多少 CPU 秒與多少位元組——容器平台便靠這個來計費與監控。現代統一的設計叫做 cgroup v2。
它為何重要:cgroups 正是阻止一個容器餓死它鄰居的東西。沒有它們,一個容器裡失控的行程可能吃光主機的全部記憶體或 CPU、把大家一起拖垮;有了它們,每個容器拿到一份有界、可計量的份額,吵鬧的鄰居就被框住了。誠實的定位是:cgroups 講的是資源限制與公平,「不是」安全隔離——那是命名空間的工作。一個常見的錯誤是想「我限制了 cgroup,所以容器很安全」。它是被「框住」了,不是被「沙箱化」了;你需要 cgroups(管限制)與命名空間(管隔離)兩者、再加上更多東西,才能造出一個真正的容器。
把一個行程放進一個 cgroup 並執行:echo 268435456 > memory.max 把該群組的記憶體上限設為 256 MiB(256 * 1024 * 1024 位元組)。若群組裡的行程配置超過了,核心便在群組「內」回收或動用 OOM 殺手——主機的其餘部分毫髮無傷。
寫入 memory.max 為一個群組的記憶體設上限;超用會在群組內處理,不會波及整台主機。
cgroups 強制的是資源「限制」與計量,不是安全隔離——那是命名空間的工作。「我設了一個 cgroup 限制」不等於「容器被沙箱化了」;那需要命名空間(以及更多)才行。