https://github.com/kubernetes/kube-state-metrics/tree/master/kubernetes
概述
已經(jīng)有了cadvisor、heapster粉铐、metric-server疼约,幾乎容器運(yùn)行的所有指標(biāo)都能拿到,但是下面這種情況卻無能為力:
- 我調(diào)度了多少個(gè)replicas蝙泼?現(xiàn)在可用的有幾個(gè)程剥?
- 多少個(gè)Pod是running/stopped/terminated狀態(tài)?
- Pod重啟了多少次汤踏?
- 我有多少job在運(yùn)行中
而這些則是kube-state-metrics提供的內(nèi)容织鲸,它基于client-go開發(fā),輪詢Kubernetes API溪胶,并將Kubernetes的結(jié)構(gòu)化信息轉(zhuǎn)換為metrics搂擦。
功能
kube-state-metrics提供的指標(biāo),按照階段分為三種類別:
- 1.實(shí)驗(yàn)性質(zhì)的:k8s api中alpha階段的或者spec的字段哗脖。
- 2.穩(wěn)定版本的:k8s中不向后兼容的主要版本的更新
- 3.被廢棄的:已經(jīng)不在維護(hù)的瀑踢。
指標(biāo)類別包括:
- CronJob Metrics
- DaemonSet Metrics
- Deployment Metrics
- Job Metrics
- LimitRange Metrics
- Node Metrics
- PersistentVolume Metrics
- PersistentVolumeClaim Metrics
- Pod Metrics
- Pod Disruption Budget Metrics
- ReplicaSet Metrics
- ReplicationController Metrics
- ResourceQuota Metrics
- Service Metrics
- StatefulSet Metrics
- Namespace 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文章扳还,用于擴(kuò)縮容)
對(duì)于pod的資源限制,一般情況下:
200MiB memory 0.1 cores
超過100節(jié)點(diǎn)的集群:
2MiB memory per node 0.001 cores per node
kube-state-metrics做過一次性能優(yōu)化橱夭,具體內(nèi)容參考下文
因?yàn)閗ube-state-metrics-service.yaml中有 prometheus.io/scrape: 'true' 標(biāo)識(shí)氨距,因此會(huì)將metric暴露給prometheus,而Prometheus會(huì)在kubernetes-service-endpoints這個(gè)job下自動(dòng)發(fā)現(xiàn)kube-state-metrics徘钥,并開始拉取metrics衔蹲,無需其他配置。
使用kube-state-metrics后的常用場景有:
存在執(zhí)行失敗的Job: kube_job_status_failed{job="kubernetes-service-endpoints",k8s_app="kube-state-metrics"}==1
集群節(jié)點(diǎn)狀態(tài)錯(cuò)誤: kube_node_status_condition{condition="Ready",status!="true"}==1
集群中存在啟動(dòng)失敗的Pod:kube_pod_status_phase{phase=~"Failed|Unknown"}==1
最近30分鐘內(nèi)有Pod容器重啟: changes(kube_pod_container_status_restarts[30m])>0
配合報(bào)警可以更好地監(jiān)控集群的運(yùn)行
與metric-server的對(duì)比
metric-server(或heapster)是從api-server中獲取cpu呈础、內(nèi)存使用率這種監(jiān)控指標(biāo)舆驶,并把他們發(fā)送給存儲(chǔ)后端,如influxdb或云廠商而钞,他當(dāng)前的核心作用是:為HPA等組件提供決策指標(biāo)支持沙廉。
kube-state-metrics關(guān)注于獲取k8s各種資源的最新狀態(tài),如deployment或者daemonset臼节,之所以沒有把kube-state-metrics納入到metric-server的能力中撬陵,是因?yàn)樗麄兊年P(guān)注點(diǎn)本質(zhì)上是不一樣的。metric-server僅僅是獲取网缝、格式化現(xiàn)有數(shù)據(jù)巨税,寫入特定的存儲(chǔ),實(shí)質(zhì)上是一個(gè)監(jiān)控系統(tǒng)粉臊。而kube-state-metrics是將k8s的運(yùn)行狀況在內(nèi)存中做了個(gè)快照草添,并且獲取新的指標(biāo),但他沒有能力導(dǎo)出這些指標(biāo)
換個(gè)角度講扼仲,kube-state-metrics本身是metric-server的一種數(shù)據(jù)來源远寸,雖然現(xiàn)在沒有這么做。
另外屠凶,像Prometheus這種監(jiān)控系統(tǒng)驰后,并不會(huì)去用metric-server中的數(shù)據(jù),他都是自己做指標(biāo)收集矗愧、集成的(Prometheus包含了metric-server的能力)灶芝,但Prometheus可以監(jiān)控metric-server本身組件的監(jiān)控狀態(tài)并適時(shí)報(bào)警,這里的監(jiān)控就可以通過kube-state-metrics來實(shí)現(xiàn)贱枣,如metric-serverpod的運(yùn)行狀態(tài)监署。
深入解析
kube-state-metrics本質(zhì)上是不斷輪詢api-server,代碼結(jié)構(gòu)也很簡單
主要代碼目錄
.
├── 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{}{},
}
)
構(gòu)建對(duì)應(yīng)的收集器
Family即一個(gè)類型的資源集合纽哥,如job下的kube_job_info钠乏、kube_job_created,都是一個(gè)FamilyGenerator實(shí)例
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)
// 將參數(shù)寫到header中
familyHeaders := extractMetricFamilyHeaders(filteredMetricFamilies)
// NewMetricsStore實(shí)現(xiàn)了client-go的cache.Store接口春塌,實(shí)現(xiàn)本地緩存晓避。
store := metricsstore.NewMetricsStore(
familyHeaders,
composedMetricGenFuncs,
)
// 按namespace構(gòu)建Reflector簇捍,監(jiān)聽變化
reflectorPerNamespace(b.ctx, b.kubeClient, &batchv1beta1.CronJob{}, store, b.namespaces, createCronJobListWatch)
return NewCollector(store)
}
性能優(yōu)化:
kube-state-metrics在之前的版本中暴露出兩個(gè)問題:
/metrics接口響應(yīng)慢(10-20s)
內(nèi)存消耗太大,導(dǎo)致超出limit被殺掉
問題一的方案就是基于client-go的cache tool實(shí)現(xiàn)本地緩存俏拱,具體結(jié)構(gòu)為:
var cache = map[uuid][]byte{}
問題二的的方案是:對(duì)于時(shí)間序列的字符串暑塑,是存在很多重復(fù)字符的(如namespace等前綴篩選),可以用指針或者結(jié)構(gòu)化這些重復(fù)字符锅必。
優(yōu)化點(diǎn)和問題
1.因?yàn)閗ube-state-metrics是監(jiān)聽資源的add事格、delete、update事件搞隐,那么在kube-state-metrics部署之前已經(jīng)運(yùn)行的資源驹愚,豈不是拿不到數(shù)據(jù)?kube-state-metric利用client-go可以初始化所有已經(jīng)存在的資源對(duì)象劣纲,確保沒有任何遺漏
2.kube-state-metrics當(dāng)前不會(huì)輸出metadata信息(如help和description)
3.緩存實(shí)現(xiàn)是基于golang的map逢捺,解決并發(fā)讀問題當(dāng)期是用了一個(gè)簡單的互斥鎖,應(yīng)該可以解決問題癞季,后續(xù)會(huì)考慮golang的sync.Map安全map劫瞳。
4.kube-state-metrics通過比較resource version來保證event的順序
5.kube-state-metrics并不保證包含所有資源