Podovi koji pokreću OpenVPN sidecar padaju na razrješavanju imena po prepoznatljivom obrascu: nazivi klastera se blokiraju, udaljeni nazivi odgovaraju dok se pod ne restartuje, a vaša uređena datoteka resolvera se vraća na staro. Ništa u tom slijedu nije kvar tunela. Pod ima jednu datoteku resolvera i dva svijeta imenovanja, a datoteka može navesti servere po redu, ali ne može izraziti zone. Trajno rješenje je resolver koji radi unutar poda i posjeduje podjelu, pa datoteka ostaje trivijalna i nijedna politika nema razlog da je prepisuje.

Zašto izmjena koju ste napravili neprestano nestaje

Datoteka pripada kubeletu, a ne vama. Pod dnsPolicy: ClusterFirst kubelet je stvara tako da pokazuje na klaster DNS i ponovno je stvara kad god se kontejner pokrene. Sve što promijenite kroz kubectl exec živi u zapisivom sloju kontejnera, pa restart, izbacivanje ili rollout to odbacuje. Specifikacija poda i dalje nosi istu politiku, zato se ista datoteka vraća.

Postavljanje dnsPolicy: None zaustavlja ponovno stvaranje i također uklanja razrješavanje unutar klastera. Dobivate datoteku koju kontrolirate i gubite nazive koji su vam trebali. Ta razmjena je cijeli problem: resolv.conf ne poznaje zone, samo servere koje treba redom isprobati, pa ne može poslati cluster.local na jednu adresu, a privatnu zonu na drugu.

Pokrenite jedan resolver u podu, na loopbacku

Usmjerite pod na jedan imenski server na loopbacku, a zatim pustite CoreDNS kontejner koji dijeli mrežni namespace poda da odgovara na portu 53. Postavite politiku na None, dajte podu tu jednu adresu i dodajte DNS kontejner uz VPN i aplikaciju:

spec:
  dnsPolicy: None
  dnsConfig:
    nameservers:
      - 127.0.0.1
    options:
      - name: ndots
        value: "5"
  containers:
    - name: dns
      image: coredns/coredns
      args: ["-conf", "/etc/coredns/Corefile"]
      volumeMounts:
        - {name: corefile, mountPath: /etc/coredns, readOnly: true}
    - name: vpn
      image: your-openvpn-client-image
    - name: app
      image: your-app-image
  volumes:
    - name: corefile
      configMap:
        name: split-dns-corefile

Sva tri kontejnera dijele jedan mrežni namespace, pa 127.0.0.1:53 iz kontejnera aplikacije dolazi do CoreDNS-a bez servisa, bez port-forwarda i bez obilaska kroz mrežu klastera. Montiranje Corefilea iz ConfigMapa čuva ga kao verzionirani ulaz umjesto datoteke koja se uređuje na mjestu. Generirani resolv.conf tada drži jedan imenski server i ništa drugo, što je stanje o kojem možete razmišljati.

Dva detalja ovdje peku. Službena slika veže port 53 kao root, a neke klaster politike zahtijevaju da to izričito navedete. Svaki kontejner u podu sada ovisi o tome da je taj jedan kontejner podignut, pa dodajte readiness probu prema bezopasnom imenu i pustite aplikaciju da tolerira padove pri pokretanju.

Dajte svakoj privatnoj zoni vlastiti upstream

Corefile je popis zona, svaka imenuje server koji joj može odgovoriti. Jedan blok pokriva tunelsku zonu, a blok koji hvata sve dolazi posljednji i uzima sve što nijedan izričiti blok nije prisvojio. Blok koji hvata sve mora ciljati pravi upstream, nikad natrag na pod: .:53 { forward . 10.100.0.10 } ponovno koristi klaster resolver jer taj resolver već prosljeđuje javna imena resolverima samog čvora. Ništa drugo u podu ne mora znati kojoj mreži ime pripada.

.:53 {
  errors
  cache 30
  forward . 10.100.0.10
}

svc.acme.internal:53 {
  errors
  cache 30
  forward . 192.168.240.1
}

Pročitajte adresu klastera iz servisa kube-dns u kube-system umjesto da je kopirate iz članka, jer se servisni CIDR-ovi razlikuju. Adresa tunela dolazi iz vrijednosti dhcp-option DNS koju šalje OpenVPN server ili iz autoritativnog servera za tu zonu. Ako vaš klaster resolver ne odgovara na javna imena, stavite adresu resolvera čvora u blok koji hvata sve, pročitanu na čvoru, a ne unutar poda.

Ne usmjeravajte blok koji hvata sve na /etc/resolv.conf, to je primamljiva jednolinijska postavka i zamka u upravo ovom slučaju. Pod dnsPolicy: None datoteka samog poda sadrži jedini imenski server 127.0.0.1, pa je ta meta sam CoreDNS i svaki neusklađeni upit rekurzira dok ne istekne. Blok nazvan svc.acme.internal odgovara tom imenu i svakom imenu ispod njega, što pokriva db.svc.acme.internal i isključuje svc.acme.internal.example.net. Završna točka je kozmetička, jer se nazivi zona normaliziraju u potpuno kvalificirani oblik; granica sufiksa odlučuje gdje upit završava.

Odlučite pripada li prosljeđivanje klaster resolveru

Ako svaki workload u namespaceu treba tunelsku zonu, blok prosljeđivanja u CoreDNS ConfigMapu pod kube-system je jeftiniji od sidecara po podu. Ta promjena je na razini klastera: traži administratorska prava i restart deploymenta o kojem svi ovise. Ograničite je na tu jednu zonu, nikad na korijen. Tunelska adresa jednog workloada tada postaje resolver svakog poda za tu zonu, a dana kad tunel padne cijeli klaster gubi ime.

Sidecar drži radijus eksplozije unutar jednog poda, što je bolji zadani izbor kad samo nekoliko servisa treba udaljenu mrežu. Što god odabrali, zapišite koji resolver posjeduje zonu, jer sljedeća osoba koja bude otklanjala timeout pitat će.

Imena koja se razrješavaju dok veze još padaju

Razrješavanje je jedna od dvije stvari koje tunel mora nositi; druga je povratni put, a mreža poda ga dobro skriva. Ako se sam OpenVPN server vrti kao pod, pravila koja dodate unutar tog kontejnera ne upravljaju prometom koji izlazi kroz čvor. Taj je kvar uzak: samo su podovi na čvoru koji je također vrtio server dobivali odgovore, a sve ostalo je isteklo.

Pokretanje servera s hostNetwork: true vraća ga u namespace čvora, gdje pravilo FORWARD i prevođenje izvora djeluju. Prevedite klijentski pool na izlazu ili nijedan udaljeni čvor nema rutu natrag do tunelske adrese kao što je 10.8.0.6. Provjerite oba smjera prije nego što ponovno dirnete Corefile. Tunel koji nosi upit, a ne odgovor, proizvodi točno isti timeout kao resolver koji upit nikad nije primio.

Provjerite iz novog poda, ne iz sesije koju ste popravili

Pitajte obje zone izričito, pa ponovite upit nakon što se pod zamijeni. Konfiguracija koja postoji samo u pokrenutom kontejneru nije konfiguracija:

kubectl exec -it deploy/app -- dig @127.0.0.1 kubernetes.default.svc.cluster.local +short
kubectl exec -it deploy/app -- dig @127.0.0.1 db.svc.acme.internal +short
kubectl delete pod -l app=your-app
kubectl wait --for=condition=Ready pod -l app=your-app --timeout=90s
kubectl exec -it deploy/app -- dig @127.0.0.1 db.svc.acme.internal +short

Ako prvi par odgovori, a par nakon zamjene ne, Corefile je u redu, a specifikacija poda nije. Ako oba odgovore, a aplikacija se još ne može spojiti, prestanite otklanjati DNS i testirajte TCP put s nc -vz db.svc.acme.internal 5432 iz unutrašnjosti kontejnera. Sačuvajte dig izlaz u tiketu, jer je to artefakt koji odvaja problem imenovanja od problema usmjeravanja.

Povezani članci