Docker資源監控

f453 9年前發布 | 11K 次閱讀 Docker

 

寫在前面

最近在研究docker集群(kubernetes)的監控,為了徹底弄清楚,也是看了一點源碼。這里分享一下我學到的東西。

docker api: stats

首先是docker的api,stats的具體使用場景如:

http://$dockerip:2375/containers/$containerid/stats

可以獲取docker機器上某一個容器的狀態,該請求的response會持續的寫響應報文回來(每秒一次)

http://$dockerip:2375/containers/$containerid/stats?stream=false 

參數stream默認是true,設為false后,response只寫一次。

docker中該api對應的操作,就相當于docker stats $CID這條命令,它調用到了ContainerStats()方法(位于docker項目目錄的/daemon/stats.go第19行),函數中啟動了一個收集器:

daemon.SubscribeToContainerStats(name)

收集器定時寫數據到update變量中。然后啟動一個協程讀數據,獲取數據的途徑包括:

update := v.(*execdriver.ResourceStats) 

nwStats, err := daemon.getNetworkStats(name)

可以看到網絡狀態是另外讀的,而cpu,內存狀態在哪讀呢?我們一步步跳轉,看到在這里:/daemon/execdriver/driver_linux.go 112行:

func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error)

在這個函數里我們看得到,其實所謂的獲取容器狀態,就是讀文件而已。我們舉一個已經在docker運行的容器來說:

cat /run/docker/execdriver/native/$containerID/state.json

這里面記錄了一個cgroup_paths字段,他的值是一個路徑,通過cstats, err := mgr.GetStats()程序才真正拿到了監控數據,如cpu的狀態信息,存儲在一個如下的路徑中:

cd /sys/fs/cgroup/cpu,cpuacct/system.slice/docker-9b479ceaf3bef1caee2c37dfdc982a968144700a2c42991b238b938788a8a91f.scope

又比如內存的大致信息存在:

cat /sys/fs/cgroup/memory/system.slice/docker-9b479ceaf3bef1caee2c37dfdc982a968144700a2c42991b238b938788a8a91f.scope/memory.stat 

具體里面放了什么數據,大家就自己看咯。

還剩下一個數據,也是我們討論的重點:網絡IO。

我們回到/daemon/stats.go:

看看函數getNetworkStats(name string):

每個docker容器創建后都會又docker創建一個網卡,網卡名以veth開頭,后面是一串隨機生成的十六進制碼。

我們只要找到該網卡,然后,像上文的cpu,內存狀態獲取的方法一樣,去找文件就行了。

然而這個網卡名似乎是存在內存中,至少我沒有看到docker將這個網卡名存到別的地方。

代碼中:

nw, err := daemon.netController.NetworkByID(c.NetworkSettings.NetworkID)

可以看出獲取了網卡(network),爾后有一個Statistics()方法,我們繼續跟蹤會發現,docker調用了一個組件包:

github.com/docker/libcontainer

其中有statistics方法,并執行了一個cat的命令(該組件包的/sandbox/interface_linux.go 第174行):

data, err := exec.Command("cat", netStatsFile).Output()

是的,又是讀文件。

這次讀的文件在:/sys/class/net/目錄下,

我們進入該目錄可以看到有許多子目錄,其中就包括了docker啟動容器時生成的網卡。

個人猜測:docker在內存中保存了容器到網卡的映射關系。通過這個映射關系可以找到網卡的統計數據(數據由內核生成,記錄在機器的文件中)

我們可以看到如下的數據:

Docker資源監控

將這些數據統一起來,就是docker stats 這條命令干的事。

kubernetes如何調用上述的監控功能

kubernetes的監控采用了cAdvisor組件。因為kubernetes中記錄了容器的信息(但是沒有記錄容器-網卡的映射關系),所以運行在節點上的cAdvisor不需要通過docker stats去獲取容器的cpu和內存使用數據。而網絡IO數據呢?

我們知道k8s部署運行一個容器是會先生成一個pause容器。是的,網絡IO都記錄在pause容器中。這里大家可以在自己的k8s環境中驗證。

所以只要我們獲取某容器對應的pause容器的containerID,我們就可以用如上的方式去抓到網絡IO。

但是cAdvisor里并沒有這么做。為什么?因為cAdvisor并不只是給k8s用的啊魂淡。。。。

所以如果在使用k8s集群,想要加入網絡IO監控功能的時候,可以參考本文,從中獲取一些靈感哦~

 本文由用戶 f453 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!