# [[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": {} } ``` %%