# Failover Testing for AI Services **Last updated:** 2026-02 **Status:** GA **Category:** Business Continuity & Disaster Recovery --- ## Introduksjon Failover-testing er en kritisk men ofte forsoemmt del av disaster recovery for AI-tjenester. En DR-plan som ikke er testet er i praksis ingen plan -- den gir en falsk trygghet som kan forsterke konsekvensene av et reelt utfall. Microsoft anbefaler eksplisitt a gjennomfoere regelmessige failover-drills for a validere at resiliens-mekanismer fungerer som forventet, og at teamet er i stand til a haandtere en krise effektivt. For AI-tjenester er failover-testing spesielt utfordrende av flere grunner. For det foerste er AI-inferens ofte tilstandsloest (stateless), men konteksten rundt -- samtalehistorikk, agent-tilstand, RAG-indekser -- er hoyst tilstandsfull. En vellykket failover av selve inferens-endepunktet betyr lite hvis samtalehistorikken gaar tapt eller kunnskapsbasen ikke er tilgjengelig i failover-regionen. For det andre har AI-tjenester kvotebegrensninger per region, saa en failover kan resultere i lavere kapasitet hvis sekundaerregionen har mindre kvote. For det tredje bruker mange AI-loesninger asynkrone pipelines (batch-prosessering, evaluering, fine-tuning) som har andre failover-moenstre enn sanntids-inferens. Denne referansen dekker planlagte failover-testscenarier, validering og overvaking under failover, suksesskriterier og akseptanseterskel, dokumentasjon og laerdommer, samt regelmessig testplanlegging og frekvens. Alt er forankret i Microsofts veiledning for chaos engineering, Azure Chaos Studio, og Well-Architected Framework for reliability testing. ## Planlagte failover-testscenarier ### Scenariokatalog for AI-tjenester Failover-tester boer dekke flere niva -- fra enkeltkomponent til fullstendig regional failover: | Nivaa | Scenario | Beskrivelse | Kompleksitet | Risiko | |-------|---------|-------------|-------------|--------| | **L1** | Enkelt AOAI-endepunkt utilgjengelig | Simuler 429/503 fra ett Azure OpenAI-endepunkt | Lav | Lav | | **L2** | Cosmos DB regional failover | Bytt skriveregion for agentdata | Middels | Middels | | **L3** | Full gateway-failover | Ruter all trafikk via sekundaer APIM | Middels | Middels | | **L4** | AI Search utilgjengelig | RAG-indeks nede, test fallback | Middels | Lav | | **L5** | Komplett regional failover | All AI-infrastruktur bytter region | Hoey | Hoey | | **L6** | Korrupt data / utilsiktet sletting | Gjenopprett fra backup | Hoey | Middels | ### Scenario L1: Azure OpenAI endepunkt-failover **Formal:** Verifisere at APIM-gatewayen korrekt ruter trafikk til sekundaert endepunkt nar primaert returnerer feil. **Fremgangsmate:** ``` 1. Forutsetninger: - APIM konfigurert med backend pool (Norway East primaer, Sweden Central sekundaer) - Overvaking aktiv (Application Insights, Azure Monitor) - Lastetest kjoerer for a generere trafikk 2. Feilinjeksjon: - Metode A: APIM policy-endring (fjern primaer backend fra pool) - Metode B: Azure Chaos Studio eksperiment - Metode C: Nettverksregel som blokkerer trafikk til primaer 3. Forventet oppfoersel: - Gateway returnerer 429/503 fra primaer backend - Circuit breaker trigger innen < 5 sekunder - Trafikk rutes automatisk til sekundaer backend - Sluttbrukere opplever < 10 sekunder forsinkelse 4. Validering: - Alle API-kall returnerer 200 innen 30 sekunder - Latens stabiliserer seg innen 60 sekunder - Ingen tapt kontekst for pagaende samtaler (med session affinity) ``` **APIM policy for simulert feil:** ```xml ``` ### Scenario L2: Cosmos DB failover **Formal:** Verifisere at agentdata er tilgjengelig etter Cosmos DB regional failover. **Fremgangsmate med Azure Chaos Studio:** ```json { "type": "Microsoft.Chaos/experiments", "name": "cosmos-failover-test", "location": "norwayeast", "properties": { "steps": [ { "name": "Failover-Cosmos-DB", "branches": [ { "name": "cosmos-branch", "actions": [ { "type": "continuous", "name": "urn:csci:microsoft:cosmosDB:failover/1.0", "duration": "PT10M", "parameters": [ { "key": "readRegion", "value": "Norway East" } ], "selectorId": "cosmos-target" } ] } ] } ], "selectors": [ { "id": "cosmos-target", "type": "List", "targets": [ { "id": "/subscriptions/{sub-id}/resourceGroups/rg-ai-prod/providers/Microsoft.DocumentDB/databaseAccounts/ddt-ai-cosmos/providers/Microsoft.Chaos/targets/Microsoft-CosmosDB", "type": "ChaosTarget" } ] } ] } } ``` **Forventet oppfoersel:** - Cosmos DB bytter skriveregion fra Norway East til Sweden Central - Lesning kan ha kortvarig hoeyre latens under failover - Agentsamtaler kan fortsette uten datatap - Failover fullfores innen < 5 minutter ### Scenario L3: Full gateway-failover **Formal:** Verifisere at all AI-trafikk kan betjenes fra sekundaer gateway-region. ``` Testoppfoersel: 1. Start med normal trafikk gjennom APIM i Norway East 2. Simuler at APIM i Norway East er utilgjengelig: - DNS-endring: Pek gateway-FQDN til Sweden Central - Eller: Azure Front Door helsesjekk feiler for Norway East 3. Verifiser: - Trafikk rutes til APIM i Sweden Central - APIM i Sweden Central nar Azure OpenAI i Sweden Central - Responstid er innenfor akseptabel terskel - Alle funksjoner (chat, RAG, agent) fungerer 4. Failback: - Gjenopprett APIM i Norway East - Verifiser at trafikk returnerer til primaer ``` ### Scenario L5: Komplett regional failover **Formal:** Validere full DR-prosedyre med alle komponenter. ``` Tidsplan for full DR-drill (estimert 4-6 timer): T+0:00 - Annonsering: "DR-drill starter" T+0:05 - Simulert utfall av Norway East (DNS/nettverk) T+0:10 - Deteksjon: Varsling utloeses automatisk T+0:15 - Vurdering: Driftsteam bekrefter utfall T+0:20 - Beslutning: Iverksett DR-plan T+0:25 - Gateway failover: APIM rutes til Sweden Central T+0:30 - Data failover: Verifiser Cosmos DB og Storage T+0:45 - Agent redeploy: Deploy agentdefinisjoner i sekundaer region T+1:00 - Validering: Funksjonelle tester T+1:30 - Stabilisering: Overvak i 30 minutter T+2:00 - Normal drift fra sekundaer region bekreftet T+3:00 - Failback paabegynnes T+3:30 - Primaer region gjenopprettet T+4:00 - Normal drift fra primaer region bekreftet T+4:30 - Retrospektiv og dokumentasjon ``` ## Validering og overvaking under failover ### Helsesjekk-endepunkter Implementer dedikerte helsesjekk-endepunkter for AI-tjenestene: ```python # health_check.py -- Eksempel pa helsesjekk for AI-stack import asyncio from datetime import datetime from openai import AzureOpenAI async def check_openai_health(endpoint: str, api_key: str) -> dict: """Sjekk Azure OpenAI tilgjengelighet og latens.""" start = datetime.now() try: client = AzureOpenAI( azure_endpoint=endpoint, api_key=api_key, api_version="2024-06-01" ) response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "ping"}], max_tokens=5, temperature=0 ) latency_ms = (datetime.now() - start).total_seconds() * 1000 return { "status": "healthy", "latency_ms": round(latency_ms), "endpoint": endpoint, "model": "gpt-4o", "timestamp": datetime.now().isoformat() } except Exception as e: return { "status": "unhealthy", "error": str(e), "endpoint": endpoint, "timestamp": datetime.now().isoformat() } async def check_cosmos_health(endpoint: str) -> dict: """Sjekk Cosmos DB tilgjengelighet.""" # Implementer med Azure Cosmos DB SDK pass async def full_health_check() -> dict: """Komplett helsesjekk for alle AI-komponenter.""" results = await asyncio.gather( check_openai_health("https://ddt-aoai-ne.openai.azure.com", "***"), check_openai_health("https://ddt-aoai-sc.openai.azure.com", "***"), check_cosmos_health("https://ddt-ai-cosmos.documents.azure.com"), ) overall = "healthy" if all(r["status"] == "healthy" for r in results) else "degraded" return {"overall": overall, "components": results} ``` ### KQL-queries for failover-overvaking ```kusto // Overvaak feilrate under failover-test AppRequests | where TimeGenerated > ago(1h) | where AppRoleName == "ai-gateway" | summarize TotalRequests = count(), FailedRequests = countif(ResultCode >= 500), AvgDuration = avg(DurationMs), P95Duration = percentile(DurationMs, 95), P99Duration = percentile(DurationMs, 99) by bin(TimeGenerated, 1m) | extend FailureRate = round(todouble(FailedRequests) / TotalRequests * 100, 2) | order by TimeGenerated desc ``` ```kusto // Sporr backend-skifte under failover AppDependencies | where TimeGenerated > ago(1h) | where DependencyType == "HTTP" | where Target contains "openai.azure.com" | summarize RequestCount = count(), AvgDuration = avg(DurationMs), FailCount = countif(ResultCode >= 400) by bin(TimeGenerated, 1m), Target | order by TimeGenerated desc ``` ```kusto // Cosmos DB failover-hendelser AzureDiagnostics | where ResourceProvider == "MICROSOFT.DOCUMENTDB" | where Category == "DataPlaneRequests" | where TimeGenerated > ago(1h) | summarize RequestCount = count(), AvgLatency = avg(duration_s * 1000), ErrorCount = countif(statusCode_s >= "400") by bin(TimeGenerated, 1m), regionName_s | order by TimeGenerated desc ``` ### Azure Monitor Dashboard for failover Opprett et dedikert dashboard for failover-overvaking: | Panel | Metrikk | Terskel (groen) | Terskel (roed) | |-------|---------|-----------------|----------------| | AOAI feilrate | % 4xx/5xx | < 1% | > 5% | | AOAI latens (P95) | Millisekunder | < 2000 ms | > 5000 ms | | APIM throughput | Requests/min | > 80% av baseline | < 50% av baseline | | Cosmos DB latens | Millisekunder | < 50 ms | > 200 ms | | Cosmos DB tilgjengelighet | % | > 99.9% | < 99% | | Aktiv region | Region-label | Primaer | Sekundaer | ## Suksesskriterier og akseptanseterskel ### Definerte suksesskriterier per testnivaa | Testnivaa | Kriterie | Maal | Akseptabelt | Feil | |-----------|---------|------|-------------|------| | **L1: Endepunkt-failover** | Gjenopprettingstid | < 10 sek | < 30 sek | > 30 sek | | | Feilrate under failover | 0% | < 2% | > 5% | | | Latensoekning | < 50% | < 100% | > 200% | | **L2: Cosmos DB failover** | Gjenopprettingstid | < 2 min | < 5 min | > 10 min | | | Datatap (RPO) | 0 sek | < 10 sek | > 60 sek | | | Agentfunksjonalitet | Full | Degradert | Utilgjengelig | | **L3: Gateway-failover** | Gjenopprettingstid | < 5 min | < 15 min | > 30 min | | | Feilrate for sluttbrukere | < 1% | < 5% | > 10% | | | Funksjonell dekning | 100% | > 90% | < 80% | | **L5: Full regional** | Gjenopprettingstid (RTO) | < 30 min | < 60 min | > 120 min | | | Datatap (RPO) | < 5 min | < 30 min | > 60 min | | | Alle tjenester operative | 100% | > 95% | < 90% | ### Akseptanseprotokoll ``` FAILOVER-TEST AKSEPTANSEPROTOKOLL ================================== Testdato: _______________ Testnivaa: [ ] L1 [ ] L2 [ ] L3 [ ] L4 [ ] L5 [ ] L6 Testleder: _______________ Deltakere: _______________ RESULTATER: ----------- Malt RTO: _____ min/sek Malt RPO: _____ min/sek Maks feilrate: _____ % Maks latensoekning: _____ % Funksjoner tilgjengelig: _____ % VURDERING: ---------- [ ] BESTATT -- Alle kriterier innenfor "Maal" [ ] AKSEPTABELT -- Alle kriterier innenfor "Akseptabelt" [ ] FEIL -- Ett eller flere kriterier i "Feil"-sonen AVVIK OG MERKNADER: ____________________________________________________ ____________________________________________________ SIGNATUR: Testleder: _____________ Dato: __________ Godkjenner: ____________ Dato: __________ ``` ### Baseline-maling Foer failover-testing ma du etablere en baseline for normal ytelse: ```bash # Kjoer baseline-lasttest med Azure Load Testing az load test create \ --name ai-baseline-test \ --resource-group rg-ai-prod \ --location norwayeast \ --test-plan tests/baseline-load-test.jmx \ --engine-instances 2 # Baseline-kriterier (eksempel): # - Gjennomsnittlig responstid: < 1500 ms # - P95 responstid: < 3000 ms # - Feilrate: < 0.5% # - Throughput: > 50 req/sek ``` ## Dokumentasjon og laerdommer ### Testreportmal ```markdown # Failover Test Report ## Testoversikt - **Dato:** 2026-02-15 - **Scenario:** L3 -- Full gateway-failover - **Varighet:** 2 timer 15 minutter - **Deltakere:** [Navn og roller] ## Sammendrag [2-3 setninger om hva som ble testet og hovedresultatet] ## Testforloep | Tid | Hendelse | Status | |-----|---------|--------| | 10:00 | Test startet, normal trafikk | OK | | 10:05 | Primaer gateway deaktivert | OK | | 10:05:12 | Foerste feil detektert av monitor | OK | | 10:05:45 | Trafikk rutes til sekundaer | OK | | 10:06:30 | Alle helsesjekker gronne | OK | | ... | ... | ... | ## Malte resultater | Kriterie | Maal | Resultat | Status | |---------|------|---------|--------| | RTO | < 5 min | 1 min 30 sek | BESTATT | | Feilrate | < 5% | 2.1% | BESTATT | | Latens P95 | < 3000 ms | 2800 ms | BESTATT | ## Funn og observasjoner 1. [Funn 1: Beskrivelse og alvorlighet] 2. [Funn 2: Beskrivelse og alvorlighet] ## Forbedringstiltak | # | Tiltak | Prioritet | Ansvarlig | Frist | |---|--------|-----------|-----------|-------| | 1 | [Tiltak] | Hoey | [Navn] | [Dato] | | 2 | [Tiltak] | Middels | [Navn] | [Dato] | ## Laerdommer (Lessons Learned) - **Hva fungerte bra:** [Beskrivelse] - **Hva kan forbedres:** [Beskrivelse] - **Uventede funn:** [Beskrivelse] ``` ### Kunnskapsbase for failover-laerdommer Bygg en loepende kunnskapsbase med laerdommer fra failover-tester: | Dato | Scenario | Laerdom | Tiltak | Status | |------|---------|---------|--------|--------| | 2026-01-15 | L1 | Circuit breaker brukte 45 sek (for lang) | Reduser timeout til 10 sek | Implementert | | 2026-02-01 | L2 | Cosmos DB failover tok 8 min (mal: 5 min) | Aktiver service-managed failover | Planlagt | | 2026-02-15 | L3 | DNS-propagering tok 10 min | Reduser TTL til 60 sek | Under arbeid | ### Post-incident review-prosess Etter hver failover-test (og spesielt etter reelle hendelser): ``` 1. Samle data (innen 24 timer) - Loggfiler fra alle komponenter - Metrikkdata fra Azure Monitor - Tidslinje for hendelser - Kommunikasjonslogg 2. Gjennomfoere retrospektiv (innen 1 uke) - Blameless post-mortem - Identifiser rotaarsaker - Dokumenter tidslinje - Klassifiser funn (kritisk/hoey/middels/lav) 3. Definere tiltak (under retrospektiv) - Konkrete tiltak med eier og frist - Oppdater DR-plan - Oppdater runbooks - Planlegg oppfoelgingstest 4. Foelg opp (loepende) - Sporr tiltak i Linear/backlog - Verifiser implementering - Test forbedringer i neste planlagte test ``` ## Regelmessig testplanlegging og frekvens ### Anbefalt testfrekvens | Testtype | Frekvens | Deltakere | Estimert tid | |----------|----------|-----------|-------------| | **L1: Endepunkt-failover** | Ukentlig (automatisert) | CI/CD pipeline | 5-10 min | | **L2: Komponent-failover** | Manedlig | Driftsteam (2-3 personer) | 1-2 timer | | **L3: Gateway-failover** | Kvartalsvis | Drifts- + utviklingsteam | 2-4 timer | | **L5: Full regional drill** | Halvaarlig | Alle (inkl. ledelse) | 4-8 timer | | **Tabletop exercise** | Kvartalsvis | Arkitektur + drift + forretning | 2 timer | | **Chaos engineering** | Lopende i CI/CD | Automatisert | Varierer | ### Arsplan for failover-testing ``` Q1 (jan-mar): - Uke 2: Tabletop exercise (alle scenarier) - Uke 4: L2 komponent-test (Cosmos DB failover) - Uke 8: L3 gateway-failover - Uke 12: L5 FULL DR-DRILL Q2 (apr-jun): - Uke 14: Tabletop exercise (nye scenarier) - Uke 17: L2 komponent-test (Storage failover) - Uke 20: L3 gateway-failover - Uke 24: L2 komponent-test (AI Search recovery) Q3 (jul-sep): - Uke 27: Tabletop exercise (oppdatert DR-plan) - Uke 30: L2 komponent-test (Cosmos DB failover) - Uke 33: L3 gateway-failover - Uke 36: L5 FULL DR-DRILL Q4 (okt-des): - Uke 40: Tabletop exercise (arsrevisjon) - Uke 43: L2 komponent-test (valgfritt scenario) - Uke 46: L3 gateway-failover - Uke 50: Arlig DR-rapportering og planrevisjon ``` ### Automatisert failover-testing i CI/CD Integrer L1-tester i CI/CD-pipeline: ```yaml # azure-pipelines.yml -- Failover test stage - stage: FailoverTest displayName: 'Automated Failover Validation' dependsOn: DeployStaging condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) jobs: - job: RunChaosExperiment steps: - task: AzureCLI@2 displayName: 'Start Chaos Experiment' inputs: azureSubscription: 'ddt-ai-staging' scriptType: 'bash' inlineScript: | # Start chaos experiment az chaos experiment start \ --name ai-gateway-failover-test \ --resource-group rg-ai-staging # Vent pa at eksperimentet fullfores az chaos experiment show \ --name ai-gateway-failover-test \ --resource-group rg-ai-staging \ --query "status" -o tsv - task: AzureCLI@2 displayName: 'Run Load Test During Chaos' inputs: azureSubscription: 'ddt-ai-staging' scriptType: 'bash' inlineScript: | # Kjoer lasttest parallelt med chaos experiment az load test run create \ --test-id ai-failover-load-test \ --resource-group rg-ai-staging \ --load-test-resource ddt-ai-load-test - task: AzureCLI@2 displayName: 'Validate Results' inputs: azureSubscription: 'ddt-ai-staging' scriptType: 'bash' inlineScript: | # Valider at feilrate er innenfor terskel ERROR_RATE=$(az monitor metrics list \ --resource "/subscriptions/{sub}/..." \ --metric "FailedRequests" \ --interval PT1M \ --query "value[0].timeseries[0].data[-1].total" -o tsv) if [ "$ERROR_RATE" -gt "5" ]; then echo "##vso[task.logissue type=error]Failover test failed: error rate $ERROR_RATE% exceeds 5% threshold" exit 1 fi echo "Failover test passed: error rate $ERROR_RATE%" ``` ### Azure Chaos Studio + Azure Load Testing-integrasjon Microsoft anbefaler a kombinere Chaos Studio (feilinjeksjon) med Azure Load Testing (syntetisk last) for realistisk failover-validering: ``` +------------------+ +---------------------+ | Azure Load | | Azure Chaos Studio | | Testing | | | | (syntetisk last) | | (feilinjeksjon) | +--------+---------+ +---------+-----------+ | | | Parallelkjoering | +------------+------------+ | +-------v--------+ | AI Application | | (staging) | +-------+--------+ | +------------+------------+ | | +--------v---------+ +--------v---------+ | Azure OpenAI | | Azure OpenAI | | (Norway East) | | (Sweden Central) | +------------------+ +------------------+ ``` **Viktig:** Under kombinert chaos + load testing vil man forvente hoeyere feilrate og latens enn normalt. Definer separate baseline-verdier for "normal" og "chaos"-tilstand. ## Referanser - [What is Azure Chaos Studio?](https://learn.microsoft.com/en-us/azure/chaos-studio/chaos-studio-overview) - [Create a chaos experiment - Cosmos DB failover](https://learn.microsoft.com/en-us/azure/chaos-studio/chaos-studio-tutorial-service-direct-portal) - [Continuous validation with Azure Load Testing and Chaos Studio](https://learn.microsoft.com/en-us/azure/architecture/guide/testing/mission-critical-deployment-testing) - [Architecture strategies for designing a reliability testing strategy](https://learn.microsoft.com/en-us/azure/well-architected/reliability/testing-strategy) - [Architecture strategies for disaster recovery](https://learn.microsoft.com/en-us/azure/well-architected/reliability/disaster-recovery) - [Shift right to test in production - Fault injection](https://learn.microsoft.com/en-us/devops/deliver/shift-right-test-production#fault-injection) - [Deployment and testing for mission-critical workloads on Azure](https://learn.microsoft.com/en-us/azure/well-architected/mission-critical/mission-critical-deployment-testing) ## For Cosmo - **Bruk denne referansen** nar kunden har implementert DR-infrastruktur men mangler en testplan -- en DR-loesning uten testing er like risikabel som ingen DR-loesning. - **Start med L1-tester (automatisert)** for a bygge erfaring og tillit foer man gradvis oeker til L3 og L5 -- dette reduserer risikoen for at tester selv forarsaker utfall. - **Anbefal Azure Chaos Studio + Azure Load Testing-kombinasjonen** som standard verktoeysett. Chaos Studio er GA og stoetter service-direct faults mot Cosmos DB, som er den mest kritiske AI-komponenten a teste. - **Fremhev at failover-testing ma inkludere hele AI-stakken** -- ikke bare inferens-endepunktet. Samtalehistorikk (Cosmos DB), kunnskapsbaser (AI Search), og agent-definisjoner ma alle valideres under failover. - **Bruk akseptanseprotokollen og rapportmalen** for a gi kunden konkrete verktøy de kan ta i bruk umiddelbart. Dokumentasjon av tester er like viktig som selve testingen for kontinuerlig forbedring.