fix(helm): require the metrics server before rendering the gateway ServiceMonitor

The http port serves /metrics/ behind virtual-key auth, so a ServiceMonitor
pointed at it only collects 401s and the RPM/TPM HPA metrics never appear

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
yassin 2026-09-09 22:46:29 +00:00
parent fdf5d99f9d
commit 460e235f82
4 changed files with 22 additions and 11 deletions

View file

@ -260,8 +260,10 @@ keda:
# carry: KEDA divides the release-wide rate by it to pick the replica count.
# The queries select samples by the release namespace and the `job` label the
# chart's ServiceMonitor produces (the metrics Service name), so enable
# serviceMonitor below. Tokens are counted at completion, so TPM trails long
# streams. serverAddress is required once either target is set.
# serviceMonitor below together with metricsServer: the http port serves
# /metrics/ behind virtual-key auth and answers an unauthenticated scrape
# with 401. Tokens are counted at completion, so TPM trails long streams.
# serverAddress is required once either target is set.
prometheus:
serverAddress: ""
requestsPerMinute: ""

View file

@ -1,4 +1,7 @@
{{- if and .Values.gateway.enabled .Values.gateway.serviceMonitor.enabled }}
{{- if not .Values.gateway.metricsServer.enabled }}
{{- fail "gateway.serviceMonitor.enabled requires gateway.metricsServer.enabled: the http port serves /metrics/ behind virtual-key auth, so an unauthenticated scrape gets 401" }}
{{- end }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
@ -17,7 +20,7 @@ spec:
matchNames:
- {{ .Release.Namespace | quote }}
endpoints:
- port: {{ ternary "metrics" "http" .Values.gateway.metricsServer.enabled }}
- port: metrics
path: /metrics/
interval: {{ .Values.gateway.serviceMonitor.interval }}
scrapeTimeout: {{ .Values.gateway.serviceMonitor.scrapeTimeout }}

View file

@ -141,13 +141,22 @@ tests:
- hasDocuments:
count: 0
- it: scrapes each gateway pod through the http port when the metrics sidecar is off
- it: refuses a ServiceMonitor without the metrics server, whose http port needs a bearer token
template: gateway/servicemonitor.yaml
set:
gateway.serviceMonitor.enabled: true
asserts:
- failedTemplate:
errorPattern: gateway.serviceMonitor.enabled requires gateway.metricsServer.enabled
- it: scrapes each gateway pod through the metrics port
template: gateway/servicemonitor.yaml
release:
name: rel
namespace: llm
set:
gateway.serviceMonitor.enabled: true
gateway.metricsServer.enabled: true
gateway.serviceMonitor.labels:
release: kube-prometheus-stack
asserts:
@ -169,22 +178,19 @@ tests:
- equal:
path: spec.endpoints
value:
- port: http
- port: metrics
path: /metrics/
interval: 15s
scrapeTimeout: 10s
scheme: http
- it: scrapes the metrics sidecar port when the metrics server is on
- it: honours a custom scrape interval
template: gateway/servicemonitor.yaml
set:
gateway.serviceMonitor.enabled: true
gateway.serviceMonitor.interval: 30s
gateway.metricsServer.enabled: true
asserts:
- equal:
path: spec.endpoints[0].port
value: metrics
- equal:
path: spec.endpoints[0].interval
value: 30s

View file

@ -285,8 +285,8 @@ gateway:
limits:
memory: 512Mi
# Prometheus Operator ServiceMonitor for the gateway pods. Scrapes the
# `<gateway>-metrics` Service when metricsServer is enabled, otherwise the
# gateway Service on the http port. Either way every pod is its own scrape
# `<gateway>-metrics` Service, so it requires metricsServer above (the http
# port serves /metrics/ behind virtual-key auth). Every pod is its own scrape
# target, so the samples carry the `pod` label the per-pod autoscaling
# queries below group by.
serviceMonitor: