Paano Hatiin ang DNS sa Pagitan ng Kubernetes at isang OpenVPN Sidecar
Kailangan ng sidecar pod ang dalawang mundo ng pangalan. Itutok ang isang loopback resolver sa cluster at sa tunnel, at itigil ang pag-asa sa na-edit na resolv.conf.
Ang mga pod na nagpapatakbo ng OpenVPN sidecar ay nabibigo sa paglutas ng pangalan sa makikilalang paraan: nag-hang ang mga pangalan ng cluster, sumasagot ang malalayong pangalan hanggang sa ma-restart ang pod, at bumabalik ang na-edit mong resolver file. Wala sa pagkakasunod-sunod na iyon ang sira ng tunnel. Ang isang pod ay may isang resolver file at dalawang mundo ng pangalan, at kayang ilista ng file ang mga server nang sunod-sunod ngunit hindi kayang ipahayag ang mga zone. Ang matibay na solusyon ay isang resolver na tumatakbo sa loob ng pod at nagmamay-ari ng paghahati, kaya nananatiling payak ang file at walang patakarang may dahilan para muling isulat ito.
Bakit laging nawawala ang ginawa mong pagbabago
Pag-aari ng kubelet ang file, hindi mo. Sa ilalim ng dnsPolicy: ClusterFirst, ginagawa ito ng kubelet para ituro sa DNS ng cluster, at muling ginagawa tuwing nagsisimula ang isang container. Anumang binago mo sa pamamagitan ng kubectl exec ay nabubuhay sa naisusulat na layer ng container, kaya itinatapon ito ng pag-restart, pagpapaalis o rollout. Dala pa rin ng pod spec ang parehong patakaran, kaya bumabalik ang parehong file.
Ang pagtatakda ng dnsPolicy: None ay humihinto sa muling paggawa at inaalis din ang paglutas sa cluster. Nakakakuha ka ng file na kontrolado mo at nawawala ang mga pangalang kailangan mo. Ang palitang ito ang buong problema: walang konsepto ng zone ang resolv.conf, mga server lang na sinusubukan nang sunod-sunod, kaya hindi nito maipapadala ang cluster.local sa isang address at isang pribadong zone sa iba.
Magpatakbo ng isang resolver sa pod, sa loopback
Itutok ang pod sa isang nameserver sa loopback, pagkatapos hayaan ang isang CoreDNS container na nagbabahagi ng network namespace ng pod na sumagot sa port 53. Itakda ang patakaran sa None, bigyan ang pod ng nag-iisang address, at idagdag ang DNS container sa tabi ng VPN at ng application:
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-corefileNaghahati ang tatlong container sa isang network namespace, kaya ang 127.0.0.1:53 mula sa application container ay umaabot sa CoreDNS nang walang service, walang port-forward at walang pag-iikot sa network ng cluster. Ang pag-mount ng Corefile mula sa ConfigMap ay nagpapanatili nito bilang bersyonadong input sa halip na file na ine-edit sa lugar. Ang nabuong resolv.conf ay may isang nameserver at wala nang iba, isang estadong maaaring pag-isipan.
Dalawang detalye ang kumakagat dito. Itinatali ng opisyal na image ang port 53 bilang root, at may mga patakaran ng cluster na nag-uutos na isulat ito nang malinaw. Ang bawat container sa pod ay umaasa na ngayon sa pagtakbo ng nag-iisang container na iyon, kaya magdagdag ng readiness probe laban sa isang walang hatid na pangalan at hayaang tiisin ng application ang mga pagkabigo sa pagsisimula.
Bigyan ang bawat pribadong zone ng sarili nitong upstream
Ang Corefile ay listahan ng mga zone, tinutukoy ng bawat isa ang server na makakasagot dito. Sinasaklaw ng isang bloke ang zone ng tunnel, at ang catch-all na bloke ay huling dumarating at kinukuha ang lahat ng hindi inangkin ng anumang malinaw na bloke. Dapat tumutok ang catch-all sa tunay na upstream, hindi kailanman babalik sa pod: ginagamit muli ng .:53 { forward . 10.100.0.10 } ang resolver ng cluster dahil nagpapasa na ito ng mga pampublikong pangalan sa mga resolver ng node mismo. Wala nang iba sa pod ang kailangang malaman kung aling network nabibilang ang isang pangalan.
.:53 {
errors
cache 30
forward . 10.100.0.10
}
svc.acme.internal:53 {
errors
cache 30
forward . 192.168.240.1
}Basahin ang address ng cluster mula sa serbisyong kube-dns sa kube-system sa halip na kopyahin mula sa artikulo, dahil naiiba ang mga CIDR ng serbisyo. Ang address ng tunnel ay galing sa halagang dhcp-option DNS na ipinapadala ng OpenVPN server, o mula sa authoritative server para sa zone na iyon. Kung hindi sumasagot ang resolver ng cluster mo sa mga pampublikong pangalan, ilagay ang address ng resolver ng node sa catch-all na bloke, binasa sa node at hindi sa loob ng pod.
Huwag itutok ang catch-all sa /etc/resolv.conf, na siyang tuksong isang-linya at bitag sa ganitong eksaktong setup. Sa ilalim ng dnsPolicy: None, ang file ng pod mismo ay may nag-iisang nameserver na 127.0.0.1, kaya ang target na iyon ay ang CoreDNS mismo at bawat hindi tugmang query ay umuulit hanggang maubos ang oras. Ang blokeng tinatawag na svc.acme.internal ay tumutugma sa pangalang iyon at sa bawat pangalan sa ilalim nito, na sumasakop sa db.svc.acme.internal at hindi kasama ang svc.acme.internal.example.net. Ang tuldok sa dulo ay kosmetiko, dahil ang mga pangalan ng zone ay ginagawang normal sa ganap na kuwalipikadong anyo; ang hangganan ng suffix ang nagpapasya kung saan dumadapo ang query.
Magpasya kung ang pagpapasa ay pag-aari ng resolver ng cluster
Kung kailangan ng bawat workload sa namespace ang zone ng tunnel, ang bloke ng pagpapasa sa ConfigMap ng CoreDNS sa ilalim ng kube-system ay mas mura kaysa sidecar bawat pod. Ang pagbabagong iyon ay nasa antas ng cluster: nangangailangan ito ng karapatan ng administrator at pag-restart ng deployment na umaasa ang lahat. Limitahan ito sa nag-iisang zone na iyon, hindi kailanman sa root. Ang address ng tunnel ng isang workload ay nagiging resolver ng bawat pod para sa zone, at sa araw na bumagsak ang tunnel, nawawala ang pangalan sa buong cluster.
Pinapanatili ng sidecar ang blast radius sa loob ng isang pod, na mas mabuting default kapag kakaunti lang ang serbisyong nangangailangan ng malayong network. Anuman ang piliin mo, itala kung aling resolver ang nagmamay-ari ng zone, dahil magtatanong ang susunod na taong magde-debug ng timeout.
Mga pangalang lumulutas habang nabibigo pa ang mga koneksyon
Ang paglutas ay isa sa dalawang bagay na dapat dalhin ng tunnel; ang isa pa ay ang daan pabalik, at mahusay itong itinatago ng pod networking. Kung ang OpenVPN server mismo ay tumatakbo bilang pod, hindi kinokontrol ng mga patakarang idinagdag mo sa container na iyon ang trapikong lumalabas sa node. Ang pagkabigong iyon ay makitid: ang mga pod lang sa node na nagpatakbo rin ng server ang nakakuha ng sagot, at ang lahat ng iba ay naubos ang oras.
Ang pagpapatakbo ng server gamit ang hostNetwork: true ay nagbabalik nito sa namespace ng node, kung saan gumagana ang patakarang FORWARD at pagsasalin ng source. Isalin ang client pool sa labasan, kung hindi ay walang malayong node ang may rutang pabalik sa address ng tunnel tulad ng 10.8.0.6. Suriin ang dalawang direksyon bago muling hawakan ang Corefile. Ang tunnel na nagdadala ng query ngunit hindi ng sagot ay gumagawa ng eksaktong parehong timeout ng resolver na hindi kailanman nakatanggap ng query.
I-verify mula sa bagong pod, hindi mula sa session na inayos mo
Itanong nang malinaw sa dalawang zone, pagkatapos ulitin ang query pagkatapos mapalitan ang pod. Ang configuration na umiiral lamang sa tumatakbong container ay hindi configuration:
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 +shortKung sumasagot ang unang pares at hindi ang pares pagkatapos ng palitan, tama ang Corefile at mali ang pod spec. Kung sumasagot ang dalawa ngunit hindi pa rin makakonekta ang application, itigil ang pag-debug ng DNS at subukan ang TCP path gamit ang nc -vz db.svc.acme.internal 5432 mula sa loob ng container. Itago ang output ng dig sa ticket, dahil iyon ang artifact na naghihiwalay ng problema sa pangalan mula sa problema sa routing.