
-
一方面吧,它生態特別好:作為 Kubernetes 監控的事實標準,(幾乎)所有 Kubernetes 相關元件都暴露了 Prometheus 的指標介面,甚至在 Kubernetes 生態之外,絕大部分傳統中介軟體(比如 MySQL、Kafka、Redis、ES)也有社群提供的 Prometheus Exporter。我們已經可以去掉 Kubernetes 這個定語,直接說 Prometheus 是開源監控方案的”頭號種子選手”了;
-
另一方面吧,都 2019 年了,一個基礎設施領域的“頭號種子”選手居然還不支援分散式、不支援資料匯入/匯出、甚至不支援透過 API 修改監控標的和報警規則,這是不是也挺匪夷所思的?
-
Alertmanager:定義一個 Alertmanager 叢集;
-
ServiceMonitor:定義一組 Pod 的指標應該如何採集;
-
PrometheusRule:定義一組 Prometheus 規則;
-
Prometheus:定義一個 Prometheus “叢集”,同時定義這個叢集要使用哪些 ServiceMonitor 和 PrometheusRule。
kind: Alertmanager ➊metadata:name: mainspec:baseImage: quay.io/prometheus/alertmanagerreplicas: 3 ➋version: v0.16.0
-
➊ 一個 Alertmanager 物件
-
➋ 定義該 Alertmanager 叢集的節點數為 3
kind: Prometheusmetadata: # 略spec:alerting:alertmanagers:- name: alertmanager-main ➊namespace: monitoringport: webbaseImage: quay.io/prometheus/prometheusreplicas: 2 ➋ruleSelector: ➌matchLabels:prometheus: k8srole: alert-rulesserviceMonitorNamespaceSelector: {} ➍serviceMonitorSelector: ➎matchLabels:k8s-app: node-exporterquery:maxConcurrency: 100 ➏version: v2.5.0
-
➊ 定義該 Prometheus 對接的 Alertmanager 叢集名字為 main,在 monitoring 這個 namespace 中;
-
➋ 定義該 Proemtheus “叢集”有兩個副本,說是叢集,其實 Prometheus 自身不帶叢集功能,這裡只是起兩個完全一樣的 Prometheus 來避免單點故障;
-
➌ 定義這個 Prometheus 需要使用帶有 prometheus=k8s 且 role=alert-rules 標簽的 PrometheusRule;
-
➍ 定義這些 Prometheus 在哪些 namespace 裡尋找 ServiceMonitor,不宣告則預設選擇 Prometheus 物件本身所處的 Namespace;
-
➎ 定義這個 Prometheus 需要使用帶有 k8s-app=node-exporter 標簽的 ServiceMonitor,不宣告則會全部選中;
-
➏ 定義 Prometheus 的最大併發查詢數為 100,幾乎所有配置都可以透過 Prometheus 物件進行宣告(包括很重要的 RemoteRead、RemoteWrite),這裡為了簡潔就不全部列出了。
kind: ServiceMonitormetadata:labels:k8s-app: node-exporter ➊name: node-exporternamespace: monitoringspec:selector:matchLabels: ➋app: node-exporterk8s-app: node-exporterendpoints:- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/tokeninterval: 30s ➌targetPort: 9100 ➍scheme: httpsjobLabel: k8s-app
-
➊ 這個 ServiceMonitor 物件帶有 k8s-app=node-exporter 標簽,因此會被上面的 Prometheus 選中;
-
➋ 定義需要監控的 Endpoints,帶有 app=node-exporter 且 k8s-app=node-exporter 標簽的 Endpoints 會被選中;
-
➌ 定義這些 Endpoints 需要每 30 秒抓取一次;
-
➍ 定義這些 Endpoints 的指標埠為 9100;
kind: PrometheusRulemetadata:labels: ➊prometheus: k8srole: alert-rulesname: prometheus-k8s-rulesspec:groups:- name: k8s.rulesrules: ➋- alert: KubeletDownannotations:message: Kubelet has disappeared from Prometheus target discovery.expr: |absent(up{job="kubelet"} == 1)for: 15mlabels:severity: critical
-
➊ 定義該 PrometheusRule 的 label,顯然它會被上面定義的 Prometheus 選中;
-
➋ 定義了一組規則,其中只有一條報警規則,用來報警 kubelet 是不是掛了。

-
那麼 Prometheus 做配置熱更新的時候就會失敗,假如配置更新失敗沒有報警,那麼 Game Over;
-
熱更新失敗有報警,但這時 Prometheus 突然重啟了,於是配置錯誤重啟失敗,Game Over。
- job_name: 'kubernetes-service-endpoints'kubernetes_sd_configs:- role: endpointsrelabel_configs:- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]action: keepregex: true- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]action: replacetarget_label: __scheme__regex: (https?)- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]action: replacetarget_label: __metrics_path__regex: (.+)- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]action: replacetarget_label: __address__regex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2- action: labelmapregex: __meta_kubernetes_service_label_(.+)- source_labels: [__meta_kubernetes_namespace]action: replacetarget_label: kubernetes_namespace- source_labels: [__meta_kubernetes_service_name]action: replacetarget_label: kubernetes_name- source_labels: [__meta_kubernetes_pod_node_name]action: replacetarget_label: kubernetes_node
-
這個 Prometheus 要針對所有 annotation 中帶有 prometheus.io/scrape=true 的 Endpoints 物件,按照 annotation 中的 prometheus.io/port,prometheus.io/scheme,prometheus.io/path 來抓取它們的指標。
-
複雜:複雜是萬惡之源;
-
沒有分離關註點:應用開發者(提供 Pod 的人)必須知道 Prometheus 維護者的配置是怎麼編寫的,才能正確提供 annotation;
-
沒有 API:更新流程複雜,需要透過 CI 或 Kubernetes ConfigMap 等手段把配置檔案更新到 Pod 內再觸發 webhook 熱更新;
知識星球
朋友會在“發現-看一看”看到你“在看”的內容