Felsöka API-server- och etcd-problem i Azure Kubernetes Services

Den här guiden är utformad för att hjälpa dig att identifiera och lösa eventuella osannolika problem som kan uppstå på API-servern i stora Distributioner av Microsoft Azure Kubernetes Services (AKS).

Microsoft har testat API-serverns tillförlitlighet och prestanda på en skala av 5 000 noder och 200 000 poddar. Klustret som innehåller API-servern har möjlighet att automatiskt skala ut och leverera Kubernetes Service Level Objectives (SLO:er). Om du får långa svarstider eller timeouter beror det förmodligen på att det finns ett resursläckage på den distribuerade etc katalogen (etcd) eller att en klient som har fel har för höga API-anrop.

Förutsättningar

  • Azure CLI.

  • Kubernetes kubectl-verktyget . Om du vill installera kubectl med hjälp av Azure CLI kör du kommandot az aks install-cli .

  • AKS-diagnostikloggar (särskilt kube-audit-händelser) som aktiveras och skickas till en Log Analytics-arbetsyta. Om du vill ta reda på om loggar samlas in med hjälp av resursspecifikt eller Azure-diagnostikläge kontrollerar du bladet Diagnostikinställningar i Azure Portal.

  • Standardnivån för AKS-kluster. Om du använder den kostnadsfria nivån innehåller API-servern och etcd begränsade resurser. AKS-kluster på den kostnadsfria nivån ger inte hög tillgänglighet. Detta är ofta rotorsaken till API-server- och etcd-problem.

  • Plugin-programmet kubectl-aks för att köra kommandon direkt på AKS-noder utan att använda Kubernetes-kontrollplanet.

Symptom

I följande tabell beskrivs vanliga symptom på API-serverfel:

Symptom Beskrivning
Tidsgränser från API-servern Frekventa timeouter som ligger utanför garantierna i AKS API-serverns serviceavtal. Kommandon överskrider kubectl till exempel tidsgränsen.
Långa svarstider Långa svarstider som gör att Kubernetes SLO:er misslyckas. Kommandot tar till exempel kubectl mer än 30 sekunder att visa poddar.
API-serverpodden i CrashLoopbackOff status eller mot webhook-anropsfel Kontrollera att du inte har någon anpassad webhook för antagning (till exempel Kyverno-principmotorn ) som blockerar anropen till API-servern.

Checklista för felsökning

Om du har långa svarstider följer du dessa steg för att hitta den felande klienten och de typer av API-anrop som misslyckas.

Steg 1: Identifiera de främsta användaragenterna efter antalet begäranden

Om du vill identifiera vilka klienter som genererar flest begäranden (och potentiellt den största API-serverbelastningen) kör du en fråga som liknar följande kod. Följande fråga visar de 10 främsta användaragenterna efter antalet API-serverbegäranden som skickats.

AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| summarize count() by UserAgent
| top 10 by count_
| project UserAgent, count_

Obs!

Om frågan inte returnerar några resultat kan du ha valt fel tabell för att fråga diagnostikloggar. I resursspecifikt läge skrivs data till enskilda tabeller beroende på resurskategori. Diagnostikloggar skrivs till tabellen AKSAudit . I Azure-diagnostikläge skrivs alla data till tabellen AzureDiagnostics . Mer information finns i Azure-resursloggar.

Även om det är bra att veta vilka klienter som genererar den högsta begärandevolymen, kan hög begärandevolym inte vara en anledning till problem. En bättre indikator på den faktiska belastning som varje klient genererar på API-servern är svarsfördröjningen som de upplever.

Steg 2: Identifiera och kartlägga den genomsnittliga svarstiden för API-serverbegäranden per användaragent

Kör följande fråga för att identifiera den genomsnittliga svarstiden för API-serverbegäranden per användaragent som ritats i ett tidsdiagram:

AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize avg(latency) by UserAgent, bin(start_time, 5m)
| render timechart

Den här frågan är en uppföljning av frågan i avsnittet "Identifiera de vanligaste användaragenterna efter antalet begäranden" . Det kan ge dig mer insikter om den faktiska belastning som genereras av varje användaragent över tid.

Tips

Genom att analysera dessa data kan du identifiera mönster och avvikelser som kan tyda på problem i aks-klustret eller programmen. Du kanske till exempel märker att en viss användare har långa svarstider. Det här scenariot kan ange vilken typ av API-anrop som orsakar för hög belastning på API-servern eller etcd.

Steg 3: Identifiera felaktiga API-anrop för en viss användaragent

Kör följande fråga för att ta en tabell över den 99:e percentilen (P99) för API-anrop mellan olika resurstyper för en viss klient:

AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend HttpMethod = Verb
| extend Resource = tostring(ObjectRef.resource)
| where UserAgent == "DUMMYUSERAGENT" // Filter by name of the useragent you are interested in
| where Resource != ""
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize p99latency=percentile(latency, 99) by HttpMethod, Resource
| render table

Resultatet från den här frågan kan vara användbart för att identifiera vilka typer av API-anrop som misslyckas med de överordnade Kubernetes-SLO:erna. I de flesta fall kan en felande klient göra för många LIST anrop på en stor uppsättning objekt eller objekt som är för stora. Tyvärr finns inga hårda skalbarhetsgränser tillgängliga för att vägleda användarna om API-serverns skalbarhet. API-servern eller skalbarhetsgränser etc. beror på olika faktorer som förklaras i Kubernetes-tröskelvärden för skalbarhet.

Orsak 1: En nätverksregel blockerar trafiken från agentnoder till API-servern

En nätverksregel kan blockera trafik mellan agentnoderna och API-servern.

Kontrollera om en felkonfigurerad nätverksprincip blockerar kommunikationen mellan API-servern och agentnoderna genom att köra följande kubectl-aks-kommandon :

kubectl aks config import \
    --subscription <mySubscriptionID> \
    --resource-group <myResourceGroup> \
    --cluster-name <myAKSCluster>

kubectl aks check-apiserver-connectivity --node <myNode>

Kommandot config import hämtar vm-skalningsuppsättningsinformationen för alla noder i klustret. Sedan använder kommandot check-apiserver-connectivity den här informationen för att verifiera nätverksanslutningen mellan API-servern och en angiven nod, särskilt för dess underliggande skalningsuppsättningsinstans.

Obs!

Om kommandots utdata check-apiserver-connectivity innehåller meddelandet Connectivity check: succeeded är nätverksanslutningen obehindrad.

Lösning 1: Åtgärda nätverksprincipen för att ta bort trafikblockering

Om kommandots utdata anger att ett anslutningsfel har uppstått konfigurerar du om nätverksprincipen så att den inte blockerar trafiken i onödan mellan agentnoderna och API-servern.

Orsak 2: En felaktig klientläckor etcd objekt och resulterar i en avmattning i etcd

Ett vanligt problem är att kontinuerligt skapa objekt utan att ta bort oanvända objekt i etcd-databasen. Detta kan orsaka prestandaproblem när etcd hanterar för många objekt (mer än 10 000) av någon typ. En snabb ökning av ändringar i sådana objekt kan också leda till att databasens etcd-storlek (4 gigabyte som standard) överskrids.

Om du vill kontrollera etsningsdatabasanvändningen går du till Diagnostisera och lösa problem i Azure Portal. Kör diagnosverktyget för tillgänglighetsproblem med Etcd genom att söka efter "etcd" i sökrutan. Diagnosverktyget visar användningsuppdelningen och den totala databasstorleken.

Azure Portal skärmbild som visar Etsningstillgänglighetsdiagnos för Azure Kubernetes Service (AKS).

Om du bara vill ha ett snabbt sätt att visa den aktuella storleken på din etcd-databas i byte kör du följande kommando:

kubectl get --raw /metrics | grep -E "etcd_db_total_size_in_bytes|apiserver_storage_size_bytes|apiserver_storage_db_total_size_in_bytes"

Obs!

Måttnamnet i föregående kommando skiljer sig åt för olika Kubernetes-versioner. För Kubernetes 1.25 och tidigare använder du etcd_db_total_size_in_bytes. För Kubernetes 1.26 till 1.28 använder du apiserver_storage_db_total_size_in_bytes.

Lösning 2: Definiera kvoter för att skapa objekt, ta bort objekt eller begränsa objektets livslängd i osv.

Om du vill förhindra att etcd når kapacitet och orsakar driftstopp i klustret kan du begränsa det maximala antalet resurser som skapas. Du kan också sakta ned antalet revisioner som genereras för resursinstanser. Om du vill begränsa antalet objekt som kan skapas kan du definiera objektkvoter.

Om du har identifierat objekt som inte längre används men som tar upp resurser bör du överväga att ta bort dem. Du kan till exempel ta bort slutförda jobb för att frigöra utrymme:

kubectl delete jobs --field-selector status.successful=1

För objekt som stöder automatisk rensning kan du ange TTL-värden (Time to Live) för att begränsa livslängden för dessa objekt. Du kan också märka dina objekt så att du kan massradera alla objekt av en viss typ med hjälp av etikettväljare. Om du upprättar ägarreferenser mellan objekt tas alla beroende objekt bort automatiskt när det överordnade objektet har tagits bort.

Orsak 3: En felaktig klient gör överdrivna LIST- eller PUT-anrop

Om du bedömer att etcd inte är överbelastad med för många objekt kan en klient som gör fel göra för många LIST eller PUT anrop till API-servern.

Lösning 3a: Justera api-anropsmönstret

Överväg att justera klientens API-anropsmönster för att minska trycket på kontrollplanet.

Lösning 3b: Begränsa en klient som överbelastar kontrollplanet

Om du inte kan finjustera klienten kan du använda funktionen Prioritet och Rättvisa i Kubernetes för att begränsa klienten. Den här funktionen kan hjälpa till att bevara kontrollplanets hälsa och förhindra att andra program misslyckas.

Följande procedur visar hur du begränsar en felaktig klients LIST Pods API inställt på fem samtidiga anrop:

  1. Skapa ett FlowSchema som matchar API-anropsmönstret för den felande klienten:

    apiVersion: flowcontrol.apiserver.k8s.io/v1beta2
    kind: FlowSchema
    metadata:
      name: restrict-bad-client
    spec:
      priorityLevelConfiguration:
        name: very-low-priority
      distinguisherMethod:
        type: ByUser
      rules:
      - resourceRules:
        - apiGroups: [""]
          namespaces: ["default"]
          resources: ["pods"]
          verbs: ["list"]
        subjects:
        - kind: ServiceAccount
          serviceAccount:
            name: bad-client-account
            namespace: default 
    
  2. Skapa en konfiguration med lägre prioritet för att begränsa felaktiga API-anrop för klienten:

    apiVersion: flowcontrol.apiserver.k8s.io/v1beta2
    kind: PriorityLevelConfiguration
    metadata:
      name: very-low-priority
    spec:
      limited:
        assuredConcurrencyShares: 5
        limitResponse:
          type: Reject
      type: Limited
    
  3. Observera det begränsade anropet i API-servermåtten.

    kubectl get --raw /metrics | grep "restrict-bad-client"
    

Orsak 4: En anpassad webhook kan orsaka ett dödläge i API-serverpoddar

En anpassad webhook, till exempel Kyverno, kan orsaka ett dödläge i API-serverpoddar.

Kontrollera de händelser som är relaterade till DIN API-server. Du kan se händelsemeddelanden som liknar följande text:

Det uppstod ett internt fel: det gick inte att anropa webhooken "mutate.kyverno.svc-fail": det gick inte att anropa webhook: Post "https://kyverno-system-kyverno-system-svc.kyverno-system.svc:443/mutate/fail?timeout=10s": write unix @->/tunnel-uds/proxysocket: write: broken pipe

I det här exemplet blockerar den verifierande webhooken skapandet av vissa API-serverobjekt. Eftersom det här scenariot kan inträffa under bootstrap-tiden kan API-servern och Konnectivity-poddarna inte skapas. Därför kan webhooken inte ansluta till dessa poddar. Den här händelsesekvensen orsakar dödläget och felmeddelandet.

Lösning 4: Ta bort webhook-konfigurationer

Åtgärda problemet genom att ta bort de verifierande och muterande webhook-konfigurationerna. Om du vill ta bort dessa webhook-konfigurationer i Kyverno läser du felsökningsartikeln för Kyverno.

Ansvarsfriskrivning för tredje part

Microsoft tillhandahåller kontaktinformation från tredje part som hjälper dig att hitta ytterligare information om det här ämnet. Denna kontaktinformation kan ändras utan föregående meddelande. Microsoft garanterar inte att kontaktinformation från tredje part är korrekt.

Ansvarsfriskrivning för information från tredje part

De produkter från andra tillverkare som diskuteras i denna artikel tillverkas oberoende av Microsoft. Produkternas funktion eller tillförlitlighet kan därför inte garanteras.

Kontakta oss för att få hjälp

Om du har frågor eller behöver hjälp skapar du en supportförfrågan eller frågar Azure community support. Du kan också skicka produktfeedback till Azure-feedbackcommunityn.