Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här självstudien distribuerar du ett exempelprogram till ett zonredundant Azure Kubernetes Service (AKS) kluster och använder sedan en Azure Chaos Studio arbetsyta för att simulera ett fel i tillgänglighetszonen två gånger. Den första körningen blottlägger en verklig brist i resiliensen: applikationens frontend är avsiktligt bunden till en enda zon, så webbutiken går ner när den zonen faller bort. Sedan åtgärdar du driftsättningen, kör samma scenario igen och ser hur applikationen klarar sig igenom felet. Längs vägen startar du en webbläsarbaserad övervakare som visar felet och korrigeringen när de inträffar, och du får lära dig varför butikens egen tillgänglighet och klustrets nodstatus inte ändras samtidigt.
Den här självstudien är en bra första demonstration och återanvänder exempeltillämpningen AKS store demo från AKS-snabbstarterna, så det behövs därför varken något containerregister eller något byggsteg. Planera i ungefär en timme: skapa kluster plus två scenariokörningar på cirka 5 minuter vardera.
Important
Chaos Studio Arbetsytor och scenarier finns i offentlig förhandsversion. Microsoft tillhandahåller den här förhandsversionen "som den är" och "som tillgänglig", och den omfattas inte av serviceavtal eller begränsad garanti. Microsoft ger kundsupport för förhandsversionen på bästa sätt. Den här förhandsversionen är inte avsedd för produktionsanvändning. Mer information finns i följande artiklar:
I den här tutorialen lär du dig följande:
- Skapa ett AKS-kluster vars noder sträcker sig över tre tillgänglighetszoner.
- Distribuera exempelappen AKS Store-demo och fäst dess frontend till en zon för en deterministisk demo.
- Starta ett webbläsarbaserat övervakningsverktyg som övervakar butiksgränssnittet, målnoden och podplaceringen i realtid.
- Skapa en arbetsyta som är begränsad till klustrets infrastrukturresursgrupp.
- Kör scenariot Compute Zone Down och observera att programmet slutar fungera.
- Åtgärda distributionen med ett hårt placeringskontrakt per zon, verifiera den och kör scenariot igen.
- Jämför de två scenariorapporterna.
Den här handledningen är optimerad för att ge en fungerande demonstration. Begreppen bakom varje steg, varningar om att störa infrastrukturen som AKS hanterar åt dig och hur du tolkar resultat på en verklig arbetsbelastning finns i Testa arbetsbelastningens återhämtning på AKS med Chaos Studio.
Förutsättningar
- Ett Azure-abonnemang. Om du inte har något Azure-konto skapar du ett kostnadsfritt konto innan du börjar.
- Azure CLI,
kubectl,kubeloginoch Python 3 (endast standardbibliotek – inga paket att installera). Azure Cloud Shell har alla fyra förinstallerade. Om du arbetar lokalt installerar dukubectlmedaz aks install-cliochkubeloginvar för sig. - Resursprovidern Microsoft.Chaos har registrerats i din prenumeration. Om du vill registrera den för första gången, se Registrera resursprovidern för Chaos Studio.
Skapa ett zonredundant AKS-kluster
Ett test av zonfel är bara meningsfullt mot ett kluster som har skapats för att överleva ett, så skapa ett kluster med tre noder spridda över tre tillgänglighetszoner. Det här exemplet använder East US 2; alla regioner med tillgänglighetszoner fungerar.
Skapa en resursgrupp och klustret:
az group create --name chaos-demo-rg --location eastus2 az aks create \ --resource-group chaos-demo-rg \ --name chaos-demo-aks \ --node-count 3 \ --zones 1 2 3 \ --generate-ssh-keysDet tar några minuter att skapa klustret.
I en ny Cloud Shell session
kubectlär den inte ansluten till något kluster än. Ange din prenumeration, hämta autentiseringsuppgifter och konvertera kubeconfig för Microsoft Entra autentisering innan du kör någotkubectlkommando:az account set --subscription <SUBSCRIPTION_ID> az aks get-credentials --resource-group chaos-demo-rg --name chaos-demo-aks kubelogin convert-kubeconfig -l azurecliErsätt ditt prenumerations-ID för
<SUBSCRIPTION_ID>. Hoppa överaz account setom prenumerationen redan är den du har aktiv. Stegetkubeloginkrävs även i en ny Cloud Shell session – utan den misslyckas det förstakubectlkommandot mot ett Entra-autentiserat kluster med ett autentiseringsfel.Kontrollera att noderna sträcker sig över tre zoner:
kubectl get nodes -L topology.kubernetes.io/zoneKolumnen
ZONEvisar en nod i varje zon, till exempeleastus2-1,eastus2-2ocheastus2-3. Zonnumret efter regionnamnet är det du riktar in dig på senare i scenariokonfigurationen.
Distribuera exempelprogrammet
AKS-butikens demo är en liten butik med en webbklientdel, en produkttjänst, en ordertjänst och en RabbitMQ-kö. Dess containeravbildningar är offentliga, så du kan distribuera den med ett enda kommando.
Distribuera programmet:
kubectl apply -f https://raw.githubusercontent.com/Azure-Samples/aks-store-demo/2.2.0/aks-store-quickstart.yamlManifestet distribuerar varje komponent med en enskild replik. Klustret är zonredundant, men applikationen är det inte. Den här handledningen blottlägger och åtgärdar sedan den här bristen i motståndskraft.
Vänta tills klientdelen har en offentlig IP-adress:
kubectl get service store-front --watchNär värdet
EXTERNAL-IPändras från<pending>till en offentlig IP-adress trycker duCtrl+Cpå för att stoppa klockan.Öppna
http://<EXTERNAL-IP>i en webbläsare och kontrollera att butiken laddas. Håll den här fliken öppen. Det är en sekundär vy över programmets hälsa under testet – övervakaren som du startar senare är den primära.
Information om hur själva programmet skapas och distribueras finns i AKS-självstudieserien.
Lås frontend till en enda zon för en deterministisk demo
Note
Att fästa en enskild replik i en zon är en avsiktlig undervisningskonfiguration för den här demonstrationen, inte en produktionsrekommendations. En produktionsdistribution bör aldrig begränsa en enskild replik till en enda zon – som tar bort redundansen som klustret skapas för att tillhandahålla. Den här självstudien gör detta avsiktligt så att felet i den första körningen blir konsekvent och kan upprepas, i stället för att bero på vilken zon schemaläggaren råkade välja.
Utan en avsiktlig pin-kod kan schemaläggaren placera klientdelens enda replik i valfri zon, och en vanlig omläggning kan ske tillräckligt snabbt för att effekten ska vara lätt att missa. Om du fäster repliken i en känd zon blir målet förutsägbart och felet kan observeras varje gång du kör demonstrationen.
Leta reda på noden som
store-frontpodden körs på och läs nodens zonetikett:STORE_NODE="$(kubectl get pods -l app=store-front -o jsonpath='{.items[0].spec.nodeName}')" PIN_ZONE="$(kubectl get node "$STORE_NODE" -o jsonpath="{.metadata.labels['topology\.kubernetes\.io/zone']}")" echo "$PIN_ZONE"PIN_ZONEär den fullständiga zonetiketten, till exempeleastus2-1. Håll den här shell-sessionen öppen – du återanvänder det här värdet för övervakaren och senare för scenariokonfigurationen (som frågar efter bara talet, delen efter det sista bindestrecket , till exempel1ieastus2-1).Korrigera distributionen
store-frontså att den kräver schemaläggning i den zonen och lägg till en anteckning som flaggar korrigeringen som ett demomönster:kubectl patch deployment store-front --patch "$(cat <<EOF { "metadata": { "annotations": { "chaos-demo.aks-zone-down-demo/deliberate-anti-pattern": "Pins the single front-end replica to zone ${PIN_ZONE} so run 1 is deterministic. Removed as part of the fix later in this tutorial - do not carry this pin into a real deployment." } }, "spec": { "template": { "spec": { "affinity": { "nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": { "nodeSelectorTerms": [ { "matchExpressions": [ {"key": "topology.kubernetes.io/zone", "operator": "In", "values": ["${PIN_ZONE}"]} ] } ] } } } } } } } EOF )" kubectl rollout restart deployment/store-front kubectl rollout status deployment/store-front --timeout=300sBekräfta pin-koden – repliken ska vara tillbaka på en nod i
$PIN_ZONE:STORE_NODE="$(kubectl get pods -l app=store-front -o jsonpath='{.items[0].spec.nodeName}')" STORE_ZONE="$(kubectl get node "$STORE_NODE" -o jsonpath="{.metadata.labels['topology\.kubernetes\.io/zone']}")" echo "Pod is in zone: $STORE_ZONE (expected $PIN_ZONE)"Om de två värdena inte överensstämmer upprepar du föregående steg – körning 1 blir inte deterministisk förrän de överensstämmer.
Ladda ned och starta demoövervakaren
En enbart terminalbaserad kubectl-bevakning är för långsam och lätt att missa under en live-demo. Butikens egen signal rör sig inte i takt med klustrets signal. I den här självstudien används ett litet övervakningsskript i Python från Chaos Studios exempellagringsplats som det främsta sättet att övervaka körningen.
Ladda ned övervakaren och skriptet för korrigeringsverifiering:
curl -O https://raw.githubusercontent.com/microsoft/chaos-studio/f9573c943694e88cf3aacbca38debe84fa91a62c/samples/aks-zone-down-demo/monitor.py curl -O https://raw.githubusercontent.com/microsoft/chaos-studio/f9573c943694e88cf3aacbca38debe84fa91a62c/samples/aks-zone-down-demo/verify-fix.sh chmod +x verify-fix.shDe här länkarna är låsta till en specifik commit så att de fortsätter att fungera oavsett vilka senare ändringar som görs i exempelkoden. När den tillhörande pull requesten har slagits samman kan senare versioner av den här handledningen i stället flyttas till en taggad utgåva.
Starta övervakningen och rikta den mot butikens externa IP-adress och den zon du fäste i föregående avsnitt:
python3 monitor.py --storefront-url http://<EXTERNAL-IP> --target-zone "$PIN_ZONE"Övervakaren använder bara Python standardbibliotek, så det finns inget annat att installera. Som standard avsöker den var 5:e sekund – kan konfigureras med
--intervalellerMONITOR_INTERVAL_SECONDSmiljövariabeln. Det standardvärdet är tillräckligt frekvent för att fastställa ordningen mellan signalerna utan att göra alltför frekventa anrop till Kubernetes-API:et eller webbutiken.I Cloud Shell väljer du Webbförhandsgranskning och anger porten till 8787 för att öppna bildskärmen på en webbläsarflik. Om du kör lokalt öppnar
http://localhost:8787du i stället.Övervakningssidan är nu din primära vy för båda körningarna. Den visar fyra signaler:
- HTTP-status för webbutiken – en begäran som kringgår cachen mot webbutiken, så att du ser en aktuell status för nåbar/inte nåbar i stället för ett cachelagrat lyckat svar.
-
Nodstatus för målzon – om noden i målzonen är
ReadyellerNotReady. -
Placering av front-end-poddar - vilka
store-frontpoddar som körs och vilken zon varje podd finns i. - Övergångshistorik – en tidslinje som körs för varje tillståndsändring ovan, med tidsstämplar, så att du kan granska sekvensen när körningen har avslutats i stället för att förlita dig på det du märkte live.
Om en avfrågning mot
kubectleller Kubernetes-API:et misslyckas – till exempel om API-servern tillfälligt inte kan nås eller kubeconfig blir inaktuell – visar övervakningen en tydlig röd banderoll med felmeddelandet, i stället för att låta den påverkade signalen fastna på platshållaren ”kontrollerar”. Resten av instrumentpanelen fortsätter att visa sitt senast kända fungerande tillstånd och sin historik medan banderollen visas. Behandla banderollen som en signal i sig: det betyder att övervakaren förlorade synligheten, inte att det den tittar på är hälsosamt.
Skapa en arbetsyta som är begränsad till infrastrukturresursgruppen
AKS placerar klustrets skalningsuppsättningar för virtuella noder i en separat infrastrukturresursgrupp (med namnet börjar med MC_ som standard), inte i resursgruppen som innehåller klusterresursen. Begränsa arbetsytan till infrastrukturresursgruppen så att den identifierar noderna. Bakgrund finns i Varför en arbetsyta som är begränsad till ditt AKS-kluster inte hittar några beräkningsmål.
Leta reda på namnet på infrastrukturresursgruppen:
az aks show --resource-group chaos-demo-rg --name chaos-demo-aks --query nodeResourceGroup -o tsvI Azure-portalen söker du efter Chaos Studio, väljer Arbetsytor och väljer sedan Skapa.
På fliken Grundläggande väljer du
chaos-demo-rgresursgruppen, namnger arbetsytanchaos-demo-workspaceoch väljer en region som stöds. Arbetsytans region behöver inte matcha klusterregionen.På fliken Omfång väljer du Resursgrupp som omfångstyp och väljer sedan infrastrukturresursgruppen från steg 1.
På fliken Identitet väljer du Systemtilldelad.
Välj Granska + Skapa>skapa och sedan Gå till resurs.
När identifieringen har slutförts visas klustrets skalningsuppsättning för virtuella noddatorer (med ett namn som
aks-nodepool1-12345678-vmss) som en identifierad resurs.Om portalen visar en banner med texten att identiteten saknar läsbehörighet på arbetsytans nivå, väljer du Tilldela läsarrollen på arbetsytans nivå. Om du vill skapa rolltilldelningar behöver du behörighet som ägare eller administratör för användaråtkomst för infrastrukturresursgruppen.
Du tilldelar identiteten de roller som scenariot behöver i nästa avsnitt, där valideringen visar exakt vad som saknas. En fullständig genomgång av varje steg för att skapa arbetsytor finns i snabbstarten för arbetsytan.
Kör scenariot och se hur appen misslyckas
Scenariot Compute Zone Down simulerar ett bortfall i en tillgänglighetszon genom att stänga av instanserna i skalningsuppsättningen för virtuella datorer i en målzon under den konfigurerade tidsperioden. Instanserna startas om när åtgärdens varaktighet slutar.
På arbetsytan väljer du Scenarier och sedan Beräkningszon nedåt från scenariobiblioteket.
Konfigurera scenariot. För tillgänglighetszonen anger du talet från
$PIN_ZONE(delen efter det sista bindestrecket, till exempel1ieastus2-1). Ange varaktigheten till 5 minuter – tillräckligt länge för att se signalerna från storefront, nod och podd stabiliseras, utan att behöva vänta för länge. Den här siffran på 5 minuter är storleksanpassad för den här specifika demonstrationen. andra scenariotyper har sin egen varaktighetsvägledning baserat på vad de testar. Ett scenario som bygger på DNS-cachelagringsbeteende behöver till exempel en varaktighet som är tillräckligt lång för att överskrida postens cache-TTL, som kan vara mycket längre än 5 minuter. Välj Spara konfiguration.Validering kontrollerar om arbetsytans hanterade identitet kan utföra varje åtgärd som scenariot behöver på målresurserna. Om verifieringsrapporter saknar behörigheter väljer du Åtgärda behörigheter på scenariokonfigurationssidan för att ge identiteten de rekommenderade inbyggda rollerna. I det här scenariot är det rollen Virtual Machine Contributor för nodens skalningsuppsättning för virtuella datorer. Om du vill tilldela rollerna själv eller använda anpassade roller med minst privilegier i stället för inbyggda roller kan du läsa Behörigheter och identiteter i Chaos Studio Arbetsytor och Använda anpassade roller med minst privilegier med Chaos Studio arbetsytor.
Om en obligatorisk roll fortfarande saknas vid körningstillfället startar körningen ändå, men avstängningsåtgärderna misslyckas på grund av ett behörighetsfel i scenariorapporten.
Välj Kör och bekräfta.
Det kan ta några minuter efter att körningen startar innan avstängningen börjar gälla, så oroa dig inte om ingenting ändras på bildskärmen omedelbart. Titta sedan på övervakningssidan:
- HTTP-signalen för storefront och målnodens status ändras inte samtidigt. Signalen på applikationsnivå är den som användarna faktiskt upplever, och det är den som bör betraktas som den primära; signalerna från noder och poddar är intern bokföring i klustret som hinner ikapp först efteråt. Förvänta dig att butikssidan visas som otillgänglig märkbart tidigare än noden visas
NotReady– den fördröjningen är normal och beror på asynkron signalpropagering, inte på något problem med demon. - Målnodens status ändras till
NotReady. - Eftersom frontenden är låst till den zonen har dess enda replik ingen annanstans där den får köras. Webbutiken förblir oåtkomlig tills Kubernetes kan omplacera podden – vilket, med pinningen på plats, bara sker när målnoden blir tillgänglig igen eller när du ändrar placeringsbegränsningen. Förlita dig inte på ett fast stilleståndstidsnummer här; titta på övervakarens övergångshistorik för vad som faktiskt hände under körningen.
Det här resultatet är fyndet. Klustret var zonredundant, men programmets placeringsval förvandlade ett zonfel till ett avbrott utan definierat slut medan begränsningen fanns kvar. Övervakningens historik över statusändringar är en logg över exakt när butikssidan blev otillgänglig och senare när den blev tillgänglig igen.
Felsökning: effekten är inte synlig
Om övervakningen visar att webbutiken fortfarande går att nå under hela körning 1, kontrollera följande innan du antar att scenariot inte fungerade:
- Bekräfta att pin-koden trädde i kraft. Kör
kubectl get pods -l app=store-front -o wideoch kontrollera att poddens nod finns i$PIN_ZONE. Om korrigeringen inte tillämpades kan schemaläggaren ha placerat repliken någon annanstans. En vanlig omplanering i samband med avbrottet kan gå så snabbt att du missar den utan nålen. - Bekräfta att övervakaren tittar på rätt zon och URL. Starta om
monitor.pymed det exakta--target-zonevärdet och lagrings-URL:en från klustret. Ett inaktuellt eller feltypat värde visar vilseledande "felfri" status. - Kontrollera scenariorapporten för
Skippedåtgärder. Om avstängningsåtgärderna visarSkippedi stället förSucceeded, hittade körningen inga matchande mål i målzonen. Se Tolka resultatet. - Ge det några sekunder till. Själva avstängningsåtgärden tar en kort stund att träda i kraft efter att körningen har startat. Övervakarens övergångshistorik visar de exakta tidsstämplarna när de inträffar.
Åtgärda distributionen och verifiera den
Ersätt nu den avsiktliga bindningen till en enda zon med en riktig lösning i klusterskala: tre repliker, strikt bundna till en per zon.
Ta bort zonstiftet som du lade till tidigare:
kubectl patch deployment store-front --type=merge --patch '{"spec":{"template":{"spec":{"affinity":null}}}}'Skala frontend till tre repliker och lägg till en topologispridningsbegränsning som kräver en replik per zon i stället för att bara ange det som ett önskemål:
kubectl patch deployment store-front --patch '{"spec":{"replicas":3,"template":{"spec":{"topologySpreadConstraints":[{"maxSkew":1,"topologyKey":"topology.kubernetes.io/zone","whenUnsatisfiable":"DoNotSchedule","labelSelector":{"matchLabels":{"app":"store-front"}}}]}}}}'whenUnsatisfiable: DoNotSchedulegör spridning med en replik per zon till ett absolut krav. En replik som inte kan uppfylla den stannarPendingi stället för att landa i en zon som redan har en. Det är en avsiktlig kompromiss – den garanterar täckning över zonerna som detta test är beroende av, till priset av att en replik kan förbli oschemalagd om en zon tillfälligt saknar kapacitet.ScheduleAnywayskulle låta schemaläggaren hoppa över restriktionen vid hög belastning, vilket är precis det felläge som den här korrigeringen åtgärdar.Kontrollera korrigeringen innan du litar på den. Kör verifieringsskriptet. Den väntar ut utrullningen så att gamla poddar från den gamla revisionen med en enda replik inte räknas, och bekräftar sedan att varje zon har minst en
Readystore-front-podd:./verify-fix.shEtt
kubectlanrop, en API-begäran eller den JSON som returneras kan misslyckas tillfälligt – en kort timeout, en borttagen anslutning – utan att själva korrigeringen misslyckades. Skriptet gör nya försök efter dessa tillfälliga fel tills dess egen tidsgräns nås i stället för att avslutas vid det första. Först efter den tidsgränsen avslutas den med statusen nonzero och ett diagnostikmeddelande som namnger vilken zon som fortfarande saknar en färdig replik. Fortsätt inte att köra 2 förrän det har passerat. Ett godkänt resultat är det som gör "en replik per zon" till ett verifierat faktum i stället för ett antagande som överförs från korrigeringskommandot.
Kör scenariot igen och jämför
På arbetsytan kör du scenariot Beräkningszon nedåt igen med samma målzon och samma varaktighet på 5 minuter.
Titta på skärmen. Målnoden slås fortfarande
NotReadyut och tar sinstore-front-replik med sig, men butiken fortsätter att svara och betjänas av replikerna i de kvarvarande zonerna. Påståendet som testas är bibehållen tillgänglighet vid ett zonavbrott, vilket visas av övervakningssystemets obrutna historik – inte att inga begäranden tappas, och inte heller att övervakningen hela tiden visar ett obrutet friskt tillstånd. En kort störning är fortfarande möjlig medan Azure Load Balancer konvergerar till de återstående felfria replikerna. En passerande körning visar en kort konvergensblip, inte ett avbrott som varar under störningens längd. Hur lång tid konvergensen tar varierar beroende på miljö, så förlita dig inte på en fast tidsgräns – använd övervakarens övergångshistorik för att skilja en tillfällig blip frånsett ett ihållande avbrott.
Komponenter med en enda replik kan fortfarande drabbas av ett kort avbrott. Om RabbitMQ-köns nod finns i målzonen, försämras orderinlämningen medan dess pod återhämtar sig. Att hitta den näst svagaste komponenten och avgöra om den är värd att åtgärda är exakt den cykel som kaostestning är utformad för att driva fram.
Jämför scenariorapporterna
På arbetsytan väljer du Körningshistorik. Nu har du två slutförda körningar av samma scenario.
Välj varje körning och välj sedan Generera rapport. Kontrollera att avstängningsåtgärderna visar statusen Lyckades i båda fallen, vilket innebär att varje körning hittade och påverkade instanser i målszonen. Om åtgärderna visar Överhoppad, hittade körningen inga matchande mål. De vanliga orsakerna är ett omfång som inte innehåller infrastrukturresursgruppen eller en målzon utan noder i den. Mer information finns i Testa arbetsbelastningens återhämtning på AKS med Chaos Studio.
Observera att båda rapporterna ser likadana ut även om programresultaten var motsatta. Lyckades innebär att störningen genomfördes – det betyder inte att applikationen fortsatte att fungera korrekt. Rapporten visar vilka störningar som inträffat och när; övervakarens övergångshistorik är det som bevisar programmets beteende som svar. Genom att kombinera de två förvandlar du en körning till bevis: rapporten tidsstämplar felet, och övervakningen visar skillnaden före och efter som korrigeringen gav.
Du kan ladda ned båda rapporterna som före-och-efter-bevis för motståndskraftsgranskningar. Mer information finns i Scenariorapporter.
Rensa resurser
Ta bort resursgruppen för att ta bort klustret, exempelprogrammet och arbetsytan. Om du tar bort klustret tas även dess infrastrukturresursgrupp bort.
az group delete --name chaos-demo-rg --yes --no-wait
Rapportera problem och begära funktioner
Azure Chaos Studio utvecklas i det öppna. Om du vill rapportera en bugg, begära en funktion eller ställa en fråga om arbetsytor, scenarier eller Azure CLI-tillägget öppnar du ett problem på Chaos Studio lagringsplats på GitHub. Genom att registrera ett problem kan du spåra dess förlopp och se begäranden från andra kunder.
Nästa steg
- Testbelastningsåterhämtning på AKS med Chaos Studio beskriver varningar och tolkningsvägledning för att köra det här testet mot en verklig arbetsbelastning.
- För att göra bedömningen godkänd eller underkänd objektiv för en verklig arbetsbelastning bör du kombinera scenariokörningar med Application Insights-tillgänglighetstester och dina egna tjänstenivåindikatorer i stället för en webbläsarflik.
- Självstudie: Kör ett zonfelväxlingsscenario för PostgreSQL lägger till en felväxling i datalagret i samma avbrottsscenario.
- Scenarier i Azure Chaos Studio beskriver det fullständiga scenariobiblioteket.
- GitHub-lagringsplatsen för Chaos Studio har driftsättningsskript för det här exemplet (inklusive övervaknings- och verifieringsskripten som används i den här självstudien), anpassade scenarier som kan delas och ett Copilot CLI-plugin för att styra Chaos Studio från GitHub Copilot.