如何使用 cgroups 將除白名單之外的所有程序限制為單個 CPU?
Red Hat有一個cgroups 指南,它可能有點幫助(但沒有回答這個問題)。
我知道如何在啟動該程序的命令期間將特定程序限制為特定 CPU,方法是:
首先,將以下*放入
/etc/cgconfig.conf
:mount { cpuset = /cgroup/cpuset; cpu = /cgroup/cpu; cpuacct = /cgroup/cpuacct; memory = /cgroup/memory; devices = /cgroup/devices; freezer = /cgroup/freezer; net_cls = /cgroup/net_cls; blkio = /cgroup/blkio; } group cpu0only { cpuset { cpuset.cpus = 0; cpuset.mems = 0; } }
然後啟動一個程序並使用以下命令將其專門分配給該 cgroup:
cgexec -g cpuset:cpu0only myprocessname
我可以通過(我認為這是正確的)將以下內容自動限制特定程序名稱的所有實例
/etc/cgrules.conf
:# user:process controller destination *:myprocessname cpuset cpu0only
我的問題是:我該如何做相反的事情?
換句話說,我如何將除一組特定的白名單程序*及其子程序之外的所有*程序分配給受限制的 cgroup?**
根據我所研究但尚未測試的內容,我相信部分**解決方案是:
添加一個“不受限制”的 cgroup:
group anycpu { cpuset { cpuset.cpus = 0-31; cpuset.mems = 0; # Not sure about this param but it seems to be required } }
將我的程序顯式分配給不受限制的組,並將其他所有內容分配給受限制的組:
# user:process controller destination *:myprocessname cpuset anycpu * cpuset cpu0only
然而,對此的警告似乎是(從閱讀文件,而不是從測試,所以一粒鹽)的孩子
myprocessname
將被重新分配到受限制的cpu0only
cgroup。一種可能的替代方法是創建一個使用者來執行
myprocessname
,並使該使用者的所有程序不受限制,而其他一切都受到限制。但是,在我的實際案例中,該程序需要由 root 執行,並且還有其他程序也必須由 root 執行,應該受到限制。如何使用 cgroups 完成此任務?
如果 cgroups 無法做到這一點(我現在懷疑是這種情況),我對部分解決方案的想法是否正確,它們會像我想的那樣工作嗎?
免責聲明:這可能不是一個最小的程式碼範例;我不了解所有*部分,所以我不知道哪些是不必要的。
更新:請注意,以下答案適用於 RHEL 6。在 RHEL 7 中,大多數 cgroup 由 systemd 管理,並且不推薦使用 libcgroup。
自從發布這個問題以來,我已經研究了上面連結到的整個指南,以及cgroups.txt文件和cpusets.txt的大部分內容。我現在對 cgroups 的了解比我預期的要多,所以我將在這裡回答我自己的問題。
您可以採取多種方法。我們公司在 Red Hat 的聯繫人(一名技術架構師)建議不要對所有流程進行全面限制,而是採用更具聲明性的方法——僅限制我們特別希望限制的流程。根據他關於該主題的陳述,其原因是系統呼叫可能依賴於使用者空間程式碼(例如 LVM 程序),如果受到限制,可能會減慢系統速度——與預期效果相反。所以我最終限制了幾個特別命名的程序,而把其他一切都放在一邊。
此外,我想提一下我在發布問題時缺少的一些cgroup 基本數據。
Cgroups不依賴於
libcgroup
安裝。 但是,這是一組用於自動處理 cgroup 配置和程序分配給 cgroup 的工具,非常有用。我發現 libcgroup 工具也可能會產生誤導,因為 libcgroup 包是建立在它自己的一組關於您使用 cgroups 的抽象和假設之上的,這與 cgroups 的實際核心級實現略有不同。(我可以舉一些例子,但這需要一些工作;如果您有興趣,請發表評論。)
因此,在使用 libcgroup 工具(例如
/etc/cgconfig.conf
,/etc/cgrules.conf
,cgexec
,cgcreate
,cgclassify
等)之前,我強烈建議您非常熟悉/cgroup
虛擬文件系統本身,並手動創建 cgroups、cgroup 層次結構(包括附加多個子系統的層次結構,libcgroup 偷偷地和洩漏地抽像出來) away),通過執行將程序重新分配給不同的 cgroupecho $the_pid > /cgroup/some_cgroup_hierarchy/a_cgroup_within_that_hierarchy/tasks
,以及在後台執行的其他看似神奇的任務libcgroup
。我缺少的另一個基本概念是,如果
/cgroup
虛擬文件系統完全安裝在您的系統上(或者更準確地說,如果安裝了任何 cgroup 子系統,即“控制器”),那麼整個系統上的每個程序**都在c組。 沒有“某些程序在 cgroup 中,而有些不在”這樣的事情。對於給定的層次結構,有一個所謂的根cgroup,它擁有所連接子系統的所有系統資源。例如,附加了 cpuset 和 blkio 子系統的 cgroup 層次結構將具有一個根 cgroup,該 cgroup 將擁有系統上的所有cpus 和系統上的所有 blkio,並且可以與**子cgroup共享其中一些資源。您不能限制根 cgroup,因為它擁有您系統的所有資源,因此限制它甚至沒有意義。
我還缺少一些關於 libcgroup 的其他簡單數據:
如果使用
/etc/cgconfig.conf
,則應確保將chkconfig --list cgconfig
顯示cgconfig
設置為在系統啟動時執行。如果更改
/etc/cgconfig.conf
,則需要執行service cgconfig restart
以載入更改。(在測試時,停止服務或執行cgclear
的問題很常見。對於調試,我建議,例如,lsof /cgroup/cpuset
如果cpuset
是您正在使用的 cgroup 層次結構的名稱。)如果要使用
/etc/cgrules.conf
,則需要確保“cgroup 規則引擎守護程序”(cgrulesengd
) 正在執行:service cgred start
並且chkconfig cgred on
. (並且您應該注意關於此服務的可能但不太可能出現的爭用情況,如頁面底部第 2.8.1 節中的紅帽資源管理指南中所述。)如果您想手動玩轉並使用虛擬文件系統(我建議首次使用)設置您的 cgroup,您可以這樣做,然後使用其各種選項創建一個
cgconfig.conf
文件來鏡像您的設置。cgsnapshot
最後,當我寫以下內容時,我缺少的關鍵資訊:
但是,對此的警告似乎是…… myprocessname 的孩子將被重新分配給受限制的 cpu0only cgroup。
我是對的,但有一個我不知道的選項。
cgexec
是啟動程序/執行命令並將其分配給 cgroup 的命令。
cgclassify
是將已經執行的程序分配給 cgroup 的命令。這兩者還將阻止
cgred
(cgrulesengd
) 將指定程序重新分配給基於/etc/cgrules.conf
.兩者
cgexec
和都cgclassify
支持該--sticky
標誌,這還可以防止cgred
重新分配基於/etc/cgrules.conf
.所以,我寫的這個問題的答案(雖然不是我最終實施的設置,因為上面提到了我們的紅帽技術架構師的建議)是:
按照我的問題中的描述創建
cpu0only
和cgroup。anycpu
(確保cgconfig
設置為在啟動時執行。)
* cpuset cpu0only
按照我的問題中的描述制定規則。(並確保cgred
設置為在啟動時執行。)啟動我想要不受限制的任何程序:
cgexec -g cpuset:anycpu --sticky myprocessname
.這些程序將不受限制,它們的所有子程序也將不受限制。 系統上的所有其他內容都將被限制為 CPU 0(一旦您重新啟動,因為
cgred
除非它們更改其 EUID,否則不會將 cgrules 應用於已經執行的程序)。這不是完全可取的,但這是我最初要求的,可以使用 cgroups 完成。