One of Kubernetes many features is auto-scaling workloads. Typically, Horizontal Pod Autoscalers scale pods based on CPU or memory usage. During other times we could better scale by using custom metrics that Prometheus is already scraping.
Fortunately, Horizontal Pod Autoscalers can support using custom metrics.
I’m a fan of the kube-prometheus project, but it wasn’t apparent how to set up a Horizontal Pod Autoscaler using custom metrics. This post walks through:
- Deploying kube-prometheus (Prometheus operator, Prometheus adapter, Grafana, and more)
- Creating a custom metrics APIService
- Configuring Prometheus adapter to support our custom metrics
- Deploying a Horizontal Pod Autoscaler for Grafana using a custom metric
Deploy kube-prometheus
We’ll need to deploy a Prometheus instance before we can begin using Prometheus metrics for scaling.
I’ll be creating a Kubernetes cluster using kind v0.10.0 by running:
|
|
Then clone kube-prometheus v0.8.0 by executing:
|
|
Then using kubectl v1.21.0, apply the kube-prometheus manifests:
|
|
This will set us up with Prometheus, Alert Manager, and Grafana instances. Important to note is a component named prometheus-adapter
.
This component is responsible for taking Prometheus metrics and translating them to Kubernetes-supported metrics using APIService objects.
Create custom metrics APIService
The kube-prometheus project includes a metrics APIService,
which supports CPU and memory usage of pods for Horizontal Pod Autoscaler and commands like kubectl top pods --all-namespaces
.
To leverage other Prometheus metrics for Horizontal Pod Autoscaler, we’ll need a custom metrics APIService, which its specification
will look very similar to the metrics APIService.
Create a file named ~/custom-metrics-apiservice.yaml
with the following:
|
|
and apply it via:
|
|
This will inform Kubernetes that the prometheus-adapter
service supports the custom.metrics.k8s.io
interface used by
Horizontal Pod Autoscaler.
To confirm the custom metrics APIService is configured correctly, run:
|
|
to see output similar to:
|
|
Edit prometheus-adapter configmap
We need to configure the Prometheus adapter to create custom metrics before using them for scaling.
For this, we’ll modify the prometheus-adapter
’s Config Map:
|
|
Take a look at the config.yaml
value and note that kube-prometheus
has already configured
resourceRules
for reporting CPU and memory usage.
At the same level as resourceRules
, create a key named rules
looking like:
|
|
I’ve annotated above to explain what’s going on in rules
.
Adding the rules
list will begin populating the custom metrics once the adapter has loaded this configuration file.
We’ll then need to re-create the prometheus-adapter
pods to take the config changes. We can delete these pods, and then Kubernetes
will re-create them by running:
|
|
To verify the new configuration changes were picked up, run:
|
|
which will output something similar to:
|
|
and we can run:
|
|
to see the metrics like:
|
|
Some of the values may seem higher than expected but note these are milli (m)
units.
Create Grafana HorizonalPodAutoscaler
Lastly, we’ll create a Horizontal Pod Autoscaler for the Grafana Deployment. Create a new file named ~/grafana-hpa.yaml
with
the following YAML:
|
|
Note: The targetAverageValue is pretty low here, simply to show the HorizonalPodAutoscaler scaling quickly soon.
Apply this manifest by running:
|
|
Afterward, watch the Grafana pod scale by running:
|
|
and over time, we’ll see the Grafana pods scale up.
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
grafana Deployment/grafana 244211m/10 1 10 1 54s
grafana Deployment/grafana 244211m/10 1 10 1 62s
grafana Deployment/grafana 112644m/10 1 10 4 77s
grafana Deployment/grafana 112644m/10 1 10 8 93s
grafana Deployment/grafana 102/10 1 10 10 108s
grafana Deployment/grafana 100533m/10 1 10 10 2m19s
How else have you been leveraging Prometheus Metrics? Or any tips for supporting Horizontal Pod Autoscalers? Let me know on Twitter, LinkedIn, or GitHub.