Ga naar inhoud

AKS Platform: load testing

Deze pagina beschrijft hoe het platform wordt belast getest en wat de test meet. De test heeft twee doelen: uitzoeken hoeveel verkeer een workload op het niet-productiecluster aankan voordat die breekt, en bewijzen dat de alertketen (Prometheus-regel, Alertmanager, PagerDuty) afgaat en weer sluit wanneer dat hoort.

Referentieontwerp, jouw deployment kan afwijken

De test draait alleen tegen het niet-productiecluster. De doelapplicatie, drempelwaarden en routes zijn die van de referentieopzet. Een uitgebreider ontwerpdocument beschrijft een breder testprogramma met een andere tool. Deze pagina behandelt wat is geïmplementeerd en noemt de rest als gepland.

Hoe een testrun werkt

Een handmatig gestarte pipeline maakt een kortlevende job in het cluster, stuurt in drie fasen verkeer, bekijkt de effecten en ruimt alles weer op. Het cluster draagt geen load generator als het niets doet.

flowchart TB
    start["Pipeline started by hand<br/>(rates, durations, failure trigger)"] --> login["OIDC login to Azure,<br/>cluster credentials"]
    login --> infra["Apply namespace, RBAC,<br/>network policy, dashboard"]
    infra --> mark1["Annotate Grafana: test start"]
    mark1 --> job["Vegeta job in the load-testing namespace"]
    job --> s1["Stage 1: warm-up"]
    s1 --> s2["Stage 2: sustained"]
    s2 --> s3["Stage 3: overload"]
    s3 --> report["Vegeta report in the run summary"]
    report --> mark2["Annotate Grafana: test end"]
    mark2 --> clean["Delete job and config map,<br/>reset the failure rate"]
Onderdeel Detail
Tool Vegeta, een HTTP-aanvaller met constante snelheid, uitgevoerd als Kubernetes job (één pod, geen retries)
Waar In het cluster in een eigen load-testing namespace, zodat het verkeer via het clusternetwerk en de DNS loopt
Trigger Een handmatige GitHub Actions-workflow met de onderstaande parameters
Identity De gefedereerde identity van de pipeline met de Azure-rol Azure Kubernetes Service RBAC Admin, beperkt tot het cluster
Voetafdruk Een service account met een rol op namespaceniveau, een network policy voor de generator-pods en een config map voor het Grafana-dashboard. De job en de config map met het script worden aan het eind verwijderd (if: always()); de job heeft ook een time-to-live
Grootte van de generator Requests 500m CPU en 1 GiB, limits 2 CPU en 4 GiB. De workerpool is begrensd op 8000 connecties, nodig om 3000 requests per seconde vast te houden als de latency stijgt
Pre-flight Het script wacht maximaal 60 seconden op het health endpoint van het doel voordat het aanvalt

Fasen en parameters

Fase Standaardsnelheid Standaardduur Doel
1. Warm-up 60 requests per seconde 30 s Gezonde baseline
2. Sustained 400 requests per seconde 1 min Belasting waarop de autoscaler reageert
3. Overload 3000 requests per seconde 5 min Voorbij de capaciteit van de workload duwen

Alle zes waarden zijn workflow-inputs. Een zevende input, trigger_failure (standaard aan), automatiseert het storingsverhaal: de pipeline verhoogt de foutfrequentie van de applicatie aan het begin van fase 2 en zet die in de laatste minuut van fase 3 terug, zodat een foutpiek gegarandeerd is zonder dat je snelheden met de hand hoeft af te stellen. Zonder die input voer je de twee wijzigingen met de hand uit met kubectl set env.

Wat wordt gemeten

De applicatie exporteert haar eigen Prometheus-metrics (de generator zelf exporteert er geen). De run wordt beoordeeld aan de kant van de applicatie en van het cluster.

Gebied Signaal Gebruikt voor
Requestsnelheid Requests per seconde per responscode Aangeboden belasting en behaalde throughput
Fouten Aandeel 5xx-responses over 5 minuten Beschikbaarheid en de fast-burn-alert
Latency p50, p90, p95, p99 uit het histogram van de requestduur Latency-doelstelling
Autoscaling Gewenste replicas van de HPA ten opzichte van huidige replicas Schaalt de workload uit, en hoe snel
Capaciteit Pod-CPU ten opzichte van requests, pending pods, restarts, out-of-memory kills Waar de workload verzadigd raakt
Alerts Prometheus-alertstatus met het load test-label, Alertmanager-receiver, PagerDuty-incident Of de keten werkt
Clientweergave Het Vegeta-rapport: totalen per fase en samen, met latencypercentielen en succespercentage Controle vanaf de clientkant

Een Grafana-dashboard voor de test wordt ingericht vanuit een config map. Een hulpscript kan na de run een samenvatting uit Prometheus tonen (totaal aantal requests, piekrate, piek van het foutpercentage, piek van p95 en p99, maximaal aantal replicas, restarts, alertstatus).

Geslaagd en mislukt

De job slaagt of faalt niet op het succespercentage van Vegeta, omdat fase 3 bedoeld is om de workload te overbelasten. De workflow faalt alleen als de job een fout geeft (bijvoorbeeld als het doel onbereikbaar is) of niet op tijd klaar is. Het echte resultaat is of de alerts afgaan en weer oplossen en of er een incident wordt aangemaakt en gesloten.

Alertvalidatie

Drie alertregels voor de load test spiegelen de service level objectives van de referentieopdracht. Ze dragen labels die ze als testalerts markeren:

Alert Voorwaarde Gedurende Severity
AvailabilityErrorBudgetBurnFast 5xx-aandeel over 5 minuten boven 10 keer het foutbudget van 0,1% 5 min page
AvailabilityErrorBudgetBurnSlow 5xx-aandeel over 30 minuten boven 2 keer het budget 12 u ticket
LatencySLOViolation p95-latency over 5 minuten boven 300 ms 15 min page

Alertmanager routeert alerts met source = load-test naar een eigen receiver. In de geïmplementeerde opzet gebruikt die dezelfde PagerDuty routing key als productie en wordt hij onderscheiden door een [LOAD-TEST]-prefix en velden in het event. Het ontwerpdocument stelde hiervoor een aparte PagerDuty-service voor.

Wat je in één run kunt zien: alleen de fast-burn-alert, omdat fase 3 standaard 5 minuten duurt, even lang als de for-periode van de regel. Laat fase 3 20 minuten of langer duren om de latency-alert te zien afgaan. De slow-burn-alert is niet live te observeren.

Bewijs om te verzamelen bij een alertvalidatie:

Controle Hoe
Alert bereikt firing Prometheus-alertspagina, gefilterd op het testlabel
Gerouteerd naar de test-receiver Alertmanager-alertspagina
Incident aangemaakt PagerDuty, titel met de [LOAD-TEST]-prefix
Incident lost zichzelf op PagerDuty, nadat de foutfrequentie is teruggezet en de metrics herstellen
Geen effect op alerting in productie Geen andere incidenten op dezelfde service in dat tijdvak

De doelworkload

Het doel is een kleine publieke demo-webapplicatie (Flask, met Prometheus-metrics), gedeployd in de namespace <team>-dev met de gedeelde applicatiechart: autoscaling van 3 tot 10 replicas op een CPU-doel van 70%, een disruption budget, een geharde security context en een service monitor die het Prometheus-label job zet, zodat regels, dashboard en queries allemaal op één naam werken. Het work-endpoint simuleert 50 tot 200 ms latency en faalt willekeurig met een instelbare frequentie (standaard 2%). Het degradeert onder belasting realistisch, zonder kunstmatige stressschakelaar.

Alleen de omgeving dev wordt ondersteund. De namespaces test en accp draaien een placeholder-webserverimage, niet de demoapplicatie.

Wat de cijfers betekenen

In de gevalideerde run vlakte de throughput af op ongeveer 1.800 tot 2.260 requests per seconde (ongeveer 220 per pod bij tien pods), schaalde de autoscaler van 3 naar 10 pods, ging de fast-burn-alert na ongeveer zes minuten af en loste die kort nadat de foutfrequentie was teruggezet weer op. Deze cijfers beschrijven de demoapplicatie (een ontwikkelserver met één proces), niet de capaciteit van het platform. Een hogere CPU-limit maakte geen verschil. Zie de run als een herhaalbare methode om het getal voor elke service te vinden.

Bekende beperkingen

Beperking Effect
Het latencyhistogram meet alleen het afhandelen van requests, niet de wachttijd in de wachtrij als de server verzadigd is De latency-alert gaat zelfs bij zware overbelasting zelden af, dus de fast-burn-alert is het betrouwbare signaal
Een self-heal van Argo CD draaide de wijziging van de foutfrequentie binnen een seconde terug Opgelost door de Argo CD-applicatie dat ene veld te laten negeren
Roltoewijzingen voor de pipeline en het Graph API-probleem Gebruik het target cicd-aks-rbac (Deployment)
Resultaten van runs worden niet automatisch opgeslagen of vergeleken Leg de samenvatting van de run en het dashboard zelf vast
Lokale runs op een laptop geven ruwe, onbetrouwbare absolute cijfers Gebruik cijfers uit het cluster

Gepland testprogramma (alleen ontwerp)

Het ontwerpdocument beschrijft verdere soorten tests voor het niet-productiecluster. Ze zijn niet in de pipeline geïmplementeerd.

Test Patroon Doel
Smoke 1 tot 5 gebruikers, 1 tot 2 minuten De testopzet en het doel controleren
Baseline Normale belasting gedurende ongeveer 13 minuten Referentiewaarden voor releasevergelijking
Load Verwachte piekbelasting gedurende ongeveer 23 minuten Alle doelstellingen van het platform worden gehaald
Stress Stapsgewijs opvoeren tot degradatie Het breekpunt vinden, informatief
Spike Plotselinge piek, daarna terug De autoscaler reageert en het systeem herstelt
Soak Matige belasting gedurende 2 tot 8 uur Leaks en geleidelijke degradatie
Capacity Opvoeren tot één doelstelling breekt Maximale houdbare throughput
Autoscaling Belasting boven het doel van de autoscaler, daarna naar nul Timing van scale-up en scale-down
Alerting Belastingpatronen die bekende alerts triggeren Keten van regel naar incident

Het ontwerp noemde ook k6 met zijn Kubernetes-operator als primaire tool en een Azure DevOps-pipeline. De implementatie is overgestapt op Vegeta, aangestuurd vanuit GitHub Actions, omdat de demo-runs met k6 herhaaldelijk niet de verwachte resultaten gaven.