Perché i pod GKE non raggiungono gli host locali tramite VPN
Il nodo raggiunge la sede locale, il pod no. Le esclusioni masquerade di GKE lasciano gli indirizzi dei pod non tradotti per le destinazioni 10.x.
Il ping funziona dal nodo e fallisce dal pod, e nulla arriva in sede. Il tunnel e la rotta sono a posto; l’indirizzo sorgente sul cavo no. Ciò che distingue i due casi è ciò che il pacchetto dichiara di essere quando lascia il cluster, e GKE ha un’opinione in merito. Il meccanismo è una lista di esclusioni masquerade, e leggerla richiede un solo comando.
Leggi l’elenco effettivo prima di cambiare qualcosa
GKE fornisce un agente che decide, per ogni intervallo di destinazione, se il traffico dei pod viene riscritto sull’indirizzo del nodo in uscita. La sua configurazione predefinita indica i tre blocchi RFC1918, 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16, come destinazioni esenti. Perciò tutto ciò che invii da un pod a un host 10.x locale lascia il nodo con l’indirizzo del pod stesso ancora attaccato. Il traffico del nodo stesso non viene riscritto, ed è esattamente per questo che il suo ping funziona.
Leggi la configurazione prevista e le regole installate, perché possono non coincidere. kubectl -n kube-system get configmap ip-masq-agent -o yaml mostra ciò che è stato detto all’agente, e kubectl -n kube-system get pods -l k8s-app=ip-masq-agent mostra se qualcosa è in esecuzione per applicarlo. Su un nodo, iptables-save | grep -i masq mostra le regole che esistono davvero nel kernel. Quando la ConfigMap dice una cosa e le regole un’altra, il sospetto è l’agente, non la rete.
Conferma l’indirizzo sorgente con una cattura
Fai una cattura prima di cambiare una lista. Un filtro sull’unica destinazione mantiene l’output leggibile: tcpdump -ni any host 10.20.30.40.
Confronta con ciò che riporta l’altro lato. Una cattura in sede che mostra l’indirizzo del pod e nessuna risposta chiude il cerchio: la lista di esclusioni spiega l’asimmetria senza alcun guasto del tunnel. Due osservazioni di un solo indirizzo sorgente bastano per smettere di tirare a indovinare sul CNI.
Restringi l’esclusione al CIDR dei pod
La riparazione supportata restringe l’esenzione invece di rimuoverla: mantieni esente il CIDR dei pod e scarta il resto dello spazio 10.x. Quella lista vive nella ConfigMap dell’agente sotto nonMasqueradeCIDRs, e cambiarla è una modifica seguita da un rollout. Sostituisci la voce ampia con l’intervallo reale dei pod del cluster, mantieni gli altri blocchi privati se il traffico interno al cluster ne ha ancora bisogno, e lascia resyncInterval in pace a meno che tu non abbia un motivo. Applicalo, conferma che i pod dell’agente si sono riavviati e conferma che le regole del kernel sono cambiate.
Questa è una modifica a livello di cluster con un raggio d’impatto reale. Una volta applicata, il traffico che prima conservava la sorgente del pod ora arriva riscritto sul nodo, quindi tutto ciò che era legato a quegli indirizzi dei pod vede un mittente diverso. Le vittime sono log, elenchi di autorizzazione e regole firewall locali che nominano indirizzi dei pod, e falliscono in silenzio. Annuncia la modifica come cambiamento di comportamento, non come correzione.
In un cluster con più pool di nodi, verifica che l’agente sia pianificato sui nodi in cui i pod interessati girano davvero. Un pool senza il DaemonSet conserva le sue vecchie regole, e nulla nella ConfigMap lo mostrerà.
L’alternativa e il suo costo
L’altra opzione mantiene intatti gli indirizzi dei pod e insegna il percorso su di essi. Il CIDR dei pod entra nei selettori di traffico di Cloud VPN, e il lato locale ha bisogno di una rotta di ritorno per esso, così che le risposte sappiano dove andare. Questo preserva l’identità del pod, che alcuni modelli di sicurezza vogliono, e amplia sia l’ambito di routing sia quello del firewall che l’altro lato deve accettare.
Lo scambio è leggibilità contro ampiezza. La traduzione fa vedere al lato locale un indirizzo per nodo, cosa facile da mettere in un elenco di autorizzazione e che nasconde quale pod ha inviato cosa. Nessuna traduzione mantiene l’indirizzo del pod da estremo a estremo, il che è meglio per l’attribuzione e peggio per ogni dispositivo del percorso che deve imparare un nuovo intervallo. Nessuna delle due opzioni è un difetto di Docker o del CNI; entrambe sono decisioni di routing con una bolletta operativa. Scegli quella la cui bolletta il tuo team può pagare, e scrivi perché.
Verifica e torna indietro
Esegui di nuovo la stessa cattura. Una cattura a livello di nodo che stampa ancora l’indirizzo del pod dopo la modifica significa che le regole non sono mai cambiate, qualunque cosa dica la ConfigMap. Il cavo è il fatto; tutto il resto è inferenza.
Poi controlla la direzione inversa, perché metà di queste modifiche viene verificata solo in uscita. Conferma che la risposta raggiunga il nodo o il pod che ha inviato la richiesta, e conferma che l’applicazione sia terminata invece di aver solo ricevuto un SYN. Una cattura che mostra una richiesta senza risposta è un problema di routing dall’altro lato, non un problema masquerade da questo lato.
Il rollback è la ConfigMap precedente, applicata allo stesso modo, con la stessa conferma che l’agente si è riavviato e le regole sono cambiate. Conserva l’indirizzo sorgente prima e dopo per una richiesta nota nel registro delle modifiche, perché è quella singola riga a dimostrare che la modifica ha fatto ciò che hai detto. La guida all’agente masquerade IP di GKE documenta i valori predefiniti e i campi della ConfigMap. Se l’indirizzo sorgente è invariato dopo il rollout, l’agente non gira su quel nodo e nessuna modifica allo YAML lo risolverà.