Näin jaat DNS:n Kubernetesin ja OpenVPN-sidecarin kesken
Sidecar-pod tarvitsee kaksi nimimaailmaa. Osoita yksi loopback-resolveri klusteriin ja tunneliin ja lopeta muokatun resolv.confin varassa eläminen.
Podit, jotka ajavat OpenVPN-sidecaria, epäonnistuvat nimien ratkaisussa tunnistettavalla tavalla: klusterin nimet jumittuvat, etänimet vastaavat, kunnes pod käynnistetään uudelleen, ja muokkaamasi resolver-tiedosto palautuu. Mikään tuossa sarjassa ei ole tunnelin vika. Podilla on yksi resolver-tiedosto ja kaksi nimimaailmaa, ja tiedosto voi luetella palvelimet järjestyksessä mutta ei voi ilmaista vyöhykkeitä. Kestävä ratkaisu on podin sisällä ajettava resolveri, joka omistaa jaon, jolloin tiedosto pysyy yksinkertaisena eikä millään käytännöllä ole syytä kirjoittaa sitä uudelleen.
Miksi tekemäsi muutos katoaa jatkuvasti
Tiedosto kuuluu kubeletille, ei sinulle. dnsPolicy: ClusterFirst-asetuksella kubelet luo sen osoittamaan klusterin DNS:ään ja luo sen uudelleen aina, kun kontti käynnistyy. Kaikki, mitä muutat kubectl exec-komennolla, elää kontin kirjoitettavassa kerroksessa, joten uudelleenkäynnistys, evictointi tai rollout hylkää sen. Podin määritys kantaa edelleen samaa käytäntöä, minkä vuoksi sama tiedosto tulee takaisin.
dnsPolicy: None-asetus pysäyttää uudelleenluonnin ja poistaa myös klusterin nimien ratkaisun. Saat tiedoston, jota hallitset, ja menetät tarvitsemasi nimet. Tämä vaihtokauppa on koko ongelma: resolv.conf ei tunne vyöhykkeitä, vain palvelimia, joita kokeillaan järjestyksessä, joten se ei voi lähettää cluster.local-osoitetta yhteen osoitteeseen ja yksityistä vyöhykettä toiseen.
Aja yksi resolveri podissa, loopbackilla
Osoita podi yhteen nimipalvelimeen loopbackilla ja anna sitten podin verkkonimiavaruuden jakavan CoreDNS-kontin vastata portissa 53. Aseta käytännöksi None, anna podille se yksi osoite ja lisää DNS-kontti VPN:n ja sovelluksen viereen:
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-corefileKaikki kolme konttia jakavat yhden verkkonimiavaruuden, joten 127.0.0.1:53 saavuttaa sovelluskontista CoreDNS:n ilman palvelua, ilman port-forwardia ja ilman kiertotietä klusteriverkon kautta. Corefilen liittäminen ConfigMapista pitää sen versioituna syötteenä paikan päällä muokattavan tiedoston sijaan. Luotu resolv.conf sisältää silloin yhden nimipalvelimen eikä muuta, mikä on tila, josta voit järkeillä.
Kaksi yksityiskohtaa puree tässä. Virallinen image sitoo portin 53 root-käyttäjänä, ja jotkin klusterikäytännöt vaativat sen kirjoittamista nimenomaisesti. Jokainen podin kontti riippuu nyt siitä, että tämä yksi kontti on pystyssä, joten lisää valmiuskoetin vaaratonta nimeä vastaan ja anna sovelluksen sietää käynnistysvirheitä.
Anna jokaiselle yksityiselle vyöhykkeelle oma upstream
Corefile on luettelo vyöhykkeistä, joista jokainen nimeää palvelimen, joka voi vastata siihen. Yksi lohko kattaa tunnelivyöhykkeen, ja kaiken nappaava lohko tulee viimeisenä ja ottaa kaiken, mitä mikään nimenomainen lohko ei vaatinut. Kaiken nappaavan lohkon on osoitettava todelliseen upstreamiin, ei koskaan takaisin podiin: .:53 { forward . 10.100.0.10 } käyttää uudelleen klusterin resolveria, koska se välittää jo julkiset nimet solmun omille resolvereille. Minkään muun podissa ei tarvitse tietää, mihin verkkoon nimi kuuluu.
.:53 {
errors
cache 30
forward . 10.100.0.10
}
svc.acme.internal:53 {
errors
cache 30
forward . 192.168.240.1
}Lue klusterin osoite kube-dns-palvelusta kube-system-kohdasta sen sijaan, että kopioisit sen artikkelista, koska palveluiden CIDR:t eroavat. Tunnelin osoite tulee dhcp-option DNS-arvosta, jonka OpenVPN-palvelin työntää, tai kyseisen vyöhykkeen autoritatiivisesta palvelimesta. Jos klusteriresolverisi ei vastaa julkisiin nimiin, laita solmun resolveriosoite kaiken nappaavaan lohkoon, luettuna solmulta eikä podin sisältä.
Älä osoita kaiken nappaavaa lohkoa /etc/resolv.conf-kohtaan, joka on houkutteleva yhden rivin ratkaisu ja ansa juuri tässä kokoonpanossa. dnsPolicy: None-asetuksella podin oma tiedosto sisältää ainoan nimipalvelimen 127.0.0.1, joten kohde on CoreDNS itse ja jokainen täsmäämätön kysely toistuu, kunnes se aikakatkaistaan. Lohko nimeltä svc.acme.internal täsmää tuon nimen ja jokaisen sen alaisen nimen kanssa, mikä kattaa db.svc.acme.internal ja sulkee pois svc.acme.internal.example.net. Loppupiste on kosmeettinen, koska vyöhykkeiden nimet normalisoidaan täysin kvalifioituun muotoon; jälkiliitteen raja ratkaisee, mihin kysely laskeutuu.
Päätä, kuuluuko välitys klusterin resolverille
Jos jokainen nimiavaruuden työkuorma tarvitsee tunnelivyöhykkeen, välityslohko CoreDNSin ConfigMapissa kube-system-kohdassa on halvempi kuin sidecar podia kohden. Muutos on klusterin laajuinen: se vaatii järjestelmänvalvojan oikeudet ja sellaisen deploymentin uudelleenkäynnistyksen, josta kaikki riippuvat. Rajaa se tuohon yhteen vyöhykkeeseen, ei koskaan juureen. Yhden työkuorman tunneliosoitteesta tulee silloin jokaisen podin resolveri vyöhykkeelle, ja sinä päivänä kun tunneli putoaa, koko klusteri menettää nimen.
Sidecar pitää räjähdyssäteen yhden podin sisällä, mikä on parempi oletus, kun vain harvat palvelut tarvitsevat etäverkkoa. Minkä valitsetkin, kirjoita muistiin, mikä resolveri omistaa vyöhykkeen, koska seuraava aikakatkaisua debuggaava henkilö kysyy sitä.
Nimet, jotka ratkeavat, kun yhteydet vielä epäonnistuvat
Ratkaisu on toinen kahdesta asiasta, jotka tunnelin on kannettava; toinen on paluupolku, ja podin verkko kätkee sen hyvin. Jos OpenVPN-palvelin itse ajetaan podina, siihen konttiin lisäämäsi säännöt eivät ohjaa liikennettä, joka lähtee solmun kautta. Tämä vika on kapea: vain solmun podit, jotka myös ajoivat palvelinta, saivat vastauksia, ja kaikki muu aikakatkaistiin.
Palvelimen ajaminen hostNetwork: true-asetuksella palauttaa sen solmun nimiavaruuteen, jossa FORWARD-sääntö ja lähdeosoitteen käännös vaikuttavat. Käännä asiakaspooli lähtiessä, tai millään etäsolmulla ei ole reittiä takaisin tunneliosoitteeseen kuten 10.8.0.6. Tarkista molemmat suunnat ennen kuin kosket Corefileen uudelleen. Tunneli, joka kantaa kyselyn mutta ei vastausta, tuottaa täsmälleen saman aikakatkaisun kuin resolveri, joka ei koskaan saanut kyselyä.
Varmista uudesta podista, älä istunnosta jonka korjasit
Kysy molemmilta vyöhykkeiltä nimenomaisesti ja toista sitten kysely, kun pod on korvattu. Kokoonpano, joka on olemassa vain käynnissä olevassa kontissa, ei ole kokoonpano:
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 +shortJos ensimmäinen pari vastaa ja korvaamisen jälkeinen pari ei, Corefile on kunnossa ja podin määritys ei. Jos molemmat vastaavat ja sovellus ei silti saa yhteyttä, lopeta DNS:n debuggaaminen ja testaa TCP-polku nc -vz db.svc.acme.internal 5432-komennolla kontin sisältä. Säilytä dig-tuloste tiketissä, koska se on artefakti, joka erottaa nimiongelman reititysongelmasta.