Ako rozdeliť DNS medzi Kubernetes a sidecar OpenVPN
Sidecar pod potrebuje dva svety mien. Nasmerujte jeden loopback resolver na klaster a tunel a prestaňte sa spoliehať na upravený resolv.conf.
Pody so sidecarom OpenVPN zlyhávajú v rozklade mien podľa rozpoznateľného vzoru: názvy klastra visia, vzdialené názvy odpovedajú do reštartu podu a vami upravený súbor resolvera sa vracia. Nič v tomto slede nie je porucha tunela. Pod má jeden súbor resolvera a dva svety mien a súbor môže vymenovať servery v poradí, no nedokáže vyjadriť zóny. Trvalým riešením je resolver, ktorý beží v pode a vlastní rozdelenie, takže súbor zostane jednoduchý a žiadna politika nemá dôvod ho prepisovať.
Prečo zmena, ktorú ste urobili, stále mizne
Súbor patrí kubeletu, nie vám. Pod dnsPolicy: ClusterFirst ho kubelet generuje, aby ukazoval na DNS klastra, a regeneruje ho pri každom štarte kontajnera. Všetko, čo zmeníte cez kubectl exec, žije v zapisovateľnej vrstve kontajnera, takže reštart, vysunutie alebo rollout to zahodia. Špecifikácia podu stále nesie rovnakú politiku, preto sa vráti rovnaký súbor.
Nastavenie dnsPolicy: None zastaví regeneráciu a odstráni aj rozklad klastra. Získate súbor, ktorý kontrolujete, a stratíte názvy, ktoré ste potrebovali. Táto výmena je celý problém: resolv.conf nepozná pojem zón, iba servery skúšané v poradí, takže nedokáže poslať cluster.local na jednu adresu a súkromnú zónu na inú.
Spustite jeden resolver v pode, na loopbacku
Nasmerujte pod na jediný menný server na loopbacku, potom nechajte kontajner CoreDNS, ktorý zdieľa sieťový menný priestor podu, odpovedať na porte 53. Nastavte politiku na None, dajte podu tú jedinú adresu a pridajte kontajner DNS vedľa VPN a aplikácie:
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-corefileVšetky tri kontajnery zdieľajú jeden sieťový menný priestor, takže 127.0.0.1:53 z kontajnera aplikácie dosiahne CoreDNS bez služby, bez port-forward a bez obchádzky cez sieť klastra. Pripojenie Corefile z ConfigMapy ho udržuje ako verzovaný vstup namiesto súboru upravovaného na mieste. Vygenerovaný resolv.conf potom obsahuje jeden menný server a nič iné, čo je stav, o ktorom sa dá uvažovať.
Dva detaily tu hryzú. Oficiálny obraz viaže port 53 ako root a niektoré politiky klastra vyžadujú, aby ste to napísali explicitne. Každý kontajner v pode teraz závisí od toho, či ten jeden kontajner beží, takže pridajte readiness sondu na neškodné meno a nechajte aplikáciu tolerovať štartové zlyhania.
Dajte každej súkromnej zóne vlastný upstream
Corefile je zoznam zón, každá menuje server, ktorý na ňu dokáže odpovedať. Jeden blok pokrýva zónu tunela a blok catch-all prichádza posledný a berie všetko, čo žiadny explicitný blok nevyžiadal. Catch-all musí mieriť na skutočný upstream, nikdy späť do podu: .:53 { forward . 10.100.0.10 } znova používa resolver klastra, pretože už preposiela verejné mená resolverom samotného uzla. Nič iné v pode nemusí vedieť, do ktorej siete meno patrí.
.:53 {
errors
cache 30
forward . 10.100.0.10
}
svc.acme.internal:53 {
errors
cache 30
forward . 192.168.240.1
}Čítajte adresu klastra zo služby kube-dns v kube-system namiesto kopírovania z článku, pretože CIDR služieb sa líšia. Adresa tunela pochádza z hodnoty dhcp-option DNS, ktorú posiela server OpenVPN, alebo z autoritatívneho servera tej zóny. Ak váš resolver klastra neodpovedá na verejné mená, dajte adresu resolvera uzla do bloku catch-all, čítanú na uzle, nie v pode.
Nemierte catch-all na /etc/resolv.conf, čo je lákavý jednoriadok a pasca presne v tomto nastavení. Pod dnsPolicy: None obsahuje súbor samotného podu jediný menný server 127.0.0.1, takže ten cieľ je samotný CoreDNS a každá nezhodná požiadavka sa opakuje, kým nevyprší čas. Blok s názvom svc.acme.internal zodpovedá tomu menu a každému menu pod ním, čo pokrýva db.svc.acme.internal a vylučuje svc.acme.internal.example.net. Bodka na konci je kozmetická, pretože názvy zón sa normalizujú na plne kvalifikovanú formu; hranica sufixu rozhoduje, kam požiadavka dopadne.
Rozhodnite, či preposielanie patrí resolveru klastra
Ak každá pracovná záťaž v mennom priestore potrebuje zónu tunela, blok preposielania v ConfigMape CoreDNS pod kube-system je lacnejší než sidecar na každý pod. Tá zmena je na úrovni klastra: vyžaduje práva správcu a reštart nasadenia, na ktorom všetci závisia. Obmedzte ju na tú jednu zónu, nikdy na koreň. Adresa tunela jednej záťaže sa potom stane resolverom každého podu pre zónu a v deň pádu tunela celý klaster stratí meno.
Sidecar drží rádius výbuchu v jednom pode, čo je lepšia predvolená hodnota, keď vzdialenú sieť potrebuje len niekoľko služieb. Čohokoľvek si vyberiete, zapíšte, ktorý resolver vlastní zónu, pretože ďalší človek, ktorý bude ladiť timeout, sa na to spýtá.
Mená, ktoré sa rozkladajú, kým spojenia ešte zlyhávajú
Rozklad je jednou z dvoch vecí, ktoré tunel musí prenášať; druhou je cesta späť a sieť podu ju dobre skrýva. Ak samotný server OpenVPN beží ako pod, pravidlá pridané v tom kontajneri neriadia prevádzku vychádzajúcu cez uzol. Táto porucha je úzka: odpovede dostávali len pody na uzle, ktorý tiež spúšťal server, a všetko ostatné vypršalo.
Spustenie servera s hostNetwork: true ho vráti do menného priestoru uzla, kde pôsobí pravidlo FORWARD a preklad zdroja. Preložte klientsky pool na výstupe, inak žiadny vzdialený uzol nemá trasu späť na adresu tunela ako 10.8.0.6. Pred ďalším dotykom Corefile skontrolujte oba smery. Tunel, ktorý prenáša požiadavku, ale nie odpoveď, vytvá presne rovnaký timeout ako resolver, ktorý požiadavku nikdy nedostal.
Overte z nového podu, nie zo sedenia, ktoré ste opravili
Opýtajte sa oboch zón explicitne, potom po výmene podu požiadavku zopakujte. Konfigurácia, ktorá existuje len v bežiacom kontajneri, nie je konfigurácia:
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 +shortAk prvá dvojica odpovedá a dvojica po výmene nie, Corefile je v poriadku a špecifikácia podu nie. Ak obe odpovedajú a aplikácia sa stále nepripojí, prestaňte ladiť DNS a otestujte cestu TCP cez nc -vz db.svc.acme.internal 5432 zvnútra kontajnera. Odložte výstup dig do tiketu, pretože to je artefakt, ktorý oddeľuje problém mien od problému smerovania.