From f06c4693ae5967e3bd7329e018129fc9d3160308 Mon Sep 17 00:00:00 2001 From: serversidehannes Date: Mon, 6 Jul 2026 20:18:44 +0200 Subject: [PATCH] feat: expose HAProxy Prometheus metrics on frontproxy Enable HAProxy's native /metrics exporter so queue depth and session counts are available for autoscaling and saturation alerts. Co-authored-by: Cursor --- chart/README.md | 6 +++++ chart/templates/frontproxy/configmap.yaml | 10 +++++++ chart/templates/frontproxy/deployment.yaml | 5 ++++ chart/templates/frontproxy/service.yaml | 6 +++++ .../templates/frontproxy/servicemonitor.yaml | 26 +++++++++++++++++++ chart/values.yaml | 11 ++++++++ 6 files changed, 64 insertions(+) create mode 100644 chart/templates/frontproxy/servicemonitor.yaml diff --git a/chart/README.md b/chart/README.md index dcfa031..e354580 100644 --- a/chart/README.md +++ b/chart/README.md @@ -70,6 +70,12 @@ helm install s3proxy oci://ghcr.io/serversidehannes/s3proxy-python/charts/s3prox | `frontproxy.timeouts.client` | `1h` | Client-side timeout (tolerate large transfers) | | `frontproxy.timeouts.server` | `1h` | Backend timeout (tolerate large transfers) | | `frontproxy.timeouts.connect` | `10s` | Backend connect timeout | +| `frontproxy.metrics.enabled` | `true` | Expose HAProxy's native `/metrics` endpoint (queue depth, sessions) | +| `frontproxy.metrics.port` | `8404` | Prometheus scrape port on the frontproxy pods | +| `frontproxy.metrics.serviceMonitor.enabled` | `true` | Create a Prometheus Operator ServiceMonitor for the frontproxy | +| `frontproxy.metrics.serviceMonitor.interval` | `30s` | Scrape interval | +| `frontproxy.metrics.serviceMonitor.scrapeTimeout` | `10s` | Scrape timeout | +| `frontproxy.metrics.serviceMonitor.labels` | `{}` | Extra labels on the ServiceMonitor (e.g. for Prometheus selector) | | `frontproxy.podDisruptionBudget.enabled` | `true` | Enable front proxy PDB | | `frontproxy.podDisruptionBudget.minAvailable` | `1` | Min available front proxy pods | | `ingress.enabled` | `false` | Expose S3 outside the cluster via Ingress (requires `frontproxy.enabled`) | diff --git a/chart/templates/frontproxy/configmap.yaml b/chart/templates/frontproxy/configmap.yaml index 706efd3..8d20833 100644 --- a/chart/templates/frontproxy/configmap.yaml +++ b/chart/templates/frontproxy/configmap.yaml @@ -37,6 +37,16 @@ data: bind *:{{ .Values.frontproxy.containerPort }} default_backend s3proxy_pods + {{- if .Values.frontproxy.metrics.enabled }} + # Native HAProxy Prometheus exporter (queue depth, sessions, backend health). + # Scraped via the `metrics` Service port + ServiceMonitor. + frontend prometheus + bind *:{{ .Values.frontproxy.metrics.port }} + mode http + no log + http-request use-service prometheus-exporter if { path /metrics } + {{- end }} + backend s3proxy_pods balance leastconn # Per-request balancing: don't pin a client to one server, and re-resolve the diff --git a/chart/templates/frontproxy/deployment.yaml b/chart/templates/frontproxy/deployment.yaml index 2b69a18..ea266ae 100644 --- a/chart/templates/frontproxy/deployment.yaml +++ b/chart/templates/frontproxy/deployment.yaml @@ -28,6 +28,11 @@ spec: - name: http containerPort: {{ .Values.frontproxy.containerPort }} protocol: TCP + {{- if .Values.frontproxy.metrics.enabled }} + - name: metrics + containerPort: {{ .Values.frontproxy.metrics.port }} + protocol: TCP + {{- end }} volumeMounts: - name: config mountPath: /usr/local/etc/haproxy/haproxy.cfg diff --git a/chart/templates/frontproxy/service.yaml b/chart/templates/frontproxy/service.yaml index 30afe47..31e14c3 100644 --- a/chart/templates/frontproxy/service.yaml +++ b/chart/templates/frontproxy/service.yaml @@ -16,4 +16,10 @@ spec: port: {{ .Values.frontproxy.service.port }} targetPort: http protocol: TCP + {{- if .Values.frontproxy.metrics.enabled }} + - name: metrics + port: {{ .Values.frontproxy.metrics.port }} + targetPort: metrics + protocol: TCP + {{- end }} {{- end }} diff --git a/chart/templates/frontproxy/servicemonitor.yaml b/chart/templates/frontproxy/servicemonitor.yaml new file mode 100644 index 0000000..f1cddec --- /dev/null +++ b/chart/templates/frontproxy/servicemonitor.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.frontproxy.enabled .Values.frontproxy.metrics.enabled .Values.frontproxy.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ .Chart.Name }}-frontproxy + labels: + {{- include "s3proxy.labels" . | nindent 4 }} + app.kubernetes.io/component: frontproxy + {{- with .Values.frontproxy.metrics.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: app.kubernetes.io/name + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "s3proxy.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: frontproxy + endpoints: + - port: metrics + path: /metrics + interval: {{ .Values.frontproxy.metrics.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.frontproxy.metrics.serviceMonitor.scrapeTimeout }} +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml index 427cc10..fc43fb5 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -218,6 +218,17 @@ frontproxy: # timeouts.queue) and redispatch to a less-loaded pod instead of hard-failing. # ~40 x worst-case part size stays well under the pod memory limit. maxConnPerPod: 40 + # HAProxy's built-in Prometheus exporter on a separate port (not exposed via + # Ingress). Exposes haproxy_frontend_current_sessions, + # haproxy_backend_current_queue, haproxy_server_current_queue, etc. + metrics: + enabled: true + port: 8404 + serviceMonitor: + enabled: true + interval: 30s + scrapeTimeout: 10s + labels: {} resources: requests: cpu: "50m"