OpenShift多Pod部署下Prometheus指标被覆盖问题求助
场景与问题
我在OpenShift上部署了名为host status monitor app的Golang应用,同时部署了Prometheus实例及Operator。应用执行操作后会向Prometheus上报指标,已创建Service和Route,可通过该Route查看所有Prometheus指标并作为Grafana数据源。
当前问题:将应用Pod数量增至2个时,第二个Pod会覆盖第一个Pod上报的所有指标。
需求:配置多Pod部署,所有Pod的指标通过同一Route展示且互不影响。
应用上报指标的核心函数:
func PublishMetrics(hostName, originalState, swarch, server, provtype string) { states := []string{STATE_ACTIVE, STATE_UNRESPONSIVE, STATE_INACTIVE, STATE_DECOMISSIONED, STATE_REMOVED} for _, state := range states { HostStateGauge.With(prometheus.Labels{ "host": hostName, "state": state, "swarch": swarch, "server": server, "provtype": provtype, }).Set(0) } HostStateGauge.With(prometheus.Labels{ "host": hostName, "state": STATE_UNKNOWN, "swarch": "", "server": "", "provtype": "", }).Set(0) HostStateGauge.With(prometheus.Labels{ "host": hostName, "state": originalState, "swarch": swarch, "server": server, "provtype": provtype, }).Set(1) }
核心原因
Prometheus采集多Pod指标时,若指标的标签集合完全一致,后续Pod的指标会覆盖之前的记录。当前场景中,所有Pod上报的HostStateGauge指标没有区分Pod实例的标签,导致Prometheus无法识别不同Pod的指标,从而产生覆盖问题。
解决步骤
1. 为指标添加Pod实例标识标签
在Golang代码中,给HostStateGauge添加唯一标识Pod的标签(如pod_name),每个Pod启动时获取自身的Pod名称作为标签值:
首先添加获取Pod名称的逻辑(OpenShift会自动为Pod注入POD_NAME环境变量,本地调试可设置默认值):
import "os" func getPodName() string { podName := os.Getenv("POD_NAME") if podName == "" { return "local-dev-pod" } return podName }
修改PublishMetrics函数,新增pod标签:
func PublishMetrics(hostName, originalState, swarch, server, provtype string) { podName := getPodName() states := []string{STATE_ACTIVE, STATE_UNRESPONSIVE, STATE_INACTIVE, STATE_DECOMISSIONED, STATE_REMOVED} for _, state := range states { HostStateGauge.With(prometheus.Labels{ "host": hostName, "state": state, "swarch": swarch, "server": server, "provtype": provtype, "pod": podName, // 添加Pod标识标签 }).Set(0) } HostStateGauge.With(prometheus.Labels{ "host": hostName, "state": STATE_UNKNOWN, "swarch": "", "server": "", "provtype": "", "pod": podName, // 添加Pod标识标签 }).Set(0) HostStateGauge.With(prometheus.Labels{ "host": hostName, "state": originalState, "swarch": swarch, "server": server, "provtype": provtype, "pod": podName, // 添加Pod标识标签 }).Set(1) }
2. 确保Deployment注入POD_NAME环境变量
如果OpenShift未自动注入该变量,可在Deployment模板中手动配置:
spec: template: spec: containers: - name: host-status-monitor image: your-image:tag env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name
3. 配置Prometheus ServiceMonitor
通过Prometheus Operator创建ServiceMonitor,让Prometheus自动发现所有Pod的指标端点:
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: host-status-monitor-servicemonitor labels: release: prometheus-operator # 匹配你的Prometheus实例release标签 spec: selector: matchLabels: app: host-status-monitor # 匹配应用Service的标签 endpoints: - port: metrics # 应用Service暴露的指标端口名称 interval: 30s
4. 验证指标展示
部署修改后的应用与配置后,通过Route访问Prometheus,查询HostStateGauge指标,会看到带有不同pod标签的多条记录,不会再出现覆盖。在Grafana中,可通过pod标签区分不同Pod的指标,或使用sum、avg等聚合函数汇总数据。
内容的提问来源于stack exchange,提问作者SRM KTR

