Kubernetes 集羣監控
**【作者】謝文博,**陽光信用保證保險股份有限公司信息安全部負責人。2020 容器雲職業技能大賽百位專家委員會成員
1 監控平臺建設
所有的優化指標都是建立在對系統的充分了解上的,常規基於 Kubernetes 的監控方案有以下大概有3種,我們就採用比較主流的方案,也降低部署成本和後期集成複雜度。
主流也是我們選取的方案是 Prometheus +Grafana +cAdvisor +(要部署:Prometheus-operator, met-ric-server),通過 Prometheus 提供相關數據,Prometheus 定期獲取數據並用 Grafana 展示,異常告警使用 AlertManager 進行告警。實際部署過程中實施也可以考慮使用 Kube-prometheus 項目(參見注釋 1)整體部署節省大量工作,以下是官方架構圖,涉及到組件如下:
-
Prometheus Operator
-
Prometheus
-
Alertmanager
-
Prometheus node-exporter
-
Prometheus Adapter for KubernetesMetrics APIs
-
kube-state-metrics
-
Grafana
上圖中的 Service 和 ServiceMonitor 都是 Kubernetes 的資源,一個 ServiceMonitor 可以通過 labelSelector 的方式去匹配一類 Service,Prometheus 也可以通過 labelSelector 去匹配多個 ServiceMonitor。
主要監控範圍分爲:資源監控,性能監控,任務監控,事件告警監控等,因爲本篇主要講的是性能優化,所以側重點放在性能監控上,但是優化是全方位的工作所以也會涉及到資源,健康度,事件,日誌等,另外就針對每種監控類型的告警管理。
- 註釋 1:項目地址如下,就部署方式可參見項目介紹在此就不贅述:
https://github.com/coreos/kube-prometheus
2 數據採集
各維度的數據採集主要通過以下方式:
-
部署 cAdvisor(參見注釋 2)採集容器相關的性能指標數據,並通過 metrics 接口用 Prometheus 抓取;
-
也可根據需求可將各種監控,日誌採集的 Agent 部署在獨立的容器中,跟隨 Pod 中的容器一起啓動監督採集各種數據,具體可根據實際需求;
-
通過 Prometheus-node-exporter 採集主機的性能指標數據,並通過暴露的 metrics 接口用 Prometheus 抓取
-
通過 exporter 採集應用的網絡性能 (Http、Tcp 等) 數據,並通過暴露的 metrics 接口用 Prometheus 抓取
-
通過 kube-state-metrics 採集 k8S 資源對象的狀態指標數據,並通過暴露的 metrics 接口用 Prometheus 抓取
-
通過 etcd、kubelet、kube-apiserver、kube-controller-manager、kube-scheduler 自身暴露的 metrics 獲取節點上與 k8S 集羣相關的一些特徵指標數據。
- 註釋 2:
node-exporter:負責採集主機的信息和操作系統的信息,以容器的方式運行在監控主機上。
cAdvisor:負責採集容器的信息,以容器的方式運行在監控主機上。
3 資源監控說明
資源監控主要分爲這幾大類:如:CPU,內存,網絡,磁盤等信息的監控(其它還有對 GPU 等監控),另外就是對各種組件服務的資源使用情況,自定義告警閾值等(簡單的告警可以沿用內部已有的,複雜的告警指標需自己根據集羣和業務特徵通過獲取參數進行計算或撰寫 PromQL 獲取),建立全方位的監控指標(主要監控指標項可參見 Kube-prometheus 部署後的相關信息,在此就不贅述),主要監控項如下;
-
容器 CPU,Mem,Disk, Network 等資源佔用等情況;
-
Node、Pod 相關的性能指標數據;
-
容器內進程自己主動暴露的各項指標數據;
-
各個組件的性能指標涉及組件如:ECTD,API Server, Controller Manager, Scheduler, Kubelet 等;
4 主要指標監控
主要的監控指標,是依據 Google 提出的四個指標:延遲(Latency)、流量(Traffic)、錯誤數(Errors)、飽和度(Saturation)。實際操作中可以使用 USE 或 RED(詳見註釋 3 和 4)方法作爲衡量方法,USE 用於資源,RED 用於服務,它們在不同的監控場景有不同維度描述,相結合能夠描述大部分監控場景指標,合理的使用以下監控指標,有助用戶判斷當前 K8S 集羣的實際運行情況,可根據指標變化反覆優化各個參數和服務,使其達到更加的狀態,更詳細的監控指標信息,可參見 Kube-prometheus 相關監控信息。
4.1 Cadvisor 指標採集
cAdvisor(詳見參考 1)提供的 Container 指標最終是底層 Linux cgroup 提供的。就像 Node 指標一樣,但是我們最關心的是 CPU / 內存 / 網絡 / 磁盤。
1.CPU(利用率)
對於 Container CPU 利用率,K8S 提供了每個容器的多個指標:
#過去 10 秒容器 CPU 的平均負載
container_cpu_load_average_10s
#累計用戶消耗 CPU 時間(即不在內核中花費的時間)
container_cpu_user_seconds_total
#累計系統 CPU 消耗的時間(即在內核中花費的時間)
container_cpu_system_seconds_total
#累計 CPU 消耗時間
container_cpu_usage_seconds_total
#容器的 CPU 份額
container_spec_cpu_quota
#容器的 CPU 配額
container_spec_cpu_shares
#查詢展示每個容器正在使用的 CPU
sum(
rate(container_cpu_usage_seconds_total [5m]))
by(container_name)
過去 10 秒內容器 CPU 的平均負載值
container_cpu_load_average_10s{container="",id="/",image="",}
#累計系統 CPU 消耗時間
sum(rate(container_cpu_usage_seconds_total{name=~".+"}[1m])) by (name) * 100
#全部容器的 CPU 使用率總和,將各個 CPU 使用率進行累加後相除
sum(rate(container_cpu_usage_seconds_total{container_}[1m])) / (sum(container_spec_cpu_quota{container_}/100000))
2.CPU(飽和度)
sum(
rate(container_cpu_cfs_throttled_seconds_total[5m]))
by (container_name)
3.內存
cAdvisor 中提供的內存指標是從可參見官方網站,以下是內存指標(如無特殊說明均以字節位單位):
#高速緩存 (Cache)的使用量
container_memory_cache
RSS 內存,即常駐內存集,是分配給進程使用實際物理內存,而不是磁盤上緩存的虛擬內存。RSS 內存包括所有分配的棧內存和堆內存,以及加載到物理內存中的共享庫佔用的內存空間,但不包括進入交換分區的內存
container_memory_rss
#容器虛擬內存使用量。虛擬內存(swap)指的是用磁盤來模擬內存使用。當物理內存快要使用完或者達到一定比例,就可以把部分不用的內存數據交換到硬盤保存,需要使用時再調入物理內存
container_memory_swap
#當前內存使用情況,包括所有使用的內存,不管是否被訪問 (包括 cache, rss, swap 等)
container_memory_usage_bytes
#最大內存使用量
container_memory_max_usage_bytes
#當前內存工作集 (working set) 使用量
container_memory_working_set_bytes
#內存使用次數達到限制
container_memory_failcnt
#內存分配失敗的累積數量
container_memory_failures_total
#內存分配失敗次數
container_memory_failcnt
4.內存(利用率)
通過 PromQL 特定條件查詢容器內 job 內存使用情況:
container_memory_usage_bytes{instance="10.10.2.200:3002",job="panamax", }18
kubelet 通過 container_memory_working_set_bytes 來判斷是否 OOM, 所以用 working set 來評價容器內存使用量更合理,以下查詢中我們需要通過過濾 “POD” 容器,它是此容器的父級 cgroup,將跟蹤 pod 中所有容器的統計信息。
sum(container_memory_working_set_bytes {name!~“ POD”})by name
5.內存(飽和度)
OOM 的異常獲取沒有直接的指標項,因爲 OOM 後 Container 會被殺掉,可以使用如下查詢來變通獲取,這裏使用 label_join 組合了 kube-state-metrics 的指標:
sum(container_memory_working_set_bytes) by (container_name) / sum(label_join(kube_pod_con-tainer_resource_limits_memory_bytes,"container_name", "","container")) by (container_name)
6.磁盤(利用率)
在處理磁盤 I/O 時,我們通過查找和讀寫來跟蹤所有磁盤利用率,Cadvisor 有以下指標可以做位基本指標:
#容器磁盤執行 I/O 的累計秒數
container_fs_io_time_seconds_total
#容器磁盤累計加權 I/O 時間
container_fs_io_time_weighted_seconds_total
#查詢容器文件系統讀取速率(字節 / 秒)
sum(rate(container_fs_writes_bytes_total{image!=""}[1m]))without (device)
#查詢容器文件系統寫入速率 (字節 / 秒)
sum(rate(container_fs_writes_bytes_total{image!=""}[1m]))without (device)
最基本的磁盤 I/O 利用率是讀 / 寫的字節數, 對這些結果求和,以獲得每個容器的總體磁盤 I/O 利用率:
sum(rate(container_fs_reads_bytes_total[5m])) by (container_name,device)
7.網絡(利用率)
容器的網絡利用率,可以選擇以字節爲單位還是以數據包爲單位。網絡的指標有些不同,因爲所有網絡請求都在 Pod 級別上進行,而不是在容器上進行以下的查詢將按 pod 名稱顯示每個 pod 的網絡利用率:
#接收時丟包累計計數
container_network_receive_bytes_total
#發送時丟包的累計計數
container_network_transmit_packets_dropped_total
#接收字節 (1m)
sum(rate(container_network_receive_bytes_total{id="/"}[1m])) by (id)
#上傳字節 (1m)
sum(rate(container_network_transmit_bytes_total{id="/"}[1m])) by (id)
8.網絡(飽和度)
在無法得知準確的網絡帶寬是多少的情況下,網絡的飽和度無法明確定義,可以考慮使用丟棄的數據包代替,表示當前已經飽和,參見以下參數:
#接收時丟包累計計數
container_network_receive_packets_dropped_total
#發送時丟包的累計計數
container_network_transmit_packets_dropped_total
- 註釋 3:
在對於 cAdvisor 容器資源,USE 方法指標相對簡單如下:
Utilization:利用率
Saturation:飽和度
Error:錯誤
- 註釋 4:
USE 方法的定義:
Resource:所有服務器功能組件(CPU,Disk,Services 等)
Utilization:資源忙於服務工作的平均時間
Saturation:需要排隊無法提供服務的時間
Errors:錯誤事件的計數
RED 方法的解釋:
Rate:每秒的請求數。
Errors:失敗的那些請求的數量。
參考 1:
更詳細關於 cAdvisor 的參數信息大家可以一下地址獲取, 也可以自己組合更加適用於自己集羣的監控指標:
https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md
參考 2:
關於 Node_exporter,大家有興趣可以參考 Prometheus 項目中關於 Node_exporter 裏面說明如下:
https://github.com/prometheus/node_exporter
5 事件告警監控
監控 Event 轉換過程種的變化信息,以下只是部份告警信息,Kube-Prometheus 項目中有大部分告警指標,也可以從第三方導入相關告警事件:
#存在執行失敗的 Job:
kube_job_status_failed{job=”kubernetes-service-endpoints”,k8s_app=”kube-state-metrics”}==1
#集羣節點狀態錯誤:
kube_node_status_condition{condition=”Ready”,status!=”true”}==1
#集羣節點內存或磁盤資源短缺:
kube_node_status_condition{condition=~”OutOfDisk|MemoryPressure|DiskPressure”,status!=”false”}==1
#集羣中存在失敗的 PVC:
kube_persistentvolumeclaim_status_phase{phase=”Failed”}==1
#集羣中存在啓動失敗的 Pod:
kube_pod_status_phase{phase=~”Failed|Unknown”}==1
#最近 30 分鐘內有 Pod 容器重啓:
changes(kube_pod_container_status_restarts[30m])>0
6 日誌監控
日誌也是 K8S 集羣和容器 / 應用服務的很重要的數據來源,日誌中也能獲取各種指標和信息,主流的方式採用常駐的 Agent 採集日誌信息,將相關發送到 Kafka 集羣最後寫入 ES,也通過 Grafana 進行統一展示各項指標。
6.1 日誌採集
-
一種方式將各個容器的日誌都寫入宿主機的磁盤,容器掛載宿主機本地 Volume, 採用 Agent(Filebeat 或 Fluentd )採集這個部署在宿主機上所有容器轉存的日誌,發送到遠端 ES 集羣進行加工處理;
-
另一種是對於業務組(或者說 Pod)採集容器內部日誌,系統 / 業務日誌可以存儲在獨立的 Volume 中,可以採用 Sidecar 模式獨立部署日誌採集容器,來對進行日誌採集,對於 DaemonSet 和 Sidecar 這兩種日誌採集模式,大家可以根據實際需要選擇部署;
-
通過部署在每個 Node 上的 Agent 進行日誌採集,Agent 會把數據彙集到 Logstash Server 集羣,再由 Logstash 加工清洗完成後發送到 Kafka 集羣,再將數據存儲到 Elasticsearch,後期可通過 Grafana 或者 Kibana 做展現,這也是比較主流的一個做法。
6.2 日誌場景
主要需要採集的各種日誌分爲以下場景:
1.主機系統內核日誌採集:
-
一方面是主機系統內核日誌,主機內核日誌可以協助開發 / 運維進行一些常見的問題分析診斷,如:Linux Kernel Panic 涉及的(Attempted to kill the idle task,Attempted to kill init,killing interrupt handler)其它致命異常,這些情況要求導致其發生的程序或任務關閉,通常異常可能是任何意想不到的情況;
-
另一方面是各種 Driver 驅動異常,比如:Driver 內核對象出現異常或者說使用 GPU 的一些場景,各種硬件的驅動異常可能是比較常見的錯誤;
-
再就是文件系統異常,一些特定場景(如:虛機化,特定文件格式),實際上是會經常出現問題的。在這些出現問題後,開發者是沒有太好的辦法來去進行監控和診斷的。這一部分,其實是可以主機內核日誌裏面來查看到一些異常。
2.組件日誌採集:
K8S 集羣中各種組件是集羣非常重要的部份,既有內部組件也有外部的如:API Server, Controller-man-ger,Kubelet , ECTD 等, 它們會產生大量日誌可用於各種錯誤分析和性能優化,也能幫助用戶很好分析 K8S 集羣各個組件資源使用情況分析,異常情況分析;還有各種第三方插件的日誌(尤其是一些廠商貢獻的網絡插件或算法),也是優化分析的重點;
3.業務日誌採集:
業務日誌分析也是優化的很重要的環節,業務系統自身的特性(如:web 類,微服務類,API 接口類,基礎組件類)都需要日誌來分析,結合後面的資源預測和業務部署章節能否更好把握業務特性,創建合理的發佈配置和 Pod 配置,根據日誌分析業務訪問量,活動週期,業務峯值,調用關係等優化整個過程。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ewySrGmS9OG6EoZkwhQOLQ