4. Prometheus Operator 架构:核心组件与自动发现原理
在生产环境中,手动管理 Prometheus 配置(如 scrape_configs、rule_files)会随着微服务数量增长而迅速失控。Prometheus Operator 通过 Kubernetes 原生声明式 API 解决了这一痛点,将 Prometheus 的部署、配置、服务发现和告警管理全部抽象为自定义资源(CRD)。本章深入剖析 Operator 的组件架构、ServiceMonitor/PodMonitor 配置细节以及自动发现机制。
4.1 整体架构与核心组件
Prometheus Operator 遵循典型的 Kubernetes Operator 模式:一个控制循环(Controller)持续监听自定义资源的变化,并调和出期望的 Prometheus 实例状态。其核心组件包括:
| 组件 | CRD 名称 | 职责 |
|---|---|---|
| Operator | — | 核心控制器,监听所有 CRD 事件,创建/更新/删除 StatefulSet、Service、ConfigMap 等底层资源 |
| Prometheus | prometheuses.monitoring.coreos.com |
定义 Prometheus 实例的规格(版本、资源、存储、副本数),Operator 据此生成 StatefulSet |
| ServiceMonitor | servicemonitors.monitoring.coreos.com |
基于 Kubernetes Service 的标签选择器,定义如何抓取 Service 背后 Pod 的指标 |
| PodMonitor | podmonitors.monitoring.coreos.com |
直接基于 Pod 标签选择器,不依赖 Service,适用于 Sidecar 或无头服务场景 |
| PrometheusRule | prometheusrules.monitoring.coreos.com |
定义告警规则和记录规则,Operator 自动合并并挂载到 Prometheus 实例 |
| Alertmanager | alertmanagers.monitoring.coreos.com |
定义 Alertmanager 集群规格,Operator 生成对应的 StatefulSet 和配置 |
prometheus.yaml 并挂载到 Pod 中。这保证了配置的幂等性和可审计性。
4.2 ServiceMonitor 配置详解
ServiceMonitor 是 Prometheus Operator 中最常用的抓取配置 CRD。它通过 标签选择器 匹配 Kubernetes Service,然后从 Service 的 spec.ports 中获取抓取端口和路径。
4.2.1 核心字段与示例
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-app-monitor
namespace: monitoring
spec:
# 选择要抓取的 Service(命名空间选择器 + 标签选择器)
namespaceSelector:
matchNames:
- production
selector:
matchLabels:
app: my-app
release: stable
# 定义抓取端点
endpoints:
- port: http-metrics # 对应 Service 的端口名称
interval: 15s
path: /metrics
scheme: http
# 可选:TLS 配置、BasicAuth、Relabel 等
relabelings:
- sourceLabels: [__meta_kubernetes_pod_node_name]
targetLabel: node
action: replace
# 目标标签(自动附加到所有抓取到的指标)
targetLabels:
- app
- version
namespaceSelector 限定命名空间范围,再通过 selector.matchLabels 匹配 Service 的标签。匹配到的 Service 下的所有 Endpoints(即 Pod IP + 端口)都会成为 Prometheus 的抓取目标。
4.2.2 ServiceMonitor 与 Service 的关联流程
- 用户创建 ServiceMonitor:指定
namespaceSelector和selector。 - Operator 监听事件:发现新的 ServiceMonitor 资源。
- 查询匹配的 Service:Operator 调用 Kubernetes API,列出指定命名空间下所有标签匹配的 Service。
- 解析 Endpoints:对于每个匹配的 Service,获取其
spec.ports中名称与endpoints.port匹配的端口,再查询该 Service 背后的 Endpoints 对象,得到所有 Pod IP。 - 生成 scrape_config:Operator 将上述信息写入 Prometheus 配置的
scrape_configs段,并触发 Prometheus 热加载。
4.3 PodMonitor 配置详解
PodMonitor 与 ServiceMonitor 类似,但 不经过 Service 层,直接通过 Pod 标签选择器抓取。适用于以下场景:
- Sidecar 模式:主业务容器与指标导出 Sidecar 同 Pod,但未创建 Service。
- 无头服务(Headless Service):需要直接抓取每个 Pod 实例。
- Batch 任务:短生命周期 Pod,不需要 Service 抽象。
4.3.1 PodMonitor 示例
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: sidecar-monitor
namespace: monitoring
spec:
namespaceSelector:
any: true # 选择所有命名空间
selector:
matchLabels:
sidecar: metrics-exporter
podMetricsEndpoints:
- port: metrics
interval: 30s
path: /metrics
relabelings:
- sourceLabels: [__meta_kubernetes_pod_container_name]
targetLabel: container
action: replace
podMetricsEndpoints 字段(而非 endpoints),且端口必须对应 Pod 内容器的 containerPort 名称。如果 Pod 有多个容器,需要确保端口名称唯一。
4.4 自动发现原理与 Relabeling 机制
Prometheus Operator 的自动发现能力建立在 Kubernetes 服务发现(SD)之上,并通过 Relabeling 对发现的目标进行过滤、修改和标记。理解 Relabeling 是排查抓取问题的关键。
4.4.1 自动发现流程
4.4.2 关键元标签与 Relabeling 实战
Prometheus 在自动发现时会为每个目标注入一组 __meta_kubernetes_* 标签。以下是最常用的元标签:
| 元标签 | 来源 | 示例值 |
|---|---|---|
__meta_kubernetes_namespace |
Pod/Service 命名空间 | production |
__meta_kubernetes_pod_name |
Pod 名称 | my-app-7d8f9c6b4c-abcde |
__meta_kubernetes_pod_node_name |
Pod 所在节点 | node-01 |
__meta_kubernetes_service_name |
Service 名称(仅 ServiceMonitor) | my-app-svc |
__meta_kubernetes_pod_label_<label> |
Pod 标签(自动展开) | __meta_kubernetes_pod_label_app |
__meta_kubernetes_pod_annotation_<annotation> |
Pod 注解 | __meta_kubernetes_pod_annotation_prometheus_io_scrape |
4.4.3 典型 Relabeling 场景
production 命名空间中 app=my-app 且 version=v2 的 Pod,并将 version 标签暴露为最终标签。
relabelings:
- sourceLabels: [__meta_kubernetes_namespace]
regex: production
action: keep
- sourceLabels: [__meta_kubernetes_pod_label_app]
regex: my-app
action: keep
- sourceLabels: [__meta_kubernetes_pod_label_version]
targetLabel: version
action: replace
- sourceLabels: [__meta_kubernetes_pod_name]
targetLabel: instance
action: replace
1. 检查 ServiceMonitor/PodMonitor 的
namespaceSelector 是否覆盖了目标命名空间。2. 检查
selector 的标签是否与 Service/Pod 完全匹配(包括 release 等附加标签)。3. 检查 Relabeling 中是否有
keep 或 drop 规则误过滤了目标。4. 查看 Prometheus 实例的日志,搜索
service monitor 或 pod monitor 相关错误。
4.5 ServiceMonitor 与 PodMonitor 对比
| 维度 | ServiceMonitor | PodMonitor |
|---|---|---|
| 发现对象 | 通过 Service 标签匹配,再解析 Endpoints | 直接通过 Pod 标签匹配 |
| 端口定义 | 引用 Service 的 spec.ports[].name |
引用 Pod 内容器的 ports[].name |
| 适用场景 | 标准微服务,有稳定 Service 层 | Sidecar、无头服务、短生命周期 Pod |
| 负载均衡 | Service 可能做负载均衡(ClusterIP) | 直接抓取每个 Pod,无负载均衡 |
| 元标签丰富度 | 包含 Service 级别的元标签 | 仅包含 Pod 级别的元标签 |
| 配置字段 | endpoints |
podMetricsEndpoints |
4.6 蓝绿发布场景下的自动发现挑战
在蓝绿发布过程中,ServiceMonitor 和 PodMonitor 的自动发现行为会直接影响流量切换的观测连续性:
- ServiceMonitor 切换滞后:当 Service 的
selector从蓝色 Pod 标签切换到绿色 Pod 标签时,Prometheus 需要等待下一次relist interval(默认 30s-60s)才能发现新的 Endpoints。这会导致抓取目标短暂为空或出现旧目标。 - PodMonitor 实时性更高:PodMonitor 直接监听 Pod 标签变化,新 Pod 创建后几乎立即被发现(取决于 Operator 的同步周期,通常 10-15s)。
- Relabeling 冲突:如果蓝绿 Pod 带有相同的
app标签但不同的version标签,Relabeling 规则需要正确处理,避免将两个版本的目标合并到同一个job中导致指标混乱。
version 或 deployment 标签区分。待流量完全切换并稳定后,再通过更新 ServiceMonitor 的 selector 或直接删除旧 Pod 来清理目标。这样可以保证发布过程中的指标不中断。