cgroup從入門到懵圈 cgroup概念

2021-08-20 21:25:42 字數 4823 閱讀 7074

從今天起,我要開始寫部落格了。先立個flag在這兒:兩周一篇。萬事開頭難,中間不容易,最後會放棄。請各位看官監督(雖然似乎肯定沒有人看)。

之前有接觸過cgroup,但東西都是同事在做(羨慕),理解不深。所以這個系列的文件,我假裝自己是cgroup菜雞(其實我不需要假裝),從零開始學習cgroup。

cgroup是linux核心實現、用於控制linux系統資源的元件。因此要了解cgroup,首先從引入這個元件的kernel文件中尋找。去到舉世聞名的www.kernel.org**尋找,嘿,找到介紹文件:documentation/cgroup-v1/cgroups.txt

1 什麼是cgroup?

cgroup ,控制組,它提供了一套機制用於控制一組特定程序對資源的使用。cgroup繫結乙個程序集合到乙個或多個子系統上。

subsystem,子系統,乙個通過cgroup提供的工具和介面來管理程序集合的模組。乙個子系統就是乙個典型的「資源控制器」,用來排程資源或者控制資源使用的上限。其實每種資源就是乙個子系統。子系統可以是以程序為單位的任何東西,比如虛擬化子系統、記憶體子系統。

hierarchy,層級樹,多個cgroup的集合,這些集合構成的樹叫hierarchy。可以認為這是乙個資源樹,附著在這上面的程序可以使用的資源上限必須受樹上節點(cgroup)的控制。hierarchy上的層次關係通過cgroupfs虛擬檔案系統顯示。系統允許多個hierarchy同時存在,每個hierachy包含系統中的部分或者全部程序集合。

cgroupfs是使用者管理操縱cgroup的主要介面:通過在cgroupfs檔案系統中建立目錄,實現cgroup的建立;通過向目錄下的屬性檔案寫入內容,設定cgroup對資源的控制;向task屬性檔案寫入程序id,可以將程序繫結到某個cgroup,以此達到控制程序資源使用的目的;也可以列出cgroup包含的程序pid。這些操作影響的是sysfs關聯的hierarchy,對其它hierarchy沒有影響。

對於cgroup,其本身的作用只是任務跟蹤。但其它系統(比如cpusets,cpuacct),可以利用cgroup的這個功能實現一些新的屬性,比如統計或者控制乙個cgroup中程序可以訪問的資源。舉個例子,cpusets子系統可以將程序繫結到特定的cpu和記憶體節點上。

2 為什麼需要cgroup?

這個問題相當於問cgroup重要嗎?有哪些地方用到了。回答是重要,又不重要。如果你用到了,那就重要,如果沒有用到,那就不重要。呵呵呵~~~~其實挺重要的。cgroup的主要運用是資源跟蹤。我接觸的場景就是用cgroup控制虛擬機器程序或者docker程序可以使用的資源。當你想在linux對應用程序做資源訪問控制的時候,cgroup就派上用場了。

3 cgroup怎麼實現的?

——    系統中的每個程序(task_struct,後面用task代指)都持有乙個指向css_set結構的指標。

——    乙個css_set結構體包含了一組指向cgroup_subsys_state物件的指標(所以乙個task可以附加到多個cgroup上),每個cgroup_subsys_state在系統中都有註冊。task結構體沒有直接指向hierarchy中乙個節點(cgroup)的指標。但可以通過其包含的cgroup_subsys_state間接確定。這樣設計的原因是cpu對subsystem state的訪問很頻繁,但涉及到將task繫結到cgroup的操作卻不多。task中還有個雙向鍊錶cg_list,這個鍊錶維護所有同屬於乙個css_set的tasks。

——    使用者可以通過cgroupfs檔案系統來瀏覽cgroup hierarchy。

——    使用者可以列出任意乙個cgroup上附著的task pid

cgroup在kernel中除了本身功能的實現外,在kernel中還有兩處修改:

——    在kernel啟動時對root cgroup的初始化和css_set結構體的初始化。這個在init/main.c檔案中實現。

——    在task的建立(fork)和退出(exit)階段,對應地將task與css_set進行繫結和解綁。

另外,cgroup為了向使用者提供操作介面,特別開發了乙個虛擬檔案系統型別(cgroupfs),這個檔案系統與sysfs,proc類似。cgroupfs是向使用者展示cgroup的hierarchy,通知kernel使用者對cgroup改動的視窗。掛載cgroupfs時通過選項(-otype)指定要掛載的子系統型別,如果不指定,預設掛載所有的註冊的子系統。

如果新掛載的cgroup關聯的hierachy與系統中存在的hierarchy完全一樣,那麼cgroupfs會拒絕掛載。如果沒有匹配到相同的hierarchy,但新掛載hierachy宣告的資源正在被已經存在的hierarchy使用,掛載會報-ebusy錯誤。

當前cgroup還沒有實現向已經存在的cgroup hierarchy繫結新子系統的操作,將子系統從cgroup hierachy解綁也不允許。這些操作在未來也許會支援,但也可能會進一步產生錯誤恢復的一系列問題。

解除安裝cgroupfs時,如果它的子cgroupfs還在活動,那麼子cgroupfs還是會持續生效。直到所有的子cgroupfs不再活動,解除安裝cgroupfs才會真正生效。

cgroupfs下不能再掛載其它型別的檔案系統。所有對cgroup的查詢修改都只通過cgroupfs檔案系統來完成。

系統中的所有task,在/proc/pid目錄下都有乙個名為cgroup的檔案,這個檔案展示了該task相對cgroupfs 根的路徑。通過檢視這個檔案,可以了解乙個程序在cgroup hierarchy的位置。以此得到task可以使用的資源資訊。

cgroupfs中目錄表示cgroup,每個目錄在建立時預設生成如下的屬性檔案,這些檔案描述了cgroup的資訊:

——    tasks: 所有附屬於這個cgroup的程序id列表。tasks檔案中增加程序id,表示將程序加入這個cgroup,程序能夠使用的資源受cgroup限制。

——    cgroup.procs: 所有附屬於這個cgroup執行緒組id,將tgid寫入這個檔案後,tgid所在程序包含的所有執行緒都加入這個cgroup,這些執行緒受cgroup限制。

——    notify_on_release flag: 標記退出時是否執行release agent

——    release_agent: 制定要執行的release agent的路徑,這個屬性檔案只在cgroup的頂層目錄中存在。

以上檔案是每個cgroup基本的屬性檔案,對於不同的子系統,對應的cgroup可能會有其它附加的屬性檔案,存在於其對應的cgroup目錄之下。

通過mkdir命令建立cgroup,通過向目錄下的檔案寫入適當的數值設定修改cgroup的屬性。

巢狀的cgroups,指定了層級結構,以此將系統資源劃分成巢狀的,動態可變的更小的資源塊。

乙個程序可以附加到多個不同的cgroup中,只要這些cgroup不在同乙個層級樹上即可。因為cgroupfs會保證新掛載的cgroup關聯的層級樹全域性唯一。子程序在被建立後預設附加到父程序所在的cgroup,後面使用者可以根據需要將其移動到別的cgroup。

當程序從乙個cgroup被移動到另乙個cgroup。程序的task_struct會獲取乙個新的css_set指標:如果這個cgroup所在的css_set已經存在就重用這個css_set,否則就新分配乙個css_set。kernel會在全域性的hash表中查詢確認cgroup所屬的css_set是否存在。

4 notify_on_release 是做什麼的?

如果cgroup中使能notify_on_release,cgroup中的最後乙個程序被移除,最後乙個子cgroup也被刪除時,cgroup會主動通知kernel。接收到訊息的kernel會執行release_agent檔案中指定的程式。notify_on_release預設是關閉的,release_agent的內容預設為空,子cgroup在建立時會繼承父cgroup中notify_on_relase和release_agent的屬性。所以這兩個檔案只存在於cgroupfs的頂層目錄中。

5 clone_children有什麼用?

clone_chilren僅針對cpu繫結(cpuset),如果clone_children使能,新的cpuset cgroup在初始化時會繼承父cgroup的屬性。

6 cgroup怎麼用?

假設現在要將乙個新的任務加入到cgroup,功能是將該任務的程序在指定的cpu上執行,因此我們使用"cpuset"cgroup 子系統,操作的大致步驟如下:

1)mount -t tmpfs cgroup_root /sys/fs/cgroup 

掛載cgroup根檔案系統,型別為tmpfs

2)mkdir /sys/fs/cgroup/cpuset

在cgroupfs根目錄下建立子cgroup,名為cpuset

3)mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset

將名為cpuset的cgroup關聯到cpuset子系統

4)在cpuset目錄下建立目錄,生成乙個子cgroup,屬性檔案中寫入相應內容,設定屬性。

5)啟動需要限制的程序,查詢其對應的程序id,將其寫入對應的task檔案中

以下操作步驟是建立乙個名為"charlie"的cgroup,這個cgroup的資源包含cpu2,cpu3和記憶體節點1,將shell程序附加到這個cgroup。

mount -t tmpfs cgroup_root /sys/fs/cgroup

mkdir /sys/fs/cgroup/cpuset

mount -t cgroup cpuset -o cpuset /sys/fs/cgroup/cpuset

cd /sys/fs/cgroup/cpuset

mkdir charlie

cd charlie

echo 2-3 > cpuset.cpus

echo 1 > cpuset.mems

echo $$ > tasks

shcat /proc/self/cgroup

K8s 從懵圈到熟練 集群網路詳解

作者 聲東 阿里雲售後技術專家 總體上來說,阿里雲 k8s 集群網路配置完成之後,如下圖所示 包括集群 cidr vpc 路由表 節點網路 節點的 podcidr 節點上的虛擬網橋 cni0 連線 pod 和網橋的 veth 等部分。基本上我們可以把這些配置分三種情況來理解 集群配置,節點配置以及 ...

K8s 從懵圈到熟練 映象拉取這件小事

順序上來說,私有映象自動拉取會首先通過阿里雲 acr credential helper 元件,再經過 k8s 集群的 api server 和 kubelet 元件,最後到 docker 容器執行時。但是我的敘述,會從後往前,從最基本的 docker 映象拉取說起。映象拉取這件小事 為了討論方便,...

KMP演算法之從懵逼到入門

寫本文的目的 1.加深自己的理解,以便自己日後複習 2.給看到此文的人一點啟發 kmp演算法看懂了就覺得特別簡單,思路也好理解,但是看不懂之前,查各種資料看大佬的部落格,都很懵逼.1.演算法過程解釋 首先,字串 bbcabcdab abcdabcdabde 的第乙個字元與搜尋詞 abcdabd 的第...