Kubernetes叢集部署史上最詳細(二)Prometheus監控Kubernetes叢集

昀溪發表於2019-04-09

使用Prometheus監控Kubernetes叢集

監控方面Grafana採用YUM安裝透過服務形式執行,部署在Master上,而Prometheus則透過POD執行,Grafana透過使用Prometheus的service地址來獲取資料來源。

Prometheus的配置清單在kubernetes二進位制程式包中就有,下載地址

解壓後有一個cluster目錄,該目錄裡面的addons裡面有所需要的外掛,比如dns、dashboard以及prometheus等。

我用的就是它自帶的這個prometheus清單檔案,但是它裡面有些問題比如prometheus這個元件需要PV但是原始的包裡面沒有這個PV你需要手動建立,我這裡已經寫好了yaml檔案不過使用的是hostpath,主要是為了測試方便如果是生產環境中不建議這樣使用至少也要用個NFS這種儲存,另外它原始的清單檔案中使用的prometheus等映象版本較低雖然也可以使用但是我修改了這些版本使用的最新的版本,最新版本中有些啟動引數變化了所以也修改了響應的內容。所以你直接使用我修改的這個就可以,從下面的連結下載,另外這裡還包括了grafana的2個dashboard,這兩個也做了修改,因為從官網下載的模板對於有些指標識別不了(因為版本問題或者其他問題導致指標名稱對不上),所以需要修改。

檔案說明

上圖是原始內容,我包裡的yaml檔案只比它多一個。上面分成4個部分,

下面這4個是部署prometheus服務端用的
prometheus-configmap.yaml # 我在原有的配置中增加了global區域
prometheus-rabc.yaml
prometheus-service.yaml
prometheus-statefulset.yaml

下面這2個是部署node_exporter用的
node-exporter-ds.yaml
node-exporter-service.yaml

下面3個是部署kube-state-metrics用的,這個元件是對監控內容的補充,雖然你部署了metric-server、kubelet也提供了cadvisor介面以及上面
部署的node_exporter,但是還有一些指標需要監控比如排程了多少副本現在有幾個可用、不同狀態的POD有多少、POD重啟了多少次、執行了多少job等
這個元件也是從API SERVER上去獲取資料但是這些資料是原始資料而不像kubectl那樣可能會為了便於理解而對某些資料做修改
kube-state-metrics-deployment.yaml
kube-state-metrics-rabc.yaml
kube-state-metrics-service.yaml

下面4個是alertmanager報警元件的部署
alertmanager-service.yaml
alertmanager-pvc.yaml
alertmanager-deployment.yaml
alertmanager-configmap.yaml

kube-state-metrics與metric-server的對比

metric-server(或heapster)是一個叢集元件定期透過kubelet來獲取叢集節點的cpu、記憶體使用率這種監控指標,而且它只保留最新資料且儲存在記憶體中,不負責傳送給第三方,你可以透過其他方式把他們傳送給儲存後端,如influxdb或雲廠商,他當前的核心作用是:為HPA等元件提供決策指標支援。

kube-state-metrics關注於獲取k8s各種資源物件的最新狀態,如deployment或者daemonset,它在記憶體中保留kubernetes叢集狀態的快照並且在隨後的時間裡基於這個快照生成新的指標,而且它也不負責發資料發給第三方。將kube-state-metrics作為單獨的專案,還可以從Prometheus等監控系統訪問這些指標。

之所以沒有把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的執行狀態。

POD的Annotations是什麼

Annotations將任何非標識metadata附加到物件,標籤可用於選擇物件並查詢滿足某些條件的物件集合。相比之下,Annotations不用於標識和選擇物件,雖然它也是鍵值形式。Annotations不會被Kubernetes直接使用,其主要目的是方便使用者閱讀查詢。

Prometheus配置檔案說明



# Kubernetes的API SERVER會暴露API服務,Promethues整合了對Kubernetes的自動發現,它有5種模式:Node、Service
# 、Pod、Endpoints、ingress,下面是Prometheus官方給出的對Kubernetes服務發現的例項。這裡你會看到大量的relabel_configs,
# 其實你就是把所有的relabel_configs去掉一樣可以對kubernetes做服務發現。relabel_configs僅僅是對採集過來的指標做二次處理,比如
# 要什麼不要什麼以及替換什麼等等。而以__meta_開頭的這些後設資料標籤都是例項中包含的,而relabel則是動態的修改、覆蓋、新增刪除這些標籤
# 或者這些標籤對應的值。而且以__開頭的標籤通常是系統內部使用的,因此這些標籤不會被寫入樣本資料中,如果我們要收集這些東西那麼則要進行
# relabel操作。當然reabel操作也不僅限於操作__開頭的標籤。
#
# action的行為:
# replace:預設行為,不配置action的話就採用這種行為,它會根據regex來去匹配source_labels標籤上的值,並將並將匹配到的值寫入target_label中
# labelmap:它會根據regex去匹配標籤名稱,並將匹配到的內容作為新標籤的名稱,其值作為新標籤的值
# keep:僅收集匹配到regex的源標籤,而會丟棄沒有匹配到的所有標籤,用於選擇
# drop:丟棄匹配到regex的源標籤,而會收集沒有匹配到的所有標籤,用於排除
# labeldrop:使用regex匹配標籤,符合regex規則的標籤將從target例項中移除,其實也就是不收集不儲存
# labelkeep:使用regex匹配標籤,僅收集符合regex規則的標籤,不符合的不收集
#
global:
scrape_interval: 10s
evaluation_interval: 30s
scrape_configs:
# 用於發現API SERVER
- job_name: 'kubernetes-apiservers'


kubernetes_sd_configs:
# 發現endpoints,它是從列出的服務端點發現目標,這個endpoints來自於Kubernetes中的service,每一個service都有對應的endpoints,這裡是一個列表
# 可以是一個IP:PORT也可以是多個,這些IP:PORT就是service透過標籤選擇器選擇的POD的IP和埠。所以endpoints角色就是用來發現server對應的pod的IP的
# kubernetes會有一個預設的service,透過找到這個service的endpoints就找到了api server的IP:PORT,那endpoints有很多,我怎麼知道哪個是api server呢
# 這個就靠source_labels指定的標籤名稱了。
- role: endpoints
# 透過什麼形式來連線,預設是https
scheme: https
# 下面這個ca_file和token_file的路徑都是預設的,你可能預設設定能用麼?其實可以,因為每一個執行起來的POD kubernetes都會為其
# 建立一個serviceaccout的Secret並且掛載到下面的目錄上,裡面就有ca.crt和token這兩個檔案,你可以自己啟動一個POD,然後透過
# kubectl describe pods 來檢視,一定會在Volumes下面有一個default-token-XXX的東西,並且Mounts裡面有下面的目錄。
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token


# 下面的含義是源標籤__meta_kubernetes_namespace等如果其值為default;kubernetes;https標籤順序和值要對應。換句話說就是
# 當__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name三者對應的
# 值為default、kubernetes、https則進行保留,而且該endpoints對應的地址為api server的地址。
#
# __meta_kubernetes_namespace 端點物件的名稱空間,在不同物件上這個標籤的含義不同,在角色是endpoints中這個是端點物件的名稱空間
# __meta_kubernetes_service_name 端點物件的服務名稱
# __meta_kubernetes_endpoint_port_name 端點的埠名稱
#
# kubernetes預設在default名稱空間有一個叫做kubernetes的service,所以這個service的有3個設定對應的就是下面三個標籤
# __meta_kubernetes_namespace 值為default
# __meta_kubernetes_service_name 值為kubernetes
# __meta_kubernetes_endpoint_port_name 值為https
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https


# 配置針對kubelet的服務發現以及對標籤的處理,是獲取kubelet上/metrics介面資料來獲取node的資源使用情況
- job_name: 'kubernetes-nodes-kubelet'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# 跳過CA驗證
# insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token


kubernetes_sd_configs:
# 使用node角色,它使用預設的kubelet提供的http埠來發現叢集中每個node節點。那具體地址是什麼呢?
# 地址型別有四種NodeInternalIP, NodeExternalIP, NodeLegacyHostIP 和 NodeHostName,預設為這四個中第一個可用的地址。
# 那麼這裡為什麼使用node角色呢?因為node角色就是用來發現kubelet的
# __meta_kubernetes_node_name:節點物件的名字
# __meta_kubernetes_node_label_<labelname>:表示節點物件上的每一個標籤
# __meta_kubernetes_node_annotation_<annotationname>:表示節點物件上的每一個annotation
# __meta_kubernetes_node_address_<address_type>:如果存在,那麼將是每一個節點地址型別的第一個地址
# Node模式,Prometheus會自動發現Kubernetes中所有Node節點的資訊並作為監控的目標Target。
# 而這些Target的訪問地址實際上就是Kubelet的訪問地址,並且Kubelet實際上直接內建了對Promtheus的支援
- role: node


relabel_configs:
# 保留(.+)匹配到的內容,去掉__meta_kubernetes_node_label_,實際上就是把(.+)當做新標籤,然後老標籤的值給這個新標籤,
# 這裡沒有設定source_labels,則表示匹配所有標籤
- action: labelmap
# 匹配節點物件上的每一個標籤
regex: __meta_kubernetes_node_label_(.+)


# 抓取cAdvisor資料,是獲取kubelet上/metrics/cadvisor介面資料來獲取容器的資源使用情況
- job_name: 'kubernetes-nodes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token


kubernetes_sd_configs:
# 使用角色為node
- role: node


relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
# 把__metrics_path__的值替換為/metrics/cadvisor,因為預設是/metrics
- target_label: __metrics_path__
replacement: /metrics/cadvisor


# 抓取服務端點,整個這個任務都是用來發現node-exporter和kube-state-metrics-service的,這裡用的是endpoints角色,這是透過這兩者的service來發現
# 的後端endpoints。另外需要說明的是如果滿足採集條件,那麼在service、POD中定義的labels也會被採集進去
- job_name: 'kubernetes-service-endpoints'


kubernetes_sd_configs:
- role: endpoints


relabel_configs:
# 重新打標僅抓取到的具有 "prometheus.io/scrape: true" 的annotation的端點,意思是說如果某個service具有prometheus.io/scrape = true annotation宣告則抓取
# annotation本身也是鍵值結構,所以這裡的源標籤設定為鍵,而regex設定值,當值匹配到regex設定的內容時則執行keep動作也就是保留,其餘則丟棄.
# node-exporter這個POD的service裡面就有一個叫做prometheus.io/scrape = true的annotations所以就找到了node-exporter這個POD
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true

# 應用中自定義暴露的指標,也許你暴露的API介面不是/metrics這個路徑,那麼你可以在這個POD對應的service中做一個
# "prometheus.io/path = /mymetrics" 宣告,下面的意思就是把你宣告的這個路徑賦值給__metrics_path__
# 其實就是讓prometheus來獲取自定義應用暴露的metrices的具體路徑,不過這裡寫的要和service中做好約定
# 如果service中這樣寫 prometheus.io/app-metrics-path: '/metrics' 那麼你這裡就要
# __meta_kubernetes_service_annotation_prometheus_io_app_metrics_path這樣寫
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)

# 暴露自定義的應用的埠,就是把地址和你在service中定義的 "prometheus.io/port = <port>" 宣告做一個拼接
# 然後賦值給__address__,這樣prometheus就能獲取自定義應用的埠,然後透過這個埠再結合__metrics_path__來獲取
# 指標,如果__metrics_path__值不是預設的/metrics那麼就要使用上面的標籤替換來獲取真正暴露的具體路徑
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__

# 重新設定scheme
# 匹配源標籤__meta_kubernetes_service_annotation_prometheus_io_scheme也就是prometheus.io/scheme annotation
# 如果源標籤的值匹配到regex則把值替換為__scheme__對應的值
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)


# 下面主要是為了給樣本新增額外資訊
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name


# 下面是自動發現service,不過如果要想監控service則需要安裝blackbox-exporter
- job_name: 'kubernetes-services-http'


metrics_path: /probe
# 生成__param_module="http_2xx"的label,如果是TCP探測則使用 module: [tcp_connect]
params:
module: [http_2xx]


kubernetes_sd_configs:
- role: service


relabel_configs:
# 為了讓service可以被探測到,那需要在service的annotation中增加 prometheus.io/scrape: true 宣告
# 也就是隻保留prometheus.io/scrape: true的service
- action: keep
regex: true
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_scrape
# 用__address__這個label的值建立一個名為__param_target的label為blackbox-exporter,值為內部service的訪問地址,作為blackbox-exporter採集用
- source_labels: [__address__]
target_label: __param_target


# 用blackbox-exporter的service地址值”prometheus-blackbox-exporter:9115"替換原__address__的值
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance

# 下面主要是為了給樣本新增額外資訊
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
target_label: kubernetes_name


# 下面是對ingresses監控,不過如果要想監控ingresses則需要安裝blackbox-exporter
- job_name: 'kubernetes-ingresses'


metrics_path: /probe
# 生成__param_module="http_2xx"的label
params:
module: [http_2xx]


kubernetes_sd_configs:
- role: ingress


relabel_configs:
# Example relabel to probe only some ingresses that have "example.io/should_be_probed = true" annotation
# - source_labels: [__meta_kubernetes_ingress_annotation_example_io_should_be_probed]
# action: keep
# regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
# 下面主要是為了給樣本新增額外資訊
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name


# 抓取POD進行監控
- job_name: 'kubernetes-pods'


kubernetes_sd_configs:
- role: pod
relabel_configs:
# POD的 annotation 中含有"prometheus.io/scrape: true" 的則保留,意思就是會被Prometheus抓取,不具有這個的POD則不會被抓取
- action: keep
regex: true
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_scrape
# 獲取POD的 annotation 中定義的"prometheus.io/path: XXX"定義的值,這個值就是你的程式暴露符合prometheus規範的metrics的地址
# 如果你的metrics的地址不是 /metrics 的話,透過這個標籤說,那麼這裡就會把這個值賦值給 __metrics_path__這個變數,因為prometheus
# 是透過這個變數獲取路徑然後進行拼接出來一個完整的URL,並透過這個URL來獲取metrics值的,因為prometheus預設使用的就是 http(s)://X.X.X.X/metrics
# 這樣一個路徑來獲取的。
- action: replace
regex: (.+)
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_path
target_label: __metrics_path__
# 這裡是埠資訊,因為你的程式很有可能在容器中並不是以80埠執行的,那麼就需要做一個拼接http(s)://x.x.x.x:xx/metrics
# __address__在prometheus中代表的就是例項的IP地址,而POD中的annotation 中定義的"prometheus.io/port: XX"就是你程式
# 被訪問到的埠,最終在prometheus中將會被顯示為 instance=X.X.X.X:XX這樣
- action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
source_labels:
- __address__
- __meta_kubernetes_pod_annotation_prometheus_io_port
target_label: __address__


- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name

prometheus是如何識別apiserver的呢?

這些亂七八糟的標籤可能讓你眼花繚亂,我們舉一個簡單的例子看一下,prometheus是如何識別apiserver的,看下圖

其他說明和參考文件

另外在grafana主機安裝外掛 grafana-cli plugins install grafana-piechart-panel 然後重啟grafana服務。否則8919中的餅圖使用不了。

https://github.com/1046102779/prometheus/blob/master/operating/configuration.md

https://blog.csdn.net/liukuan73/article/details/78881008

https://github.com/yunlzheng/prometheus-book

監控清單檔案下載

相關文章