Lab 03: Übungsaufgabe: Horizontal Pod Autoscaling mit HPA und KEDA auf AKS¶
Erzeuge dir für diese Übung einen Cluster wie in Aufgabe 1 und setze dir Umgebungsvariablen wie dort beschrieben.
Teil 1: Horizontal Pod Autoscaler (HPA) – Grundlagen¶
Aufgabe 1.1: Demo-Anwendung deployen¶
Erstelle eine CPU-intensive Anwendung für die Lasttest-Szenarien.
Datei: cpu-stress-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cpu-stress-app
labels:
app: cpu-stress
spec:
replicas: 1
selector:
matchLabels:
app: cpu-stress
template:
metadata:
labels:
app: cpu-stress
spec:
containers:
- name: stress
image: vish/stress
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"
args:
- -cpus
- "1"
---
apiVersion: v1
kind: Service
metadata:
name: cpu-stress-svc
spec:
selector:
app: cpu-stress
ports:
- port: 80
targetPort: 8080
kubectl apply -f cpu-stress-deployment.yaml
Aufgabe 1.2: HPA mit CPU-Metrik erstellen¶
Erstelle einen HPA, der auf CPU-Auslastung reagiert.
Datei: hpa-cpu.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: cpu-stress-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: cpu-stress-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
behavior:
scaleDown:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 30
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
kubectl apply -f hpa-cpu.yaml
Aufgabe 1.3: HPA beobachten und testen¶
Beobachte das Verhalten des HPA. Es kann etwa eine Minute dauern, bis er seine
Arbeit aufgenommen hat – solange ist die letztgemessene CPU-Auslastung noch
<unknown>.
# HPA Status kontinuierlich beobachten
kubectl get hpa cpu-stress-hpa --watch
# In einem separaten Terminal: Details anzeigen
kubectl describe hpa cpu-stress-hpa
Fragen zur Reflexion:
- Welche Metriken werden aktuell vom HPA erfasst?
- Was bedeuten die Werte in der TARGETS-Spalte?
- Wie lange dauert es typischerweise, bis der HPA auf Lastveränderungen reagiert?
Du kannst nun übrigens auch das Cluster-Autoscaling testen, wenn es im Cluster
aktiviert ist. Wenn du das maxReplicas-Feld der YAML auf einen sehr hohen Wert
setzt, z.B. 100, so muss AKS bald neue Nodes starten. Denke aber bitte daran,
um Anschluss das Deployment zu löschen, um den Cluster wieder zu entlasten.
Teil 2: KEDA auf AKS aktivieren¶
Aufgabe 2.1: KEDA Add-on aktivieren¶
KEDA ist als natives AKS-Add-on verfügbar und wird von Microsoft verwaltet. Dies ist die empfohlene Methode für AKS.
Bei bestehendem Cluster aktivieren:
# KEDA Add-on aktivieren
az aks update \
--resource-group $RESOURCE_GROUP \
--name $CLUSTER_NAME \
--enable-keda
# Installation prüfen
kubectl get pods -n kube-system -l app=keda-operator
Hinweis: Bei der Cluster-Erstellung kann KEDA direkt mit --enable-keda
aktiviert werden (siehe Voraussetzungen).
Aufgabe 2.2: KEDA Add-on Status prüfen¶
Als letzten Test prüfen wir nun noch, ob KEDA wirklich aktiviert ist:
# Add-on Status im Cluster anzeigen
az aks show \
--resource-group $RESOURCE_GROUP \
--name $CLUSTER_NAME \
--query "workloadAutoScalerProfile.keda" -o json
Teil 3: Event-basiertes Autoscaling mit KEDA¶
Szenario A: Azure Service Bus Queue Scaler¶
Dieses Szenario zeigt, wie KEDA basierend auf der Nachrichtenlänge einer Azure Service Bus Queue skaliert.
Azure Service Bus ist ein Azure-Dienst, der Nachrichten zwischen Anwendungen transportiert. Dies entkoppelt Systeme voneinander, sodass sie unabhängig arbeiten können und keine Nachrichten verloren gehen, selbst wenn ein System kurz offline ist.
Aufgabe 3.1: Azure Service Bus einrichten¶
# Service Bus Namespace erstellen
az servicebus namespace create \
--resource-group $RESOURCE_GROUP \
--name sb-keda-demo-$RANDOM \
--location germanywestcentral \
--sku Standard
# Queue erstellen
SB_NAMESPACE=$(az servicebus namespace list -g $RESOURCE_GROUP --query "[0].name" -o tsv)
az servicebus queue create \
--resource-group $RESOURCE_GROUP \
--namespace-name $SB_NAMESPACE \
--name orders-queue
# Connection String abrufen
SB_CONNECTION=$(az servicebus namespace authorization-rule keys list \
--resource-group $RESOURCE_GROUP \
--namespace-name $SB_NAMESPACE \
--name RootManageSharedAccessKey \
--query primaryConnectionString -o tsv)
echo "Connection String: $SB_CONNECTION"
Aufgabe 3.2: Queue-Consumer Deployment erstellen¶
In diesem Szenario simulieren wir einen Order-Processor, der Nachrichten aus einer Service Bus Queue verarbeitet. In der Praxis wäre dies eine Anwendung, die:
- Nachrichten aus der Queue liest
- Die Bestellung verarbeitet (z.B. Validierung, Datenbankschreibung)
- Die Nachricht nach erfolgreicher Verarbeitung bestätigt
Für die Übung verwenden wir ein einfaches Demo-Image, das die Verarbeitung simuliert:
Datei: queue-consumer-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-processor
labels:
app: order-processor
spec:
replicas: 0 # KEDA startet bei 0 und skaliert basierend auf Queue-Länge
selector:
matchLabels:
app: order-processor
template:
metadata:
labels:
app: order-processor
spec:
containers:
- name: processor
# Demo-Image: Simuliert Nachrichtenverarbeitung durch Sleep
# In Produktion: Ihre eigene Consumer-Anwendung (z.B. .NET, Java, Python)
image: busybox:1.36
command:
- /bin/sh
- -c
- |
echo "Order Processor gestartet"
echo "Warte auf Nachrichten aus Queue: $QUEUE_NAME"
# Simuliert kontinuierliche Verarbeitung
while true; do
echo "[$(date)] Verarbeite Bestellungen..."
sleep 10
done
env:
- name: QUEUE_NAME
value: "orders-queue"
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "100m"
memory: "128Mi"
Hinweis für die Praxis: Ein echter Service Bus Consumer würde z.B. so aussehen:
- .NET:
Azure.Messaging.ServiceBus-SDK mitServiceBusProcessor - Java:
azure-messaging-servicebusmitServiceBusProcessorClient - Python:
azure-servicebusmitServiceBusReceiver
kubectl apply -f queue-consumer-deployment.yaml
# Prüfen, dass kein Pod läuft (replicas: 0)
kubectl get pods -l app=order-processor
Aufgabe 3.3: KEDA TriggerAuthentication und ScaledObject¶
KEDA muss sich mit Azure Service Bus verbinden, um zu prüfen, ob Nachrichten in der Queue vorhanden sind. Dazu müssen wir den Connection-String als Kubernetes-Secret hinterlegen:
# Secret mit echter Connection String erstellen
kubectl create secret generic servicebus-secret \
--from-literal=connectionString="$SB_CONNECTION"
Weiterhin brauchen wir eine sogenannte TriggerAuthentication:
Sie teilt KEDA mit, wie es sich mit der Auslöser-Quelle verbindet. In diesem
Fall läuft dies über unser Secret ab, was wir gerade angelegt haben.
Datei: keda-servicebus-auth.yaml
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: azure-servicebus-auth
spec:
secretTargetRef:
- parameter: connection
name: servicebus-secret
key: connectionString
Außerdem müssen wir KEDA so konfigurieren, dass es unseren Order-Processor
skaliert, den wir vorhin angelegt haben. Dies geht über ein sogenanntes
ScaledObject. Es wird einen HorizontalPodAutoscaler für uns anlegen und
entsprechend des Durchsatzes der Message Queue einstellen.
Datei: keda-servicebus-scaledobject.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-processor-scaler
spec:
scaleTargetRef:
name: order-processor
pollingInterval: 15
cooldownPeriod: 300
minReplicaCount: 0
maxReplicaCount: 30
advanced:
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 120
policies:
- type: Percent
value: 25
periodSeconds: 60
triggers:
- type: azure-servicebus
metadata:
queueName: orders-queue
messageCount: "5"
activationMessageCount: "1"
authenticationRef:
name: azure-servicebus-auth
Nun müssen wir die Dateien natürlich noch anwenden:
kubectl apply -f keda-servicebus-auth.yaml
kubectl apply -f keda-servicebus-scaledobject.yaml
Aufgabe 3.4: Skalierung testen¶
Die Azure CLI unterstützt kein direktes Senden von Service Bus Nachrichten (nur Management-Operationen). Daher werden wir die Last über das Azure-Portal simulieren.
- Öffne den Service Bus Namespace im Azure Portal
- Wähle unter "Entities" die Queue
orders-queue - Klicke auf "Service Bus Explorer" im linken Menü
- Wähle "Send messages"
- Gebe eine Nachricht ein und klicken auf "Send"
- Wiederhole dies mehrfach oder nutze "Repeat send"
Beobachte nebenbei das Verhalten des Deployments und des HPA.
kubectl get pods -l app=order-processor --watch
kubectl get scaledobject order-processor-scaler -o yaml
kubectl get hpa
Schau dir an:
- Wie viele Sekunden nach dem Senden der Nachrichten beginnt die Skalierung?
- Auf wie viele Pods wird skaliert?
- Wie verhält sich das Scale-Down nach Verarbeitung aller Nachrichten?