從kubectl top看K8S監控

一. 前言

kubectl top 能夠很方便地查看node、pod的實時資源使用狀況:如CPU、內存。這篇文章會介紹其數據鏈路和實現原理,同時借kubectl top 闡述 k8s 中的監控體系,窺一斑而知全豹。最後會解釋常見的一些問題:html

  • kubectl top 爲何會報錯?
  • kubectl top node 怎麼計算,和節點上直接 top 有什麼區別?
  • kubectl top pod 怎麼計算,包含 pause 嗎?
  • kubectl top pod 和exec 進入 pod 後看到的 top 不同?
  • kubectl top pod 和 docker stats獲得的值爲何不一樣?

如下命令的運行環境爲:node

  • k8s 1.8
  • k8s 1.13

二. 使用

kubectl top 是基礎命令,可是須要部署配套的組件才能獲取到監控值linux

kubectl top node: 查看node的使用狀況git

kubectl top pod: 查看 pod 的使用狀況github

不指定pod 名稱,則顯示命名空間下全部 pod,--containers能夠顯示 pod 內全部的containerdocker

指標含義:api

  • 和k8s中的request、limit一致,CPU單位100m=0.1 內存單位1Mi=1024Ki
  • pod的內存值是其實際使用量,也是作limit限制時判斷oom的依據。pod的使用量等於其全部業務容器的總和,不包括 pause 容器,值等於cadvisr中的container_memory_working_set_bytes指標
  • node的值並不等於該node 上全部 pod 值的總和,也不等於直接在機器上運行 top 或 free 看到的值

三. 實現原理

3.1 數據鏈路

kubectl top 、 k8s dashboard 以及 HPA 等調度組件使用的數據是同樣,數據鏈路以下:緩存

使用 heapster 時:apiserver 會直接將metric請求經過 proxy 的方式轉發給集羣內的 hepaster 服務。安全

而使用 metrics-server 時:apiserver是經過/apis/metrics.k8s.io/的地址訪問metric網絡

這裏能夠對比下kubect get pod時的日誌:

3.2 metric api

能夠發現,heapster使用的是 proxy 轉發,而 metric-server 和普通 pod都是使用 api/xx 的資源接口,heapster採用的這種 proxy 方式是有問題的:

    1. proxy只是代理請求,通常用於問題排查,不夠穩定,且版本不可控
    1. heapster的接口不能像apiserver同樣有完整的鑑權以及client集成,兩邊都維護的話代價高,如generic apiserver
    1. pod 的監控數據是核心指標(HPA調度),應該和 pod 自己擁有同等地位,即 metric應該做爲一種資源存在,如metrics.k8s.io 的形式,稱之爲 Metric Api

因而官方從 1.8 版本開始逐步廢棄 heapster,並提出了上邊Metric api 的概念,而metrics-server 就是這種概念下官方的一種實現,用於從 kubelet獲取指標,替換掉以前的 heapster

3.3 kube-aggregator

有了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 時:

3.4 監控體系

在提出 metric api 的概念時,官方頁提出了新的監控體系,監控資源被分爲了2種:

  • Core metrics(核心指標):從 Kubelet、cAdvisor 等獲取度量數據,再由metrics-server提供給 Dashboard、HPA 控制器等使用。
  • Custom Metrics(自定義指標):由Prometheus Adapter提供API custom.metrics.k8s.io,由此可支持任意Prometheus採集到的指標。

核心指標只包含node和pod的cpu、內存等,通常來講,核心指標做HPA已經足夠,但若是想根據自定義指標:如請求qps/5xx錯誤數來實現HPA,就須要使用自定義指標了。

目前Kubernetes中自定義指標通常由Prometheus來提供,再利用k8s-prometheus-adpater聚合到apiserver,實現和核心指標(metric-server)一樣的效果。

3.5 kubelet

前面提到,不管是 heapster仍是 metric-server,都只是數據的中轉和聚合,二者都是調用的 kubelet 的 api 接口獲取的數據,而 kubelet 代碼中實際採集指標的是 cadvisor 模塊,你能夠在 node 節點訪問 10255 端口 (read-only-port)獲取監控數據:

  • Kubelet Summary metrics: 127.0.0.1:10255/metrics,暴露 node、pod 彙總數據
  • Cadvisor metrics: 127.0.0.1:10255/metrics/cadvisor,暴露 container 維度數據

示例,容器的內存使用量:

kubelet雖然提供了 metric 接口,但實際監控邏輯由內置的cAdvisor模塊負責,演變過程以下:

  • 從k8s 1.6開始,kubernetes將cAdvisor開始集成在kubelet中,不須要單獨配置
  • 從k8s 1.7開始,Kubelet metrics API 再也不包含 cadvisor metrics,而是提供了一個獨立的 API 接口來作彙總
  • 從k8s 1.12開始,cadvisor 監聽的端口在k8s中被刪除,全部監控數據統一由Kubelet的API提供

到這裏爲止,k8s範圍內的監控體系就結束了,若是你想繼續瞭解cadvisor和 cgroup 的內容,能夠向下閱讀

3.6 cadvisor

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文件。

3.7 cgroup

cgroup文件中的值是監控數據的最終來源,如

  • mem usage的值,來自於

/sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes

  • 若是沒限制內存,Limit = machine_mem,不然來自於

/sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytes

  • 內存使用率 = memory.usage_in_bytes/memory.limit_in_bytes

通常狀況下,cgroup文件夾下的內容包括CPU、內存、磁盤、網絡等信息:


如memory下的幾個經常使用的指標含義:

memory.stat中的信息是最全的:

原理到這裏結束,這裏解釋下最開始的kubectl top 的幾個問題:

四. 問題

4.1 kubectl top 爲何會報錯

通常狀況下 top 報錯有如下幾種,能夠 kubectl top pod -v=10看到具體的調用日誌

  1. 沒有部署 heapster 或者 metric-server,或者pod運行異常,能夠排查對應 pod日誌
  2. 要看的pod 剛剛建出來,還沒來得及採集指標,報 not found 錯誤,默認1 分鐘
  3. 以上兩種都不是,能夠檢查下kubelet 的 10255 端口是否開放,默認狀況下會使用這個只讀端口獲取指標,也能夠在heapster或metric-server的配置中增長證書,換成 10250 認證端口

4.2 kubectl top pod 內存怎麼計算,包含 pause容器 嗎

每次啓動 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_usage_bytes == container_memory_rss + container_memory_cache + kernel memory
  • container_memory_working_set_bytes = container_memory_usage_bytes - total_inactive_file(未激活的匿名緩存頁)

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

4.3 kubectl top node 怎麼計算,和節點上直接 top 有什麼區別

kubectl top node獲得的 cpu 和內存值,並非節點上全部 pod 的總和,不要直接相加。top node是機器上cgroup根目錄下的彙總統計

在機器上直接 top命令看到的值和 kubectl top node 不能直接對比,由於計算邏輯不一樣,如內存,大體的對應關係是(前者是機器上 top,後者是kubectl top):

rss + cache = (in)active_anon + (in)active_file

4.4 kubectl top pod 和exec 進入 pod 後看到的 top 不同

top命令的差別和上邊 一致,沒法直接對比,同時,就算你對 pod 作了limit 限制,pod 內的 top 看到的內存和 cpu總量仍然是機器總量,並非pod 可分配量

  • 進程的RSS爲進程使用的全部物理內存(file_rss+anon_rss),即Anonymous pages+Mapped apges(包含共享內存)
  • cgroup RSS爲(anonymous and swap cache memory),不包含共享內存。二者都不包含file cache

4.5 kubectl top pod 和 docker stats獲得的值爲何不一樣?

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的內容能夠看容器監控系列

其餘補充:

  1. 雖然kubectl top help中顯示支持Storage,但直到 1.16 版本仍然不支持
  2. 1.13 以前須要 heapster,1.13 之後須要metric-server,這部分kubectl top help的輸出 有誤,裏面只提到了heapster
  3. k8s dashboard 中的監控圖默認使用的是 heapster,切換爲 metric-server後數據會異常,須要多部署一個metric-server-scraper 的 pod 來作接口轉換,具體參考 pr:https://github.com/kubernetes...

六. 參考資料

相關文章
相關標籤/搜索