容器監控實踐—kube-state-metrics


概述

已經有了cadvisor、heapster(metric server),幾乎容器運行的所有指標都能拿到,但是下面這種情況卻無能為力:

  • 我調度了多少個replicas?現在可用的有幾個?
  • 多少個Pod是running/stopped/terminated狀態?
  • Pod重啟了多少次?
  • 我有多少job在運行中

而這些則是kube-state-metrics提供的內容,它基於client-go開發,輪詢Kubernetes API,並將Kubernetes的結構化信息轉換為metrics。

功能

kube-state-metrics提供的指標,按照階段分為三種類別:

  • 1.實驗性質的:k8s api中alpha階段的或者spec的字段。
  • 2.穩定版本的:k8s中不向后兼容的主要版本的更新
  • 3.被廢棄的:已經不在維護的。

指標類別包括:

  • CronJob Metrics
  • DaemonSet Metrics
  • Deployment Metrics
  • Job Metrics
  • LimitRange Metrics
  • Node Metrics
  • PersistentVolume Metrics
  • PersistentVolumeClaim Metrics
  • Pod Metrics
  • Pod Disruption Budget Metrics
  • Horizontal Pod Autoscaler Metrics
  • Endpoint Metrics
  • Secret Metrics
  • ConfigMap Metrics
  • …..

以pod為例:

  • kube_pod_info
  • kube_pod_owner
  • kube_pod_status_phase
  • kube_pod_status_ready
  • kube_pod_status_scheduled
  • kube_pod_container_status_waiting
  • kube_pod_container_status_terminated_reason

使用

部署清單

 kube-state-metrics/ ├── kube-state-metrics-cluster-role-binding.yaml ├── kube-state-metrics-cluster-role.yaml ├── kube-state-metrics-deployment.yaml ├── kube-state-metrics-role-binding.yaml ├── kube-state-metrics-role.yaml ├── kube-state-metrics-service-account.yaml ├── kube-state-metrics-service.yaml

主要鏡像有:
image: quay.io/coreos/kube-state-metrics:v1.5.0
image: k8s.gcr.io/addon-resizer:1.8.3(參考metric server文章,用於擴縮容)

對於pod的資源限制,一般情況下:

200MiB memory 0.1 cores

超過100節點的集群:

2MiB memory per node 0.001 cores per node

kube-state-metrics做過一次性能優化,具體內容參考下文

部署成功后,prometheus的target會出現如下標志

因為kube-state-metrics-service.yaml中有prometheus.io/scrape: ‘true’標識,因此會將metric暴露給prometheus,而Prometheus會在kubernetes-service-endpoints這個job下自動發現kube-state-metrics,並開始拉取metrics,無需其他配置。

使用kube-state-metrics后的常用場景有:

  • 存在執行失敗的Job: kube_job_status_failed{job=”kubernetes-service-endpoints”,k8s_app=”kube-state-metrics”}==1
  • 集群節點狀態錯誤: kube_node_status_condition{condition=”Ready”,status!=”true”}==1
  • 集群中存在啟動失敗的Pod:kube_pod_status_phase{phase=~”Failed|Unknown”}==1
  • 最近30分鍾內有Pod容器重啟: changes(kube_pod_container_status_restarts[30m])>0

配合報警可以更好地監控集群的運行

與metric-server的對比

  • metric-server(或heapster)是從api-server中獲取cpu、內存使用率這種監控指標,並把他們發送給存儲后端,如influxdb或雲廠商,他當前的核心作用是:為HPA等組件提供決策指標支持。
  • kube-state-metrics關注於獲取k8s各種資源的最新狀態,如deployment或者daemonset,之所以沒有把kube-state-metrics納入到metric-server的能力中,是因為他們的關注點本質上是不一樣的。metric-server僅僅是獲取、格式化現有數據,寫入特定的存儲,實質上是一個監控系統。而kube-state-metrics是將k8s的運行狀況在內存中做了個快照,並且獲取新的指標,但他沒有能力導出這些指標
  • 換個角度講,kube-state-metrics本身是metric-server的一種數據來源,雖然現在沒有這么做。
  • 另外,像Prometheus這種監控系統,並不會去用metric-server中的數據,他都是自己做指標收集、集成的(Prometheus包含了metric-server的能力),但Prometheus可以監控metric-server本身組件的監控狀態並適時報警,這里的監控就可以通過kube-state-metrics來實現,如metric-serverpod的運行狀態。

深入解析

kube-state-metrics本質上是不斷輪詢api-server,代碼結構也很簡單
主要代碼目錄

. ├── collectors  ├── builder.go  ├── collectors.go  ├── configmap.go  ......  ├── testutils.go  ├── testutils_test.go  └── utils.go ├── constant  └── resource_unit.go ├── metrics  ├── metrics.go  └── metrics_test.go ├── metrics_store  ├── metrics_store.go  └── metrics_store_test.go ├── options  ├── collector.go  ├── options.go  ├── options_test.go  ├── types.go  └── types_test.go ├── version  └── version.go └── whiteblacklist ├── whiteblacklist.go └── whiteblacklist_test.go

所有類型:

var ( DefaultNamespaces = NamespaceList{metav1.NamespaceAll} DefaultCollectors = CollectorSet{ "daemonsets": struct{}{}, "deployments": struct{}{}, "limitranges": struct{}{}, "nodes": struct{}{}, "pods": struct{}{}, "poddisruptionbudgets": struct{}{}, "replicasets": struct{}{}, "replicationcontrollers": struct{}{}, "resourcequotas": struct{}{}, "services": struct{}{}, "jobs": struct{}{}, "cronjobs": struct{}{}, "statefulsets": struct{}{}, "persistentvolumes": struct{}{}, "persistentvolumeclaims": struct{}{}, "namespaces": struct{}{}, "horizontalpodautoscalers": struct{}{}, "endpoints": struct{}{}, "secrets": struct{}{}, "configmaps": struct{}{}, } )

構建對應的收集器

Family即一個類型的資源集合,如job下的kube_job_info、kube_job_created,都是一個FamilyGenerator實例

metrics.FamilyGenerator{ Name: "kube_job_info", Type: metrics.MetricTypeGauge, Help: "Information about job.", GenerateFunc: wrapJobFunc(func(j *v1batch.Job) metrics.Family { return metrics.Family{&metrics.Metric{ Name: "kube_job_info", Value: 1, }} }), },
func (b *Builder) buildCronJobCollector() *Collector { // 過濾傳入的白名單 filteredMetricFamilies := filterMetricFamilies(b.whiteBlackList, cronJobMetricFamilies) composedMetricGenFuncs := composeMetricGenFuncs(filteredMetricFamilies) // 將參數寫到header中 familyHeaders := extractMetricFamilyHeaders(filteredMetricFamilies) // NewMetricsStore實現了client-go的cache.Store接口,實現本地緩存。 store := metricsstore.NewMetricsStore( familyHeaders, composedMetricGenFuncs, ) // 按namespace構建Reflector,監聽變化 reflectorPerNamespace(b.ctx, b.kubeClient, &batchv1beta1.CronJob{}, store, b.namespaces, createCronJobListWatch) return NewCollector(store) }

性能優化:

kube-state-metrics在之前的版本中暴露出兩個問題:

  1. metrics接口響應慢(10-20s)
  2. 內存消耗太大,導致超出limit被殺掉

問題一的方案就是基於client-go的cache tool實現本地緩存,具體結構為:

var cache = map[uuid][]byte{}

問題二的的方案是:對於時間序列的字符串,是存在很多重復字符的(如namespace等前綴篩選),可以用指針或者結構化這些重復字符。

優化點和問題

  • 1.因為kube-state-metrics是監聽資源的add、delete、update事件,那么在kube-state-metrics部署之前已經運行的資源,豈不是拿不到數據?kube-state-metric利用client-go可以初始化所有已經存在的資源對象,確保沒有任何遺漏
  • 2.kube-state-metrics當前不會輸出metadata信息(如help和description)
  • 3.緩存實現是基於golang的map,解決並發讀問題當期是用了一個簡單的互斥鎖,應該可以解決問題,后續會考慮golang的sync.Map安全map。
  • 4.kube-state-metrics通過比較resource version來保證event的順序
  • 5.kube-state-metrics並不保證包含所有資源

監控數據展示

基於kube-state-metrics的監控數據,可以組裝一些常用的監控面板,如下面的grafana面板

原文來自:https://www.jianshu.com/p/2c899452ab5a


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM