cgroup 介紹 與使用

一.cgroup介紹

  1. Cgroups是control groups的縮寫,是Linux內核提供的一種可以限制、記錄、隔離進程組(process groups)所使用的物理資源(如:cpu,memory,IO等等)的機制。最初由google的工程師提出,後來被整合進Linux內核。Cgroups也是LXC爲實現虛擬化所使用的資源管理手段,可以說沒有cgroups就沒有LXC。
  2. 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. 相關概念
    1).任務(task)。在cgroups中,任務就是系統的一個進程。
    2).控制族羣(control group)。控制族羣就是一組按照某種標準劃分的進程。Cgroups中的資源控制都是以控制族羣爲單位實現。一個進程可以加入到某個控制族羣,也從一個進程組遷移到另一個控制族羣。一個進程組的進程可以使用cgroups以控制族羣爲單位分配的資源,同時受到cgroups以控制族羣爲單位設定的限制。
    3).層級(hierarchy)。控制族羣可以組織成hierarchical的形式,既一顆控制族羣樹。控制族羣樹上的子節點控制族羣是父節點控制族羣的孩子,繼承父控制族羣的特定的屬性。
    4).子系統(subsytem)。一個子系統就是一個資源控制器,比如cpu子系統就是控制cpu時間分配的一個控制器。子系統必須附加(attach)到一個層級上才能起作用,一個子系統附加到某個層級以後,這個層級上的所有控制族羣都受到這個子系統的控制。


  1. 相互關係
    1).每次在系統中創建新層級時,該系統中的所有任務都是那個層級的默認 cgroup(我們稱之爲 root cgroup ,此cgroup在創建層級時自動創建,後面在該層級中創建的cgroup都是此cgroup的後代)的初始成員。
    2).一個子系統最多隻能附加到一個層級。
    3).一個層級可以附加多個子系統
    4).一個任務可以是多個cgroup的成員,但是這些cgroup必須在不同的層級。
    5).系統中的進程(任務)創建子進程(任務)時,該子任務自動成爲其父進程所在 cgroup 的成員。然後可根據需要將該子任務移動到不同的 cgroup 中,但開始時它總是繼承其父任務的cgroup。


  1. 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進行管控。通過資源再分配合理的優化虛擬化或者容器。

未完待續

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章