# [[How to install and configure KEDA]]
![[How to install and configure KEDA.svg]]
## What is KEDA?
KEDA (Kubernetes Event Driven Autoscaling) is a Kubernetes-based event-driven autoscaler. It extends Kubernetes' Horizontal Pod Autoscaler (HPA) to scale workloads based on various event sources including:
- CPU/Memory metrics
- Queue depth (SQS, RabbitMQ, Kafka)
- HTTP request rates
- Cloud metrics (CloudWatch, Azure Monitor)
- Custom metrics from Prometheus
## Prerequisites
- Kubernetes cluster version 1.23 or later
- `kubectl` configured to access your cluster
- Helm 3.x (for Helm installation method)
- Metrics Server installed (for CPU/memory scaling)
### Verify Metrics Server
```bash
# Check if metrics server is running
kubectl get deployment metrics-server -n kube-system
# If not installed, install it
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
```
## Installation Methods
### Method 1: Helm (Recommended)
Helm provides the easiest installation and upgrade path.
```bash
# Add KEDA Helm repository
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
# Install KEDA in the keda namespace
helm install keda kedacore/keda --namespace keda --create-namespace
# For a specific version (recommended for production)
helm install keda kedacore/keda --namespace keda --create-namespace --version 2.13.1
```
### Method 2: kubectl (YAML Manifests)
```bash
# Install KEDA with kubectl
kubectl apply --server-side -f https://github.com/kedacore/keda/releases/download/v2.13.1/keda-2.13.1.yaml
# This creates the keda namespace and installs all components
```
### Method 3: Operator Hub (OpenShift)
If you're using OpenShift, you can install KEDA from the Operator Hub:
1. Navigate to Operators → OperatorHub in the OpenShift console
2. Search for "KEDA"
3. Click Install and follow the prompts
## Verify Installation
```bash
# Check KEDA namespace and pods
kubectl get namespace keda
kubectl get pods -n keda
# Expected output: 3 pods running
# - keda-operator (manages ScaledObjects)
# - keda-operator-metrics-apiserver (provides external metrics API)
# - keda-admission-webhooks (validates KEDA resources)
# Check KEDA version
kubectl get deployment keda-operator -n keda -o jsonpath='{.spec.template.spec.containers[0].image}'
# Verify metrics API is available
kubectl get apiservices | grep keda
# Should show: v1beta1.external.metrics.k8s.io
```
## Configuration
### Basic Configuration Options
KEDA can be configured during Helm installation:
```bash
helm install keda kedacore/keda --namespace keda --create-namespace \
--set replicaCount=2 \
--set operator.replicaCount=2 \
--set metricsServer.replicaCount=2 \
--set webhooks.replicaCount=2
```
### Advanced Configuration (values.yaml)
Create a `keda-values.yaml` file for custom configuration:
```yaml
# Resource limits for KEDA components
resources:
operator:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
metricsAdapter:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# High availability setup
replicaCount: 2
# Security context
securityContext:
runAsNonRoot: true
runAsUser: 1000
# Logging level (debug, info, error)
logging:
operator:
level: info
metricServer:
level: info
# Service account annotations (for cloud provider IAM)
serviceAccount:
annotations:
# AWS example
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/keda-role
# GCP example
iam.gke.io/gcp-service-account:
[email protected]
```
Apply the custom configuration:
```bash
helm install keda kedacore/keda --namespace keda --create-namespace -f keda-values.yaml
```
## Creating ScaledObjects
### Basic CPU/Memory Scaling Example
```yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: app-scaler
namespace: default
spec:
scaleTargetRef:
name: my-deployment # Target deployment name
minReplicaCount: 1 # Minimum pods
maxReplicaCount: 10 # Maximum pods
pollingInterval: 30 # How often to check metrics (seconds)
cooldownPeriod: 300 # Wait before scaling down (seconds)
triggers:
- type: cpu
metricType: Utilization
metadata:
value: "70" # Target 70% CPU utilization
- type: memory
metricType: Utilization
metadata:
value: "80" # Target 80% memory utilization
```
### Prometheus Metrics Scaling Example
```yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: app-prometheus-scaler
namespace: default
spec:
scaleTargetRef:
name: my-deployment
minReplicaCount: 2
maxReplicaCount: 20
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.observability.svc:9090
metricName: http_requests_per_second
query: sum(rate(http_requests_total[2m]))
threshold: "100" # Scale when > 100 requests/sec
```
### Cron-based Scaling Example
```yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: app-cron-scaler
namespace: default
spec:
scaleTargetRef:
name: my-deployment
minReplicaCount: 1
maxReplicaCount: 5
triggers:
- type: cron
metadata:
timezone: America/New_York
start: "0 8 * * *" # Scale up at 8 AM
end: "0 18 * * *" # Scale down at 6 PM
desiredReplicas: "5" # 5 replicas during business hours
```
## Common Configuration Patterns
### Multiple Triggers (OR Logic)
KEDA uses OR logic by default - scaling occurs if ANY trigger threshold is met:
```yaml
triggers:
- type: cpu
metricType: Utilization
metadata:
value: "70"
- type: memory
metricType: Utilization
metadata:
value: "80"
# Scales if CPU > 70% OR memory > 80%
```
### Advanced Mode (Custom HPA Behavior)
Control scaling velocity and stabilization:
```yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: app-advanced-scaler
spec:
scaleTargetRef:
name: my-deployment
minReplicaCount: 1
maxReplicaCount: 10
advanced:
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # Wait 5 min before scaling down
policies:
- type: Percent
value: 50 # Scale down by max 50% at a time
periodSeconds: 60
- type: Pods
value: 2 # Or max 2 pods at a time
periodSeconds: 60
selectPolicy: Min # Choose the most conservative
scaleUp:
stabilizationWindowSeconds: 0 # Scale up immediately
policies:
- type: Percent
value: 100 # Scale up by max 100% at a time
periodSeconds: 15
- type: Pods
value: 4 # Or max 4 pods at a time
periodSeconds: 15
selectPolicy: Max # Choose the most aggressive
triggers:
- type: cpu
metricType: Utilization
metadata:
value: "70"
```
## Monitoring KEDA
### Check ScaledObject Status
```bash
# List all ScaledObjects
kubectl get scaledobjects --all-namespaces
# Describe a specific ScaledObject
kubectl describe scaledobject <name> -n <namespace>
# Check the HPA created by KEDA
kubectl get hpa -n <namespace>
```
### View KEDA Metrics
```bash
# Check external metrics API
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
# View specific metric for a namespace
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/<namespace>/metric-name" | jq .
```
### KEDA Operator Logs
```bash
# View operator logs
kubectl logs -n keda -l app.kubernetes.io/name=keda-operator -f
# View metrics server logs
kubectl logs -n keda -l app.kubernetes.io/name=keda-operator-metrics-apiserver -f
# View webhook logs
kubectl logs -n keda -l app.kubernetes.io/name=keda-admission-webhooks -f
```
## Troubleshooting
### ScaledObject Not Working
```bash
# 1. Check ScaledObject status
kubectl describe scaledobject <name> -n <namespace>
# Look for "Status.Conditions" - should show "Ready: True"
# 2. Verify HPA was created
kubectl get hpa -n <namespace>
# 3. Check KEDA operator logs
kubectl logs -n keda -l app.kubernetes.io/name=keda-operator --tail=100
# 4. Verify metrics are available
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
# 5. Check target deployment exists
kubectl get deployment <deployment-name> -n <namespace>
```
### Metrics Not Available
```bash
# Check metrics server is running
kubectl get pods -n kube-system -l k8s-app=metrics-server
# Check KEDA metrics apiserver
kubectl get pods -n keda -l app.kubernetes.io/name=keda-operator-metrics-apiserver
# Verify API service registration
kubectl get apiservices v1beta1.external.metrics.k8s.io
```
### Pods Not Scaling
```bash
# Check HPA status
kubectl describe hpa <name> -n <namespace>
# Look for "Conditions" and "Events"
# Check current metrics
kubectl get hpa <name> -n <namespace> -o yaml
# View ScaledObject details
kubectl describe scaledobject <name> -n <namespace>
# Check deployment has correct labels
kubectl get deployment <name> -n <namespace> -o yaml
```
### KEDA Operator CrashLooping
```bash
# Check operator logs
kubectl logs -n keda -l app.kubernetes.io/name=keda-operator --previous
# Check resource limits
kubectl describe pod -n keda -l app.kubernetes.io/name=keda-operator
# Verify RBAC permissions
kubectl auth can-i get deployments --as=system:serviceaccount:keda:keda-operator -n <namespace>
```
## Upgrading KEDA
### Helm Upgrade
```bash
# Update Helm repo
helm repo update kedacore
# Upgrade KEDA
helm upgrade keda kedacore/keda -n keda
# Upgrade to specific version
helm upgrade keda kedacore/keda -n keda --version 2.13.1
```
### kubectl Upgrade
```bash
# Apply new version
kubectl apply --server-side -f https://github.com/kedacore/keda/releases/download/v2.13.1/keda-2.13.1.yaml
```
## Uninstalling KEDA
```bash
# Helm uninstall
helm uninstall keda -n keda
# kubectl uninstall
kubectl delete -f https://github.com/kedacore/keda/releases/download/v2.13.1/keda-2.13.1.yaml
# Delete namespace (optional)
kubectl delete namespace keda
```
## Best Practices
1. **Start Conservative**: Begin with higher thresholds and longer cooldown periods
2. **Monitor First**: Deploy with metrics-only mode (thresholds at 200%) to observe behavior
3. **Use Stabilization Windows**: Prevent flapping with appropriate cooldown periods
4. **Set Resource Limits**: Ensure KEDA components have adequate resources
5. **Test Scaling**: Validate autoscaling behavior in staging before production
6. **Version Lock**: Pin KEDA version in production environments
7. **High Availability**: Run multiple KEDA operator replicas for HA setups
8. **Namespace Isolation**: Consider deploying KEDA per namespace for large clusters
## Security Considerations
1. **RBAC**: KEDA needs permissions to read metrics and scale deployments
2. **Service Accounts**: Use dedicated service accounts with minimal permissions
3. **Network Policies**: Restrict KEDA's network access to required services only
4. **Secret Management**: Use Kubernetes secrets or external secret managers for sensitive scaler credentials
5. **TLS**: Enable TLS for KEDA webhooks and metrics server in production
## Additional Resources
- [KEDA Documentation](https://keda.sh/docs/)
- [KEDA Scalers](https://keda.sh/docs/scalers/)
- [KEDA GitHub](https://github.com/kedacore/keda)
- [KEDA Community](https://keda.sh/community/)
%%
# Excalidraw Data
## Text Elements
## Drawing
```json
{
"type": "excalidraw",
"version": 2,
"source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/2.1.4",
"elements": [
{
"id": "4y8R7iOA",
"type": "text",
"x": 118.49495565891266,
"y": -333.44393157958984,
"width": 3.8599853515625,
"height": 24,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"groupIds": [],
"frameId": null,
"roundness": null,
"seed": 967149026,
"version": 2,
"versionNonce": 939059582,
"isDeleted": true,
"boundElements": null,
"updated": 1713723615080,
"link": null,
"locked": false,
"text": "",
"rawText": "",
"fontSize": 20,
"fontFamily": 4,
"textAlign": "left",
"verticalAlign": "top",
"containerId": null,
"originalText": "",
"lineHeight": 1.2
}
],
"appState": {
"theme": "dark",
"viewBackgroundColor": "#ffffff",
"currentItemStrokeColor": "#1e1e1e",
"currentItemBackgroundColor": "transparent",
"currentItemFillStyle": "solid",
"currentItemStrokeWidth": 2,
"currentItemStrokeStyle": "solid",
"currentItemRoughness": 1,
"currentItemOpacity": 100,
"currentItemFontFamily": 4,
"currentItemFontSize": 20,
"currentItemTextAlign": "left",
"currentItemStartArrowhead": null,
"currentItemEndArrowhead": "arrow",
"scrollX": 583.2388916015625,
"scrollY": 573.6323852539062,
"zoom": {
"value": 1
},
"currentItemRoundness": "round",
"gridSize": null,
"gridColor": {
"Bold": "#C9C9C9FF",
"Regular": "#EDEDEDFF"
},
"currentStrokeOptions": null,
"previousGridSize": null,
"frameRendering": {
"enabled": true,
"clip": true,
"name": true,
"outline": true
}
},
"files": {}
}
```
%%