Hoe om DNS tussen Kubernetes en 'n OpenVPN-syskar te verdeel
'n Syskar-pod het twee naamwêrelde nodig. Wys een loopback-oplosser na die cluster en die tonnel, en hou op om op 'n gewysigde resolv.conf te staatmaak.
Pods wat 'n OpenVPN-syskar laat loop, faal naamoplossing in 'n herkenbare patroon: clustername hang, afgeleë name antwoord tot die pod herbegin, en jou gewysigde resolverlêer keer terug na die ou inhoud. Niks in daardie reeks is 'n tonnelfout nie. 'n Pod het een resolverlêer en twee naamwêrelde, en die lêer kan bedieners in volgorde lys maar nie sones uitdruk nie. Die blywende oplossing is 'n oplosser wat binne die pod loop en die verdeling besit, sodat die lêer eenvoudig bly en geen beleid 'n rede het om dit te herskryf nie.
Waarom die wysiging wat jy gemaak het, bly verdwyn
Die lêer behoort aan die kubelet, nie aan jou nie. Onder dnsPolicy: ClusterFirst skep die kubelet dit om na cluster-DNS te wys, en herskep dit elke keer wanneer 'n houer begin. Wat jy ook al deur kubectl exec verander, leef in die houer se skryfbare laag, so 'n herbegin, 'n uitsetting of 'n uitrol gooi dit weg. Die pod-spesifikasie dra steeds dieselfde beleid, en daarom kom dieselfde lêer terug.
Om dnsPolicy: None te stel, stop die herskeping en verwyder ook cluster-oplossing. Jy kry 'n lêer wat jy beheer en verloor die name wat jy nodig gehad het. Daardie ruil is die hele probleem: resolv.conf het geen begrip van sones nie, net van bedieners om in volgorde te probeer, so dit kan nie cluster.local na een adres en 'n private sone na 'n ander stuur nie.
Laat een oplosser in die pod loop, op loopback
Wys die pod na 'n enkele naambediener op loopback, en laat 'n CoreDNS-houer wat die pod se netwerknaamruimte deel, op poort 53 antwoord. Stel die beleid op None, gee die pod daardie een adres, en voeg die DNS-houer by die VPN en die toepassing:
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-corefileAl drie houers deel een netwerknaamruimte, so 127.0.0.1:53 vanaf die toepassing-houer bereik CoreDNS sonder 'n diens, sonder port-forward en sonder 'n ompad deur die clusternetwerk. Om die Corefile vanaf 'n ConfigMap te monteer, hou dit 'n weergawebeheerde invoer eerder as 'n lêer wat ter plaatse gewysig word. Die geskepte resolv.conf hou dan een naambediener en niks anders nie, wat 'n toestand is waaroor jy kan redekawel.
Twee besonderhede byt hier. Die amptelike beeld bind poort 53 as root, en sommige cluster-beleide maak jou dit eksplisiet skryf. Elke houer in die pod hang nou daarvan af dat daardie een houer aan die lewe is, so voeg 'n gereedheidsprobe teen 'n skadelose naam by en laat die toepassing beginfoute verdra.
Gee elke private sone sy eie opstroom
'n Corefile is 'n lys sones, elkeen noem die bediener wat dit kan antwoord. Een blok dek die tonnelsone, en die vang-alles kom laaste en neem alles wat geen eksplisiete blok geëis het nie. Die vang-alles moet na 'n werklike opstroom mik, nooit terug na die pod nie: .:53 { forward . 10.100.0.10 } hergebruik die cluster-oplosser omdat daardie oplosser reeds publieke name na die node se eie oplossers aanstuur. Niks anders in die pod hoef te weet aan watter netwerk 'n naam behoort nie.
.:53 {
errors
cache 30
forward . 10.100.0.10
}
svc.acme.internal:53 {
errors
cache 30
forward . 192.168.240.1
}Lees die cluster-adres van die kube-dns-diens in kube-system eerder as om een uit 'n artikel te kopieer, want diens-CIDR's verskil. Die tonneladres kom van die dhcp-option DNS-waarde wat die OpenVPN-bediener stoot, of van die gesaghebbende bediener vir daardie sone. As jou cluster-oplosser nie publieke name antwoord nie, sit die node se oplosseradres in die vang-alles eerder, gelees op die node en nie binne die pod nie.
Moenie die vang-alles na /etc/resolv.conf wys nie, wat die aanloklike eenreël is en 'n lokval in hierdie presiese opstelling. Onder dnsPolicy: None bevat die pod se eie lêer die enkele naambediener 127.0.0.1, so daardie teiken is CoreDNS self en elke onbeantwoorde navraag herhaal homself tot dit uittyd. 'n Blok met die naam svc.acme.internal pas by daardie naam en elke naam daaronder, wat db.svc.acme.internal dek en svc.acme.internal.example.net uitsluit. Die volg punt is kosmeties, want sonename word na volledig gekwalifiseerde vorm genormaliseer; die agtervoegselgrens is wat besluit waar 'n navraag beland.
Besluit of die aanstuur in die cluster-oplosser hoort
As elke werklading in die naamruimte die tonnelsone nodig het, is 'n aanstuurblok in die CoreDNS ConfigMap onder kube-system goedkoper as 'n syskar per pod. Daardie verandering is clusterwyd: dit vereis administrateurrechte en 'n herbegin van 'n ontplooiing waarvan almal afhanklik is. Beperk dit tot daardie een sone, nooit tot die wortel nie. 'n Enkele werklading se tonneladres word dan elke pod se oplosser vir die sone, en die dag wanneer die tonnel val, verloor die hele cluster die naam.
Die syskar hou die skadegebied binne een pod, wat die beter verstek is wanneer net 'n paar dienste die afgeleë netwerk nodig het. Watter een jy ook kies, skryf neer watter oplosser die sone besit, want die volgende persoon wat 'n uittyding ontfout, sal vra.
Name wat oplos terwyl verbindings steeds faal
Naamoplossing is een van die twee dinge wat die tonnel moet dra; die ander is die terugpad, en pod-netwerking verberg dit goed. As die OpenVPN-bediener self as 'n pod loop, beheer reëls wat jy binne daardie houer byvoeg nie verkeer wat deur die node vertrek nie. Daardie fout is smal: net pods op die node wat ook die bediener laat loop het, het antwoorde gekry, en alles anders het uitgetyd.
Om die bediener met hostNetwork: true te laat loop, plaas dit terug in die node-naamruimte, waar 'n FORWARD-reël en brontranslasie effek het. Vertaal die kliëntpoel op pad uit, anders het geen afgeleë node 'n roete terug na 'n tonneladres soos 10.8.0.6 nie. Kontroleer beide rigtings voordat jy weer aan die Corefile raak. 'n Tonnel wat die navraag dra en nie die antwoord nie, lewer presies dieselfde uittyding as 'n oplosser wat die navraag nooit ontvang het nie.
Verifieer vanuit 'n nuwe pod, nie die sessie wat jy reggemaak het nie
Vra beide sones eksplisiet, en herhaal dan die navraag nadat die pod vervang is. Konfigurasie wat net in 'n lopende houer bestaan, is nie konfigurasie nie:
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 +shortAs die eerste paar antwoord en die paar ná die vervanging nie, is die Corefile reg en die pod-spesifikasie nie. As albei antwoord en die toepassing steeds nie kan koppel nie, stop om DNS te ontfout en toets die TCP-pad met nc -vz db.svc.acme.internal 5432 van binne die houer. Hou die dig-uitset in die kaartjie, want dit is die artefak wat 'n naamprobleem van 'n roeteprobleem skei.