{{- if .Values.serviceMonitor.enabled }} {{/* Chart-native, values-gated. A hand-authored ServiceMonitor CR applied next to the release is banned: it drifts from the chart, survives a `helm uninstall`, and nothing owns it. The api is scraped through its Service. The worker and reconciler have no Service — they are scraped by pod, which is why their metrics port is named and their pods carry the component label. A ServiceMonitor's selector matches the SERVICE OBJECT's own metadata labels, not the Service's pod selector. api-service.yaml labels itself with `svcforge.labels` plus `app.kubernetes.io/component: api` — it does NOT carry the `app: api` that `svcforge.selectorLabels` adds, because that label exists for the chaos experiments' `kubectl delete pod -l app=worker` and belongs on pods. So this must not reuse selectorLabels: doing so matched nothing and api metrics were never scraped. These three keys are exactly the ones the Service metadata carries, and are enough to be unambiguous. */}} apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: {{ include "svcforge.fullname" . }}-api labels: {{- include "svcforge.labels" . | nindent 4 }} spec: selector: matchLabels: app.kubernetes.io/name: {{ include "svcforge.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: api endpoints: - port: http path: /metrics interval: {{ .Values.serviceMonitor.interval }} --- apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: {{ include "svcforge.fullname" . }}-workers labels: {{- include "svcforge.labels" . | nindent 4 }} spec: selector: matchExpressions: - key: app.kubernetes.io/component operator: In values: [worker, reconciler] - key: app.kubernetes.io/instance operator: In values: [{{ .Release.Name }}] podMetricsEndpoints: - port: metrics path: /metrics interval: {{ .Values.serviceMonitor.interval }} {{- end }}