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:
- Controlla lo Stato: Usa
kubectl get podsper identificare lo stato di fallimento (Pending,CrashLoopBackOff,ImagePullBackOff, ecc.). - Ottieni Contesto ed Eventi: Usa
kubectl describe podper capire perché è avvenuta la transizione di stato (es., scheduler fallito, probe di liveness fallito, volume non montato). - Ispeziona l'Output dell'Applicazione: Usa
kubectl logsper 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.