Docker資源限制與Cgroups
一、Linux control groups
簡(jiǎn)介
Linux CGroup全稱Linux Control Group, 是Linux內(nèi)核的一個(gè)功能,用來限制悍募,控制與分離一個(gè)進(jìn)程組群的資源(如CPU、內(nèi)存、磁盤輸入輸出等)胡本。這個(gè)項(xiàng)目最早是由Google的工程師在2006年發(fā)起(主要是Paul Menage和Rohit Seth),最早的名稱為進(jìn)程容器(process containers)畸悬。在2007年時(shí)侧甫,因?yàn)樵贚inux內(nèi)核中,容器(container)這個(gè)名詞太過廣泛蹋宦,為避免混亂披粟,被重命名為cgroup,并且被合并到2.6.24版的內(nèi)核中冷冗。
主要提供了如下功能:
- Resource limitation: 限制資源使用守屉,比如內(nèi)存使用上限以及文件系統(tǒng)的緩存限制。
- Prioritization: 優(yōu)先級(jí)控制蒿辙,比如:CPU利用和磁盤IO吞吐拇泛。
- Accounting: 一些審計(jì)或一些統(tǒng)計(jì),主要目的是為了計(jì)費(fèi)思灌。
- Control: 掛起進(jìn)程碰镜,恢復(fù)執(zhí)行進(jìn)程。
CGroup的術(shù)語
任務(wù)(Tasks):就是系統(tǒng)的一個(gè)進(jìn)程习瑰。
控制組(Control Group):一組按照某種標(biāo)準(zhǔn)劃分的進(jìn)程绪颖,其表示了某進(jìn)程組,Cgroups中的資源控制都是以控制組為單位實(shí)現(xiàn),一個(gè)進(jìn)程可以加入到某個(gè)控制組柠横。而資源的限制是定義在這個(gè)組上窃款,簡(jiǎn)單點(diǎn)說,cgroup的呈現(xiàn)就是一個(gè)目錄帶一系列的可配置文件牍氛。
層級(jí)(Hierarchy):控制組可以組織成hierarchical的形式晨继,既一顆控制組的樹(目錄結(jié)構(gòu))“峥。控制組樹上的子節(jié)點(diǎn)繼承父結(jié)點(diǎn)的屬性紊扬。簡(jiǎn)單點(diǎn)說,hierarchy就是在一個(gè)或多個(gè)子系統(tǒng)上的cgroups目錄樹唉擂。
子系統(tǒng)(Subsystem):一個(gè)子系統(tǒng)就是一個(gè)資源控制器餐屎,比如CPU子系統(tǒng)就是控制CPU時(shí)間分配的一個(gè)控制器。子系統(tǒng)必須附加到一個(gè)層級(jí)上才能起作用玩祟,一個(gè)子系統(tǒng)附加到某個(gè)層級(jí)以后腹缩,這個(gè)層級(jí)上的所有控制族群都受到這個(gè)子系統(tǒng)的控制。Cgroup的子系統(tǒng)可以有很多空扎,也在不斷增加中藏鹊。以下為內(nèi)核3.10+支持的子系統(tǒng)(可以通過 ls /sys/fs/cgroup 查看到):
blkio — 這個(gè)子系統(tǒng)為塊設(shè)備設(shè)定輸入/輸出限制,比如物理設(shè)備(磁盤转锈,固態(tài)硬盤盘寡,USB 等等)。
cpu — 這個(gè)子系統(tǒng)使用調(diào)度程序提供對(duì) CPU 的 cgroup 任務(wù)訪問撮慨。
cpuacct — 這個(gè)子系統(tǒng)自動(dòng)生成 cgroup 中任務(wù)所使用的 CPU 報(bào)告竿痰。
cpuset — 這個(gè)子系統(tǒng)為 cgroup 中的任務(wù)分配獨(dú)立 CPU(在多核系統(tǒng))和內(nèi)存節(jié)點(diǎn)。
devices — 這個(gè)子系統(tǒng)可允許或者拒絕 cgroup 中的任務(wù)訪問設(shè)備甫煞。
freezer — 這個(gè)子系統(tǒng)掛起或者恢復(fù) cgroup 中的任務(wù)。
memory — 這個(gè)子系統(tǒng)設(shè)定 cgroup 中任務(wù)使用的內(nèi)存限制冠绢,并自動(dòng)生成內(nèi)存資源使用報(bào)告抚吠。
net_cls — 這個(gè)子系統(tǒng)使用等級(jí)識(shí)別符(classid)標(biāo)記網(wǎng)絡(luò)數(shù)據(jù)包,可允許 Linux 流量控制程序(tc)識(shí)別從具體 cgroup 中生成的數(shù)據(jù)包弟胀。
net_prio — 這個(gè)子系統(tǒng)用來設(shè)計(jì)網(wǎng)絡(luò)流量的優(yōu)先級(jí)
hugetlb — 這個(gè)子系統(tǒng)主要針對(duì)于HugeTLB系統(tǒng)進(jìn)行限制楷力,這是一個(gè)大頁文件系統(tǒng)。
操作接口
在linux系統(tǒng)中一皆文件孵户,當(dāng)然對(duì)CGroup的接口操作也是通過文件來實(shí)現(xiàn)的萧朝,我們可以通過mount命令查看其掛載目錄:
以上目錄都可以是限制的對(duì)象,也就是對(duì)應(yīng)的術(shù)語中的各個(gè)子系統(tǒng)夏哭。例如查看這里的CPU限制目錄:
如果你熟悉CPU管理的話检柬,cfs_period 和 cfs_quota兩個(gè)可能不會(huì)陌生,這兩個(gè)參數(shù)需要組合使用竖配,可以用來限制進(jìn)程在長(zhǎng)度為cfs_period 的一段時(shí)間內(nèi)何址,只能被分配到總量為cfs_quota 的 CPU 時(shí)間里逆。以下示例將會(huì)演示如何限制。
限制CPU
限制CPU的使用需要在子系統(tǒng)目錄(/sys/fs/cgroup/cpu)下創(chuàng)建目錄用爪,這里創(chuàng)建一個(gè)cpu_limit_demo目錄:
可以看到當(dāng)我們?cè)贑PU子系統(tǒng)下創(chuàng)建目錄時(shí)候原押,其對(duì)應(yīng)的限制配置文件會(huì)自動(dòng)進(jìn)行創(chuàng)建,現(xiàn)在在后臺(tái)寫個(gè)死循環(huán)跑滿CPU:
此時(shí)使用top命令查看pid為10069的進(jìn)程CPU使用狀況:
如圖可見偎血,此時(shí)該進(jìn)程使用的CPU1已經(jīng)是100%诸衔,即%Cpu :100.0 us,我們先來查看我們剛才創(chuàng)建的cpu_limit_demo目錄下這兩個(gè)參數(shù)默認(rèn)值是多少:
cpu.cfs_quota_us值為-1代表沒有任何限制颇玷,cpu.cfs_period_us 則是默認(rèn)的 100 ms笨农,即100000us,下面將向cpu_limit_demo控制組的cpu.cfs_quota_us文件寫入50ms即50000us,這表示在100ms周期內(nèi)亚隙,cpu最多使用%50磁餐,同時(shí)將該進(jìn)程的pid號(hào)為10069寫入對(duì)應(yīng)的tasks文件,表示對(duì)那個(gè)進(jìn)程限制:
于是pid為10069的進(jìn)程cpu就被限制成了%Cpu :50.0 us阿弃,此時(shí)利用top在此查看cpu使用情況(top后按1可看到每個(gè)邏輯cpu具體使用):
以上可以看到此時(shí)pid10069的進(jìn)程使用率已經(jīng)變成了50%了诊霹,說明限制生效了。同樣的道理渣淳,在/sys/fs/cgroup下的子系統(tǒng)都可以限制不通的資源使用如Block IO脾还、Memory等。
限制內(nèi)存
首先在 /sys/fs/cgroup/memory 下新建一個(gè)名為 limit_memory_demo 的 cgroup:
mkdir /sys/fs/cgroup/memory/limit_memory_demo
限制該 cgroup 的內(nèi)存使用量為 500 MB:
# 物理內(nèi)存500M(下面單位Byte) MB并且不使用swap
echo 524288000 > /sys/fs/cgroup/memory/limit_memory/memory.limit_in_bytes
echo 0 > /sys/fs/cgroup/memory/limit_memory/memory.swappiness
最后將需要限制的進(jìn)程號(hào)的pid寫入task文件就可以了:
echo [pid] > /sys/fs/cgroup/memory/limit_memory_demo/tasks
限制磁盤IO
使用dd寫到null設(shè)備:
[root@app51 blkio]# dd if=/dev/sda of=/dev/null bs=1M
使用iotop(安裝使用yum install -y iotop)查看io速率入愧,此時(shí)讀的速率為2.17G/s
創(chuàng)建一個(gè)blkio(塊設(shè)備IO)的cgroup鄙漏,并查看設(shè)備號(hào),然后將pid和限制的設(shè)備以及速度寫入文件:
然后在觀察dd命令的進(jìn)程:10178,如圖顯示該進(jìn)程讀的的速率已經(jīng)變成了3.8M/s了
注:8:0 是設(shè)備號(hào)棺蛛,你可以通過ls -l /dev/sda1查看怔蚌。
可以簡(jiǎn)寫為以下步驟:
mkdir /sys/fs/cgroup/blkio/ echo '8:0 1048576' > /sys/fs/cgroup/blkio/limit_io/blkio.throttle.read_bps_device
echo [pid] > /sys/fs/cgroup/blkio/limit_io/tasks
二、 Docker中資源限制原理
在了解了Cgroup對(duì)資源的限制方法旁赊,再來理解Docker中的資源限制其實(shí)就變的容易了桦踊。默認(rèn)情況下,Docker會(huì)在需要限制的子系統(tǒng)下創(chuàng)建一個(gè)目錄為docker的控制組如下:
當(dāng)容器運(yùn)行后终畅,會(huì)在這些目錄生成以容器ID為目錄的子目錄用于限制的容器資源籍胯。例如,以cpu為例离福,docker run啟動(dòng)參數(shù)中--cpu-quota 參數(shù)可以指定默認(rèn)時(shí)間內(nèi)使用的cpu:
[root@app51 docker]# docker run -d --name nginx-c1 --cpu-quota 50000 nginx:latest
e9432a513e4bed0a744a29a8eaba2b27d9e40efabfe479d19d32f9558888ed29
[root@app51 docker]#
此時(shí)我們查看cpu對(duì)應(yīng)的容器資源限制:
[root@app51 docker]# cd /sys/fs/cgroup/cpu/docker/
[root@app51 docker]# cat e9432a513e4bed0a744a29a8eaba2b27d9e40efabfe479d19d32f9558888ed29/cpu.cfs_quota_us
50000 [root@app51 docker]# cat e9432a513e4bed0a744a29a8eaba2b27d9e40efabfe479d19d32f9558888ed29/tasks
10561
10598
從上面結(jié)果我們能看出杖狼,docker run的啟動(dòng)限制參數(shù)值,被注入到了Cgroups的cpu控制組的對(duì)應(yīng)配置文件中了妖爷。同時(shí)還有看到有兩個(gè)進(jìn)程同時(shí)被限制了蝶涩,這是因?yàn)槲覀儐?dòng)的nginx,nginx的主進(jìn)程會(huì)啟動(dòng)多個(gè)子進(jìn)程,使用ps -ef可以查看:
[root@app51 docker]# ps -ef |grep 10561
root 10561 10544 0 16:32 ? 00:00:00 nginx: master process nginx -g daemon off; 101 10598 10561 0 16:32 ? 00:00:00 nginx: worker process
root 10614 10179 0 16:38 pts/2 00:00:00 grep --color=auto 10561
[root@app51 docker]#
不難看到子寓,其中主進(jìn)程為10561(nginx master)暗挑,子進(jìn)程為10598(nginx worker)。以上則是docker的資源限制原理斜友。Docker對(duì)資源限制主要是CPU和內(nèi)存炸裆,其中還有很多參數(shù)可以使用,以下將會(huì)介紹docker中CPU和MEMERY限制參數(shù)。
三鲜屏、CPU限制參數(shù)
默認(rèn)情況下烹看,容器的資源是不受限制的,宿主機(jī)提供多少資源洛史,容器就可以使用多少資源惯殊,如果不對(duì)容器做資源限制,很有可能一個(gè)或幾個(gè)容器把宿主機(jī)的資源耗盡也殖,而導(dǎo)致應(yīng)用或者服務(wù)不可用土思。所以對(duì)容器資源的限制顯得非常重要,而docker主要提供兩種類別的資源限制:CPU和內(nèi)存忆嗜,通過docker run 時(shí)指定參數(shù)實(shí)現(xiàn)己儒。cpu限制資源限制有多種維度,以下將詳細(xì)介紹捆毫。
限制cpu配額
參數(shù)通過--cpu-period=<value>和--cpu-quota=<value>共同起作用闪湾,即介紹上述Cgroups使用的例子。表示在cpu-period時(shí)間(默認(rèn)100ms)內(nèi)绩卤,可用的cpu配額途样。
示例:
docker run -d --cpu-period=100000 --cpu-quota=250000 --name test-c1 nginx:latest
限制cpu可用數(shù)量
參數(shù)通過--cpus=<value>指定濒憋,意思限制可用cpu個(gè)數(shù),列如--cpus=2.5表示該容器可使用的cpu個(gè)數(shù)最多是2.5個(gè)凛驮,這相當(dāng)與設(shè)置了--cpu-period=100000和 --cpu-quota=250000該指令在docker版本1.13以及以上使用。
示例:
[root@app51 ~]# docker run -d --cpus=2 --name test-c2 nginx:latest
5347269d0974e37af843b303124d8799c6f4336a14f61334d21ce9356b1535bc
使用固定的cpu
通過--cpuset-cpus參數(shù)指定辐烂,表示指定容器運(yùn)行在某個(gè)或某些個(gè)固定的cpu上遏插,多個(gè)cpu使用逗號(hào)隔開纠修。例如四個(gè)cpu厂僧,0代表第一個(gè)cpu扣草,--cpuset-cpus=1,3代表該容器只能運(yùn)行在第二個(gè)或第四個(gè)cpu上。查看cpu可以通過cat /proc/cpuinfo查看。
示例:
[root@app51 ~]# docker run -d --cpuset-cpus=1,3 --name test-c3 nginx:latest
276056fce04982c2de7969ca309560ce60b0ebf960cf7197808616d65aa112d4
設(shè)置CPU比例(權(quán)重)
通過參數(shù)--cpu-shares指定辰妙,值為大于或小于1024的整數(shù)(默認(rèn)1024),代表當(dāng)主機(jī)cpu資源使用緊張時(shí)蛙婴,每個(gè)容器所使用的cpu資源的比例(權(quán)重)尔破。當(dāng)有足夠的CPU資源時(shí),所有容器都會(huì)根據(jù)需要使用盡可能多的CPU懒构。當(dāng)?shù)谝粋€(gè)容器設(shè)置該參數(shù)的值為2048,第二個(gè)容器設(shè)置該參數(shù)的值為4096絮姆,那么當(dāng)cpu資源不夠用時(shí)候秩霍,兩個(gè)容器cpu資源使用比例為1:2,
示例:
[root@app51 ~]# docker run -d --cpu-shares=2048 --name test-c4 nginx:latest
578506d61324b38d7a01bf1d2ec87cb5d1ab50276ef6f7b28858f2d2e78b2860
[root@app51 ~]# docker run -d --cpu-shares=4096 --name test-c5 nginx:latest
d56a90bf080b70d11d112468348874e48fe4a78d09d98813a0377b34fa382924
四、 MEMORY限制參數(shù)
內(nèi)存是一種不可壓縮資源辕近,一旦某個(gè)進(jìn)程或者容器中應(yīng)用內(nèi)存不足就會(huì)引起OOM異常(Out Of Memory Exception)匿垄,這將導(dǎo)致應(yīng)用不可用,并且在Linux主機(jī)上漏峰,如果內(nèi)核檢測(cè)到?jīng)]有足夠的內(nèi)存來執(zhí)行重要的系統(tǒng)功能届榄,系統(tǒng)會(huì)按照一定優(yōu)先級(jí)殺死進(jìn)程來釋放系統(tǒng)內(nèi)存。docker對(duì)內(nèi)存的限制分為swap限制和物理內(nèi)存限制靖苇,單位可以使用b班缰,k, m埠忘,g馒索。
限制最大物理內(nèi)存使用
通過-m或者—memory指定绰上,是硬限制渠驼,如果設(shè)置此選項(xiàng),則允許設(shè)置的最小值為4m疯趟,該參數(shù)是最常用參數(shù)谋梭。
示例:
[root@app51 ~]# docker run -d --memory=512m --name mem-c1 nginx:latest
67b0cb645c401bc6df3235d27d629185870716351396c71dfa3877abbbd377c8
限制swap使用
通過--memory-swap參數(shù)指定,不過此參數(shù)設(shè)置時(shí)候盹舞,情況比較較多隘庄。當(dāng)容器中的物理內(nèi)存使用不足時(shí)候,swap才會(huì)被允許使用获印,所以當(dāng)--memory參數(shù)設(shè)置時(shí)候街州,此參數(shù)才會(huì)有意義:
- --memory-swap 設(shè)置為正整數(shù),那么這兩個(gè)--memory和 --memory-swap 必須設(shè)置鳍征。--memory-swap 表示可以使用的memory 和 swap面徽,并且--memory控制非交換內(nèi)存(物理內(nèi)存)使用的量。列如--memory=300m 和--memory-swap=1g氮双,容器可以使用300m的內(nèi)存和700m(1g - 300m)swap霎匈。
- --memory-swap 設(shè)置為0唧躲,則忽略該設(shè)置,并將該值視為未設(shè)置弄痹。
- --memory-swap 設(shè)置為與值相同的值--memory肛真,并且--memory設(shè)置為正整數(shù),則容器不能使用swap蚓让,可以通過此方法限制容器不使用swap历极。
- --memory-swap 未設(shè)置并--memory 設(shè)置,則容器可以使用兩倍于--memory設(shè)置的swap蹄葱,主機(jī)容器需要配置有swap锄列。例如,如果設(shè)置--memory="300m" 和--memory-swap 未設(shè)置竣况,容器可以使用300m的內(nèi)存和600m的swap筒严。
- --memory-swap 設(shè)置為-1,則允許容器使用無限制swap嘀掸,最多可達(dá)宿主機(jī)系統(tǒng)上可用的數(shù)量规惰。
示例:
[root@app51 ~]# docker run -d --memory=512m --memory-swap=512m --name mem-c2 nginx:latest
6b52c015a53be2c3e0e509eea918125a760c1c14df4cc977f05b5b31b83161d5
其他
- --oom-kill-disable :默認(rèn)情況下,如果發(fā)生內(nèi)存不足(OOM)錯(cuò)誤揩晴,內(nèi)核會(huì)終止容器中的進(jìn)程贪磺,如要更改此行為寒锚,使用該--oom-kill-disable選項(xiàng)违孝,但是該選項(xiàng)有個(gè)前提就是-m選項(xiàng)必須設(shè)置泳赋。
- --memory-swappiness:默認(rèn)情況下,容器的內(nèi)核可以交換出一定比例的匿名頁校坑。--memory-swappiness就是用來設(shè)置這個(gè)比例的千诬。--memory-swappiness可以設(shè)置為從 0 到 100徐绑。0 表示關(guān)閉匿名頁面交換。100 表示所有的匿名頁都可以交換傲茄。默認(rèn)情況下烫幕,如果不適用--memory-swappiness,則該值從父進(jìn)程繼承而來较曼。
- --memory-reservation:Memory reservation 是一種軟性限制捷犹,用于限制物理內(nèi)存的最大用值,它只是確保容器不會(huì)長(zhǎng)時(shí)間占用超過--memory-reservation限制的內(nèi)存大小侣颂。給--memory-reservation設(shè)置一個(gè)比-m小的值后枪孩,雖然容器最多可以使用-m使用的內(nèi)存大小,但在宿主機(jī)內(nèi)存資源緊張時(shí)拒担,在系統(tǒng)的下次內(nèi)存回收時(shí)攻询,系統(tǒng)會(huì)回收容器的部分內(nèi)存頁,強(qiáng)迫容器的內(nèi)存占用回到--memory-reservation設(shè)置的值大小低零。
五、總結(jié)
本文簡(jiǎn)單介紹了Linux Cgroups以及它對(duì)資源限制的使用方法啃奴,并提供了簡(jiǎn)單的示例。此外還介紹了Docker如何使用該方式對(duì)容器進(jìn)行資源限制畔咧,本質(zhì)上是docker run時(shí)將限制參數(shù)注入到Cgroups的各個(gè)資源限制的配置文件中,從而達(dá)到對(duì)容器的資源限制梅桩。希望大家對(duì)容器的資源限制有一定的理解拜隧。
參考:
《DOCKER 基礎(chǔ)技術(shù):LINUX CGROUP》
《Limit a container's resources》
Memo
本文轉(zhuǎn)載整理來源: https://www.cnblogs.com/wdliu/p/10509045.html