OpenVPN pod Kubernetesis ei edasta midagi? Kontrollige ip_forward
Kliendid pingivad VPN podi ja sealt edasi ei tule midagi. Namespace'is on edastamine väljas, ja parandus peab üle elama admission'i, taaskäivitused ja tagasitee.
Teie sülearvuti näitab rohelist tunnelit, kliendi logi teatab, et marsruudid lükati, ja ainus vastav aadress on VPN-serveri enda tunneli IP. Pingid sellest edasi surevad ükskõik, mida sihite, olgu see ClusterIP, teise podi aadress või avalik hostinimi. See kombinatsioon on diagnostiline, mitte udune: dekapsuleerimine töötab ja teine hüpe mitte.
Puutusin sellega kokku Debiani sõlmel, kus jooksis charti kaudu paigaldatud OpenVPN-i image, ja tunnel oli lihtne osa. Klient sai 10.8.0.x liisingu, 10.8.0.1 vastas ning 10.96.0.10, klastri DNS-teenus, aegus. Serveri logis ei paistnud miski haigena, ja täpselt sellepärast hakkavad inimesed ümber kirjutama iptables'i reegleid, mida neil polnud kunagi vaja puutuda.
VPN pod on ruuter, ja seda tasub otse öelda. Krüpteeritud paketid saabuvad, pakendatakse lahti podi enda võrgu-namespace'is ja peavad seejärel väljuma teise liidese kaudu. Linux keeldub sellest teisest sammust, kui edastamine pole just selles namespace'is lubatud.
Mida klient saab ja mida ei saa kätte
Vastav aadress kuulub tunneli lõpp-punktile ja VPN-protsess omab seda lokaalselt, nii et edastamine ei osale üldse. Kõik muu, sealhulgas teine pod, teenuse VIP või internet, vajab, et kernel liigutaks paketi tun0-st eth0-le. Kui see liigutus keeldutakse, on sümptom ühtlane vaikus, mitte tagasilükkamine, sest miski ei genereeri ICMP-viga tagasi tunnelisse. Saate aegumised, mitte kättesaamatuse teateid, ja see on vihje, et keegi ei marsruudi üldse.
Kaks minutit klassifitseerimist kitsendab kihi. Kui DNS-nimed ebaõnnestuvad, samal ajal kui toorpingsid teenuse IP-le õnnestuvad, on probleem DNS-i torutöödes, mitte edastamises. Kui iga sihtkoht peer-aadressist kaugemal aegub, sealhulgas paljas IP, alustage namespace'ist.
Lugege seadet namespace'i sees
Iga pod saab oma võrgu-namespace'i ja net.ipv4.ip_forward on sysctl iga namespace'i kohta. Selle muutmine sõlmel ei ütle teile konteineri kohta midagi, ja see on usaldusväärne viis veeta pärastlõuna vale masina peal.
kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0
Null kinnitab diagnoosi. Väärtust ei pärita ka sõlme käitusaegsest konfiguratsioonist: see algab image'i vaikeväärtusest iga kord, kui konteiner luuakse. Seega kaob käsitsi kubectl exec ... sysctl -w-ga rakendatud parandus järgmisel taaskäivitusel ja tuleb tagasi tõrkena, mis näib katkendlik.
See sisse lülitada, et manifest seda hoiaks
Vastupidav valik on init-konteiner, mis töötab samas pod-sandboxis ja kirjutab väärtuse enne, kui VPN-konteiner käivitub. Podi konteinerid jagavad võrgu-namespace'i, nii et seade kandub üle põhikonteinerisse.
initContainers:
- name: enable-forwarding
image: busybox:1.36
command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
securityContext:
privileged: true
Just privileged: true on rida, mille vastu ülevaatajad vaidlevad, ja neil on õigus. Sysctli kirjutamiseks on vaja kas privileegi või kitsalt piiritletud võimet, ja piiratud Pod Security Standardiga klastr võib privilegeeritud init-konteineri sootuks tagasi lükata. Kui admission podi tagasi lükkab, saate sellest teada loomise hetkel, mis on vähemalt aus ja kergesti loetav.
Puhtam alternatiiv on podi tasandi securityContext.sysctls loend, mis laseb kubeletil rakendada namespace'iga sysctle ilma ühelegi konteinerile privileegi andmata. See katab ainult klastri lubatud loendis olevaid nimesid. Kas net.ipv4.ip_forward on selles loendis, sõltub kubeleti konfiguratsioonist, ja pod, mis küsib sysctli väljaspool seda, lükatakse admission'is tagasi või jääb kinni CreateContainerConfigError-sse, samal ajal kui sandbox'i uuesti proovitakse. Kontrollige lubatud loendit, enne kui eeldate, et väli on katki.
Enne kui hakkate kumbagi lähenemist käsitsi ehitama, vaadake, kas chart juba lülitit pakub, sageli midagi sellist nagu ipForwardInitContainer: true. Charti väärtuse kasutamine hoiab teie override-faili väikese ja elab üle järgmise uuenduse, mida käsitsi laigatud Deploymenti muudatused ei tee.
Teine pool: tagasitee ja poliitika
Sisselülitatud edastamine on vajalik, mitte piisav. Kui kliendid kasutavad privaatset basseini, mille jaoks klastri võrgul marsruuti pole, ei leia vastused teed tagasi tunnelisse, ja pod peab selle liikluse oma sihtkoha suunas maskeerima.
Poliitika istub selle peal. NetworkPolicy objektid ja pilve tulemüüri reeglid hinnatakse lähteaadressi järgi, mida pakett pärast tõlget kannab, nii et kliendibasseini jaoks kirjutatud reegel võib maskeerimise sisselülitamisel vaikselt lakkata sobimast.
Kui kliendid peavad jõudma ainult klastri sees olevate teenusteni, on VPN-i lõpetamine teenuse VIP-il väiksem disain kui podivõrku marsruutimine. See hoiab ka kliendibasseini CNI marsruutimistabelist täiesti väljas.
Ebaõnnestuva hüppe isoleerimine kliendist
Töötage väljapoole ja peatuge esimesel vaiksel sammul. Alustage VPN-i peerist, seejärel proovige mõne podi aadressi, siis teenuse VIP-i ja alles pärast seda avalikku sihtkohta. Iga õnnestumine liigutab piiri ühe hüppe võrra ja iga ebaõnnestumine nimetab kihi, mida tasub uurida. Pärast igat juurutust minge sisse ja lugege sysctl uuesti, sest asendatud pod algab image'i vaikeväärtusest ja parandus, mida manifestis kunagi polnud, on juba kadunud.
Kubernetese dokumentatsioon sysctlide kasutamise kohta klastris loetleb, milliseid nimesid saab podi turbekonteksti kaudu seada, ja see on esimene koht, kuhu vaadata, kui admission muudatuse tagasi lükkab.