kubectl top 能夠很方便地查看node、pod的實時資源使用狀況:如CPU、內存。這篇文章會介紹其數據鏈路和實現原理,同時借kubectl top 闡述 k8s 中的監控體系,窺一斑而知全豹。最後會解釋常見的一些問題:html
如下命令的運行環境爲:node
kubectl top 是基礎命令,可是須要部署配套的組件才能獲取到監控值linux
kubectl top node: 查看node的使用狀況git
kubectl top pod: 查看 pod 的使用狀況github
不指定pod 名稱,則顯示命名空間下全部 pod,--containers能夠顯示 pod 內全部的containerdocker
指標含義:api
kubectl top 、 k8s dashboard 以及 HPA 等調度組件使用的數據是同樣,數據鏈路以下:緩存
使用 heapster 時:apiserver 會直接將metric請求經過 proxy 的方式轉發給集羣內的 hepaster 服務。安全
而使用 metrics-server 時:apiserver是經過/apis/metrics.k8s.io/的地址訪問metric網絡
這裏能夠對比下kubect get pod時的日誌:
能夠發現,heapster使用的是 proxy 轉發,而 metric-server 和普通 pod都是使用 api/xx 的資源接口,heapster採用的這種 proxy 方式是有問題的:
因而官方從 1.8 版本開始逐步廢棄 heapster,並提出了上邊Metric api 的概念,而metrics-server 就是這種概念下官方的一種實現,用於從 kubelet獲取指標,替換掉以前的 heapster
有了metrics-server組件,採集到了須要的數據,也暴露了接口,但走到這一步和 heapster 其實沒有區別,最關鍵的一步就是如何將打到apiserver的/apis/metrics.k8s.io
請求轉發給metrics-server組件?解決方案就是:kube-aggregator。
kube-aggregator是對 apiserver 的有力擴展,它容許k8s的開發人員編寫一個本身的服務,並把這個服務註冊到k8s的api裏面,即擴展 API,metric-server其實在 1.7版本就已經完成了,只是在等kube-aggregator的出現。
kube-aggregator是 apiserver 中的實現,有些 k8s 版本默認沒開啓,你能夠加上這些配置
來開啓。他的核心功能是動態註冊、發現彙總、安全代理。
如metric-server註冊 pod 和 node 時:
在提出 metric api 的概念時,官方頁提出了新的監控體系,監控資源被分爲了2種:
核心指標只包含node和pod的cpu、內存等,通常來講,核心指標做HPA已經足夠,但若是想根據自定義指標:如請求qps/5xx錯誤數來實現HPA,就須要使用自定義指標了。
目前Kubernetes中自定義指標通常由Prometheus來提供,再利用k8s-prometheus-adpater聚合到apiserver,實現和核心指標(metric-server)一樣的效果。
前面提到,不管是 heapster仍是 metric-server,都只是數據的中轉和聚合,二者都是調用的 kubelet 的 api 接口獲取的數據,而 kubelet 代碼中實際採集指標的是 cadvisor 模塊,你能夠在 node 節點訪問 10255 端口 (read-only-port)獲取監控數據:
示例,容器的內存使用量:
kubelet雖然提供了 metric 接口,但實際監控邏輯由內置的cAdvisor模塊負責,演變過程以下:
到這裏爲止,k8s範圍內的監控體系就結束了,若是你想繼續瞭解cadvisor和 cgroup 的內容,能夠向下閱讀
cadvisor由谷歌開源,使用Go開發,項目地址也是google/cadvisor,cadvisor不只能夠蒐集一臺機器上全部運行的容器信息,包括CPU使用狀況、內存使用狀況、網絡吞吐量及文件系統使用狀況,還提供基礎查詢界面和http接口,方便其餘組件進行數據抓取。在K8S中集成在Kubelet裏做爲默認啓動項,k8s官方標配。
cadvisor 拿到的數據結構示例:
核心邏輯:
經過new出來的memoryStorage以及sysfs實例,建立一個manager實例,manager的interface中定義了許多用於獲取容器和machine信息的函數
cadvisor的指標解讀:cgroup-v1
cadvisor獲取指標時實際調用的是 runc/libcontainer庫,而libcontainer是對 cgroup文件 的封裝,即 cadvsior也只是個轉發者,它的數據來自於cgroup文件。
cgroup文件中的值是監控數據的最終來源,如
/sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes
/sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytes
通常狀況下,cgroup文件夾下的內容包括CPU、內存、磁盤、網絡等信息:
如memory下的幾個經常使用的指標含義:
memory.stat中的信息是最全的:
原理到這裏結束,這裏解釋下最開始的kubectl top 的幾個問題:
通常狀況下 top 報錯有如下幾種,能夠 kubectl top pod -v=10看到具體的調用日誌
每次啓動 pod,都會有一個 pause 容器,既然是容器就必定有資源消耗(通常在 2-3M 的內存),cgroup 文件中,業務容器和 pause 容器都在同一個 pod的文件夾下。
但 cadvisor 在查詢 pod 的內存使用量時,是先獲取了 pod 下的container列表,再逐個獲取container的內存佔用,不過這裏的 container 列表並無包含 pause,所以最終 top pod 的結果也不包含 pause 容器
pod 的內存使用量計算
kubectl top pod 獲得的內存使用量,並非cadvisor 中的container_memory_usage_bytes,而是container_memory_working_set_bytes,計算方式爲:
container_memory_working_set_bytes是容器真實使用的內存量,也是limit限制時的 oom 判斷依據
cadvisor 中的 container_memory_usage_bytes對應 cgroup 中的 memory.usage_in_bytes文件,但container_memory_working_set_bytes並無具體的文件,他的計算邏輯在 cadvisor 的代碼中,以下:
同理,node 的內存使用量也是container_memory_working_set_bytes
kubectl top node獲得的 cpu 和內存值,並非節點上全部 pod 的總和,不要直接相加。top node是機器上cgroup根目錄下的彙總統計
在機器上直接 top命令看到的值和 kubectl top node 不能直接對比,由於計算邏輯不一樣,如內存,大體的對應關係是(前者是機器上 top,後者是kubectl top):
rss + cache = (in)active_anon + (in)active_file
top命令的差別和上邊 一致,沒法直接對比,同時,就算你對 pod 作了limit 限制,pod 內的 top 看到的內存和 cpu總量仍然是機器總量,並非pod 可分配量
docker stats dockerID 能夠看到容器當前的使用量:
若是你的 pod中只有一個 container,你會發現docker stats 值不等於kubectl top 的值,既不等於 container_memory_usage_bytes,也不等於container_memory_working_set_bytes。
由於docker stats 和 cadvisor 的計算方式不一樣,整體值會小於 kubectl top:計算邏輯是:
docker stats = container_memory_usage_bytes - container_memory_cache
通常狀況下,咱們並不須要時刻關心node 或 pod 的使用量,由於有集羣自動擴縮容(cluster-autoscaler)和pod 水平擴縮容(HPA)來應對這兩種資源變化,資源指標的意義更適合使用prometheus來持久化 cadvisor 的數據,用於回溯歷史或者發送報警。
關於prometheus的內容能夠看容器監控系列
其餘補充: