Skip to content

Prometheus Adapter HPA on k3s

First PublishedByAtif Alam

This lab adds prometheus-adapter to an existing kube-prometheus-stack install on k3s, then scales a Deployment with HPA on a custom metric.

Prerequisites: Installing Prometheus and Grafana on k3s completed (monitoring namespace, release name monitoring). CPU-only HPA first: HPA on k3s.

EKS production path: Prometheus Adapter for HPA on EKS.

Terminal window
kubectl get pods -n monitoring
kubectl port-forward -n monitoring svc/monitoring-kube-prometheus-prometheus 9090:9090

Open http://127.0.0.1:9090 and run Status → Targets — core targets should be UP.

Prometheus Service DNS (used by the adapter):

http://monitoring-kube-prometheus-prometheus.monitoring.svc:9090

If your release name differs, adjust: kubectl get svc -n monitoring.

Create adapter-rules.yaml:

rules:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
resources:
overrides:
namespace: { resource: "namespace" }
pod: { resource: "pod" }
name:
matches: "^(.*)_total$"
as: "${1}_per_second"
metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'

Create prometheus-adapter-values.yaml:

prometheus:
url: http://monitoring-kube-prometheus-prometheus.monitoring.svc
port: 9090
rules:
existing: adapter-rules
replicas: 1
Terminal window
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm upgrade --install prometheus-adapter prometheus-community/prometheus-adapter \
--namespace monitoring \
-f prometheus-adapter-values.yaml \
--wait

Verify:

Terminal window
kubectl get apiservice v1beta1.custom.metrics.k8s.io
kubectl get pods -n monitoring -l app.kubernetes.io/name=prometheus-adapter
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | head -c 1500

Deploy httpbin (or any exporter of http_requests_total) in namespace hpa-promo:

Terminal window
kubectl create namespace hpa-promo

httpbin-promo.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: hpa-promo
spec:
replicas: 2
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- name: httpbin
image: mccutchen/go-httpbin:v2.15.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 50m
memory: 64Mi
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: hpa-promo
labels:
app: httpbin
spec:
selector:
app: httpbin
ports:
- name: http
port: 80
targetPort: 8080

For kube-prometheus-stack to scrape the app, add a ServiceMonitor (labels must match your Prometheus serviceMonitorSelector — often release: monitoring):

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: httpbin
namespace: hpa-promo
labels:
release: monitoring
spec:
selector:
matchLabels:
app: httpbin
endpoints:
- port: http
path: /metrics
interval: 15s

go-httpbin may not expose Prometheus metrics by default — for a reliable lab, use an image with /metrics or add a small exporter sidecar. If no series appear, HPA will not scale; confirm a metric exists in Prometheus Explore before applying HPA.

For a known-good pattern, copy scrape config from Observability setup — ServiceMonitor for your app’s metric names.

Terminal window
kubectl apply -f httpbin-promo.yaml
# apply ServiceMonitor when your app exports /metrics

When Prometheus shows http_requests_per_second (or your rule’s output name):

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: httpbin-hpa
namespace: hpa-promo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: httpbin
minReplicas: 2
maxReplicas: 6
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "10"
Terminal window
kubectl apply -f httpbin-hpa.yaml
kubectl describe hpa httpbin-hpa -n hpa-promo

Generate load (port-forward + hey, or wget loop) as in HPA on k3s.

SymptomCheck
custom.metrics APIService missingAdapter pod logs, Helm release
No metric in APIPromQL in Prometheus UI; adapter rules
HPA unknownMetric name must match adapter as: rule
ServiceMonitor ignoredrelease label vs Prometheus selector
Terminal window
helm uninstall prometheus-adapter -n monitoring
kubectl delete namespace hpa-promo

To remove the full stack, see Prometheus + Grafana on k3s — Cleanup.