Pody so sidecarom OpenVPN zlyhávajú v rozklade mien podľa rozpoznateľného vzoru: názvy klastra visia, vzdialené názvy odpovedajú do reštartu podu a vami upravený súbor resolvera sa vracia. Nič v tomto slede nie je porucha tunela. Pod má jeden súbor resolvera a dva svety mien a súbor môže vymenovať servery v poradí, no nedokáže vyjadriť zóny. Trvalým riešením je resolver, ktorý beží v pode a vlastní rozdelenie, takže súbor zostane jednoduchý a žiadna politika nemá dôvod ho prepisovať.

Prečo zmena, ktorú ste urobili, stále mizne

Súbor patrí kubeletu, nie vám. Pod dnsPolicy: ClusterFirst ho kubelet generuje, aby ukazoval na DNS klastra, a regeneruje ho pri každom štarte kontajnera. Všetko, čo zmeníte cez kubectl exec, žije v zapisovateľnej vrstve kontajnera, takže reštart, vysunutie alebo rollout to zahodia. Špecifikácia podu stále nesie rovnakú politiku, preto sa vráti rovnaký súbor.

Nastavenie dnsPolicy: None zastaví regeneráciu a odstráni aj rozklad klastra. Získate súbor, ktorý kontrolujete, a stratíte názvy, ktoré ste potrebovali. Táto výmena je celý problém: resolv.conf nepozná pojem zón, iba servery skúšané v poradí, takže nedokáže poslať cluster.local na jednu adresu a súkromnú zónu na inú.

Spustite jeden resolver v pode, na loopbacku

Nasmerujte pod na jediný menný server na loopbacku, potom nechajte kontajner CoreDNS, ktorý zdieľa sieťový menný priestor podu, odpovedať na porte 53. Nastavte politiku na None, dajte podu tú jedinú adresu a pridajte kontajner DNS vedľa VPN a aplikácie:

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

Všetky tri kontajnery zdieľajú jeden sieťový menný priestor, takže 127.0.0.1:53 z kontajnera aplikácie dosiahne CoreDNS bez služby, bez port-forward a bez obchádzky cez sieť klastra. Pripojenie Corefile z ConfigMapy ho udržuje ako verzovaný vstup namiesto súboru upravovaného na mieste. Vygenerovaný resolv.conf potom obsahuje jeden menný server a nič iné, čo je stav, o ktorom sa dá uvažovať.

Dva detaily tu hryzú. Oficiálny obraz viaže port 53 ako root a niektoré politiky klastra vyžadujú, aby ste to napísali explicitne. Každý kontajner v pode teraz závisí od toho, či ten jeden kontajner beží, takže pridajte readiness sondu na neškodné meno a nechajte aplikáciu tolerovať štartové zlyhania.

Dajte každej súkromnej zóne vlastný upstream

Corefile je zoznam zón, každá menuje server, ktorý na ňu dokáže odpovedať. Jeden blok pokrýva zónu tunela a blok catch-all prichádza posledný a berie všetko, čo žiadny explicitný blok nevyžiadal. Catch-all musí mieriť na skutočný upstream, nikdy späť do podu: .:53 { forward . 10.100.0.10 } znova používa resolver klastra, pretože už preposiela verejné mená resolverom samotného uzla. Nič iné v pode nemusí vedieť, do ktorej siete meno patrí.

.:53 {
  errors
  cache 30
  forward . 10.100.0.10
}

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

Čítajte adresu klastra zo služby kube-dns v kube-system namiesto kopírovania z článku, pretože CIDR služieb sa líšia. Adresa tunela pochádza z hodnoty dhcp-option DNS, ktorú posiela server OpenVPN, alebo z autoritatívneho servera tej zóny. Ak váš resolver klastra neodpovedá na verejné mená, dajte adresu resolvera uzla do bloku catch-all, čítanú na uzle, nie v pode.

Nemierte catch-all na /etc/resolv.conf, čo je lákavý jednoriadok a pasca presne v tomto nastavení. Pod dnsPolicy: None obsahuje súbor samotného podu jediný menný server 127.0.0.1, takže ten cieľ je samotný CoreDNS a každá nezhodná požiadavka sa opakuje, kým nevyprší čas. Blok s názvom svc.acme.internal zodpovedá tomu menu a každému menu pod ním, čo pokrýva db.svc.acme.internal a vylučuje svc.acme.internal.example.net. Bodka na konci je kozmetická, pretože názvy zón sa normalizujú na plne kvalifikovanú formu; hranica sufixu rozhoduje, kam požiadavka dopadne.

Rozhodnite, či preposielanie patrí resolveru klastra

Ak každá pracovná záťaž v mennom priestore potrebuje zónu tunela, blok preposielania v ConfigMape CoreDNS pod kube-system je lacnejší než sidecar na každý pod. Tá zmena je na úrovni klastra: vyžaduje práva správcu a reštart nasadenia, na ktorom všetci závisia. Obmedzte ju na tú jednu zónu, nikdy na koreň. Adresa tunela jednej záťaže sa potom stane resolverom každého podu pre zónu a v deň pádu tunela celý klaster stratí meno.

Sidecar drží rádius výbuchu v jednom pode, čo je lepšia predvolená hodnota, keď vzdialenú sieť potrebuje len niekoľko služieb. Čohokoľvek si vyberiete, zapíšte, ktorý resolver vlastní zónu, pretože ďalší človek, ktorý bude ladiť timeout, sa na to spýtá.

Mená, ktoré sa rozkladajú, kým spojenia ešte zlyhávajú

Rozklad je jednou z dvoch vecí, ktoré tunel musí prenášať; druhou je cesta späť a sieť podu ju dobre skrýva. Ak samotný server OpenVPN beží ako pod, pravidlá pridané v tom kontajneri neriadia prevádzku vychádzajúcu cez uzol. Táto porucha je úzka: odpovede dostávali len pody na uzle, ktorý tiež spúšťal server, a všetko ostatné vypršalo.

Spustenie servera s hostNetwork: true ho vráti do menného priestoru uzla, kde pôsobí pravidlo FORWARD a preklad zdroja. Preložte klientsky pool na výstupe, inak žiadny vzdialený uzol nemá trasu späť na adresu tunela ako 10.8.0.6. Pred ďalším dotykom Corefile skontrolujte oba smery. Tunel, ktorý prenáša požiadavku, ale nie odpoveď, vytvá presne rovnaký timeout ako resolver, ktorý požiadavku nikdy nedostal.

Overte z nového podu, nie zo sedenia, ktoré ste opravili

Opýtajte sa oboch zón explicitne, potom po výmene podu požiadavku zopakujte. Konfigurácia, ktorá existuje len v bežiacom kontajneri, nie je konfigurácia:

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

Ak prvá dvojica odpovedá a dvojica po výmene nie, Corefile je v poriadku a špecifikácia podu nie. Ak obe odpovedajú a aplikácia sa stále nepripojí, prestaňte ladiť DNS a otestujte cestu TCP cez nc -vz db.svc.acme.internal 5432 zvnútra kontajnera. Odložte výstup dig do tiketu, pretože to je artefakt, ktorý oddeľuje problém mien od problému smerovania.

Súvisiace články