Prometheus-Operator使用ServiceMonitor監控配置時遇坑與解決總結

YOYOFx發表於2023-05-05

摘要

本文範圍: Prometheus-Operator & kube-prometheus 安裝;以及在解決使用ServiceMonitor時遇到的坑。

Prometheus Operator 簡介

隨著雲原生概念盛行,對於容器、服務、節點以及叢集的監控變得越來越重要。Prometheus 作為 Kubernetes 監控的事實標準,有著強大的功能和良好的生態。但是它不支援分散式,不支援資料匯入、匯出,不支援透過 API 修改監控目標和報警規則,所以在使用它時,通常需要寫指令碼和程式碼來簡化操作。Prometheus Operator 為監控 Kubernetes service、deployment 和 Prometheus 例項的管理提供了簡單的定義,簡化在 Kubernetes 上部署、管理和執行 Prometheus 和 Alertmanager 叢集。

Prometheus Operator 功能如下:

  • 建立/銷燬:在 Kubernetes namespace 中更加容易地啟動一個 Prometheues 例項,一個特定應用程式或者團隊可以更容易使用 Operator。
  • 便捷配置:透過 Kubernetes CRD資源配置 Prometheus 的基本資訊,比如版本、(分散式)儲存、副本集、高可用等。
  • 透過標籤標記目標服務: 基於常見的 Kubernetes label 查詢自動生成監控目標配置;不需要學習 Prometheus 特定的配置語言。

它使用如下的 Kubernetes CRD 資源對 Prometheus進行配置:

  • Prometheus
  • Alertmanager
  • ThanosRuler
  • ServiceMonitor
  • PodMonitor
  • Probe
  • PrometheusRule
  • AlertmanagerConfig

參考文件:

kube-prometheus 包含的軟體包:

  • The Prometheus Operator
  • Highly available Prometheus
  • Highly available Alertmanager
  • Prometheus node-exporter
  • Prometheus Adapter for Kubernetes Metrics APIs
  • kube-state-metrics
  • Grafana

Prometheus Operator 相容性

  • Kubernetes 1.16+ ,如需更低版本的 Kubernetes 相容性,請參考官方文件對應的版本分支。

以下程式碼分支對應的 Kubernetes 版本如下:

  • release-0.9 1.21,1.22
  • release-0.10 1.22,1.23
  • release-0.11 1.23,1.24
  • release-0.12 1.24,1.25

文章中已驗證的版本(PaaS 安裝版本)

  • 本地叢集(kind 1.25) release-0.12
  • 騰訊雲叢集(TKE 1.20) release-0.9

kube-prometheus 安裝解除安裝

安裝

git clone https://github.com/prometheus-operator/kube-prometheus.git
git checkout release-0.12

cd kube-prometheus

kubectl apply --server-side -f manifests/setup

kubectl wait \
	--for condition=Established \
	--all CustomResourceDefinition \
	--namespace=monitoring
	
kubectl apply -f manifests/

解除安裝

kubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup

helm安裝

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus-community/kube-prometheus-stack --namespace monitoring --generate-name

無論哪種安裝方式,遇到映象拉取失敗的情況,可以使用如下命令手動拉取映象並推送到自己的倉庫,本文中推送到自己的docker hub倉庫中,替換yaml中的image地址,然後再次執行安裝命令。

ServiceMonitor

ServiceMonitor 自定義資源(CRD)能夠宣告如何監控一組動態服務的定義。它使用標籤選擇定義一組需要被監控的服務。這樣就允許組織引入如何暴露 metrics 的規定,只要符合這些規定新服務就會被發現列入監控,而不需要重新配置系統。
一個 Service 可以公開一個或多個服務埠,通常情況下,這些埠由指向一個 Pod 的多個 Endpoints 支援。這也反映在各自的 Endpoints 物件中。
ServiceMonitorSpec 的 endpoints 部分用於配置需要收集 metrics 的 Endpoints 的埠和其他引數。在一些用例中會直接監控不在服務 endpoints 中的 pods 的埠。

例子

之前寫過一篇 《YoyoGo微服務框架入門系列-使用Prometheus監控Golang服務》 文章中的暴露的指標服務與本例中為同一個。
有如下 Service 指向 labels: k8s-app=dev-yoyogodemo-kind-kind 的 部署(Deployment):

apiVersion: v1
kind: Service
metadata:
  name: dev-yoyogodemo-kind-kind-svc-cluster-sgr
  namespace: klns-administration
  labels:
    k8s-app: dev-yoyogodemo-kind-kind
spec:
  ports:
    - name: default-tcp
      protocol: TCP
      port: 8080
      targetPort: 8080
  selector:
    k8s-app: dev-yoyogodemo-kind-kind

  type: ClusterIP
  sessionAffinity: None

為其建立 ServiceMonitor 資源定義如下:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: dev-yoyogodemo-kind-kind-servicemontor
  namespace: klns-administration
  labels:
    k8s-app: dev-yoyogodemo-kind-kind
spec:
  endpoints:
    - interval: 15s
      path: /app/actuator/metrics
      port: default-tcp
  namespaceSelector:
    matchNames:
    - klns-administration
  selector:
    matchLabels:
      k8s-app: dev-yoyogodemo-kind-kind

採坑

在預設配置中,此 ServiceMonitor 會因為 Kubenertes RBAC 叢集許可權問題,導致 ServiceMonitor不生效,表現為在Prometheus 的 targets 中看不到該 ServiceMonitor 的 targets。
檢視StatefulSet工作負載 prometheus-k8s 的狀態,檢視日誌,看到如下報錯:

services is forbidden: User "system:serviceaccount:monitoring:prometheus-k8s" cannot list services in the namespace monitoring

這是因為預設只配置了get許可權 。解決辦法是為 ServiceMonitor 新增如下的 ClusterRoleBinding,編輯 prometheus-k8s 角色繫結,新增如下內容:

...
- apiGroups:
    - ""
  resources:
    - services
    - endpoints
    - pods
  verbs:
    - get
    - list
    - watch

修改後重啟 StatefulSet: prometheus-k8s; ServiceMonitor就會找到對應 Service 資源的 labels 選擇器的Endpoint資源, 並且會被 Prometheus Operator 自動配置為 Prometheus 的 targets。

當然ServiceMonitor不生效的原因還有很多,比如ServiceMonitor的namespaceSelector和selector不匹配,或者ServiceMonitor的namespaceSelector和Service的namespace不匹配等等。

為什麼配置的ServiceMonitor或PodMonitor未生效?

排查步驟:

  • 確認Target是否已經被發現,找到目標Prometheus例項,然後在左側導航欄單擊服務發現,然後單擊Targets頁籤,檢查相應的Target是否已經被發現。
  • 檢視叢集CRD中是否存在相應的ServiceMonitor資源。
  • 確認Label Selector是否能選擇到期望的Pod或者Service
    # 以上面那個例子為例。執行以下命令,觀察返回結果,若無返回結果,則需要調整Label Selector或Namespace Selector,即可篩選出期望的Pod或者Service。
    
    kubectl get service -l k8s-app=dev-yoyogodemo-kind-kind -n klns-administration
    
  • 檢查埠設定,埠port欄位,需要指定為pod定義中spec.containers[i].ports[i].name,或services定義中spec.ports[i].name欄位的值。

推廣

目前正在將Prometheus Operator整合到PaaS專案中,後續會將整合過程中遇到的問題和解決方案分享出來。

kubelilin 多雲 PaaS 開源專案: https://github.com/KubeLilin/kubelilin