kubectl fallisce nella risoluzione del nome mentre il tunnel è attivo e l’indirizzo privato dell’API risponde ancora al ping. La rotta è a posto; il client interroga un resolver che non ha mai sentito parlare della zona privata del cluster. Le due correzioni più usate sono: inviare il resolver della rete virtuale a ogni client VPN, oppure fissare il nome localmente con una voce hosts o un forwarder condizionale. Risolvono lo stesso sintomo con responsabilità diverse, e confonderle è il modo in cui i team finiscono per modificare i file hosts ogni volta che un endpoint viene ricostruito.

Risoluzione e raggiungibilità falliscono a livelli diversi

Eseguite voi stessi la ricerca prima di cambiare qualsiasi cosa. getent hosts su Linux o nslookup su Windows vi dice se il client riceve una risposta; un timeout o NXDOMAIN indicano il resolver, mentre una risposta con l’indirizzo sbagliato indica un record obsoleto o una caduta pubblica.

Poi verificate quale server contatta davvero kubectl. Un contesto kubeconfig memorizza un URL, e una rotta VPN non lo riscrive: se il contesto indica un endpoint pubblico, il DNS può essere perfetto e il comando fallisce comunque.

getent hosts api.internal.example
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'
kubectl -v=8 get nodes 2>&1 | head -40

Il terzo segnale è la forma del guasto dopo la ricerca. Un nome che si risolve nell’indirizzo privato e poi subisce un timeout TCP è un problema di firewall o di rete autorizzata. Un nome che si risolve in un indirizzo pubblico significa che la query è uscita dalla zona privata. Tenete separati questi tre esiti; ciascuno vi porta da un responsabile diverso.

Opzione A: inviare il resolver della rete virtuale nel tunnel

Quando il server VPN gira dentro la rete virtuale, i client possono usare lo stesso resolver dell’host del server. In OpenVPN Community il server invia un’opzione DNS; Access Server espone la stessa impostazione nell’interfaccia di amministrazione, e i client devono scaricare di nuovo il profilo perché la direttiva DNS viaggia al suo interno.

# server.conf
push "dhcp-option DNS 10.0.0.4"
push "route 10.0.0.4 255.255.255.255"

La riga di rotta conta nei profili split tunnel. Inviare un indirizzo di resolver non è la stessa cosa che renderlo raggiungibile: se solo la sottorete del cluster passa dal tunnel, la query verso 10.0.0.4 esce dalla LAN locale e muore. Inviate una rotta host per il resolver, o includete la sua sottorete nel tunnel.

Anche il lato ricevente ha una policy. Un resolver raggiungibile dall’intervallo di indirizzi del client può comunque rifiutarne le query, e una zona privata collegata alla rete virtuale risponde solo ai client che arrivano dal percorso DNS di quella rete. Se la ricerca va in timeout dopo l’invio, controllate i log del resolver prima di toccare di nuovo il client.

Sul client, verificate cosa è stato applicato: resolvectl status su Linux con systemd-resolved, scutil --dns su macOS, ipconfig /all su Windows. Un server DNS inviato che non compare mai significa che il profilo non è stato ricaricato.

Opzione B: voci hosts e inoltro condizionale

Una voce hosts è la correzione più piccola possibile e la più fragile. Mappa un nome su un indirizzo su una macchina, quindi funziona per una demo e si rompe quando l’endpoint privato o il suo IP viene ricostruito. Nasconde anche il vero divario al resto del team.

Un forwarder condizionale scala meglio senza inviare DNS a ogni client. dnsmasq può inviare una zona al resolver della VNet e lasciare in pace tutto il resto: server=/cluster.internal/10.0.0.4. Il DNS di Windows ha forwarder condizionali, e i client Windows possono usare una regola NRPT per la stessa suddivisione. Il forwarder ha comunque bisogno di una rotta verso il resolver della VNet.

L’inoltro mantiene locale la navigazione normale, cosa che conta in split tunnel. Vi dà anche un solo posto per registrare le query della zona privata, e un solo posto che si rompe quando l’host del forwarder si sposta.

Scegliete per responsabilità, non per comodità

Inviate il resolver quando controllate il profilo VPN e volete che ogni nome privato funzioni, non solo l’API. Scegliete un forwarder quando i client devono mantenere il DNS locale per tutto il resto, o quando la VPN è gestita da un team diverso dal cluster.

Le voci hosts sono una diagnosi, non un deployment. Usatene una per dimostrare che l’API è raggiungibile, poi rimuovetela e correggete il percorso del resolver; lasciarla al suo posto trasforma una questione di routing in una caccia al tesoro più avanti. Qualunque opzione scegliate, annotate la zona, l’indirizzo del resolver e la rotta che trasporta la query.

Provate l’endpoint dell’API, non solo il nome

Una volta riuscita la ricerca, recuperate l’endpoint di versione dell’API con la CA del cluster. curl --cacert ca.crt https://api.internal.example:6443/version separa i guasti TLS e di autorizzazione dal DNS. Un 403 significa che il nome e la connessione funzionano e l’identità no.

Controllate anche se l’intervallo di indirizzi del client è consentito dalle reti autorizzate o dal firewall del cluster. I cluster privati spesso accettano traffico API solo dalla VNet o da intervalli peered, quindi un tunnel che assegna indirizzi da un altro pool si connette a livello di rete e viene scartato all’API.

Annotate quattro fatti quando escalate: il resolver usato dal client, l’indirizzo restituito, l’URL del server nel contesto kubeconfig selezionato e la prima operazione fallita. Quel verbale dice al prossimo ingegnere se cambiare DNS, routing o policy del firewall, e ferma la prossima modifica del file hosts.

Partite dalla ricerca, scegliete il percorso del resolver che corrisponde a chi possiede la zona, poi verificate l’endpoint. Se tutte e tre passano, il problema rimasto è l’autorizzazione, non la risoluzione dei nomi.

Articoli correlati