Az OpenVPN sidecart futtató podok felismerhető mintázat szerint hibáznak a névfeloldásban: a klaszter nevei megakadnak, a távoli nevek a pod újraindításáig válaszolnak, és a szerkesztett resolver fájl visszaáll. Ebben a sorrendben semmi nem a tunel hibája. Egy podnak egy resolver fájlja és két névvilága van, a fájl pedig sorrendben listázhatja a kiszolgálókat, de zónákat nem tud kifejezni. A tartós megoldás egy a podon belül futó resolver, amely a felosztás birtokosa, így a fájl egyszerű marad, és egyetlen szabályzatnak sincs oka újraírni.

Miért tűnik el folyton az elvégzett módosítás

A fájl a kubeleté, nem a tiéd. dnsPolicy: ClusterFirst alatt a kubelet azért hozza létre, hogy a klaszter DNS-ére mutasson, és minden konténerindításkor újragenerálja. Minden, amit kubectl exec útján módosítasz, a konténer írható rétegében él, ezért az újraindítás, a kiszorítás vagy a rollout eldobja. A pod specifikációja továbbra is ugyanazt a szabályzatot hordozza, ezért tér vissza ugyanaz a fájl.

A dnsPolicy: None beállítása leállítja az újragenerálást, és a klaszter feloldását is eltávolítja. Kapsz egy fájlt, amelyet te irányítasz, és elveszíted a szükséges neveket. Ez a csere a teljes probléma: a resolv.conf nem ismeri a zóna fogalmát, csak a sorrendben próbált kiszolgálókat, ezért nem tudja a cluster.local-t az egyik címre, egy privát zónát pedig a másikra küldeni.

Futtass egy resolvert a podban, loopbacken

Irányítsd a podot egyetlen névkiszolgálóra a loopbacken, majd engedd, hogy a pod hálózati névterét megosztó CoreDNS konténer az 53-as porton válaszoljon. Állítsd a szabályzatot None-re, add a podnak ezt az egyetlen címet, és tedd a DNS konténert a VPN és az alkalmazás mellé:

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

Mindhárom konténer egy hálózati névteret oszt meg, ezért az alkalmazáskonténerből a 127.0.0.1:53 szolgáltatás nélkül, port-forward nélkül és a klaszterhálózaton át kerülve éri el a CoreDNS-t. A Corefile ConfigMapből való csatolása verziózott bemenetként tartja meg a helyben szerkesztett fájl helyett. A generált resolv.conf ezután egyetlen névkiszolgálót tartalmaz és semmi mást, egy olyan állapotot, amelyről gondolkodni lehet.

Két részlet harap itt. A hivatalos image rootként köti az 53-as portot, és egyes klaszterszabályzatok megkövetelik ennek kifejezett kiírását. A pod minden konténere most azon az egyetlen konténeren múlik, ezért adj hozzá readiness próbát egy ártalmatlan névhez, és engedd, hogy az alkalmazás elviselje az indítási hibákat.

Adj minden privát zónának saját upstreamet

A Corefile zónák listája, mindegyik megnevezi a válaszolni képes kiszolgálót. Egy blokk lefedi a tunel zónáját, a mindent elkapó blokk pedig utolsóként jön, és mindent elvesz, amire egyetlen kifejezett blokk sem tartott igényt. A mindent elkapó blokknak valódi upstreamre kell mutatnia, soha nem vissza a podra: a .:53 { forward . 10.100.0.10 } újrahasználja a klaszter resolvert, mert az már a nyilvános neveket a csomópont saját resolvereihez továbbítja. A podban semmi másnak nem kell tudnia, melyik hálózathoz tartozik egy név.

.:53 {
  errors
  cache 30
  forward . 10.100.0.10
}

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

A klaszter címét a kube-system-ben lévő kube-dns szolgáltatásból olvasd ki, ne cikkből másold, mert a szolgáltatás CIDR-ek eltérnek. A tunel címe a OpenVPN kiszolgáló által küldött dhcp-option DNS értékből vagy a zóna hiteles kiszolgálójából származik. Ha a klaszter resolvered nem válaszol a nyilvános nevekre, tedd a csomópont resolverének címét a mindent elkapó blokkba, a csomóponton olvasva, nem a podban.

Ne irányítsd a mindent elkapó blokkot a /etc/resolv.conf-re, ez a csábító egysoros és éppen ebben a beállításban csapda. dnsPolicy: None alatt a pod saját fájlja az egyetlen 127.0.0.1 névkiszolgálót tartalmazza, ezért ez a cél maga a CoreDNS, és minden nem illeszkedő lekérdezés ismétlődik, amíg le nem jár az idő. A svc.acme.internal nevű blokk arra a névre és minden alatta lévő névre illeszkedik, ami lefedi a db.svc.acme.internal-t és kizárja a svc.acme.internal.example.net-t. A záró pont kozmetikai, mert a zónanevek a teljesen minősített formára normalizálódnak; a toldalék határa dönti el, hová esik a lekérdezés.

Döntsd el, a klaszter resolveréhez tartozik-e a továbbítás

Ha a névtér minden munkaterhelésének kell a tunel zónája, a kube-system alatti CoreDNS ConfigMapben egy továbbítási blokk olcsóbb, mint a podonkénti sidecar. Ez a változás klaszterszintű: adminisztrátori jogokat és egy mindenki által használt telepítés újraindítását igényli. Csak arra az egy zónára korlátozd, soha a gyökérre. Egy munkaterhelés tunelcíme ekkor a zóna minden podjának resolverévé válik, és a tunel leállásának napján az egész klaszter elveszíti a nevet.

A sidecar a robbanási sugarat egy podon belül tartja, ami jobb alapértelmezés, ha csak néhány szolgáltatásnak kell a távoli hálózat. Bármit választasz, jegyezd fel, melyik resolver birtokolja a zónát, mert a következő ember, aki időtúllépést hibakeres, kérdezni fog.

Nevek, amelyek feloldódnak, miközben a kapcsolatok még hibáznak

A feloldás az egyik a két dolog közül, amelyet a tunelnek vinnie kell; a másik a visszaút, és a pod hálózata jól elrejti. Ha maga az OpenVPN kiszolgáló fut podként, az abba a konténerbe tett szabályok nem irányítják a csomóponton át kimenő forgalmat. Ez a hiba szűk: csak a kiszolgálót is futtató csomópont podjai kaptak választ, minden más lejárt.

A kiszolgáló hostNetwork: true-gyel való futtatása visszateszi a csomópont névterébe, ahol a FORWARD szabály és a forrásfordítás érvényesül. Fordítsd a klienspoolt kifelé, különben egyetlen távoli csomópontnak sincs visszaútja egy 10.8.0.6 szerű tunelcímre. Ellenőrizd mindkét irányt, mielőtt újra hozzányúlsz a Corefile-hoz. Az a tunel, amely viszi a lekérdezést, de nem a választ, pontosan ugyanazt az időtúllépést adja, mint egy resolver, amely soha nem kapott lekérdezést.

Új podból ellenőrizd, ne abból a munkamenetből, amelyet javítottál

Kérdezd meg mindkét zónát kifejezetten, majd ismételd meg a lekérdezést a pod cseréje után. A csak futó konténerben létező konfiguráció nem konfiguráció:

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

Ha az első pár válaszol, a csere utáni pár pedig nem, a Corefile rendben van, a pod specifikációja pedig nem. Ha mindkettő válaszol, de az alkalmazás még mindig nem kapcsolódik, állítsd le a DNS hibakeresést, és teszteld a TCP utat nc -vz db.svc.acme.internal 5432-tel a konténer belsejéből. Őrizd meg a dig kimenetét a jegyben, mert ez az a bizonyíték, amely elválasztja a névproblémát az útvonalproblémától.

Kapcsolódó cikkek