Подовите што работат OpenVPN sidecar не успеваат во разрешувањето на имиња по препознатлив образец: имињата на кластерот висат, оддалечените имиња одговараат додека подот не се рестартира, и вашата уредена resolver датотека се враќа назад. Ништо во тој редослед не е дефект на тунелот. Подот има една resolver датотека и два света на именување, а датотеката може да ги наведе серверите по ред но не може да изрази зони. Трајното решение е resolver што работи во подот и ја поседува поделбата, па датотеката останува едноставна и ниедна политика нема причина да ја препише.

Зошто промената што ја направивте постојано исчезнува

Датотеката му припаѓа на kubelet, не вам. Под dnsPolicy: ClusterFirst kubelet ја создава за да покажува на кластерскиот DNS и ја создава повторно секој пат кога контејнерот стартува. Сі што го менувате преку kubectl exec живее во запишливиот слој на контејнерот, па рестарт, исфрлање или rollout го фрлаат. Спецификацијата на подот сѐ уште ја носи истата политика, затоа истата датотека се враќа.

Поставувањето на dnsPolicy: None го запира повторното создавање и исто така го отстранува разрешувањето во кластерот. Добивате датотека што ја контролирате и ги губите имињата што ви требаа. Таа размена е целиот проблем: resolv.conf нема поим за зони, само за сервери што треба да се пробаат по ред, па не може да го прати cluster.local на една адреса, а приватна зона на друга.

Стартувајте еден resolver во подот, на loopback

Насочете го подот кон еден име-сервер на loopback, потоа дозволете му на CoreDNS контејнерот што го дели мрежниот именски простор на подот да одговара на портата 53. Поставете ја политиката на None, дајте му на подот таа една адреса и додајте го DNS контејнерот покрај VPN и апликацијата:

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

Сите три контејнери делат еден мрежен именски простор, па 127.0.0.1:53 од контејнерот на апликацијата стигнува до CoreDNS без услуга, без port-forward и без обиколка низ кластерската мрежа. Монтирањето на Corefile од ConfigMap го чува како верзиониран влез наместо датотека што се уредува на место. Генерираниот resolv.conf тогаш држи еден име-сервер и ништо друго, што е состојба за која може да се размислува.

Два детали касаат овде. Официјалната слика ја врзува портата 53 како root, а некои кластерски политики бараат тоа експлицитно да го напишете. Секој контејнер во подот сега зависи од тоа тој еден контејнер да е кренат, па додајте readiness проба кон безазлено име и дозволете ј на апликацијата да ги толерира неуспесите при стартување.

Дајте ј на секоја приватна зона свој upstream

Corefile е список на зони, секоја го именува серверот што може да ј одговори. Еден блок ја покрива зоната на тунелот, а блокот што фаќа сѐ доаѓа последен и зема сѐ што ниеден експлицитен блок не го побарал. Блокот што фаќа сѐ мора да цели кон вистински upstream, никогаш назад кон подот: .:53 { forward . 10.100.0.10 } повторно го користи кластерскиот resolver бидејќи тој веќе ги проследува јавните имиња до resolver-ите на самиот јазол. Ништо друго во подот не мора да знае на која мрежа му припаѓа името.

.:53 {
  errors
  cache 30
  forward . 10.100.0.10
}

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

Прочитајте ја адресата на кластерот од услугата kube-dns во kube-system наместо да копирате од статија, бидејќи CIDR-ите на услугите се разликуваат. Адресата на тунелот доаѓа од вредноста dhcp-option DNS што ја праќа OpenVPN серверот, или од авторитативниот сервер за таа зона. Ако вашиот кластерски resolver не одговара на јавни имиња, ставете ја адресата на resolver-от на јазолот во блокот што фаќа сѐ, прочитана на јазолот а не во подот.

Не насочувајте го блокот што фаќа сѐ кон /etc/resolv.conf, тоа е привлечната едноредна поставка и замка во токму оваа конфигурација. Под dnsPolicy: None датотеката на самиот под го содржи единствениот име-сервер 127.0.0.1, па таа цел е самиот CoreDNS и секое барање што не се совпаѓа се повторува додека не истече. Блок именуван svc.acme.internal се совпаѓа со тоа име и секое име под него, што го покрива db.svc.acme.internal и го исклучува svc.acme.internal.example.net. Крајната точка е козметска, бидејќи имињата на зоните се нормализираат во целосно квалификувана форма; границата на суфиксот одлучува каде слетува барањето.

Одлучете дали проследувањето припаѓа на кластерскиот resolver

Ако секое работно оптоварување во именскиот простор бара зоната на тунелот, блок за проследување во CoreDNS ConfigMap под kube-system е поевтин од sidecar по под. Таа промена е на ниво на кластерот: бара администраторски права и рестарт на распоредување од кое сите зависат. Ограничете ја на таа една зона, никогаш на коренот. Адресата на тунелот на едно работно оптоварување тогаш станува resolver на секој под за зоната, и во денот кога тунелот паѓа целиот кластер го губи името.

Sidecar-от го држи радиусот на експлозија во еден под, што е подобра стандардна поставка кога само неколку услуги бараат оддалечена мрежа. Што и да изберете, запишете кој resolver ја поседува зоната, бидејќи следниот човек што ќе го отстранува timeout-от ќе праша.

Имиња што се разрешуваат додека врските сѐ уште не успеваат

Разрешувањето е една од двете работи што тунелот мора да ги носи; другата е повратниот пат, а мрежата на подот го крие добро. Ако самиот OpenVPN сервер работи како под, правилата што ќе ги додадете во тој контејнер не управуваат со сообраќајот што излегува низ јазолот. Тој неуспех е тесен: само подовите на јазолот што го стартувале и серверот добиваа одговори, а сѐ останато истече.

Стартувањето на серверот со hostNetwork: true го враќа во именскиот простор на јазолот, каде што дејствуваат правилото FORWARD и преводот на изворот. Преведете го клиентскиот базен на излез, инаку ниеден оддалечен јазол нема рута назад до адреса на тунел како 10.8.0.6. Проверете ги двата правци пред да го допрете Corefile повторно. Тунел што го носи барањето а не одговорот произведува точно истиот timeout како resolver што никогаш не го примил барањето.

Проверете од нов под, не од сесијата што ја поправивте

Прашајте ги двете зони експлицитно, потоа повторете го барањето откако подот ќе се замени. Конфигурација што постои само во контејнер што работи не е конфигурација:

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

Ако првиот пар одговара, а парот по замената не, Corefile е во ред, а спецификацијата на подот не е. Ако двата одговараат, а апликацијата сѐ уште не може да се поврзе, престанете да го отстранувате проблемот со DNS и тестирајте ја TCP патеката со nc -vz db.svc.acme.internal 5432 од внатрешноста на контејнерот. Зачувајте го излезот од dig во тикетот, бидејќи тоа е артефактот што го дели проблемот со имиња од проблемот со рутирање.

Поврзани статии