Operator必须暴露/metrics端点并监听0.0.0.0,启用controller-runtime内置metrics server(设Mgr.Options.MetricsBindAddress为":8080"),指标须注册到mgr.GetMetricsRegistry()而非默认registry,Service与ServiceMonitor标签及端口名(metrics)须严格匹配。

你的 Operator 本身(即 controller 进程)必须暴露 /metrics 端点,且监听 0.0.0.0,否则 Prometheus Operator 无法抓取其内部运行指标(如 reconcile 耗时、错误计数、队列长度等)。这不是可选项,是 Operator 健康可观测性的基础。
controller-runtime 默认已集成 metrics server,但默认不启用
使用 controller-runtime(如 Kubebuilder 生成的项目)时,metrics server 是内置的,但默认绑定在 localhost:8080,且仅在开发环境启用。生产部署中它不会自动暴露,也不会响应集群内请求。
- 必须显式启用并重绑定地址:在
main.go中修改mgr.Options.MetricsBindAddress,设为":8080"(不是"localhost:8080") - 确保容器
containerPort和 Service 的port.name都设为metrics(这是ServiceMonitor默认匹配的端口名) - 若用 Helm Chart 部署,需确认
deployment.spec.template.spec.containers[0].ports包含该端口定义
Service 和 ServiceMonitor 必须标签严格匹配
ServiceMonitor 不会“猜”你要监控哪个 Service —— 它靠 selector.matchLabels 精确匹配 Service 的 labels,靠 endpoints.port 名称匹配 Service 的 port 名。
- Service 必须带 label,例如
monitoring: "true" -
ServiceMonitor的spec.selector.matchLabels必须完全一致(键和值都得对) - Service 的
spec.ports[0].name必须是metrics(或你在ServiceMonitor.endpoints[0].port中指定的同名值) - Service 的
spec.ports[0].targetPort必须指向 controller 容器中实际监听的端口(即8080)
抓不到指标?先验证三件事
别急着改 YAML,先进 Pod 确认基础连通性是否成立:
立即学习“go语言免费学习笔记(深入)”;
- 执行
kubectl exec -it <operator-pod> -- curl -s http://localhost:8080/metrics | head -n 3,应看到以# HELP开头的文本;若报Connection refused,说明 controller 没启动 metrics server 或绑定错了地址 - 检查 Service 是否能被解析:
kubectl get endpoints <your-operator-service>,输出中SUBSETS.ADDRESSES应有 IP,且PORTS显示metrics - 确认
ServiceMonitor被 Prometheus 实例识别:kubectl get servicemonitor -o wide,再查对应 Prometheus 的日志,搜索"discovered target"或"dropping target"
自定义指标要注册到 controller-runtime 的 registry
你写的业务指标(比如 myoperator_reconcile_errors_total)不能只注册到全局 registry(prometheus.DefaultRegisterer),而必须注入到 controller-runtime 使用的 registry 中,否则会被 metrics server 忽略。
- 获取当前 manager 的 registry:
mgr.GetMetricsRegistry() - 用
promauto.With(<registry>)构造指标,而不是直接用promauto.NewCounter(...) - 示例:
reconcileErrors = promauto.With(mgr.GetMetricsRegistry()).NewCounter(...) - 避免混用
prometheus.MustRegister()—— 它注册到默认 registry,对 controller-runtime metrics server 无效
最容易被忽略的是 registry 绑定方式:controller-runtime 的 metrics server 默认只暴露自己 registry 里的指标,哪怕你把自定义指标注册到了全局 registry,它也看不见。这导致本地 curl localhost:8080/metrics 能看到指标,但 Prometheus 抓不到——因为两者读的是不同的 registry 实例。


















