Padroneggiare kubectl logs e describe per un Debug Efficiente dei Pod

Questa guida fornisce tecniche esperte per padroneggiare i comandi essenziali di debugging di Kubernetes: `kubectl logs` e `kubectl describe`. Impara i flag critici, come `-f`, `--tail`, `-c` e `--previous`, necessari per una risoluzione efficiente dei problemi. Spieghiamo in dettaglio come interpretare la sezione cruciale 'Eventi' in `describe` per diagnosticare problemi di scheduling e configurazione, e come usare `logs` per estrarre errori di runtime da pod in crash o multi-contenitore, accelerando il tuo flusso di lavoro di debugging.

Padroneggiare kubectl logs e describe per un Debug Efficiente dei Pod

Quando un pod Kubernetes fallisce, kubectl describe e kubectl logs di solito ti dicono dove guardare dopo. describe spiega cosa Kubernetes ha tentato di fare. logs mostra cosa il contenitore ha scritto prima, durante o dopo il fallimento.

Questi comandi forniscono viste diverse, ma complementari, dello stato e della cronologia di un Pod Kubernetes. kubectl describe fornisce i metadati del Pod, lo stato, le variabili d'ambiente e, cosa cruciale, una cronologia degli eventi di sistema. kubectl logs fornisce i flussi di output standard (stdout) e errore standard (stderr) generati dall'applicazione containerizzata stessa.

Il trucco è usarli nell'ordine giusto. Se il pod non è mai stato schedulato, i logs non aiuteranno. Se il pod si avvia e termina, gli eventi potrebbero dirti solo che è andato in crash; i log dell'applicazione di solito spiegano perché.


Il Flusso di Lavoro di Debugging in Tre Passi

Prima di immergerci nei comandi, è utile comprendere il tipico flusso di lavoro di debugging:

  1. Controlla lo Stato: Usa kubectl get pods per identificare lo stato di fallimento (Pending, CrashLoopBackOff, ImagePullBackOff, ecc.).
  2. Ottieni Contesto ed Eventi: Usa kubectl describe pod per capire perché è avvenuta la transizione di stato (es., scheduler fallito, probe di liveness fallito, volume non montato).
  3. Ispeziona l'Output dell'Applicazione: Usa kubectl logs per esaminare il comportamento runtime dell'applicazione (es., errori di configurazione, fallimenti di connessione al database, stack trace).

1. kubectl describe: Lo Strumento di Triage di Sistema

kubectl describe è il primo comando che dovresti eseguire quando un Pod si comporta male. Non mostra l'output dell'applicazione, ma fornisce i metadati critici e la cronologia che Kubernetes stesso ha registrato sul Pod.

Utilizzo Base

L'utilizzo fondamentale richiede solo il nome del Pod:

kubectl describe pod my-failing-app-xyz789

Usa esplicitamente i namespace quando non sei nel namespace predefinito:

kubectl describe pod my-failing-app-xyz789 -n payments

Se conosci solo il deployment o l'etichetta, trova prima il pod:

kubectl get pods -n payments -l app=checkout -o wide

Sezioni Chiave nell'Output

Quando esamini l'output di describe, concentrati su queste sezioni critiche:

A. Stato e Condizione

Guarda il campo Status in alto, poi esamina gli stati dei singoli contenitori all'interno del Pod. Questo ti dice se il contenitore è Running, Waiting o Terminated, e fornisce il motivo per quello stato.

Campo Stato/Motivo Comune Significato
Status Pending Il Pod è in attesa di essere schedulato o ha risorse mancanti.
Reason ContainerCreating Il runtime del contenitore sta scaricando l'immagine o eseguendo la configurazione.
State Waiting / Reason: CrashLoopBackOff Il contenitore si è avviato e terminato ripetutamente.
State Terminated / Exit Code Il contenitore ha terminato l'esecuzione. Codici di uscita diversi da zero di solito indicano errori.

B. Configurazione del Contenitore

Questa sezione verifica che le tue variabili d'ambiente, le richieste/limiti di risorse, i montaggi di volume e i probe di liveness/readiness siano definiti correttamente, corrispondenti al manifest che hai applicato.

C. La Sezione Events (Cruciale)

La sezione Events, situata in fondo all'output, è probabilmente la parte più preziosa. Fornisce un registro cronologico di ciò che il piano di controllo di Kubernetes ha fatto al e per il Pod, inclusi avvisi ed errori.

Errori Comuni Rivelati dagli Events:

  • Problemi di Scheduling: Warning FailedScheduling: Indica che lo scheduler non ha trovato un nodo adatto (es., a causa di vincoli di risorse, taint del nodo o regole di affinità).
  • Fallimenti nel Pull dell'Immagine: Warning Failed: ImagePullBackOff: Indica che il nome dell'immagine è sbagliato, il tag non esiste o a Kubernetes mancano le credenziali per eseguire il pull da un registro privato.
  • Errori di Volume: Warning FailedAttachVolume: Indica problemi nel collegare l'archiviazione esterna.

Suggerimento: Se la sezione Events è pulita e il contenitore è stato avviato, il problema è spesso legato all'applicazione: una variabile d'ambiente errata, una migrazione fallita, un secret mancante, una dipendenza irraggiungibile o un processo che termina immediatamente.

2. kubectl logs: Ispezione dell'Output dell'Applicazione

Se describe mostra che il Pod è stato schedulato con successo e i contenitori hanno tentato di eseguire, il passo successivo è controllare i flussi di output standard usando kubectl logs.

Recupero Base dei Log e Streaming in Tempo Reale

Per visualizzare i log correnti per il contenitore principale in un Pod:

# Recupera tutti i log fino al momento corrente
kubectl logs my-failing-app-xyz789

# Stream dei log in tempo reale (utile per monitorare l'avvio)
kubectl logs -f my-failing-app-xyz789

Gestione di Pod Multi-Contenitore

Per pod che utilizzano il pattern Sidecar o altri progetti multi-contenitore, devi specificare di quale contenitore vuoi visualizzare i log usando il flag -c o --container.

# Visualizza i log per il contenitore 'sidecar-proxy' all'interno del Pod
kubectl logs my-multi-container-pod -c sidecar-proxy

# Stream dei log per il contenitore dell'applicazione principale
kubectl logs -f my-multi-container-pod -c main-app

Debugging di Contenitori che Riavvia (--previous)

Uno degli scenari di debugging più comuni è lo stato CrashLoopBackOff. Quando un contenitore si riavvia, kubectl logs mostra solo l'output del tentativo corrente (fallito), che spesso contiene solo il messaggio di avvio prima del crash.

Per visualizzare i log dall'istanza precedente e terminata—che contiene l'errore effettivo che ha causato l'uscita—usa il flag --previous (-p):

# Visualizza i log dall'istanza del contenitore precedente e crashato
kubectl logs my-crashloop-pod --previous

# Combina con la specifica del contenitore se necessario
kubectl logs my-crashloop-pod -c worker --previous

Limitazione dell'Output

Per log ad alto volume, recuperare l'intera cronologia può essere lento o opprimente. Usa --tail per limitare l'output alle ultime N righe.

# Mostra solo le ultime 50 righe dei log del contenitore
kubectl logs my-high-traffic-app --tail=50

Puoi anche aggiungere timestamp e una finestra temporale:

kubectl logs my-high-traffic-app --tail=100 --timestamps
kubectl logs my-high-traffic-app --since=10m

Per un deployment, le versioni recenti di kubectl possono recuperare i log tramite il nome del carico di lavoro:

kubectl logs deploy/checkout-api -n payments --tail=100

Quando è troppo ampio, usa un selettore di etichette:

kubectl logs -n payments -l app=checkout --all-containers=true --tail=50

3. Combinare le Tecniche per una Diagnosi Avanzata

Un debugging efficace spesso implica passare rapidamente tra describe e comandi logs specifici.

Caso di Studio: Diagnosi di un Fallimento del Probe di Liveness

Immagina un Pod bloccato in Running ma che occasionalmente si riavvia, causando interruzioni.

Passo 1: Controlla describe per la vista di sistema.

kubectl describe pod web-server-dpl-abc

L'output mostra nella sezione Events:

Type     Reason      Age   From               Message
----     ------      ----  ----               -------
Warning  Unhealthy   2s    kubelet, node-a01  Liveness probe failed: HTTP GET http://10.42.0.5:8080/health failed: 503 Service Unavailable

Conclusione dal Passo 1: Il contenitore è in esecuzione, ma il probe di Liveness sta fallendo con un errore 503, causando il riavvio del contenitore da parte di Kubernetes.

Passo 2: Controlla i logs per il contesto dell'applicazione.

Ora, indaga sul perché l'applicazione sta restituendo uno stato 503, che è un fallimento a livello di applicazione.

kubectl logs web-server-dpl-abc --tail=200

L'output del log rivela:

2023-10-26 14:01:15 ERROR Database connection failure: Timeout connecting to DB instance 192.168.1.10

Conclusione Finale: Il Pod si sta riavviando a causa di un probe di Liveness fallito, e il probe sta fallendo perché l'applicazione non può connettersi al database. Il problema è di rete esterna o di configurazione del database, non del contenitore stesso.

Caso di Studio: Pod in Pending Senza Log

Un pod in Pending spesso non ha log di contenitore utili perché nessun contenitore è ancora stato avviato.

kubectl get pod report-worker-6f9c7b9b7d-f2q8m -n analytics

Output:

NAME                                  READY   STATUS    RESTARTS   AGE
report-worker-6f9c7b9b7d-f2q8m        0/1     Pending   0          4m

Vai direttamente a describe:

kubectl describe pod report-worker-6f9c7b9b7d-f2q8m -n analytics

Gli eventi potrebbero mostrare:

Warning  FailedScheduling  default-scheduler  0/6 nodes are available: 6 Insufficient memory.

Questo non è un bug dell'applicazione. Il pod sta chiedendo più memoria di quanta lo scheduler possa allocare. Il passo successivo è ispezionare le richieste del deployment, la capacità del cluster, i taint dei nodi e il comportamento dell'autoscaler:

kubectl get deploy report-worker -n analytics -o yaml
kubectl top nodes

Caso di Studio: ImagePullBackOff

Per ImagePullBackOff, i log sono solitamente vuoti perché l'immagine del contenitore non è mai stata avviata. describe fornisce l'errore utile:

kubectl describe pod api-7dfb9c8b7f-bd2p9 -n staging

I messaggi di evento comuni includono un tag dell'immagine che non esiste, un fallimento di autenticazione contro un registro privato o un problema DNS/rete per raggiungere il registro. La soluzione potrebbe essere semplice come correggere il tag:

kubectl set image deploy/api api=registry.example.com/api:2026-05-24 -n staging

Oppure potrebbe richiedere il controllo del segreto per il pull dell'immagine:

kubectl get secret regcred -n staging
kubectl describe serviceaccount default -n staging

Caso di Studio: Pod Multi-Contenitore con un'App Silenziosa

I sidecar possono nascondere il segnale se guardi il contenitore sbagliato. Prima elenca i nomi dei contenitori:

kubectl get pod checkout-84f7c9d7bf-px5mx -n payments \
  -o jsonpath='{.spec.containers[*].name}{"\n"}'

Poi ispeziona ciascuno deliberatamente:

kubectl logs checkout-84f7c9d7bf-px5mx -n payments -c checkout --tail=100
kubectl logs checkout-84f7c9d7bf-px5mx -n payments -c envoy --tail=100

Se i log dell'app sono silenziosi ma i log del proxy mostrano fallimenti di connessione a monte, il pod potrebbe essere sano dal punto di vista di Kubernetes mentre il traffico fallisce ancora attraverso la configurazione del service mesh o del proxy.

Best Practice e Avvertenze

Pratica Comando Motivazione
Controlla sempre i log precedenti kubectl logs --previous Necessario per diagnosticare CrashLoopBackOff. L'errore critico è quasi sempre nell'esecuzione precedente.
Specifica i contenitori kubectl logs -c <nome> Evita ambiguità nei Pod multi-contenitore e previene il recupero di log da sidecar non desiderati.
Usa le etichette per operazioni bulk kubectl logs -l app=frontend -f Permette lo streaming di log da più Pod che corrispondono a un selettore simultaneamente (utile per aggiornamenti progressivi).
Avvertenza: Rotazione dei Log N/A I nodi Kubernetes eseguono la rotazione dei log. I log più vecchi della politica di conservazione configurata del nodo (spesso pochi giorni o basata sulla dimensione) verranno eliminati e non saranno disponibili tramite kubectl logs. Usa una soluzione di logging centralizzata esterna (es., Fluentd, Loki, Elastic Stack) per la conservazione a lungo termine.

Cosa Questi Comandi Non Possono Dire

kubectl logs mostra solo stdout e stderr del contenitore come conservati dal nodo. Se l'applicazione scrive su un file all'interno del contenitore, kubectl logs potrebbe non mostrare nulla. Questo è un problema di progettazione del logging, non un problema di kubectl.

kubectl describe mostra lo stato dell'oggetto Kubernetes e gli eventi recenti, ma gli eventi non sono log di audit permanenti. Gli eventi vecchi scadono. Per indagini di lunga durata, copia l'output rilevante nelle note dell'incidente.

Nessuno dei due comandi sostituisce le metriche. Un pod può essere in esecuzione e registrare normalmente mentre il throttling della CPU, la pressione della memoria o la latenza a valle causano problemi visibili all'utente. Dopo describe e logs, i comandi successivi sono spesso:

kubectl top pod -n payments
kubectl top node
kubectl get events -n payments --sort-by=.lastTimestamp

Usa describe prima quando Kubernetes non ha potuto creare o mantenere il pod in esecuzione. Usa logs prima quando il pod è in esecuzione ma l'applicazione si comporta male. Passa dall'uno all'altro finché non riesci a separare i sintomi della piattaforma dai sintomi dell'applicazione.

Un Flusso di Debugging Che Puoi Riutilizzare

Quando sei sotto pressione, usa lo stesso flusso ogni volta:

kubectl get pod <pod> -n <namespace> -o wide
kubectl describe pod <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --all-containers=true --tail=100
kubectl logs <pod> -n <namespace> --all-containers=true --previous --tail=100
kubectl get events -n <namespace> --sort-by=.lastTimestamp

L'ordine è importante. get pod -o wide ti dice il nodo, l'IP del pod, il conteggio dei riavvii e l'età. describe ti dice i dettagli di scheduling, immagine, volume, probe e stato del contenitore. I log correnti mostrano cosa sta facendo il contenitore in esecuzione ora. I log precedenti catturano il crash che è già avvenuto. Gli eventi mostrano se lo stesso problema sta accadendo in tutto il namespace.

Per i deployment, aggiungi un controllo del rollout:

kubectl rollout status deploy/<nome> -n <namespace>
kubectl describe deploy/<nome> -n <namespace>
kubectl get rs -n <namespace> -l app=<etichetta>

A volte il pod che stai debugando proviene da un vecchio ReplicaSet durante un rollout. Se risolvi il deployment ma continui a leggere i log da un vecchio pod in terminazione, puoi inseguire il problema sbagliato per mezz'ora.

Leggere Correttamente i Riavvi

La colonna RESTARTS è un indizio, non una diagnosi. Un conteggio di riavvii pari a 1 dopo un drenaggio del nodo potrebbe essere innocuo. Un conteggio di riavvii che aumenta ogni minuto è un fallimento in corso. Usa describe per controllare l'ultimo stato:

Last State:     Terminated
  Reason:       Error
  Exit Code:    1
  Started:      Sun, 24 May 2026 10:14:02 +0800
  Finished:     Sun, 24 May 2026 10:14:07 +0800

Un codice di uscita 1 di solito significa che il processo è terminato con un errore generale dell'applicazione. 137 spesso significa che il processo è stato ucciso, comunemente perché ha superato i limiti di memoria, anche se dovresti confermare con il campo Reason e il contesto del nodo/runtime del contenitore. 143 appare spesso quando un processo riceve SIGTERM durante la terminazione normale. Non trattare ogni codice di uscita diverso da zero come lo stesso tipo di fallimento.

Quando si sospetta la memoria, cerca:

Reason:       OOMKilled
Exit Code:    137

Poi confronta il limite del contenitore con l'utilizzo effettivo:

kubectl describe pod <pod> -n <namespace> | rg -A5 'Limits|Requests'
kubectl top pod <pod> -n <namespace>

Se metrics-server non è installato, kubectl top non funzionerà. In tal caso, usa il sistema di metriche della tua piattaforma o gli strumenti a livello di nodo.