淺談Cgroups

奇技指南
在開發一款軟件時,爲了延長軟件的生命週期,須要一款配套軟件來對發佈的軟件進行監控。隨着容器技術的成熟,系統的定製和軟件的打包變得愈來愈容易,同時,對容器進行監控成爲了容器使用者所必備的技能。下來,做者將帶領你們認識一下容器的資源管理工具Cgroups。

提及容器監控,首先會想到經過Cadvisor, Docker stats等多種方式獲取容器的監控數據,並同時會想到容器經過Cgroups實現對容器中的資源進行限制。可是這些數據來自哪裏,而且如何計算的?答案是Cgroups。最近在寫docker容器監控組件,在深刻Cadvisor和Docker stats源碼發現數據都來源於Cgroups。瞭解之餘,並對Cgroups作下筆記。html

0一、Cgroups介紹

Cgroups 是 control groups 的縮寫,是Linux內核提供的一種能夠限制,記錄,隔離進程組(process groups)所使用物理資源的機制。最初有google工程師提出,後來被整合進Linux的內核。所以,Cgroups爲容器實現虛擬化提供了基本保證,是構建Docker,LXC等一系列虛擬化管理工具的基石。linux

0二、Cgroups做用

  • 資源限制(Resource limiting):
  • Cgroups能夠對進程組使用的資源總額進行限制。如對特定的進程進行內存使用上限限制,當超出上限時,會觸發OOM。
  • 優先級分配(Prioritization): 經過分配的CPU時間片數量及硬盤IO帶寬大小,實際上就至關於控制了進程運行的優先級。
  • 資源統計(Accounting): Cgroups能夠統計系統的資源使用量,如CPU使用時長、內存用量等等,這個功能很是適用於計費。
  • 進程控制(ControlCgroups): 能夠對進程組執行掛起、恢復等操做。

0三、Cgroups 組成

Cgroups主要由task,cgroup,subsystem及hierarchy構成。下面分別介紹下各自的概念。docker

  • task: 在Cgroups中,task就是系統的一個進程。
  • cgroup: Cgroups中的資源控制都以cgroup爲單位實現的。cgroup表示按照某種資源控制標準劃分而成的任務組,包含一個或多個子系統。一個任務能夠加入某個cgroup,也能夠從某個cgroup遷移到另一個cgroup。
  • subsystem: Cgroups中的subsystem就是一個資源調度控制器(Resource Controller)。好比CPU子系統能夠控制CPU時間分配,內存子系統能夠限制cgroup內存使用量。
  • hierarchy: hierarchy由一系列cgroup以一個樹狀結構排列而成,每一個hierarchy經過綁定對應的subsystem進行資源調度。hierarchy中的cgroup節點能夠包含零或多個子節點,子節點繼承父節點的屬性。整個系統能夠有多個hierarchy。

組件之間的關係

Subsystems, Hierarchies,Control Group和Tasks之間有許多的規則,下面介紹下:
一、同一個hierarchy可以附加一個或多個subsystem。
以下圖,將cpu和memory subsystems(或者任意多個subsystems)附加到同一個hierarchy。shell

clipboard.png

二、一個subsystem只能附加到一個hierarchy上。
以下圖,cpu subsystem已經附加到了hierarchy A,而且memory subsystem已經附加到了hierarchy B。所以cpusubsystem不能在附加到hierarchy B。centos

clipboard.png

三、系統每次新建一個hierarchy時,該系統上的全部task默認構成了這個新建的hierarchy的初始化cgroup,這個cgroup也稱爲root cgroup。對於你建立的每一個hierarchy,task只能存在於其中一個cgroup中,即一個task不能存在於同一個hierarchy的不一樣cgroup中,可是一個task能夠存在在不一樣hierarchy中的多個cgroup中。若是操做時把一個task添加到同一個hierarchy中的另外一個cgroup中,則會從第一個cgroup中移除。
以下圖,cpu和memory被附加到cpu_mem_cg的hierarchy。而net_cls被附加到net_cls hierarchy。而且httpd進程被同時加到了cpu_mem_cg hierarchy的cg1 cgroup中和net hierarchy的cg3 cgroup中。並經過兩個hierarchy的subsystem分別對httpd進程進行cpu,memory及網絡帶寬的限制。微信

clipboard.png

四、系統中的任何一個task(Linux中的進程)fork本身建立一個子task(子進程)時,子task會自動的繼承父task cgroup的關係,在同一個cgroup中,可是子task能夠根據須要移到其它不一樣的cgroup中。父子task之間是相互獨立不依賴的。
以下圖,httpd進程在cpu_and_mem hierarchy的/cg1 cgroup中並把PID 4537寫到該cgroup的tasks中。以後httpd(PID=4537)進程fork一個子進程httpd(PID=4840)與其父進程在同一個hierarchy的統一個cgroup中,可是因爲父task和子task之間的關係獨立不依賴的,因此子task能夠移到其它的cgroup中。網絡

clipboard.png

0四、Cgroups使用

咱們直接使用shell 命令直接操做hierarchy並設置cgroup參數。在centos6上也能夠直接使用libcgroup提供的工具可簡化對cgroup的使用。ide

clipboard.png

Create a Hierarchy

使用shell命令建立hierarchy並附加subsystems到該hierarchy上。 做爲root爲hierarchy建立一個mount point。而且在mount point中包含cgrou的名字。工具

clipboard.png

例如:測試

clipboard.png

接下來使用mount命令去掛載hierarchy並附加一個或多個subsystem到該hierarchy上。

clipboard.png

例如:

clipboard.png

若是想在已有的hierarchy上attch或detach subsystem,可使用remount操做,例如咱們想detach掉memory subsystem。

clipboard.png

Unmounting a Hierarchy

能夠直接用umount命令來unmount一個已有的Hierarchy:

clipboard.png

例如:

clipboard.png

Creating Control Groups

直接使用shell命令mkdir建立一個子cgroup:

clipboard.png

例如:

clipboard.png

Setting Control Cgroup Parameters

在group1中使用echo命令插入0-1到cpuset.cpus,來限制該cgroup中的tasks只能跑在0和1的cpu core上。以下:

clipboard.png

Moving a Process to a Control Group

只要將想要限制的進程PID,追加到想要的cgroup的tasks文件中就能夠了。例如:將PID=1701的進程放到「/cgroup/cpu_and_mem/group1/」的cgroup中。

clipboard.png

0五、Subsystem 介紹

  • blkio: blkio 子系統控制並監控cgroup中的task對塊設備的I/O的訪問。如:限制訪問及帶寬等。
  • cpu: 主要限制進程的cpu使用率。
  • cpuacct: 能夠統計cgroup中進程的cpu使用報告。 cpuset: 能夠爲cgroup中的進程分配獨立的cpu和內存節點。
  • memory: 自動生成cgroup中task使用的內存資源報告,並對該cgroup的task進行內存使用限制。 devices:
  • 能夠控制進程可否訪問某些設備。 net_cls:
  • 使用等級標識符(clssid)標記網絡數據包,可容許Linux流量控制程序(tc)識別從具體cgroup中生成的數據包。 freezer:
  • 能夠掛起或回覆cgroup中的進程。 ns: 可使不一樣cgroup中的進程使用不一樣的namespace。

0六、容器使用Cgroups進行資源限制

不管是使用docker run方式直接建立容器,仍是經過各種容器編排工具(如:Kubernetes)建立容器,對於容器的限制本質都是經過Cgroups。咱們分別使用這兩種方式來建立容器並觀察cgroups:
測試環境:

clipboard.png

使用docker run方式建立容器

一、限制CPU share,建立兩個容器,則會在運行該容器宿主的/sys/fs/cgroup/cpu/docker/ 下分別建立兩個子cgroup,格式以下。

clipboard.png

二、建立一個容器,並設置--cpu-shares參數爲:1024*10。

clipboard.png

查看該容器cgroup的cpu.shares文件內容以下。

clipboard.png

三、建立一個容器,並設置--cpu-shares參數爲: 1024*14。

clipboard.png

查看該容器cgroup的cpu.shares文件內容以下。

clipboard.png

四、兩個容器使用cpu的stats,一個容器分到14核的相對cpu計算時間,另外一個容器分到10核的相對cpu計算時間:

clipboard.png

限制容器內存使用量

一、建立一個容器,限制容器能使用的內存上限爲1024M。

clipboard.png

二、查看容器memory的stats,內存使用率100%。

clipboard.png

三、當容器使用的內存量超過1024M,則容器會被kill -9掉。

clipboard.png

使用Kubenetes容器編排工具建立容器

使用kubernetes編排工具建立的容器,則與容器關聯的cgroup均在運行該容器宿主機的/sys/fs/cgroup/cpu/kubepods/下,具體的格式以下所示:

clipboard.png

使用Pod建立一個容器,對應的yaml文件內容以下:

clipboard.png

在運行該容器的宿主機上查看該容器的cgroup信息,會觀察到cpu.shares爲1核,memory.limit_in_bytes爲2G。

clipboard.png

相關文章
https://access.redhat.com/doc...
https://www.kernel.org/doc/Do...
http://www.infoq.com/cn/artic...

關於360技術

360技術是360技術團隊打造的技術分享公衆號,天天推送技術乾貨內容

更多技術信息歡迎關注「360技術」微信公衆號

圖片描述

相關文章
相關標籤/搜索