KEDA (Kubernetes Event-Driven Autoscaling) extends the standard Horizontal Pod Autoscaler with event-source-driven scaling — including scale-to-zero. This guide covers install and a few scaler patterns commonly useful on a VPS cluster (queue-driven jobs, metrics-driven web scaling, cron-based batch work).
Assumption: same cluster as the Longhorn guide — kubeadm on RamNode KVM VPS nodes,
kubectl/helmfrom the jump host.
1. Prerequisites
- Kubernetes 1.27+
metrics-serverinstalled (KEDA works alongside standard HPA metrics)
kubectl get deployment metrics-server -n kube-systemIf it's missing:
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm install metrics-server metrics-server/metrics-server -n kube-system2. Install KEDA (Helm)
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
kubectl create namespace keda
helm install keda kedacore/keda \
--namespace keda \
--set resources.operator.requests.cpu=100m \
--set resources.operator.requests.memory=100MiVerify:
kubectl -n keda get pods
# expect: keda-operator, keda-operator-metrics-apiserver, keda-admission-webhooks3. Core concepts (quick reference)
- ScaledObject — attaches a scaler to an existing Deployment/StatefulSet.
- ScaledJob — creates Kubernetes Jobs per event, good for batch/queue work that isn't a long-running service (e.g., one-shot migration or export scripts).
- TriggerAuthentication — holds credentials for a scaler (API keys, connection strings) as a Secret reference.
4. Example: scale a queue-consumer deployment (RabbitMQ)
If you run job queues through RabbitMQ:
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: rabbitmq-auth
namespace: default
spec:
secretTargetRef:
- parameter: host
name: rabbitmq-secret
key: host
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: migration-worker-scaler
namespace: default
spec:
scaleTargetRef:
name: migration-worker # your existing Deployment
minReplicaCount: 0
maxReplicaCount: 10
cooldownPeriod: 60
triggers:
- type: rabbitmq
metadata:
queueName: migration-jobs
mode: QueueLength
value: "5" # scale up 1 replica per 5 queued messages
authenticationRef:
name: rabbitmq-authThis scales the migration-worker Deployment from 0 up to 10 pods based on
queue depth — useful if migration jobs are bursty rather than constant.
5. Example: cron-based scaling for scheduled collectors
For something like your capacity collector script that only needs to run on a schedule rather than continuously:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: capacity-collector-cron
namespace: default
spec:
scaleTargetRef:
name: capacity-collector
minReplicaCount: 0
maxReplicaCount: 1
triggers:
- type: cron
metadata:
timezone: America/New_York
start: 0 */6 * * * # scale up at :00 every 6 hours
end: 5 */6 * * * # scale back down 5 min later
desiredReplicas: "1"This is a cleaner alternative to a CronJob if the collector needs to stay a long-running Deployment for other reasons (e.g., shared connection pooling) but you don't want it running 24/7.
6. Example: Prometheus-driven scaling
If Nagios/NRPE metrics or app metrics are exported to Prometheus, you can scale directly off a PromQL query:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: web-app-scaler
namespace: default
spec:
scaleTargetRef:
name: web-app
minReplicaCount: 1
maxReplicaCount: 6
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring.svc:9090
metricName: http_requests_per_second
query: sum(rate(http_requests_total{app="web-app"}[2m]))
threshold: "50"7. ScaledJob pattern (one-shot batch work)
For work that's genuinely job-shaped (run once per event, then exit) rather than a long-lived service:
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
name: solusvm-export-job
spec:
jobTargetRef:
template:
spec:
containers:
- name: export
image: registry.internal/solusvm-export:latest
restartPolicy: Never
pollingInterval: 30
maxReplicaCount: 3
triggers:
- type: rabbitmq
metadata:
queueName: export-jobs
mode: QueueLength
value: "1"Each queued export request spins up its own isolated Job pod, which is useful if the Python 2.7-compatible export script needs isolation from other runs.
8. Verification checklist
kubectl -n keda get pods # operator + webhook running
kubectl get scaledobjects -A # your ScaledObjects listed
kubectl describe scaledobject <name> # check "Active" and "Ready" conditions
kubectl get hpa # KEDA creates a backing HPA per ScaledObjectSend a test event (queue message, or wait for a cron window) and confirm pod count changes:
kubectl get pods -w9. Notes
- KEDA does not replace metrics-server/HPA — it creates and manages HPA objects on your behalf, so both need to be healthy.
- Scale-to-zero only works for Deployments/StatefulSets fronted by something
tolerant of a cold start (add a small
activationCooldownPeriodif downstream services are latency-sensitive). - If regions run separate clusters (per the Longhorn guide's recommendation), install KEDA independently per-region cluster — it's not cluster-spanning.
