一.cgroup介紹
- Cgroups是control groups的縮寫,是Linux內核提供的一種可以限制、記錄、隔離進程組(process groups)所使用的物理資源(如:cpu,memory,IO等等)的機制。最初由google的工程師提出,後來被整合進Linux內核。Cgroups也是LXC爲實現虛擬化所使用的資源管理手段,可以說沒有cgroups就沒有LXC。
- Cgroups最初的目標是爲資源管理提供的一個統一的框架,既整合現有的cpuset等子系統,也爲未來開發新的子系統提供接口。現在的cgroups適用於多種應用場景,從單個進程的資源控制,到實現操作系統層次的虛擬化(OS Level Virtualization)。Cgroups提供了一下功能:
1).限制進程組可以使用的資源數量(Resource limiting )。比如:memory子系統可以爲進程組設定一個memory使用上限,一旦進程組使用的內存達到限額再申請內存,就會出發OOM(out of memory)。
2).進程組的優先級控制(Prioritization )。比如:可以使用cpu子系統爲某個進程組分配特定cpu share。
3).記錄進程組使用的資源數量(Accounting )。比如:可以使用cpuacct子系統記錄某個進程組使用的cpu時間
4).進程組隔離(Isolation)。比如:使用ns子系統可以使不同的進程組使用不同的namespace,以達到隔離的目的,不同的進程組有各自的進程、網絡、文件系統掛載空間。
5).進程組控制(Control)。比如:使用freezer子系統可以將進程組掛起和恢復。
Cgroups相關概念及其關係
- 相關概念
1).任務(task)。在cgroups中,任務就是系統的一個進程。
2).控制族羣(control group)。控制族羣就是一組按照某種標準劃分的進程。Cgroups中的資源控制都是以控制族羣爲單位實現。一個進程可以加入到某個控制族羣,也從一個進程組遷移到另一個控制族羣。一個進程組的進程可以使用cgroups以控制族羣爲單位分配的資源,同時受到cgroups以控制族羣爲單位設定的限制。
3).層級(hierarchy)。控制族羣可以組織成hierarchical的形式,既一顆控制族羣樹。控制族羣樹上的子節點控制族羣是父節點控制族羣的孩子,繼承父控制族羣的特定的屬性。
4).子系統(subsytem)。一個子系統就是一個資源控制器,比如cpu子系統就是控制cpu時間分配的一個控制器。子系統必須附加(attach)到一個層級上才能起作用,一個子系統附加到某個層級以後,這個層級上的所有控制族羣都受到這個子系統的控制。
- 相互關係
1).每次在系統中創建新層級時,該系統中的所有任務都是那個層級的默認 cgroup(我們稱之爲 root cgroup ,此cgroup在創建層級時自動創建,後面在該層級中創建的cgroup都是此cgroup的後代)的初始成員。
2).一個子系統最多隻能附加到一個層級。
3).一個層級可以附加多個子系統
4).一個任務可以是多個cgroup的成員,但是這些cgroup必須在不同的層級。
5).系統中的進程(任務)創建子進程(任務)時,該子任務自動成爲其父進程所在 cgroup 的成員。然後可根據需要將該子任務移動到不同的 cgroup 中,但開始時它總是繼承其父任務的cgroup。
- Cgroups子系統介紹
1)blkio 這個子系統爲塊設備設定輸入/輸出限制,比如物理設備(磁盤,固態硬盤,USB 等等)。
2)cpu 這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問。
3)cpuacct 這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。
4)cpuset 這個子系統爲 cgroup 中的任務分配獨立 CPU(在多核系統)和內存節點。
5)devices 這個子系統可允許或者拒絕 cgroup 中的任務訪問設備。
6)freezer 這個子系統掛起或者恢復 cgroup 中的任務。
7)memory 這個子系統設定 cgroup 中任務使用的內存限制,並自動生成由那些任務使用的內存資源報告。
8)net_cls 這個子系統使用等級識別符(classid)標記網絡數據包,可允許 Linux 流量控制程序(tc)識別從具體 cgroup 中生成的數據包。
9)ns 名稱空間子系統。
二.使用
#yum install libcgroup
#cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
配置文件
#cat /etc/cgconfig.conf
- mount {
- cpuset = /cgroup/cpuset;
- memory = /cgroup/memory;
- net_cls = /cgroup/net_cls;
- freezer = /cgroup/freezer;
- }
- group httpd {
- memory {
- memory.limit_in_bytes = 10M;
- }
- }
配置介紹
- group name {
- [permissions]
- controller {
- param name = param value;
- …
- }
- …}
name: 指定cgroup的名稱
permissions:可選項,指定cgroup對應的掛載點文件系統的權限,root用戶擁有所有權限。
controller:子系統的名稱
param name 和 param value:子系統的屬性及其屬性值
#cat /etc/cgrules.conf
auser:ab memory httpd
用戶或@組:命令 子系統 cgroup名稱
@auser:ab memory httpd
#systemctl restart cgconfig.service
#systemctl restart cgred.service
配置是限制auser用戶 執行ab時,當使用內存超過10M時,進程就會被殺。(默認配置)
內核相關的配置
由於memory subsystem比較耗資源,所以內核專門添加了一個參數cgroup_disable=memory來禁用整個memory subsystem,這個參數可以通過GRUB在啓動系統的時候傳給內核,加了這個參數後內核將不再進行memory subsystem相關的計算工作,在系統中也不能掛載memory subsystem。
上面提到的CONFIG_MEMCG_SWAP和CONFIG_MEMCG_KMEM都是擴展功能,在使用前請確認當前內核是否支持,
這裏CONFIG_MEMCG_SWAP和CONFIG_MEMCG_KMEM等於y表示內核已經編譯了該模塊,即支持相關功能
$cat /boot/config-uname -r
|grep CONFIG_MEMCG (我也是醉了,新版51,這引號自帶背影的)
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
#CONFIG_MEMCG_SWAP_ENABLED is not set
CONFIG_MEMCG_KMEM=y
CONFIG_MEMCG_SWAP控制內核是否支持Swap 擴展,而CONFIG_MEMCG_SWAP_ENABLED(3.6以後的內核新加的參數)控制默認情況下是否使用Swap 擴展,由於Swap 擴展比較耗資源,所以很多發行版(比如ubuntu)默認情況下會禁用該功能(這也是上面那行被註釋掉的原因),當然用戶也可以根據實際情況,通過設置內核參數swapaccount=0或者1來手動禁用和啓用Swap Extension。
測試
[auser@app ~]$ ab -c 10 -n 1000000 http://IP/index.html
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.90.177 (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
已殺死
#top 觀察auser使用ab命令時候內存使用情況,當使用超過10M大概持續2到3秒時,會發現進程被殺死。
一旦設置了內存限制,將立即生效,並且當物理內存使用量達到limit的時候,memory.failcnt的內容會加1,但這時進程不一定就會被kill掉,內核會盡量將物理內存中的數據移到swap空間上去,如果實在是沒辦法移動了(設置的limit過小,或者swap空間不足),默認情況下,就會kill掉cgroup裏面繼續申請內存的進程。
當物理內存達到上限後,系統的默認行爲是kill掉cgroup中繼續申請內存的進程,那麼怎麼控制這樣的行爲呢?答案是配置memory.oom_control
這個文件裏面包含了一個控制是否爲當前cgroup啓動OOM-killer的標識。如果寫0到這個文件,將啓動OOM-killer,當內核無法給進程分配足夠的內存時,將會直接kill掉該進程;如果寫1到這個文件,表示不啓動OOM-killer,當內核無法給進程分配足夠的內存時,將會暫停該進程直到有空餘的內存之後再繼續運行;同時,memory.oom_control還包含一個只讀的under_oom字段,用來表示當前是否已經進入oom狀態,也即是否有進程被暫停了。
#cat /cgroup/memory/httpd/memory.oom_control
oom_kill_disable 0
under_oom 0
#echo 0 > memory.swappiness 設置swappiness爲0 禁止當前cgroup使用swap
當超過限額,會被直接殺掉,不會使用swap空間。
#echo 1 > /cgroup/memory/httpd/memory.oom_control 注意:不要vim編輯去寫,直接echo 1進去,雖然有兩行配置
oom_kill_disable等於1的時候內存達到限額的時候會暫停
當臨時修改擴大內存時,進程又繼續工作,當又不夠時,就會再次暫停工作。
進程遷移
當一個進程從一個cgroup移動到另一個cgroup時,默認情況下,該進程已經佔用的內存還是統計在原來的cgroup裏面,不會佔用新cgroup的配額,但新分配的內存會統計到新的cgroup中(包括swap out到交換空間後再swap in到物理內存中的部分)。
我們可以通過設置memory.move_charge_at_immigrate讓進程所佔用的內存隨着進程的遷移一起遷移到新的cgroup中
enable: echo 1 > memory.move_charge_at_immigrate
disable:echo 0 > memory.move_charge_at_immigrate
注意: 就算設置爲1,但如果不是thread group的leader,這個task佔用的內存也不能被遷移過去。換句話說,如果以線程爲單位進行遷移,必須是進程的第一個線程,如果以進程爲單位進行遷移,就沒有這個問題。
當memory.move_charge_at_immigrate爲0時,就算當前cgroup中裏面的進程都已經移動到其它cgropu中去了,由於進程已經佔用的內存沒有被統計過去,當前cgroup有可能還佔用很多內存,當移除該cgroup時,佔用的內存需要統計到誰頭上呢?答案是依賴memory.use_hierarchy的值,如果該值爲0,將會統計到root cgroup裏;如果值爲1,將統計到它的父cgroup裏面。
相關參數:
1)force_empty :
當向memory.force_empty文件寫入0時(echo 0 > memory.force_empty),將會立即觸發系統儘可能的回收該cgroup佔用的內存。該功能主要使用場景是移除cgroup前(cgroup中沒有進程),先執行該命令,可以儘可能的回收該cgropu佔用的內存,這樣遷移內存的佔用數據到父cgroup或者root cgroup時會快些。
memory.swappiness :
該文件的值默認和全局的swappiness(/proc/sys/vm/swappiness)一樣,修改該文件只對當前cgroup生效,其功能和全局的swappiness一樣
有一點和全局的swappiness不同,那就是如果這個文件被設置成0,就算系統配置的有交換空間,當前cgroup也不會使用交換空間。
2)memory.use_hierarchy:
該文件內容爲0時,表示不使用繼承,即父子cgroup之間沒有關係;當該文件內容爲1時,子cgroup所佔用的內存會統計到所有祖先cgroup中。
如果該文件內容爲1,當一個cgroup內存吃緊時,會觸發系統回收它以及它所有子孫cgroup的內存。
注意: 當該cgroup下面有子cgroup或者父cgroup已經將該文件設置成了1,那麼當前cgroup中的該文件就不能被修改。
3)memory.soft_limit_in_bytes:
有了hard limit(memory.limit_in_bytes),爲什麼還要soft limit呢?hard limit是一個硬性標準,絕對不能超過這個值,而soft limit可以被超越,既然能被超越,要這個配置還有啥用?先看看它的特點
當系統內存充裕時,soft limit不起任何作用
當系統內存吃緊時,系統會盡量的將cgroup的內存限制在soft limit值之下(內核會盡量,但不100%保證)
從它的特點可以看出,它的作用主要發生在系統內存吃緊時,如果沒有soft limit,那麼所有的cgroup一起競爭內存資源,佔用內存多的cgroup不會讓着內存佔用少的cgroup,這樣就會出現某些cgroup內存飢餓的情況。如果配置了soft limit,那麼當系統內存吃緊時,系統會讓超過soft limit的cgroup釋放出超過soft limit的那部分內存(有可能更多),這樣其它cgroup就有了更多的機會分配到內存。
從上面的分析看出,這其實是系統內存不足時的一種妥協機制,給次等重要的進程設置soft limit,當系統內存吃緊時,把機會讓給其它重要的進程。
注意: 當系統內存吃緊且cgroup達到soft limit時,系統爲了把當前cgroup的內存使用量控制在soft limit下,在收到當前cgroup新的內存分配請求時,就會觸發回收內存操作,所以一旦到達這個狀態,就會頻繁的觸發對當前cgroup的內存回收操作,會嚴重影響當前cgroup的性能。
CPU、內存、IO和網絡都能通過cgroup進行管控。通過資源再分配合理的優化虛擬化或者容器。
未完待續