Installing KEDA on Kubernetes with Helm: Production-Ready Setup
Learn how to install and configure KEDA on Kubernetes with Helm for scalable, secure, and production-ready environments.
Published · Republished on Medium

Installing the KEDA chart is straightforward. Making event-driven autoscaling safe in production is mostly about the surrounding decisions: version compatibility, metric ownership, trigger credentials, workload limits, failure behavior, observability, and rollback.
KEDA connects event sources to Kubernetes scaling. It handles activation from zero and deactivation back to zero, while Kubernetes Horizontal Pod Autoscaler handles scaling between one and the configured maximum. That boundary matters when debugging timing or replica decisions.
KEDA does not provide full high-availability support. Multiple operator replicas use leader election, leaving one active and the others on standby; multiple replicas reduce failover time but do not increase reconciliation throughput. The external metrics API also has upstream constraints. Treat extra replicas as failure-recovery capacity, not proof of end-to-end HA.
1. Record compatibility and ownership
Before installation, record:
- Kubernetes version
- KEDA chart and application version
- Helm version
- existing HPAs and autoscaling controllers
- target workloads and event sources
- credential mechanism for each scaler
Check the supported Kubernetes version in the documentation for the KEDA release you plan to install. Do not copy a minimum version from a different documentation release.
One workload must not be controlled by two independent HPAs. KEDA's admission webhook detects conflicting ScaledObject/HPA ownership, but migration from an existing HPA should still be planned and tested explicitly.
2. Pin and inspect the Helm chart
Add the official chart repository and inspect available releases:
bash
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm search repo kedacore/keda --versions
helm show values kedacore/keda --version <PINNED_CHART_VERSION> > keda-default-values.yamlSelect a released chart compatible with the cluster, pin it in Git, and review the rendered resources before applying them. KEDA's chart manages CRDs for current releases, but installations upgraded from old versions may have different CRD ownership. Establish whether Helm or a separate platform process owns CRD upgrades before the first production rollout.
bash
helm template keda kedacore/keda \
--namespace keda \
--version <PINNED_CHART_VERSION> \
--values keda-values.yaml > rendered-keda.yamlReview the operator, metrics API server, admission webhook, RBAC, Pod security settings, service accounts, and CRDs in the rendered output.
3. Install KEDA
Start with a small values file that expresses only environment-specific requirements. Do not copy arbitrary replica counts, disruption budgets, node selectors, or affinity rules unless they are supported by the pinned chart and match real labels and failure domains in your cluster. Derive every chart key from the output of helm show values for the selected release.
Install with an atomic rollback on failure:
bash
helm upgrade --install keda kedacore/keda \
--namespace keda \
--create-namespace \
--version <PINNED_CHART_VERSION> \
--values keda-values.yaml \
--atomic \
--timeout 10m4. Verify the control plane
Verify more than Pod phase:
bash
kubectl -n keda get deploy,pod,service
kubectl get crd | grep keda.sh
kubectl get apiservice v1beta1.external.metrics.k8s.io
kubectl get validatingwebhookconfiguration | grep keda
kubectl -n keda get events --sort-by=.lastTimestampThe external metrics API should report as available, the webhook should have valid endpoints and certificates, and the operator logs should not show permission or scaler-connection errors.
bash
kubectl get --raw /apis/external.metrics.k8s.io/v1beta1
kubectl -n keda logs deploy/keda-operator --tail=100
kubectl -n keda logs deploy/keda-operator-metrics-apiserver --tail=100
kubectl -n keda logs deploy/keda-admission-webhooks --tail=100Deployment names can vary by chart version. Inspect the resources first and adjust the commands rather than assuming names in a runbook.
5. Create a bounded ScaledObject
This example scales an existing Deployment named worker from zero based on a Prometheus query. Replace the server address and query with values validated in your environment.
yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: worker-queue-depth
namespace: application
spec:
scaleTargetRef:
name: worker
pollingInterval: 30
initialCooldownPeriod: 60
cooldownPeriod: 300
minReplicaCount: 0
maxReplicaCount: 20
fallback:
failureThreshold: 3
replicas: 2
advanced:
horizontalPodAutoscalerConfig:
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring.svc.cluster.local:9090
query: sum(application_queue_depth)
threshold: "10"Important behavior:
pollingIntervalcontrols KEDA polling while the workload is at zero.cooldownPeriodapplies to scaling back to zero.- HPA behavior controls scaling between one and
maxReplicaCount. fallbackgives a defined replica count after repeated supported-scaler errors; it is not available for every trigger type.maxReplicaCountmust fit downstream capacity such as database connections, queue partitions, API quotas, and cluster node limits.
Do not add a separate HPA for the same Deployment. KEDA creates and owns the HPA associated with the ScaledObject.
6. Keep trigger credentials out of the ScaledObject
Use TriggerAuthentication or ClusterTriggerAuthentication with the platform's workload-identity or secret-management standard. Prefer provider-native pod/workload identity over long-lived cloud keys.
A namespaced secret reference looks like this:
yaml
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: queue-auth
namespace: application
spec:
secretTargetRef:
- parameter: password
name: queue-scaler
key: passwordThe Secret should be encrypted at rest, narrowly readable, rotated, and supplied by the environment's secret system. Avoid placing credentials directly in trigger metadata or Git.
7. Test the scaling lifecycle
Inspect the generated HPA and ScaledObject conditions:
bash
kubectl -n application get scaledobject worker-queue-depth
kubectl -n application describe scaledobject worker-queue-depth
kubectl -n application get hpa
kubectl -n application describe hpaThen exercise these cases with a controlled workload:
- zero demand keeps the target at the intended minimum
- a known event backlog activates the workload
- sustained demand scales toward the expected replica count
- demand removal respects stabilization and cooldown
- trigger-source failure produces the expected fallback behavior
- recovery from trigger failure returns to metric-based scaling
maxReplicaCountprotects downstream systems- an invalid second ScaledObject is rejected by admission validation
Record timestamps for trigger changes, KEDA decisions, HPA changes, Pod readiness, and completed work. This distinguishes control-plane delay from slow application startup.
8. Observability and alerts
Monitor:
- ScaledObject
READY,ACTIVE, and fallback conditions - operator and metrics-server reconciliation errors
- external metrics API availability and latency
- admission-webhook failures
- current versus desired replicas
- time from event arrival to a ready worker
- work backlog and oldest-event age
- scaling limited by the configured maximum
- unschedulable Pods after workload scale-up
Alerting only on KEDA Pod health misses the failure mode where KEDA is running but cannot reach the trigger source.
9. Upgrade and rollback
Before upgrading:
- read the KEDA release and migration notes
- compare CRDs and rendered manifests
- confirm the Kubernetes compatibility range
- test existing ScaledObjects and authentication resources
- record the current Helm release and values
bash
helm get values keda -n keda > keda-values-before-upgrade.yaml
helm history keda -n kedaHelm rollback can restore namespaced resources, but CRD schema changes may require separate handling. Never assume a chart rollback reverses CRDs automatically. Keep the prior workload-autoscaling configuration available until the new version passes scale-up, scale-down, trigger-failure, and authorization tests.
Production-readiness boundary
KEDA is ready for production only when the complete scaling system has been tested: trigger availability, credentials, external metrics, HPA behavior, application startup, node capacity, downstream limits, observability, and rollback. Installing three healthy KEDA Deployments is necessary, but it is not sufficient evidence.