Risoluzione dei Problemi di Connettività Kubernetes: Utilizzare exec e port-forward in Modo Efficace
Risolvi con sicurezza i problemi di connettività Kubernetes e le problematiche interne delle applicazioni. Questa guida fornisce esempi pratici di utilizzo di `kubectl exec` per eseguire comandi all'interno dei container e `kubectl port-forward` per accedere in modo sicuro ai servizi dal tuo computer locale. Impara a diagnosticare problemi di rete, ispezionare configurazioni e ottenere approfondimenti sul comportamento della tua applicazione all'interno del cluster.
Risoluzione dei Problemi di Connettività Kubernetes: Utilizzare exec e port-forward in Modo Efficace
Quando un servizio Kubernetes va in timeout, di solito devi rispondere a una semplice domanda prima di poter risolvere qualsiasi cosa: dove smette di funzionare la connessione? kubectl exec ti permette di testare dall'interno del cluster, vicino all'applicazione. kubectl port-forward ti permette di riportare un pod o un servizio sul tuo laptop senza modificare un Ingress, LoadBalancer, regole firewall o record DNS.
Usati insieme, questi due comandi ti aiutano a evitare supposizioni. Puoi testare se l'app è in ascolto, se il DNS del cluster funziona, se un Service punta ai pod corretti e se il problema risiede nella rete Kubernetes o nell'applicazione stessa.
Comprendere kubectl exec
Il comando kubectl exec ti permette di eseguire comandi all'interno di un container in esecuzione in un pod. Questo è estremamente utile per ispezionare log, controllare configurazioni ed eseguire strumenti diagnostici direttamente dove vive la tua applicazione.
Usalo con cautela in produzione. Stai eseguendo un comando all'interno di un container di carico di lavoro reale. Un innocuo env, cat, curl o ss è normale. Installare pacchetti, modificare file o eseguire diagnostiche costose all'interno di un pod live può nascondere il problema originale o crearne uno nuovo.
Sintassi di Base
La sintassi fondamentale per kubectl exec è:
kubectl exec <nome-pod> -- <comando> [argomenti...]
<nome-pod>: Il nome del pod in cui vuoi eseguire un comando.--: Questo separatore è cruciale. Distingue tra i flag dikubectle il comando che vuoi eseguire all'interno del container.<comando>: Il comando da eseguire all'interno del container (es.,ls,cat,ping).[argomenti...]: Eventuali argomenti per il comando.
Accesso Interattivo alla Shell
Uno degli usi più comuni di kubectl exec è ottenere una shell interattiva (come bash o sh) all'interno di un container. Questo ti permette di esplorare il filesystem del container ed eseguire più comandi.
Per ottenere una shell interattiva:
kubectl exec -it <nome-pod> -- /bin/bash
-i(o--stdin): Mantiene lo stdin aperto anche se non collegato.-t(o--tty): Alloca un pseudo-TTY, necessario per sessioni di shell interattive.
Esempio: Accesso a una shell bash in un pod chiamato my-app-pod:
kubectl exec -it my-app-pod -- /bin/bash
Una volta dentro, puoi usare i comandi Linux standard. Per uscire dalla shell, digita exit o premi Ctrl+D. Se /bin/bash non è presente, prova /bin/sh; molte immagini piccole non includono Bash.
Esecuzione di un Singolo Comando
Puoi anche eseguire un singolo comando senza una shell interattiva. Questo è utile per controlli rapidi o script.
Esempio: Controllo dei file nella directory /app di my-app-pod:
kubectl exec my-app-pod -- ls /app
Esempio: Visualizzazione del contenuto di un file di configurazione config.yaml:
kubectl exec my-app-pod -- cat /etc/my-app/config.yaml
Specificare un Container all'interno di un Pod
Se il tuo pod ha più container, devi specificare in quale container eseguire il comando usando il flag -c.
kubectl exec <nome-pod> -c <nome-container> -- <comando>
Esempio: Esecuzione di env in sidecar-container di multi-container-pod:
kubectl exec multi-container-pod -c sidecar-container -- env
Comprendere kubectl port-forward
Il comando kubectl port-forward ti permette di stabilire un tunnel sicuro dal tuo computer locale a un pod o servizio specifico nel tuo cluster Kubernetes. Questo è prezioso per eseguire il debug di applicazioni non esposte esternamente, accedere a database o testare API interne.
Non è un percorso di traffico di produzione. È un tunnel di debug sulla tua connessione API Kubernetes. Se la connessione al server API cade, anche il tuo tunnel locale cade.
Sintassi di Base
La sintassi generale è:
kubectl port-forward <nome-pod> <porta-locale>:<porta-remota>
<nome-pod>: Il nome del pod a cui vuoi connetterti.<porta-locale>: La porta sul tuo computer locale che rimarrà in ascolto per le connessioni.<porta-remota>: La porta sul pod che riceverà il traffico inoltrato.
Esempio: Inoltro della porta locale 8080 alla porta 80 di my-app-pod:
kubectl port-forward my-app-pod 8080:80
Una volta che questo comando è in esecuzione, puoi accedere alla tua applicazione navigando su http://localhost:8080 nel tuo browser web o usando strumenti come curl sul tuo computer locale.
Inoltro a un Servizio
Puoi anche inoltrare il traffico a un Servizio Kubernetes invece che a un pod specifico. kubectl selezionerà automaticamente un pod che supporta quel servizio.
kubectl port-forward service/<nome-servizio> <porta-locale>:<porta-servizio>
Esempio: Inoltro della porta locale 3000 alla porta 80 del servizio my-service:
kubectl port-forward service/my-service 3000:80
Quando inoltri a un Servizio, ricorda che kubectl sceglie un pod di supporto. Se solo una replica è rotta, l'inoltro a livello di servizio potrebbe non rilevarla. Ad esempio, un Deployment con tre pod può avere due pod sani e un pod con una configurazione errata. Inoltrare a service/my-service potrebbe selezionare un pod sano e far sembrare il servizio funzionante. Quando sospetti un problema specifico di una replica, inoltra al nome esatto del pod.
Inoltro a Deployment o StatefulSet
Allo stesso modo, puoi inoltrare a Deployment o StatefulSet. kubectl selezionerà uno dei pod gestiti dalla risorsa specificata.
kubectl port-forward deployment/<nome-deployment> <porta-locale>:<porta-container>
kubectl port-forward statefulset/<nome-statefulset> <porta-locale>:<porta-container>
Binding a un Indirizzo Specifico
Per impostazione predefinita, port-forward si lega a localhost. Puoi specificare un indirizzo locale diverso usando il flag --address.
kubectl port-forward --address 127.0.0.1 <nome-pod> <porta-locale>:<porta-remota>
Inoltro di Più Porte
kubectl port-forward può inoltrare più porte contemporaneamente.
kubectl port-forward my-app-pod 8080:80 9090:90
Questo comando inoltra la porta locale 8080 alla porta del pod 80 e la porta locale 9090 alla porta del pod 90.
Scenari Comuni di Risoluzione dei Problemi e Soluzioni
Scenario 1: L'applicazione non risponde, ma il pod sembra sano.
- Problema: Il pod è in esecuzione, ma le richieste al suo servizio falliscono o vanno in timeout. L'applicazione potrebbe avere problemi di configurazione interna o essere bloccata.
- Soluzione con
kubectl exec:- Ottieni una shell interattiva nel pod:
kubectl exec -it <nome-pod> -- /bin/bash - All'interno della shell, controlla i log dell'applicazione (es.,
tail -f /var/log/myapp.log). - Verifica i file di configurazione interna dell'applicazione.
- Controlla la connettività di rete dal pod ad altri servizi usando
pingocurl(se installati).
- Ottieni una shell interattiva nel pod:
- Soluzione con
kubectl port-forward:- Inoltra una porta alla porta di ascolto dell'applicazione:
kubectl port-forward <nome-pod> 8080:<porta-app> - Prova ad accedere all'applicazione localmente tramite
http://localhost:8080. Questo aiuta a determinare se il problema è con la scoperta del servizio Kubernetes o l'ingress, o se l'applicazione stessa non risponde.
- Inoltra una porta alla porta di ascolto dell'applicazione:
Se il port-forward funziona ma l'URL del servizio normale fallisce, ispeziona il selettore del Servizio e gli endpoint:
kubectl get service <nome-servizio> -n <namespace> -o yaml
kubectl get endpoints <nome-servizio> -n <namespace>
kubectl get pods -n <namespace> --show-labels
Un errore molto comune è una mancata corrispondenza delle etichette. I pod sono sani, il servizio esiste, ma il selettore non corrisponde alle etichette dei pod, quindi il Servizio non ha endpoint.
Scenario 2: Necessità di eseguire il debug di un database in esecuzione in un pod.
- Problema: Devi connettere il tuo client di database locale a un database in esecuzione all'interno di un pod Kubernetes per ispezionare i dati o eseguire query.
- Soluzione con
kubectl port-forward:- Identifica il pod che esegue il database e la sua porta (es.,
mysql-pod, porta3306). - Inoltra una porta locale alla porta del database:
kubectl port-forward mysql-pod 3306:3306 - Configura il tuo client di database locale per connettersi a
localhost:3306usando le credenziali appropriate del database.
- Identifica il pod che esegue il database e la sua porta (es.,
Scenario 3: Diagnosi di problemi di risoluzione DNS all'interno di un pod.
- Problema: Un'applicazione all'interno di un pod non riesce a raggiungere altri servizi tramite i loro nomi di servizio, suggerendo un problema DNS.
- Soluzione con
kubectl exec:- Ottieni una shell interattiva nel pod:
kubectl exec -it <nome-pod> -- /bin/bash - All'interno della shell, prova a risolvere un nome di servizio noto:
nslookup <nome-servizio>.<namespace>.svc.cluster.localodig <nome-servizio>.<namespace>.svc.cluster.local. - Controlla il contenuto di
/etc/resolv.confper assicurarti che la configurazione DNS del cluster sia corretta all'interno del pod.
- Ottieni una shell interattiva nel pod:
Se l'immagine non include nslookup, dig o curl, usa un pod di debug temporaneo nello stesso namespace:
kubectl run net-debug -n <namespace> --rm -it --image=curlimages/curl -- sh
Da lì, testa lo stesso nome di servizio utilizzato dalla tua applicazione. Questo aiuta a separare "la mia immagine dell'applicazione non ha strumenti" da "il DNS del cluster è rotto".
Scenario 4: Port-forward si connette, poi si chiude immediatamente.
- Problema:
kubectl port-forwardstampa un messaggio di inoltro, ma la connessione si chiude quando apri il browser o eseguicurl. - Cause probabili: Il processo di destinazione non è in ascolto sulla porta remota, l'applicazione si lega solo a
127.0.0.1all'interno del container, o il pod si riavvia mentre il tunnel è aperto. - Controlli:
kubectl exec <nome-pod> -n <namespace> -- ss -lntp kubectl get pod <nome-pod> -n <namespace> -w kubectl logs <nome-pod> -n <namespace> --tail=100
Se il processo è in ascolto sulla porta 8080 ma inoltri alla 80, il tunnel stesso è a posto; la destinazione è sbagliata. Se il pod si riavvia mentre testi, risolvi la causa del riavvio prima di inseguire problemi di rete.
Scenario 5: Il servizio funziona da un pod ma non da un altro.
- Problema: Un backend può raggiungere Redis, ma un pod worker in un altro namespace non può.
- Controlli con
exec:kubectl exec <pod-sorgente> -n <namespace-sorgente> -- curl -v http://<servizio>.<namespace-destinazione>.svc.cluster.local:<porta> kubectl exec <pod-sorgente> -n <namespace-sorgente> -- cat /etc/resolv.conf
Se il DNS risolve ma TCP fallisce, controlla NetworkPolicies, endpoint del servizio e se l'applicazione di destinazione accetta traffico da quel namespace. Se il DNS non risolve, testa il nome di servizio completo prima di incolpare l'app.
Una Semplice Scala di Connettività
Quando una richiesta fallisce, testa dal più vicino al più lontano:
- All'interno del pod, testa il processo dell'app locale:
kubectl exec <pod> -n <namespace> -- curl -v http://127.0.0.1:<porta>/health - Da un pod diverso nello stesso namespace, testa il Servizio:
kubectl run curl-test -n <namespace> --rm -it --image=curlimages/curl -- curl -v http://<servizio>:<porta>/health - Dal tuo laptop, testa tramite port-forward:
kubectl port-forward service/<servizio> -n <namespace> 8080:<porta-servizio> curl -v http://localhost:8080/health - Solo dopo che questi passano, spostati verso Ingress, bilanciatori di carico, DNS e regole firewall.
Questo ordine fa risparmiare tempo perché ogni passaggio prova un livello. Se localhost all'interno del pod fallisce, Ingress è irrilevante. Se pod-locale ha successo ma l'accesso al Servizio fallisce, l'app è probabilmente a posto e la scoperta del servizio Kubernetes necessita di attenzione.
Un'altra abitudine utile: mantieni il namespace esplicito durante il debug. Molte sessioni confuse derivano dall'esecuzione di kubectl exec nel namespace predefinito mentre il carico di lavoro rotto vive altrove. Imposta il namespace nel tuo contesto per la sessione o aggiungi -n <namespace> a ogni comando. La digitazione extra è più economica che testare il pod sbagliato.
Salva anche il comando esatto che ha dimostrato il fallimento. La prossima persona di turno può rieseguirlo senza ricostruire il tuo contesto dalla memoria.
Best Practice e Suggerimenti
- Mantieni
port-forwardin esecuzione:kubectl port-forwardviene eseguito in primo piano. Dovrai tenere aperta la finestra del terminale. Per eseguirlo in background, puoi usare strumenti comenohuposcreen/tmux. - Usa pod specifici durante il debug: Sebbene l'inoltro ai servizi sia comodo, per individuare problemi con un'istanza specifica, l'inoltro a un particolare pod usando il suo nome è spesso più efficace.
- Sicurezza: Fai attenzione a quali porte esponi. Evita di inoltrare porte sensibili a meno che non sia assolutamente necessario e assicurati che il tuo computer locale sia protetto.
- Utilizzo delle Risorse:
kubectl execpuò consumare risorse. Usalo con giudizio, specialmente su cluster di produzione. - Permessi: Assicurati che il tuo contesto
kubectlabbia i permessi necessari per eseguire comandi nei pod o inoltrare porte.
Cosa Annotare Dopo Aver Risolto
Un buon debug lascia una traccia. Cattura l'URL fallito, il pod sorgente, il servizio di destinazione, il namespace, il comando esatto che ha riprodotto il problema e il livello in cui è fallito. "Problema di connettività" è troppo vago per aiutare la prossima volta. "Il selettore del Servizio non corrispondeva ai pod dopo la ridenominazione delle etichette" è uno schema risolvibile.