為什么說Prometheus是為云原生監(jiān)控而生的?
原文鏈接:https://segmentfault.com/a/1190000040150566
為什么prometheus是為云原生監(jiān)控而生的?
想必你不止一次的地聽說了prometheus是為云原生監(jiān)控而生的,那你有沒有想過這句話意味著什么呢?
我們知道在云原生中使用容器和k8s環(huán)境作為基礎(chǔ)運行環(huán)境
一體化架構(gòu)被拆分成眾多分散的微服務(wù),而微服務(wù)的變更和擴(kuò)縮容是特別頻繁的,也就導(dǎo)致采集的目標(biāo)信息變化頻繁。這就給時序監(jiān)控系統(tǒng)提出了兩個要求:
需要采集運行在跨多個宿主機(jī)上的海量pod容器
同時要及時感知到他們的變化
同時要構(gòu)建完整的k8s監(jiān)控生態(tài),能有
其實說白了就是在云原生環(huán)境中監(jiān)控變得更難了,更復(fù)雜了。所以需要一個在設(shè)計之初就適合云原生監(jiān)控場景的系統(tǒng),而prometheus就是這么設(shè)計的。
Prometheus到底做了哪些改進(jìn),能配得上k8s ?
k8s中應(yīng)該關(guān)注哪些指標(biāo)?在下面的表格中簡單列舉了下我們在k8s需要關(guān)注的四大塊指標(biāo):

適配1. sdk+指標(biāo)自暴露+pull模型:構(gòu)建k8s監(jiān)控的整個生態(tài)
在上面的列舉的表格中我們看到在k8s需要關(guān)注的四大塊指標(biāo)
其實我們可以簡單地把k8s的使用者分為兩種角色:k8s集群管理員和普通用戶。每種角色關(guān)注的指標(biāo)不相同
自己采集豈不累死了?
既然需求這么多,如果只是由監(jiān)控系統(tǒng)自己采集,第一很累,第二構(gòu)建不出這么完整的生態(tài)
奧妙
prometheus是pull模型采集的,各個被監(jiān)控的源只需要將自身指標(biāo)暴露在本地http端口中,prometheus就可以訪問接口來采集指標(biāo)
prometheus在k8s中也是這樣的,組件需要暴露自身指標(biāo),如我們在容器基礎(chǔ)資源指標(biāo)中提到的kubelet 內(nèi)置cadvisor指標(biāo)就是暴露在10250端口下的/metrics/cadvisor下。
prometheus通過 k8s服務(wù)發(fā)現(xiàn)這些指標(biāo)源完成采集
適配2. k8s服務(wù)發(fā)現(xiàn)
舉例
一、endpoint級別的服務(wù)發(fā)現(xiàn) :舉例 在采集apiserver、kube-controller-manager等
kubernetes_sd_configs:
role: endpoints
二、node級別的服務(wù)發(fā)現(xiàn) :舉例 在采集cadvisor和kubelet自身指標(biāo)時
kubernetes_sd_configs:
- role: node三、node級別的服務(wù)發(fā)現(xiàn) :舉例 在采集pod自打點指標(biāo)時
kubernetes_sd_configs:
- role: pod
follow_redirects: true解讀:watch即時更新
通過watch即時發(fā)現(xiàn)資源變化,就滿足了我們一開始提出的云原生情況下監(jiān)控的挑戰(zhàn)之一,要及時感知到采集源的變化。
同時在k8s大二層環(huán)境中,prometheus可以訪問到發(fā)現(xiàn)出來的的 endpoint 、node、pod
適配3. 采集鑒權(quán):token & 證書
k8s中很多接口都要鑒權(quán),甚至還需要tls雙向認(rèn)證
同時我們知道在k8s中很多接口都是帶有訪問鑒權(quán)的,比如我們直接訪問k8s node上的kubelet的/metrics/cadvisor接口會返回未授權(quán)。如下面所示
[root@Kubernetes-node01 logs]# curl -k https://localhost:10250/metrics/cadvisor
Unauthorizedprometheus在采集cadvisor指標(biāo)時同樣面臨鑒權(quán)問題
解決方法
聰明的prometheus開發(fā)人員通過在采集中支持配置中相關(guān)token和證書來解決這個問題,如下面的配置代表有一個token文件,同時還有一個證書文件。
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true我們在使用k8s時知道,k8s通過 service account,clusterrolebinding來解決token、證書掛載問題
prometheus也是利用了這一點,在創(chuàng)建prometheus容器是相關(guān)的service account,clusterrolebinding配置的示例如下:
apiVersion: rbac.authorization.k8s.io/v1 # api的version
kind: ClusterRole # 類型
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources: # 資源
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus # 自定義名字
namespace: kube-system # 命名空間
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef: # 選擇需要綁定的Role
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects: # 對象
- kind: ServiceAccount
name: prometheus
namespace: kube-system
我們在創(chuàng)建相關(guān)prometheus 的statsfulset時需要在prometheus yaml中需要配置對應(yīng)的serviceAccountName
serviceAccountName: prometheus配置好之后Kubernetes會將對應(yīng)的token和證書文件掛載到pod中。
我們exec進(jìn)入prometheus的pod中就可以查看到相關(guān)文件在
/var/run/secrets/kubernetes.io/serviceaccount/,如下圖所示:
/ # ls /var/run/secrets/kubernetes.io/serviceaccount/ -l
total 0
lrwxrwxrwx 1 root root 13 Jan 7 20:54 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Jan 7 20:54 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Jan 7 20:54 token -> ..data/token
/ # df -h |grep service
tmpfs 7.8G 12.0K 7.8G 0% /var/run/secrets/kubernetes.io/serviceaccount
/ # 在采集etcd時需要配置相關(guān)證書的secret
kubectl create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key --from-file=/etc/kubernetes/pki/etcd/ca.crt -n kube-system
適配4. 強(qiáng)大的relabel能力 做標(biāo)簽截取、變換、靜態(tài)分片
prometheus relabel說明
文檔地址 https://prometheus.io/docs/pr...
應(yīng)用1:labelmap 在采集cadvisor指標(biāo)時 對服務(wù)發(fā)現(xiàn)標(biāo)簽key名字截取
在采集cadvisor時可以看到服務(wù)發(fā)現(xiàn)源給添加了很多
__meta_kubernetes_node_label_開頭的標(biāo)簽
但是這些標(biāo)簽名字太長了,需要精簡。我們使用如下的relabel配置
relabel_configs:
- separator: ;
regex: __meta_kubernetes_node_label_(.+)
replacement: $1
action: labelmap以這個標(biāo)簽為例,
__meta_kubernetes_node_label_kubernetes_io_os="linux",上面的配置代表匹配_meta_kubernetes_node_label_開頭的key,只保留后面的部分,所以在最終的標(biāo)簽看到的就是beta_kubernetes_io_os="linux"。labelmap代表匹配到的標(biāo)簽賦值給目標(biāo)標(biāo)簽
應(yīng)用2:replace 在采集pod自定義指標(biāo) 對標(biāo)簽進(jìn)行賦值
我們在使用pod自定義指標(biāo)時在pod yaml 的spec.template.metadata.annotations中需要定義三個以
prometheus.io開頭的配置,分布代表是否需要prometheus采集、metrics暴露的端口、metrics的http path信息,詳細(xì)配置如下:spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9102'
prometheus.io/path: 'metrics'在采集pod自定義指標(biāo)時采用如下
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
separator: ;
regex: "true"
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
separator: ;
regex: (.+)
target_label: __metrics_path__
replacement: $1
action: replace
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
separator: ;
regex: ([^:]+)(?::\d+)?;(\d+)
target_label: __address__
replacement: $1:$2
action: replace意思是將
__meta_kubernetes_pod_annotation_prometheus_io_path賦值給__metrics_path__意思是將相關(guān)
__meta_kubernetes_pod_annotation_prometheus_io_port賦值給__address__后面的端口
應(yīng)用2:keep 做過濾,在采集服務(wù)組件endpoint時
endpoint資源是暴露一個服務(wù)的ip地址和port的列表
代表采用k8s服務(wù)發(fā)現(xiàn) endpoint,endpoint會非常多,所以需要過濾apiserver的
kubernetes_sd_configs:
- role: endpoints過濾手段為 標(biāo)簽 __meta_kubernetes_namespace匹配default并且 __meta_kubernetes_service_name 匹配kubernetes 并且 __meta_kubernetes_endpoint_port_name 匹配https,咋樣呢 :
keep
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
separator: ;
regex: default;kubernetes;https
replacement: $1
action: keep
k8s 會在default namespace中創(chuàng)建apiserver的 service
$ kubectl get svc -A |grep 443
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d最后獲取到的endpoint轉(zhuǎn)換為采集路徑為:
https://masterip:6443/metrics
Prometheus為k8s監(jiān)控做的適配工作:


長按掃描
系統(tǒng)學(xué)習(xí)Prometheus監(jiān)控系統(tǒng)
- END -
推薦閱讀 K8s運維架構(gòu)師實戰(zhàn)集訓(xùn)營【多個企業(yè)項目】 Prometheus+Granafa構(gòu)建高大上的MySQL監(jiān)控平臺 12年資深運維老司機(jī)的成長感悟 快速入門 Ansible 自動化運維工具 | 16張圖 運維的工作邊界,這次真的搞明白了! 最強(qiáng)整理!常用正則表達(dá)式速查手冊 60道常見的 Kubernetes 面試題總結(jié) 不管你是開發(fā)還是運維,微服務(wù)這些你得知道! 從零開始搭建創(chuàng)業(yè)公司DevOps技術(shù)棧 2021年的DevOps趨勢預(yù)測 搭建一套完整的企業(yè)級 K8s 集群(v1.20,kubeadm方式)
點亮,服務(wù)器三年不宕機(jī)


