Risolvere i problemi relativi al server API e agli eventi etcd nei servizi Azure Kubernetes

Questa guida è progettata per consentire di identificare e risolvere eventuali problemi improbabili che potrebbero verificarsi all'interno del server API in distribuzioni di servizi Microsoft Azure Kubernetes di grandi dimensioni.

Microsoft ha testato l'affidabilità e le prestazioni del server API su una scala di 5.000 nodi e 200.000 pod. Il cluster che contiene il server API ha la possibilità di aumentare automaticamente il numero di istanze e distribuire gli obiettivi del livello di servizio Kubernetes.The cluster that contains the API server has the ability to automatically scale out and deliver Kubernetes Service Level Objectives (SLO). Se si verificano latenze o timeout elevati, è probabile che si verifichi una perdita di risorse nella directory distribuita etc (e così via) o che un client in errore abbia chiamate API eccessive.

Prerequisiti

  • Interfaccia della riga di comando di Azure.

  • Strumento Kubernetes kubectl . Per installare kubectl usando l'interfaccia della riga di comando di Azure, eseguire il comando az aks install-cli .

  • Log di diagnostica del servizio Azure Kubernetes (in particolare, eventi kube-audit) abilitati e inviati a un'area di lavoro Log Analytics. Per determinare se i log vengono raccolti usando la modalità diagnostica specifica della risorsa o di Azure, controllare il pannello Impostazioni di diagnostica nella portale di Azure.

  • Livello Standard per i cluster del servizio Azure Kubernetes. Se si usa il livello Gratuito, il server API e così via contengono risorse limitate. I cluster del servizio Azure Kubernetes nel livello gratuito non offrono disponibilità elevata. Questa è spesso la causa radice dei problemi del server API e di etcd.

  • Plug-in kubectl-aks per l'esecuzione di comandi direttamente nei nodi del servizio Azure Kubernetes senza usare il piano di controllo Kubernetes.

Sintomi

La tabella seguente illustra i sintomi comuni degli errori del server API:

Sintomo Descrizione
Timeout dal server API Timeout frequenti che esulano dalle garanzie nel contratto di servizio del server API del servizio Azure Kubernetes. Ad esempio, kubectl il timeout dei comandi.
Latenze elevate Latenze elevate che rendono i contratti di servizio Kubernetes non riusciti. Ad esempio, il kubectl comando richiede più di 30 secondi per elencare i pod.
Pod del server API in CrashLoopbackOff stato o in caso di errori di chiamata del webhook Verificare di non avere alcun webhook di ammissione personalizzato (ad esempio il motore dei criteri Kyverno ) che blocca le chiamate al server API.

Elenco di controllo per la risoluzione dei problemi

Se si verificano tempi di latenza elevati, seguire questa procedura per individuare il client danneggiato e i tipi di chiamate API che hanno esito negativo.

Passaggio 1: Identificare i principali agenti utente in base al numero di richieste

Per identificare i client che generano il maggior numero di richieste (e potenzialmente la maggior parte del carico del server API), eseguire una query simile al codice seguente. La query seguente elenca i primi 10 agenti utente in base al numero di richieste del server API inviate.

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

Nota

Se la query non restituisce risultati, è possibile che sia stata selezionata la tabella errata per eseguire query sui log di diagnostica. In modalità specifica della risorsa, i dati vengono scritti in singole tabelle a seconda della categoria della risorsa. I log di diagnostica vengono scritti nella AKSAudit tabella. In modalità diagnostica di Azure tutti i dati vengono scritti nella AzureDiagnostics tabella. Per altre informazioni, vedere Log delle risorse di Azure.

Anche se è utile sapere quali client generano il volume di richieste più alto, il volume di richieste elevato da solo potrebbe non essere motivo di preoccupazione. Un indicatore migliore del carico effettivo generato da ogni client nel server API è la latenza di risposta eseguita.

Passaggio 2: Identificare e tracciare la latenza media delle richieste del server API per agente utente

Per identificare la latenza media delle richieste del server API per agente utente come tracciato in un grafico temporale, eseguire la query seguente:

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

Questa query è un completamento della query nella sezione "Identificare i principali agenti utente in base al numero di richieste". Potrebbe fornire maggiori informazioni dettagliate sul carico effettivo generato da ogni agente utente nel tempo.

Consiglio

Analizzando questi dati, è possibile identificare modelli e anomalie che possono indicare problemi nel cluster o nelle applicazioni del servizio Azure Kubernetes. Ad esempio, si potrebbe notare che un particolare utente sta riscontrando una latenza elevata. Questo scenario può indicare il tipo di chiamate API che causano un carico eccessivo nel server API o in altri casi.

Passaggio 3: Identificare le chiamate API non valido per un determinato agente utente

Eseguire la query seguente per tabulare la latenza del 99° percentile (P99) delle chiamate API tra tipi di risorse diversi per un determinato client:

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

I risultati di questa query possono essere utili per identificare i tipi di chiamate API che hanno esito negativo nei contratti di servizio Kubernetes upstream. Nella maggior parte dei casi, un client in errore potrebbe effettuare troppe LIST chiamate su un set di oggetti o oggetti di grandi dimensioni. Sfortunatamente, non sono disponibili limiti di scalabilità rigidi per guidare gli utenti sulla scalabilità del server API. I limiti di scalabilità del server API o etcd dipendono da vari fattori illustrati nelle soglie di scalabilità di Kubernetes.

Causa 1: una regola di rete blocca il traffico dai nodi dell'agente al server API

Una regola di rete può bloccare il traffico tra i nodi dell'agente e il server API.

Per verificare se i criteri di rete non configurati correttamente bloccano la comunicazione tra il server API e i nodi dell'agente, eseguire i comandi kubectl-aks seguenti:

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

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

Il comando config import recupera le informazioni sul set di scalabilità di macchine virtuali per tutti i nodi del cluster. Il comando check-apiserver-connectivity usa quindi queste informazioni per verificare la connettività di rete tra il server API e un nodo specificato, in particolare per l'istanza del set di scalabilità sottostante.

Nota

Se l'output del check-apiserver-connectivity comando contiene il Connectivity check: succeeded messaggio, la connettività di rete non è compressa.

Soluzione 1: correggere i criteri di rete per rimuovere il blocco del traffico

Se l'output del comando indica che si è verificato un errore di connessione, riconfigurare i criteri di rete in modo che non blocchi inutilmente il traffico tra i nodi dell'agente e il server API.

Causa 2: un client offensivo perde oggetti etcd e si traduce in un rallentamento di etcd

Un problema comune è la creazione continua di oggetti senza eliminare quelli inutilizzati nel database etcd. Ciò può causare problemi di prestazioni quando etcd gestisce troppi oggetti (più di 10.000) di qualsiasi tipo. Un rapido aumento delle modifiche apportate a tali oggetti potrebbe anche causare il superamento delle dimensioni del database etcd (4 gigabyte per impostazione predefinita).

Per controllare l'utilizzo del database etcd, passare a Diagnosticare e risolvere i problemi nel portale di Azure. Eseguire lo strumento di diagnosi dei problemi di disponibilità etcd cercando "etcd" nella casella di ricerca. Lo strumento di diagnosi mostra la suddivisione dell'utilizzo e le dimensioni totali del database.

portale di Azure screenshot che mostra la diagnosi di disponibilità etcd per servizio Azure Kubernetes ( Servizio Azure Kubernetes).

Per visualizzare rapidamente le dimensioni correnti del database etcd in byte, eseguire il comando seguente:

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

Nota

Il nome della metrica nel comando precedente è diverso per le diverse versioni di Kubernetes. Per Kubernetes 1.25 e versioni precedenti, usare etcd_db_total_size_in_bytes. Per Kubernetes da 1.26 a 1.28, usare apiserver_storage_db_total_size_in_bytes.

Soluzione 2: definire quote per la creazione di oggetti, eliminare oggetti o limitare la durata degli oggetti in etcd

Per impedire a etcd di raggiungere la capacità e causare tempi di inattività del cluster, è possibile limitare il numero massimo di risorse create. È anche possibile rallentare il numero di revisioni generate per le istanze delle risorse. Per limitare il numero di oggetti che è possibile creare, è possibile definire quote di oggetti.

Se sono stati identificati oggetti che non sono più in uso ma che utilizzano risorse, provare a eliminarli. Ad esempio, è possibile eliminare i processi completati per liberare spazio:

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

Per gli oggetti che supportano la pulizia automatica, è possibile impostare i valori TTL (Time to Live) per limitare la durata di questi oggetti. È anche possibile etichettare gli oggetti in modo da poter eliminare in blocco tutti gli oggetti di un tipo specifico usando selettori di etichetta. Se si stabiliscono riferimenti di proprietario tra gli oggetti, tutti gli oggetti dipendenti vengono eliminati automaticamente dopo l'eliminazione dell'oggetto padre.

Causa 3: un client che causa un'violazione effettua chiamate LIST o PUT eccessive

Se si determina che etcd non è sovraccarico di troppi oggetti, un client in errore potrebbe effettuare troppe LIST chiamate o PUT al server API.

Soluzione 3a: ottimizzare il modello di chiamata API

Valutare la possibilità di ottimizzare il modello di chiamata API del client per ridurre la pressione sul piano di controllo.

Soluzione 3b: Limitare un client che sta sovraccaricando il piano di controllo

Se non è possibile ottimizzare il client, è possibile usare la funzionalità Priorità ed equità in Kubernetes per limitare il client. Questa funzionalità consente di mantenere l'integrità del piano di controllo e di evitare il fallimento di altre applicazioni.

La procedura seguente illustra come limitare l'API LIST Pods di un client in errore impostata su cinque chiamate simultanee:

  1. Create un FlowSchema che corrisponde al modello di chiamata API del client che causa l'errore:

    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. Create una configurazione con priorità inferiore per limitare le chiamate API non valido del client:

    apiVersion: flowcontrol.apiserver.k8s.io/v1beta2
    kind: PriorityLevelConfiguration
    metadata:
      name: very-low-priority
    spec:
      limited:
        assuredConcurrencyShares: 5
        limitResponse:
          type: Reject
      type: Limited
    
  3. Osservare la chiamata limitata nelle metriche del server API.

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

Causa 4: un webhook personalizzato potrebbe causare un deadlock nei pod del server API

Un webhook personalizzato, ad esempio Kyverno, potrebbe causare un deadlock all'interno dei pod del server API.

Controllare gli eventi correlati al server API. È possibile che vengano visualizzati messaggi di evento simili al testo seguente:

Errore interno: impossibile chiamare il webhook "mutate.kyverno.svc-fail": impossibile chiamare il webhook: Post "https://kyverno-system-kyverno-system-svc.kyverno-system.svc:443/mutate/fail?timeout=10s": write unix @->/tunnel-uds/proxysocket: write: broken pipe

In questo esempio, il webhook di convalida blocca la creazione di alcuni oggetti server API. Poiché questo scenario potrebbe verificarsi durante il bootstrap, non è possibile creare il server API e i pod Konnectivity. Pertanto, il webhook non può connettersi a tali pod. Questa sequenza di eventi causa il deadlock e il messaggio di errore.

Soluzione 4: Eliminare le configurazioni del webhook

Per risolvere questo problema, eliminare le configurazioni webhook di convalida e modifica. Per eliminare queste configurazioni di webhook in Kyverno, vedere l'articolo sulla risoluzione dei problemi di Kyverno.

Dichiarazione di non responsabilità di contatti di terze parti

Microsoft fornisce informazioni di contatto di terze parti per aiutarti a trovare ulteriori informazioni su questo argomento. Queste informazioni di contatto sono soggette a modifica senza preavviso. Microsoft non garantisce l'accuratezza delle informazioni di contatto di terze parti.

Dichiarazione di non responsabilità sulle informazioni di terze parti

I prodotti di terzi citati in questo articolo sono prodotti da società indipendenti da Microsoft. Microsoft non rilascia alcuna garanzia implicita o esplicita relativa alle prestazioni o all'affidabilità di tali prodotti

Contattaci per ricevere assistenza

In caso di domande o bisogno di assistenza, creare una richiesta di supporto tecnico oppure formula una domanda nel Supporto della community di Azure. È possibile anche inviare un feedback sul prodotto al feedback della community di Azure.