Podi s sidecarjem OpenVPN spodletijo pri razreševanju imen po prepoznavnem vzorcu: imena gruče visijo, oddaljena imena odgovarjajo do ponovnega zagona poda, urejena datoteka resolverja pa se vrne. Nič v tem zaporedju ni okvara tunela. Pod ima eno datoteko resolverja in dva svetova imen, datoteka pa lahko navede strežnike po vrsti, ne more pa izraziti območij. Trajna rešitev je resolver, ki teče v podu in ima razdelitev, zato datoteka ostane preprosta in nobena politika nima razloga, da bi jo prepisala.

Zakaj sprememba, ki ste jo naredili, kar naprej izgine

Datoteka pripada kubeletu, ne vam. Pod dnsPolicy: ClusterFirst jo kubelet ustvari, da kaže na DNS gruče, in jo obnovi ob vsakem zagonu vsebnika. Vse, kar spremenite prek kubectl exec, živi v zapisljivi plasti vsebnika, zato ponovni zagon, izpodrivanje ali rollout to zavržejo. Specifikacija poda še vedno nosi isto politiko, zato se vrne ista datoteka.

Nastavitev dnsPolicy: None ustavi obnavljanje in odstrani tudi razreševanje v gruči. Dobite datoteko, ki jo nadzorujete, in izgubite imena, ki ste jih potrebovali. Ta menjava je vsa težava: resolv.conf ne pozna pojma območij, le strežnike, ki jih poskusi po vrsti, zato ne more poslati cluster.local na en naslov, zasebnega območja pa na drugega.

Zaženite en resolver v podu, na loopbacku

Usmerite pod na en sam strežnik imen na loopbacku, nato pustite vsebniku CoreDNS, ki si deli omrežni imenski prostor poda, da odgovarja na vratih 53. Nastavite politiko na None, dajte podu ta en naslov in dodajte vsebnik DNS ob VPN in aplikacijo:

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-corefile

Vsi trije vsebniki si delijo en omrežni imenski prostor, zato 127.0.0.1:53 iz vsebnika aplikacije doseže CoreDNS brez storitve, brez port-forward in brez obvoza skozi omrežje gruče. Priklop Corefile iz ConfigMapa ga ohrani kot verzioniran vhod namesto datoteke, urejene na mestu. Ustvarjeni resolv.conf nato vsebuje en strežnik imen in nič drugega, stanje, o katerem je mogoče razmišljati.

Dve podrobnosti tu ugrizneta. Uradna slika veže vrata 53 kot root in nekatere politike gruče zahtevajo, da to izrecno napišete. Vsak vsebnik v podu je zdaj odvisen od tega, ali ta en vsebnik teče, zato dodajte readiness sondo na neškodljivo ime in pustite aplikaciji, da prenaša zagonske napake.

Dajte vsakemu zasebnemu območju svoj upstream

Corefile je seznam območij, vsako navede strežnik, ki lahko odgovori nanj. En blok pokriva območje tunela, blok catch-all pa pride zadnji in vzame vse, kar ni zahteval noben izrecen blok. Catch-all mora ciljati na pravi upstream, nikoli nazaj v pod: .:53 { forward . 10.100.0.10 } znova uporabi resolver gruče, ker že posreduje javna imena resolverjem samega vozlišča. Ničemur drugemu v podu ni treba vedeti, kateremu omrežju pripada ime.

.:53 {
  errors
  cache 30
  forward . 10.100.0.10
}

svc.acme.internal:53 {
  errors
  cache 30
  forward . 192.168.240.1
}

Preberite naslov gruče iz storitve kube-dns v kube-system, namesto da ga kopirate iz članka, ker se CIDR-ji storitev razlikujejo. Naslov tunela pride iz vrednosti dhcp-option DNS, ki jo pošilja strežnik OpenVPN, ali od avtoritativnega strežnika tega območja. Če vaš resolver gruče ne odgovarja na javna imena, vstavite naslov resolverja vozlišča v blok catch-all, prebran na vozlišču in ne v podu.

Catch-all ne usmerjajte na /etc/resolv.conf, to je vabljiva enovrstična rešitev in past v natanko tej postavitvi. Pod dnsPolicy: None datoteka samega poda vsebuje edini strežnik imen 127.0.0.1, zato je ta cilj sam CoreDNS in vsaka neustrezna poizvedba se ponavlja, dokler ne poteče čas. Blok z imenom svc.acme.internal se ujema s tem imenom in vsakim imenom pod njim, kar pokriva db.svc.acme.internal in izključuje svc.acme.internal.example.net. Pika na koncu je kozmetična, ker se imena območij normalizirajo v polno kvalificirano obliko; meja pripone odloči, kam poizvedba pade.

Odločite, ali posredovanje pripada resolverju gruče

Če vsaka delovna obremenitev v imenskem prostoru potrebuje območje tunela, je blok posredovanja v ConfigMapu CoreDNS pod kube-system cenejši od sidecarja na pod. Ta sprememba je na ravni gruče: zahteva skrbniške pravice in ponovni zagon namestitve, od katere so odvisni vsi. Omejite jo na to eno območje, nikoli na koren. Naslov tunela ene obremenitve potem postane resolver vsakega poda za območje in na dan padca tunela vsa gruča izgubi ime.

Sidecar drži polmer eksplozije v enem podu, kar je boljša privzeta vrednost, ko potrebuje oddaljeno omrežje le nekaj storitev. Karkoli izberete, zapišite, kateri resolver ima območje, ker bo naslednja oseba, ki bo odpravljala timeout, to vprašala.

Imena, ki se razrešijo, medtem ko povezave še spodletijo

Razreševanje je ena od dveh stvari, ki jih mora tunel prenašati; druga je pot nazaj in omrežje poda jo dobro skrije. Če sam strežnik OpenVPN teče kot pod, pravila, dodana v tem vsebniku, ne upravljajo prometa, ki odhaja skozi vozlišče. Ta okvara je ozka: odgovore so dobili le podi na vozlišču, ki je tudi zagnal strežnik, vse drugo pa je poteklo.

Zagon strežnika z hostNetwork: true ga vrne v imenski prostor vozlišča, kjer delujeta pravilo FORWARD in prevajanje vira. Prevedite odjemalčni bazen na izhodu, sicer nobeno oddaljeno vozlišče nima poti nazaj na naslov tunela, kot je 10.8.0.6. Preverite obe smeri, preden se znova dotaknete Corefile. Tunel, ki prenaša poizvedbo, ne pa odgovora, ustvari natanko enak timeout kot resolver, ki poizvedbe ni nikoli prejel.

Preverite iz novega poda, ne iz seje, ki ste jo popravili

Vprašajte obe območji izrecno, nato po zamenjavi poda poizvedbo ponovite. Konfiguracija, ki obstaja le v tekočem vsebniku, ni konfiguracija:

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 +short

Če prvi par odgovori, par po zamenjavi pa ne, je Corefile v redu, specifikacija poda pa ne. Če oba odgovorita, aplikacija pa se še vedno ne poveže, prenehajte odpravljati DNS in preizkusite pot TCP z nc -vz db.svc.acme.internal 5432 znotraj vsebnika. Shranite izpis dig v zahtevek, ker je to artefakt, ki loči težavo imen od težave usmerjanja.

Sorodni članki