-
一方面吧,它生態特別好:作為 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: main
spec:
baseImage: quay.io/prometheus/alertmanager
replicas: 3 ➋
version: v0.16.0
-
➊ 一個 Alertmanager 物件
-
➋ 定義該 Alertmanager 叢集的節點數為 3
kind: Prometheus
metadata: # 略
spec:
alerting:
alertmanagers:
- name: alertmanager-main ➊
namespace: monitoring
port: web
baseImage: quay.io/prometheus/prometheus
replicas: 2 ➋
ruleSelector: ➌
matchLabels:
prometheus: k8s
role: alert-rules
serviceMonitorNamespaceSelector: {} ➍
serviceMonitorSelector: ➎
matchLabels:
k8s-app: node-exporter
query:
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: ServiceMonitor
metadata:
labels:
k8s-app: node-exporter ➊
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels: ➋
app: node-exporter
k8s-app: node-exporter
endpoints:
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
interval: 30s ➌
targetPort: 9100 ➍
scheme: https
jobLabel: k8s-app
-
➊ 這個 ServiceMonitor 物件帶有 k8s-app=node-exporter 標簽,因此會被上面的 Prometheus 選中;
-
➋ 定義需要監控的 Endpoints,帶有 app=node-exporter 且 k8s-app=node-exporter 標簽的 Endpoints 會被選中;
-
➌ 定義這些 Endpoints 需要每 30 秒抓取一次;
-
➍ 定義這些 Endpoints 的指標埠為 9100;
kind: PrometheusRule
metadata:
labels: ➊
prometheus: k8s
role: alert-rules
name: prometheus-k8s-rules
spec:
groups:
- name: k8s.rules
rules: ➋
- alert: KubeletDown
annotations:
message: Kubelet has disappeared from Prometheus target discovery.
expr: |
absent(up{job="kubelet"} == 1)
for: 15m
labels:
severity: critical
-
➊ 定義該 PrometheusRule 的 label,顯然它會被上面定義的 Prometheus 選中;
-
➋ 定義了一組規則,其中只有一條報警規則,用來報警 kubelet 是不是掛了。
-
那麼 Prometheus 做配置熱更新的時候就會失敗,假如配置更新失敗沒有報警,那麼 Game Over;
-
熱更新失敗有報警,但這時 Prometheus 突然重啟了,於是配置錯誤重啟失敗,Game Over。
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- 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
- source_labels: [__meta_kubernetes_pod_node_name]
action: replace
target_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 熱更新;
朋友會在“發現-看一看”看到你“在看”的內容