本文來自網易雲社群
docker監控的調研實踐
docker發展到這麼久,湧現了非常多的延伸工具,有的甚至自成一套系統。相信大家都對各類編排工具有所了解。而各類監控方案也都應運而生。linux核心以及cgroup技術其實已經為監控的技術可行性提供了所有的基礎。這裡我們列舉一些監控工具:
docker原生監控
docker 提供了command方法(docker stats CID)和API: http://$dockerip:2375/containers/$containerid/stats 其本質是讀檔案,提供了CPU,記憶體,BIO,NIO的監控,想探究其實作的同學可以去查閱開源項目libcontainer,或閱讀淺談k8s+docker 資源監控了解詳細的技術内容。
cAdvisor
cAdvisor是一個被k8s內建的監控agent(谷歌自家用),與docker原生監控一樣采用了libcontainer的接口。cadvisor還增加了對主控端的監控,包括CPU,記憶體,網卡和磁盤裝置,甚至還調用了docker的api,去整合了容器的基本資訊如labels,resource limits等。可以說cadvisor的監控已經比較全面了,然而容易引人吐槽的是:至今cadvisor還沒有推出一個穩定的大版本,最新版本是0.24.1,可它的API版本已經出到2.1版了。這裡列出幾個cadvisor的關鍵API(隻采用最新的v2.1 api):
1. http://localhost:4194/api/v2.1/stats/:containerid 檢視容器的資源資料
2. http://localhost:4194/api/v2.1/machine 檢視機器的資訊
3. http://localhost:4194/api/v2.1/machinestats 檢視機器的資源資料,包括磁盤的讀寫資料
4. http://localhost:4194/api/v2.1/spec/:containerid 檢視容器的基礎資訊
5. http://localhost:4194/api/v2.1/summary:containerid 檢視容器在幾個時間片的各項名額狀态分布值
6. http://localhost:4194/api/v2.1/storage/:containerid 檢視容器中的磁盤挂載情況
需要注意的是,此處的containerid由podID和container ID,以一定規則,按照不同的QoS命名,如: /kubepods/burstable/pode0f6a540-90af-11e8-8ae8-fa163edcbbdb/2bb0179713a20d3f96c85d7fcd1354277270c413f7970b7b6c0db8363bbf892b 表示一個沒有定義容器resources.requests 和resources.limits 的pod(pod的uuid:e0f6a540-90af-11e8-8ae8-fa163edcbbdb)中的容器(容器id:2bb0179713a20d3f96c85d7fcd1354277270c413f7970b7b6c0db8363bbf892b ) /kubepods/podc3b4fc59-9462-11e8-9fcd-fa163edcbbdb/282755d06a51d84c1dc0d3153b1bf4604cc37ae2ccb26c69b3855176894da50c 表示一個定義了容器resources.requests 和resources.limits 的pod中的容器。
以上幾個接口其實看名字就能大概知道是什麼意思,有興趣的同學不妨在自己的機器上部署kubernetes,然後在計算節點運作這幾個api試試。 cadvisor預設監聽咋在4194端口,而kubelet其實也代理了cadvisor的監控,是以,我們除了上述的接口,還可以通過通路kubelet(10255端口)來擷取監控資料。
這裡還要再提一下heapster,cadvisor+heapster可以很好的實作kubernetes容器叢集的資源監控。heapster在釋出穩定版本(1.0)後,增加了對pause容器的識别,可以更直覺地通過heapster的API檢視到Pod級别的網絡IO。資料存儲用elasticsearch/influxDB/hawkular等各種存儲都可以(heapster支援使用者以storage driver plugin的形式将抓取的metrics sink 自由整合并推送給存儲服務)資料展示使用grafana,這就打造了一套基本完整的的資料監控服務。而使用k8s可以将三個元件(heapster+influxdb+grafana)一鍵部署。 *k8s1.9後heapster已經被社群廢棄。社群将使用metrics-server進行基礎的叢集性能監控,并使用prometheus來支援更細緻的名額監控。
其他項目如zabbix,openfalcon,promethus,metrics-server
Zabbix更面向裸機和IaaS虛拟機,容器監控是他的軟肋,而openfalcon則被許多企業或docker團隊選型為容器叢集監控的方案。openfalcon有完整的監控項,增加了郵件告警功能,可自定義的agnet SDK。但整套系統子產品繁多,學習成本大。要想用好,還需要針對容器/kubernetes進行二次開發。
prometheus是一套非常成熟的監控,它可以監控很多細節的性能名額,比如http請求次數,磁盤讀寫io和延遲,cpu負載等,同時prometheus友好地支援自定義名額的采集,使用者可以以此為基礎設計自己服務的QPS監控、通路延遲監控、業務處理速度監控等。目前prometheus已經被很多廠商用于生産環境,也是以它已經順利從CNCF項目中畢業。
metrics-server嚴格來說是heapster的替代品,它作為kubernetes的“周邊”,在叢集中以deployment方式部署,metrics-server會注冊一套用于監控的api,監控資料則是從目前叢集的所有node中拉取(也就是上文提到的kubelet代理的監控接口)。在叢集中部署好metrics-server後,過一分鐘我們可以通過執行kubectl top node *** 檢視一個node節點的cpu和記憶體使用情況。 metrics-server主要應用在社群的HPA(horizontal pod autoscaler)功能中。
追根溯源
在linux中,一切都是檔案,是以基于LXC技術的虛拟化方案中,對資源的監控其實也是檔案,我們知道docker依賴cgroup做資源的限制,而實際上cgroup也記錄了資源的使用情況。我們在容器主控端的/sys/fs/cgroup/目錄下可以看到諸如cpu,memory,blkio的子目錄,他們分别存放了對機器上某些程序的資源限制和使用情況。比如: /sys/fs/cgroup/blkio/docker/1c04cedf48560c37cbac695809f8d50d632faa6b1aaeaf40d269756eb912597b/blkio.throttle.io_service_bytes 記錄了某個容器的塊裝置IO位元組數。 而容器的網絡裝置流量,我們可以在/sys/class/net/目錄下根據對應的網卡裝置名,找到統計資料檔案: /sys/class/net/vethc56160e/statistics/tx_bytes 記錄了某個網卡的發出位元組數。 (更多知識可以學習cgroup的資源限制)
可見,監控資料的抓取并不是難事,真正困難的是将這些資料以容器次元,甚至k8s的Pod,RC次元整合。
網易雲計算基礎服務的容器監控設計
網易雲計算基礎服務在自研的雲監控服務的基礎上,結合開源元件cadvisor二次開發,實作了雲計算基礎服務的監控系統。

實際上,我們不創造監控,我們是監控的搬運工。網易雲平台已經有成熟的自研監控系統(NMS)為我們提供了監控資料的存儲,整理和展示。開源元件cadvisor也提供了cpu,記憶體,網絡等名額的監控支援和資料緩存(保證監控資料的可讀性)。 本着實用性和可用性的原則,我們還做了如下設計:
1.獨立的agent子產品
通過一個獨立的agent子產品,去收集cadvisor采集的資料,并推送給雲監控。我們這麼設計的初衷,最主要為了避免對cadvisor做侵入式開發,避免後續cadvisor的版本更新帶來的大範圍代碼改動。cadvisor本身是一個pull server,不是一個push agent,強行加入push 子產品會增加kubelet的複雜性和性能負擔,也會提高整個系統的耦合度;二是雲監控有自己一套API,對資料的次元和監控的demision都有其規範,比如,我們将每次push給雲監控的CPU使用率以Namespace#Service#Pod#Container為辨別,確定該監控資料能比對到制定的容器,進而實作頁面上的展示。而引入這套規範到cadvisor中也會提高整個系統的耦合度。
2.使用DaemonSet特性建構分布式監控
在agent的部署上我們直接利用了kubernetes的DaemonSet特性。
我們知道,k8s最常用的兩個資源是pod和replication,daemonset是一個剛趨于穩定的特性,和deployment類似,然而十分的實用。使用daemonset會保證這個agent Pod會在每一個計算節點上啟動并保持一個執行個體。agent調用cadvisor的接口收集資料,根據雲計算基礎服務産品的需求,對資料做過濾和加工,最後推送給雲監控。agent既是kubernetes叢集監控的元件,也是k8s-DaemonSet的應用範例。
3.增加了對容器磁盤的各項監控
雲計算基礎服務實作了有狀态服務的部署,并支援挂載雲硬碟,針對使用者的回報,我們了解到必須增加對容器的系統盤、資料盤使用率的監控(後續還會提供inode,IOPS,BPS這些名額),提出門檻值預警,避免使用者的誤操作導緻的不良影響進一步擴大。cadvisor的幾個接口(下文會列出)會分别提供一部分磁盤的監控資料,但是并沒有做好整合(可以看到容器stats API中Filesystem字段的内容并不是我們想要的資料).
基于cadvisor的接口和對linux底層的認識,我們是這麼實作對磁盤的監控的:
1.為了不破壞cadvisor原來的代碼結構,在v2.1中新增一個API,提供次元為一個/多個容器的所有挂載裝置的監控資訊。監控資訊包括:容器名、負載名、容器挂載的雲盤類型、挂載目錄、雲盤uuid等。這裡挂載路徑可以通過容器的描述檔案(或直接docker inspect)得到。
2.通過原生接口/api/v2.1/stats/machinestats,我們能看到容器挂載的所有磁盤裝置的IOPS和BPS(JSON中的io_serviced字段和io_service_bytes字段記錄了累計值,通過計算可以求出IOPS和BPS)。結合步驟1的資料,整合出一個容器挂載的所有雲盤的使用率、inode使用率、IOPS和BPS;
3.結合我們在kubernetes使用過程中的規範,區分确認系統盤(容器系統盤一般挂載在容器的/目錄下)和資料盤(來自網易雲存儲NBS提供的卷資訊),按不同次元推送給雲監控。比如cloud#deployment:netease#nginx#ng1 次元,表示cloud namespace、deployment:netease、pod:nginx,容器名:ng1 。
4.雲監控處理監控資料時,根據次元進行資料聚合,以此提供多視角(容器視角、pod視角、負載視角)的監控展示。
如果讀者們閱讀過cadvisor的代碼,會發現裡面對機器的描述資訊、檔案系統的描述資訊,是全局的(感興趣的可以在源碼中閱讀以下machineInfo、fsInfo兩個變量),且在一個cadvisor Manager對象初始化後就不會再被修改。這導緻我們在測試環境發現:動态挂載一個雲盤到主控端上,并挂載作為容器的資料盤時,cadvisor無法讀取新挂的磁盤的資料,除非重新開機kubelet(相當于重新初始化cadvisor中的fsInfo)。我們在cadvisor的代碼中增加了自檢邏輯,當檢查到機器上有新挂載的雲盤時,對machineInfo、fsInfo做更新(需加鎖,否則會引入竟态)。但這個更改沒有被社群采納。
網易雲容器服務為使用者提供了無伺服器容器,讓企業能夠快速部署業務,輕松運維服務。容器服務支援彈性伸縮、垂直擴容、灰階更新、服務發現、服務編排、錯誤恢複及性能監測等功能,點選可免費試用。
網易雲新使用者大禮包:https://www.163yun.com/gift
本文來自網易實踐者社群,經作者黃揚授權釋出。