Kaip padalyti DNS tarp Kubernetes ir OpenVPN sidecar
Sidecar podui reikia dviejų vardų pasaulių. Nukreipkite vieną loopback resolverį į klasterį ir tunelį, ir nustokite pasikliauti redaguotu resolv.conf.
Podai, kuriuose veikia OpenVPN sidecar, nepavyksta išspręsti vardų pagal atpažįstamą modelį: klasterio vardai užstrinka, nuotoliniai vardai atsako iki podo paleidimo iš naujo, o jūsų redaguotas resolver failas grįžta atgal. Niekas šioje sekoje nėra tunelio gedimas. Podas turi vieną resolver failą ir du vardų pasaulis, o failas gali išvardyti serverius eilės tvarka, bet negali išreikšti zonų. Ilgalaikis sprendimas yra resolver, kuris veikia podo viduje ir valdo padalijimą, todėl failas lieka paprastas ir jokia politika neturi priežasties jį perrašyti.
Kodėl jūsų padarytas pakeitimas nuolat dingsta
Failas priklauso kubelet, o ne jums. Pagal dnsPolicy: ClusterFirst kubelet sukuria jį, kad rodytų į klasterio DNS, ir atkuria jį kiekvieną kartą paleidus konteinerį. Viskas, ką pakeičiate per kubectl exec, gyvena konteinerio rašomajame sluoksnyje, todėl paleidimas iš naujo, iškeldinimas arba rollout tai išmeta. Podo specifikacija vis dar turi tą pačią politiką, todėl tas pats failas grįžta.
Nustačius dnsPolicy: None sustabdomas atkūrimas ir taip pat pašalinamas klasterio sprendimas. Gaunate failą, kurį kontroliuojate, ir prarandate vardus, kurių jums reikėjo. Šis mainai yra visa problema: resolv.conf neturi zonų sąvokos, tik serverių, kuriuos reikia bandyti eilėje, todėl negali nusiųsti cluster.local į vieną adresą, o privačią zoną į kitą.
Paleiskite vieną resolverį pode, ant loopback
Nukreipkite podą į vieną vardų serverį ant loopback, tada leiskite CoreDNS konteineriui, kuris dalijasi podo tinklo vardų erdve, atsakyti 53 prievarte. Nustatykite politiką į None, duokite podui tą vieną adresą ir pridėkite DNS konteinerį prie VPN ir programos:
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-corefileVisi trys konteineriai dalijasi viena tinklo vardų erdve, todėl 127.0.0.1:53 iš programos konteinerio pasiekia CoreDNS be paslaugos, be port-forward ir be apylankos per klasterio tinklą. Corefile prijungimas iš ConfigMap išlaiko jį kaip versijuotą įvestį, o ne failą, redaguojamą vietoje. Sugeneruotas resolv.conf tuomet turi vieną vardų serverį ir nieko daugiau, o tai yra būsena, apie kurią galima samprotauti.
Du dalykai čia kanda. Oficialus atvaizdas susieja 53 prievartą kaip root, o kai kurios klasterio politikos reikalauja tai parašyti aiškiai. Kiekvienas podo konteineris dabar priklauso nuo to, ar tas vienas konteineris veikia, todėl pridėkite readiness zondą prie nekenksmingo vardo ir leiskite programai toleruoti paleidimo klaidas.
Duokite kiekvienai privačiai zonai savo upstream
Corefile yra zonų sąrašas, kiekviena nurodo serverį, kuris gali jai atsakyti. Vienas blokas apima tunelio zoną, o viską pagaunantis blokas ateina paskutinis ir paima viską, ko nepaprašė joks aiškus blokas. Viską pagaunantis blokas turi nukreipti į tikrą upstream, niekada atgal į podą: .:53 { forward . 10.100.0.10 } pakartotinai naudoja klasterio resolverį, nes jis jau perduoda viešus vardus paties mazgo resolveriams. Niekas kitas pode neturi žinoti, kuriam tinklui priklauso vardas.
.:53 {
errors
cache 30
forward . 10.100.0.10
}
svc.acme.internal:53 {
errors
cache 30
forward . 192.168.240.1
}Skaitykite klasterio adresą iš kube-dns paslaugos kube-system, o ne kopijuokite jį iš straipsnio, nes paslaugų CIDR skiriasi. Tunelio adresas ateina iš dhcp-option DNS reikšmės, kurią siunčia OpenVPN serveris, arba iš tos zonos autoritetingo serverio. Jei jūsų klasterio resolveris neatsako į viešus vardus, įdėkite mazgo resolverio adresą į viską pagaunantį bloką, perskaitytą mazge, o ne pode.
Nenukreipkite viską pagaunančio bloko į /etc/resolv.conf, tai viliojanti vienos eilutės eilutė ir spąstai būtent šioje konfigūracijoje. Pagal dnsPolicy: None paties podo failas turi vienintelį vardų serverį 127.0.0.1, todėl tas taikinys yra pats CoreDNS ir kiekviena nesutampanti užklausa kartojasi, kol baigiasi laikas. Blokas pavadinimu svc.acme.internal atitinka tą vardą ir kiekvieną vardą po juo, o tai apima db.svc.acme.internal ir neapima svc.acme.internal.example.net. Galutinis taškas yra kosmetinis, nes zonų vardai normalizuojami į pilnai kvalifikuotą formą; priesagos riba nusprendžia, kur užklausa nusileidžia.
Nuspręskite, ar persiuntimas priklauso klasterio resolveriui
Jei kiekvienai vardų erdvės apkrovai reikia tunelio zonos, persiuntimo blokas CoreDNS ConfigMap pagal kube-system yra pigesnis nei sidecar kiekvienam podui. Šis pakeitimas yra klasterio masto: jam reikia administratoriaus teisių ir visų priklausomo diegimo paleidimo iš naujo. Apribokite jį ta viena zona, niekada šaknimi. Vienos apkrovos tunelio adresas tampa kiekvieno podo resolveriu tai zonai, o tą dieną, kai tunelis nukrenta, visas klasteris praranda vardą.
Sidecar laiko sprogimo spindulį vieno podo viduje, o tai yra geresnė numatytoji reikšmė, kai tik kelioms paslaugoms reikia nuotolinio tinklo. Kad ir ką pasirinktumėte, užsirašykite, kuris resolveris valdo zoną, nes kitas žmogus, derinantis timeout, paklaus.
Vardai, kurie išsprendžiami, kol ryšiai dar nepavyksta
Sprendimas yra vienas iš dviejų dalykų, kuriuos tunelis turi nešti; kitas yra grįžimo kelias, o podo tinklas jį gerai slepia. Jei pats OpenVPN serveris veikia kaip podas, taisyklės, kurias pridedate tame konteineryje, nevaldo srauto, išeinančio per mazgą. Ta gedimas yra siauras: atsakymus gaudavo tik to mazgo podai, kuris taip pat paleido serverį, o viskas kita baigėsi laiku.
Serverio paleidimas su hostNetwork: true grąžina jį į mazgo vardų erdvę, kur veikia FORWARD taisyklė ir šaltinio vertimas. Išverskite klientų baseiną išeinant, kitaip nė vienas nuotolinis mazgas neturi maršruto atgal į tunelio adresą, pavyzdžiui, 10.8.0.6. Patikrinkite abi kryptis prieš vėl liedami Corefile. Tunelis, kuris neša užklausą, bet ne atsakymą, sukuria lygiai tokį patį timeout, kaip resolveris, kuris niekada negavo užklausos.
Tikrinkite iš naujo podo, o ne iš sesijos, kurią taisėte
Paklauskite abiejų zonų aiškiai, tada pakartokite užklausą po to, kai podas pakeičiamas. Konfigūracija, kuri egzistuoja tik veikiančiame konteineryje, nėra konfigūracija:
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 +shortJei pirmoji pora atsako, o pora po pakeitimo ne, Corefile yra tvarkingas, o podo specifikacija ne. Jei abi atsako, bet programa vis tiek negali prisijungti, nustokite derinti DNS ir išbandykite TCP kelią su nc -vz db.svc.acme.internal 5432 konteinerio viduje. Išsaugokite dig išvestį biliete, nes tai yra artefaktas, skiriantis vardų problemą nuo maršrutizavimo problemos.