?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
您可以使用該docker stats
命令實(shí)時(shí)流式傳輸容器的運(yùn)行時(shí)指標(biāo)。該命令支持CPU,內(nèi)存使用情況,內(nèi)存限制和網(wǎng)絡(luò)IO度量標(biāo)準(zhǔn)。
以下是docker stats
命令的輸出示例
$ docker stats redis1 redis2 CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O redis1 0.07% 796 KB / 64 MB 1.21% 788 B / 648 B 3.568 MB / 512 KB redis2 0.07% 2.746 MB / 64 MB 4.29% 1.266 KB / 648 B 12.4 MB / 0 B
docker統(tǒng)計(jì)參考頁(yè)面有關(guān)于docker stats
命令的更多詳細(xì)信息。
Linux Containers依賴于控制組,這些組不僅跟蹤進(jìn)程組,還公開(kāi)有關(guān)CPU,內(nèi)存和塊I / O使用情況的度量標(biāo)準(zhǔn)。您也可以訪問(wèn)這些指標(biāo)并獲取網(wǎng)絡(luò)使用指標(biāo)。這與“純”LXC容器以及Docker容器有關(guān)。
控制組通過(guò)偽文件系統(tǒng)公開(kāi)。在最近的發(fā)行版中,你應(yīng)該找到這個(gè)文件系統(tǒng)/sys/fs/cgroup
。在該目錄下,您將看到多個(gè)子目錄,稱為設(shè)備,冰柜,blkio等; 每個(gè)子目錄實(shí)際上對(duì)應(yīng)于不同的cgroup層次結(jié)構(gòu)。
在較早的系統(tǒng)上,控制組可能會(huì)安裝在/cgroup
,而沒(méi)有明確的層次結(jié)構(gòu)。在這種情況下,您不會(huì)看到子目錄,而是會(huì)在該目錄中看到一堆文件,并且可能會(huì)有一些與現(xiàn)有容器相對(duì)應(yīng)的目錄。
若要確定將控件組安裝在何處,可以運(yùn)行:
$ grep cgroup /proc/mounts
您可以查看/proc/cgroups
系統(tǒng)已知的不同控制組子系統(tǒng),它們所屬的層次結(jié)構(gòu)以及它們包含的組數(shù)。
你也可以看看/proc/<pid>/cgroup
哪些控制組屬于一個(gè)進(jìn)程。控制組將顯示為相對(duì)于層次結(jié)構(gòu)安裝點(diǎn)根的路徑; 例如,/
意思是“這個(gè)過(guò)程沒(méi)有被分配到一個(gè)特定的組中”,而/lxc/pumpkin
意味著這個(gè)過(guò)程很可能是一個(gè)被命名為pumpkin
的容器的成員
對(duì)于每個(gè)容器,將在每個(gè)層次結(jié)構(gòu)中創(chuàng)建一個(gè)cgroup。在較舊版本的LXC userland工具的舊系統(tǒng)上,cgroup的名稱將是容器的名稱。隨著更新版本的LXC工具,cgroup將會(huì)lxc/<container_name>.
對(duì)于使用cgroup的Docker容器,容器名稱將是容器的完整ID或長(zhǎng)ID。如果容器顯示為ae836c95b4c3 docker ps
,則其長(zhǎng)ID可能類(lèi)似于ae836c95b4c3c9e9179e0e91015512da89fdec91612f63cebae57df9a5444c79
。你可以用docker inspect
或查找docker ps --no-trunc
。
綜合考慮Docker容器的內(nèi)存指標(biāo),請(qǐng)看看/sys/fs/cgroup/memory/docker/<longid>/
。
對(duì)于每個(gè)子系統(tǒng)(內(nèi)存,CPU和塊I / O),您將找到一個(gè)或多個(gè)包含統(tǒng)計(jì)信息的偽文件。
memory.stat
內(nèi)存指標(biāo)可在“內(nèi)存”cgroup中找到。請(qǐng)注意,內(nèi)存控制組會(huì)增加一些開(kāi)銷(xiāo),因?yàn)樗鼤?huì)對(duì)主機(jī)上的內(nèi)存使用情況進(jìn)行非常細(xì)致的記帳。因此,許多發(fā)行版默認(rèn)選擇不啟用它。一般來(lái)說(shuō),要啟用它,你所要做的就是添加一些內(nèi)核命令行參數(shù):cgroup_enable=memory swapaccount=1
。
度量標(biāo)準(zhǔn)位于偽文件memory.stat
。以下是它的樣子:
cache 11492564992rss 1930993664mapped_file 306728960pgpgin 406632648pgpgout 403355412swap 0pgfault 728281223pgmajfault 1724inactive_anon 46608384active_anon 1884520448inactive_file 7003344896active_file 4489052160unevictable 32768hierarchical_memory_limit 9223372036854775807hierarchical_memsw_limit 9223372036854775807total_cache 11492564992total_rss 1930993664total_mapped_file 306728960total_pgpgin 406632648total_pgpgout 403355412total_swap 0total_pgfault 728281223total_pgmajfault 1724total_inactive_anon 46608384total_active_anon 1884520448total_inactive_file 7003344896total_active_file 4489052160total_unevictable 32768
前半部分(不含total_
前綴)包含與cgroup內(nèi)進(jìn)程相關(guān)的統(tǒng)計(jì)信息,不包括子cgroup。下半部分(帶total_
前綴)也包含子cgroups。
一些指標(biāo)是“計(jì)量器”,即可以增加或減少的值(例如,交換cgroup成員使用的交換空間量)。其他一些是“計(jì)數(shù)器”,即只能上升的值,因?yàn)樗鼈兇硖囟ㄊ录陌l(fā)生(例如,pgfault,它表示自創(chuàng)建cgroup以來(lái)發(fā)生的頁(yè)面錯(cuò)誤的數(shù)量;該數(shù)字永遠(yuǎn)不會(huì)減少)。
Metric | 描述 |
---|---|
cache | 此控制組的進(jìn)程使用的內(nèi)存量可以與塊設(shè)備上的塊精確關(guān)聯(lián)。當(dāng)你讀取和寫(xiě)入磁盤(pán)上的文件時(shí),這個(gè)數(shù)量會(huì)增加。如果您使用“常規(guī)”I / O(打開(kāi),讀取,寫(xiě)入系統(tǒng)調(diào)用)以及映射文件(使用mmap),情況就會(huì)如此。它也解釋了tmpfs坐騎使用的內(nèi)存,但原因尚不清楚。 |
RSS | 與磁盤(pán)上的任何內(nèi)容不對(duì)應(yīng)的內(nèi)存量:堆棧,堆和匿名內(nèi)存映射。 |
mapped_file | 指示控制組中的進(jìn)程映射的內(nèi)存量。它不會(huì)告訴你有多少內(nèi)存被使用; 它會(huì)告訴你它是如何使用的。 |
pgfault,pgmajfault | 指示cgroup的進(jìn)程分別觸發(fā)“頁(yè)面錯(cuò)誤”和“嚴(yán)重錯(cuò)誤”的次數(shù)。當(dāng)進(jìn)程訪問(wèn)不存在或受保護(hù)的部分虛擬內(nèi)存空間時(shí),會(huì)發(fā)生頁(yè)面錯(cuò)誤。如果進(jìn)程有問(wèn)題并嘗試訪問(wèn)無(wú)效地址(它將被發(fā)送一個(gè)SIGSEGV信號(hào),通常使用著名的分段錯(cuò)誤消息將其殺死),前者可能發(fā)生。當(dāng)進(jìn)程從已被換出的內(nèi)存區(qū)讀取或者對(duì)應(yīng)于映射文件時(shí),后者可能發(fā)生:在這種情況下,內(nèi)核將從磁盤(pán)加載頁(yè)面,并讓CPU完成內(nèi)存訪問(wèn)。當(dāng)進(jìn)程寫(xiě)入寫(xiě)時(shí)復(fù)制內(nèi)存區(qū)域時(shí)也會(huì)發(fā)生:同樣,內(nèi)核將搶占進(jìn)程,復(fù)制內(nèi)存頁(yè)面,并在頁(yè)面的進(jìn)程自己的副本上恢復(fù)寫(xiě)入操作。內(nèi)核實(shí)際上必須從磁盤(pán)讀取數(shù)據(jù)時(shí)才會(huì)發(fā)生“重大”故障。當(dāng)它只需復(fù)制現(xiàn)有頁(yè)面或分配一個(gè)空白頁(yè)面時(shí),它就是一個(gè)常規(guī)(或“次要”)錯(cuò)誤。| |
swap | 此cgroup中進(jìn)程當(dāng)前使用的交換量。 |
active_anon,inactive_anon | 內(nèi)核已識(shí)別的匿名內(nèi)存數(shù)量分別處于活動(dòng)狀態(tài)和非活動(dòng)狀態(tài)?!澳涿眱?nèi)存是未鏈接到磁盤(pán)頁(yè)面的內(nèi)存。換句話說(shuō),這就是上述rss計(jì)數(shù)器的等價(jià)物。實(shí)際上,rss計(jì)數(shù)器的定義是active_anon + inactive_anon - tmpfs(其中,tmpfs是由此控制組裝載的tmpfs文件系統(tǒng)使用的內(nèi)存量)。現(xiàn)在,“主動(dòng)”和“非主動(dòng)”之間有什么區(qū)別?頁(yè)面最初是“活動(dòng)的”; 并定期將內(nèi)核掃描到內(nèi)存中,并將某些頁(yè)面標(biāo)記為“不活動(dòng)”。每當(dāng)他們?cè)俅卧L問(wèn)時(shí),他們立即被重新標(biāo)記為“活躍”。當(dāng)內(nèi)核幾乎內(nèi)存不足,并且需要時(shí)間換出磁盤(pán)時(shí),內(nèi)核將交換“非活動(dòng)”頁(yè)面。 |
active_file,inactive_file | 高速緩沖存儲(chǔ)器,具有與上述匿名存儲(chǔ)器相似的活動(dòng)和非活動(dòng)狀態(tài)。確切的公式是cache = active_file + inactive_file + tmpfs。內(nèi)核用于在活動(dòng)和非活動(dòng)集之間移動(dòng)內(nèi)存頁(yè)的確切規(guī)則與用于匿名內(nèi)存的確切規(guī)則不同,但一般原則相同。請(qǐng)注意,當(dāng)內(nèi)核需要回收內(nèi)存時(shí),從該池回收干凈(=未修改)頁(yè)面會(huì)更便宜,因?yàn)樗梢粤⒓椿厥眨ǘ涿?yè)面和臟/修改頁(yè)面必須先寫(xiě)入磁盤(pán)) 。 |
unevictable | 無(wú)法回收的內(nèi)存量; 一般來(lái)說(shuō),它會(huì)占用已被mlock“鎖定”的內(nèi)存。它通常被加密框架用來(lái)確保秘密密鑰和其他敏感材料永遠(yuǎn)不會(huì)換出到磁盤(pán)。 |
memory_limit,memsw_limit | 這些并不是真正的指標(biāo),但是提醒了應(yīng)用于此cgroup的限制。第一個(gè)表示該控制組的進(jìn)程可以使用的最大物理內(nèi)存量; 第二個(gè)表示RAM +交換的最大數(shù)量。 |
記錄頁(yè)面緩存中的內(nèi)存非常復(fù)雜。如果不同控制組中的兩個(gè)進(jìn)程都讀取同一文件(最終依靠磁盤(pán)上的相同塊),則相應(yīng)的內(nèi)存費(fèi)用將在控制組之間分配。這很好,但這也意味著當(dāng)一個(gè)cgroup被終止時(shí),它可能會(huì)增加另一個(gè)cgroup的內(nèi)存使用率,因?yàn)樗鼈儾辉贋檫@些內(nèi)存頁(yè)面分?jǐn)偝杀尽?/p>
cpuacct.stat
現(xiàn)在我們已經(jīng)介紹了內(nèi)存度量標(biāo)準(zhǔn),其他一切都會(huì)看起來(lái)非常簡(jiǎn)單。CPU指標(biāo)將在cpuacct
控制器中找到。
對(duì)于每個(gè)容器,你會(huì)發(fā)現(xiàn)一個(gè)偽文件cpuacct.stat
,載有集裝箱的過(guò)程中積累的CPU使用率,之間分解user
和system
時(shí)間。如果您對(duì)區(qū)分不熟悉,user
是進(jìn)程直接控制CPU的時(shí)間(即執(zhí)行進(jìn)程代碼),并且system
是CPU代表這些進(jìn)程執(zhí)行系統(tǒng)調(diào)用的時(shí)間。
這些時(shí)間以1/100秒的刻度表示。實(shí)際上,它們是以“用戶jiffies”表示的。每秒有USER_HZ
“jiffies”,在x86系統(tǒng)上USER_HZ
是100。這用于精確地映射每秒調(diào)度器“ticks”的數(shù)量; 但隨著更高頻率調(diào)度的出現(xiàn)以及無(wú)滴答內(nèi)核的出現(xiàn),內(nèi)核滴答的數(shù)量不再相關(guān)。無(wú)論如何,它主要出于傳統(tǒng)和兼容性的原因。
塊I/O在blkio
控制器。不同的指標(biāo)分散在不同的文件中。而您可以在BLKIO控制器在內(nèi)核文檔中,下面列出了一些最相關(guān)的文件:
Metric | 描述 |
---|---|
blkio.sectors | 包含由cgroup的進(jìn)程成員逐個(gè)設(shè)備讀取和寫(xiě)入的512字節(jié)扇區(qū)數(shù)。讀取和寫(xiě)入被合并在一個(gè)計(jì)數(shù)器中。 |
blkio.io_service_bytes | 指示由cgroup讀取和寫(xiě)入的字節(jié)數(shù)。它每個(gè)設(shè)備有4個(gè)計(jì)數(shù)器,因?yàn)閷?duì)于每個(gè)設(shè)備,它區(qū)分同步I / O和異步I / O,以及讀取與寫(xiě)入。 |
blkio.io_serviced | 不論其大小如何,執(zhí)行的I / O操作的數(shù)量。它也有每個(gè)設(shè)備4個(gè)計(jì)數(shù)器。 |
blkio.io_queued | 指示當(dāng)前為此cgroup排隊(duì)的I / O操作的數(shù)量。換句話說(shuō),如果cgroup沒(méi)有執(zhí)行任何I / O操作,則這將為零。請(qǐng)注意,相反情況并非如此。換句話說(shuō),如果沒(méi)有排隊(duì)的I / O,這并不意味著cgroup是空閑的(I / O方式)。它可以在其他靜態(tài)設(shè)備上進(jìn)行純同步讀取,因此可以立即處理它們,而無(wú)需排隊(duì)。此外,盡管找出哪個(gè)cgroup正在對(duì)I / O子系統(tǒng)施加壓力是有幫助的,但請(qǐng)記住它是一個(gè)相對(duì)數(shù)量。即使進(jìn)程組沒(méi)有執(zhí)行更多的I / O,其隊(duì)列大小也會(huì)因?yàn)槠渌O(shè)備的負(fù)載增加而增加。 |
網(wǎng)絡(luò)指標(biāo)不直接由控制組公開(kāi)。有一個(gè)很好的解釋?zhuān)壕W(wǎng)絡(luò)接口存在于網(wǎng)絡(luò)命名空間的上下文中。內(nèi)核可能會(huì)累積有關(guān)一組進(jìn)程發(fā)送和接收的數(shù)據(jù)包和字節(jié)的度量標(biāo)準(zhǔn),但這些度量標(biāo)準(zhǔn)不會(huì)很有用。您需要每個(gè)接口的度量標(biāo)準(zhǔn)(因?yàn)樵诒镜?code>lo接口上發(fā)生的流量并不真正計(jì)數(shù))。但是由于單個(gè)cgroup中的進(jìn)程可能屬于多個(gè)網(wǎng)絡(luò)名稱空間,因此這些度量標(biāo)準(zhǔn)很難解釋?zhuān)憾鄠€(gè)網(wǎng)絡(luò)名稱空間意味著多個(gè)lo
接口,可能有多個(gè)eth0
接口等; 所以這就是為什么沒(méi)有簡(jiǎn)單的方法來(lái)收集控制組的網(wǎng)絡(luò)指標(biāo)。
相反,我們可以從其他來(lái)源收集網(wǎng)絡(luò)度量:
IPtables(或者說(shuō),iptables只是一個(gè)接口的netfilter框架)可以做一些嚴(yán)肅的會(huì)計(jì)。
例如,您可以設(shè)置一個(gè)規(guī)則來(lái)說(shuō)明Web服務(wù)器上的出站HTTP流量:
$ iptables -I OUTPUT -p tcp --sport 80
沒(méi)有-j
或-g
標(biāo)志,所以規(guī)則將只計(jì)算匹配的數(shù)據(jù)包并轉(zhuǎn)到以下規(guī)則。
稍后,您可以通過(guò)以下方法檢查計(jì)數(shù)器的值:
$ iptables -nxvL OUTPUT
從技術(shù)上講,-n
不是必需的,但它將阻止iptables執(zhí)行DNS反向查找,在此場(chǎng)景中可能沒(méi)有用處。
計(jì)數(shù)器包括數(shù)據(jù)包和字節(jié)。如果您想為此類(lèi)容器流量設(shè)置度量標(biāo)準(zhǔn),則可以執(zhí)行一個(gè)for
循環(huán)以iptables
在FORWARD
鏈中為每個(gè)容器IP地址(每個(gè)方向一個(gè))添加兩條規(guī)則。這將只計(jì)量通過(guò)NAT層的流量; 您還必須添加通過(guò)用戶級(jí)代理的流量。
然后,您需要定期檢查這些計(jì)數(shù)器。如果你碰巧用collectd
,有一個(gè)不錯(cuò)的插件若要自動(dòng)化iptables計(jì)數(shù)器集合,請(qǐng)執(zhí)行以下操作。
因?yàn)槊總€(gè)容器都有一個(gè)虛擬以太網(wǎng)接口,所以您可能需要直接檢查該接口的TX和RX計(jì)數(shù)器。您將注意到,每個(gè)容器都與主機(jī)中的虛擬以太網(wǎng)接口相關(guān)聯(lián),名稱如下vethKk8Zqi
.不幸的是,找出哪個(gè)接口對(duì)應(yīng)于哪個(gè)容器是困難的。
但現(xiàn)在,最好的方法是從容器中檢查指標(biāo)。為了達(dá)到這個(gè)目的,你可以使用ip-netns magic在容器的網(wǎng)絡(luò)命名空間內(nèi)的主機(jī)環(huán)境中運(yùn)行一個(gè)可執(zhí)行文件。
ip-netns exec
命令將允許您在當(dāng)前進(jìn)程可見(jiàn)的任何網(wǎng)絡(luò)名稱空間內(nèi)執(zhí)行任何程序(存在于主機(jī)系統(tǒng)中)。這意味著您的主機(jī)將能夠輸入您的容器的網(wǎng)絡(luò)名稱空間,但您的容器將無(wú)法訪問(wèn)主機(jī),也不能訪問(wèn)它們的兄弟容器。盡管如此,容器將能夠“看到”并影響其子容器。
命令的確切格式是:
$ ip netns exec <nsname> <command...>
例如:
$ ip netns exec mycontainer netstat -i
ip netns
通過(guò)使用命名空間偽文件找到“mycontainer”容器。每個(gè)進(jìn)程屬于一個(gè)網(wǎng)絡(luò)名稱空間,一個(gè)PID名稱空間,一個(gè)mnt
名稱空間等,并且這些名稱空間在/proc/<pid>/ns/
下具體化。例如,PID 42的網(wǎng)絡(luò)名稱空間由偽文件/proc/42/ns/net
實(shí)現(xiàn)。
運(yùn)行ip netns exec mycontainer ...
,它期望/var/run/netns/mycontainer
成為這些偽文件之一。(符號(hào)鏈接被接受。)
換句話說(shuō),要在容器的網(wǎng)絡(luò)命名空間中執(zhí)行命令,我們需要:
找出我們要調(diào)查的容器內(nèi)任何進(jìn)程的PID;
從創(chuàng)建一個(gè)符號(hào)鏈接/var/run/netns/<somename>
到/proc/<thepid>/ns/net
執(zhí)行 ip netns exec <somename> ....
請(qǐng)查閱枚舉Cgroups以了解如何查找要在其中測(cè)量網(wǎng)絡(luò)使用情況的容器中運(yùn)行的進(jìn)程的cgroup。從那里,您可以檢查名為的偽文件tasks
,其中包含控件組(即容器中)的PID。選擇他們中的任何一個(gè)。
將所有內(nèi)容組合在一起,如果容器的“短ID”保存在環(huán)境變量中$CID
,然后你就可以這樣做:
$ TASKS=/sys/fs/cgroup/devices/docker/$CID*/tasks $ PID=$(head -n 1 $TASKS)$ mkdir -p /var/run/netns $ ln -sf /proc/$PID/ns/net /var/run/netns/$CID $ ip netns exec $CID netstat -i
請(qǐng)注意,每次您要更新指標(biāo)時(shí)運(yùn)行一個(gè)新流程都相當(dāng)昂貴。如果您想要以高分辨率和/或通過(guò)大量容器收集度量標(biāo)準(zhǔn)(將單個(gè)主機(jī)上的容器想成1000個(gè)),則不需要每次都分配一個(gè)新進(jìn)程。
以下是如何從單個(gè)流程收集指標(biāo)。您必須使用C編寫(xiě)公制收集器(或任何允許執(zhí)行低級(jí)別系統(tǒng)調(diào)用的語(yǔ)言)。你需要使用一個(gè)特殊的系統(tǒng)調(diào)用,setns()
它允許當(dāng)前進(jìn)程輸入任意的命名空間。然而,它需要一個(gè)打開(kāi)的文件描述符到命名空間偽文件(記?。哼@是偽文件/proc/<pid>/ns/net
)。
然而,有一個(gè)問(wèn)題:你不能保持這個(gè)文件描述符打開(kāi)。如果這樣做,當(dāng)控制組的最后一個(gè)進(jìn)程退出時(shí),命名空間不會(huì)被銷(xiāo)毀,并且其網(wǎng)絡(luò)資源(如容器的虛擬接口)將一直保留(或直到關(guān)閉該文件描述符)。
正確的方法是跟蹤每個(gè)容器的第一個(gè)PID,每次重新打開(kāi)名稱空間偽文件。
有時(shí),您并不關(guān)心實(shí)時(shí)度量集合,但是當(dāng)容器退出時(shí),您想知道它使用了多少CPU、內(nèi)存等等。
Docker使它變得困難,因?yàn)樗蕾囉?code>lxc-start它,它會(huì)在它自己之后仔細(xì)清理,但它仍然是可能的。定期收集指標(biāo)通常更容易(例如,每隔一分鐘,使用collectd LXC插件)并依靠它來(lái)代替。
但是,如果您仍然希望在容器停止時(shí)收集統(tǒng)計(jì)數(shù)據(jù),下面為方法:
對(duì)于每個(gè)容器,啟動(dòng)一個(gè)收集過(guò)程,并通過(guò)將其PID寫(xiě)入cgroup的任務(wù)文件,將其移至要監(jiān)控的控制組。收集過(guò)程應(yīng)定期重新讀取任務(wù)文件以檢查它是否是控制組的最后一個(gè)過(guò)程。(如果您還想按前一節(jié)中的說(shuō)明收集網(wǎng)絡(luò)統(tǒng)計(jì)信息,則還應(yīng)該將過(guò)程移至適當(dāng)?shù)木W(wǎng)絡(luò)名稱空間。)
當(dāng)容器退出時(shí),lxc-start
會(huì)嘗試刪除控制組。它會(huì)失敗,因?yàn)榭刂平M仍在使用中; 但沒(méi)關(guān)系?,F(xiàn)在您的過(guò)程應(yīng)該檢測(cè)到它是該組中剩下的唯一一個(gè)。現(xiàn)在是收集您需要的所有指標(biāo)的適當(dāng)時(shí)機(jī)!
最后,你的過(guò)程應(yīng)該移回到根控制組,并刪除容器控制組。刪除一個(gè)控制組,只是rmdir
是目錄。由于仍然包含文件,因此它對(duì)目錄不直觀; 但請(qǐng)記住這是一個(gè)偽文件系統(tǒng),所以通常的規(guī)則不適用。清理完成后,收集過(guò)程可以安全地退出。