Kubernetesin OpenVPN-pod ei välitä mitään? Tarkista ip_forward
Asiakkaat pingaavat VPN-podia eikä sen taakse pääse. Namespaceissä välitys on pois päältä, ja korjauksen on kestettävä admission, uudelleenkäynnistykset ja paluureitti.
Kannettavasi näyttää vihreän tunnelin, asiakasloki kertoo reittien työnnetyn, ja ainoa vastaava osoite on VPN-palvelimen oma tunnelin IP. Pingit sen taakse kuolevat riippumatta siitä, mitä tähtäät, oli se sitten ClusterIP, toisen podin osoite tai julkinen isäntänimi. Tämä yhdistelmä on diagnostinen eikä epämääräinen: purku toimii, ja toinen hyppy ei.
Törmäsin tähän Debian-solmuun, jossa ajettiin chartilla asennettua OpenVPN-imagea, ja tunneli oli helppo osa. Asiakas sai 10.8.0.x-vuokran, 10.8.0.1 vastasi ja 10.96.0.10, klusterin DNS-palvelu, aikakatkesi. Palvelimen lokissa mikään ei näyttänyt sairaalta, ja juuri siksi ihmiset alkavat kirjoittaa uudelleen iptables-sääntöjä, joihin heidän ei koskaan tarvinnut koskea.
VPN-pod on reititin, ja se kannattaa sanoa suoraan. Salatut paketit saapuvat, puretaan podin omassa verkkonamespacessa ja niiden on sitten poistuttava toisen liitännän kautta. Linux kieltäytyy tästä toisesta vaiheesta, ellei välitys ole käytössä juuri siinä namespacessa.
Mihin asiakas pääsee ja mihin ei
Vastaava osoite kuuluu tunnelin päätepisteelle, ja VPN-prosessi omistaa sen paikallisesti, joten välitys ei ole lainkaan mukana. Kaikki muu, mukaan lukien toinen pod, palvelun VIP tai internet, tarvitsee ytimen siirtämään paketin tun0:sta eth0:een. Kun tämä siirto evätään, oire on tasainen hiljaisuus eikä hylkäys, koska mikään ei tuota ICMP-virhettä takaisin tunnelia pitkin. Saat aikakatkaisuja, et tavoittamattomuusviestejä, ja se on vihje siitä, ettei kukaan reititä lainkaan.
Kaksi minuuttia luokittelua kaventaa kerrosta. Jos DNS-nimet epäonnistuvat, mutta raa'at pingit palvelun IP:hen onnistuvat, ongelma on DNS-putkityössä, ei välityksessä. Jos jokainen kohde peer-osoitteen takana aikakatkeaa, mukaan lukien paljas IP, aloita namespacesta.
Lue asetus namespacen sisältä
Jokainen pod saa oman verkkonamespacensa, ja net.ipv4.ip_forward on sysctl per namespace. Sen muuttaminen solmussa ei kerro sinulle mitään kontista, ja se on luotettava tapa viettää iltapäivä väärällä koneella.
kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0
Nolla vahvistaa diagnoosin. Arvoa ei myöskään periä solmun ajonaikaisesta kokoonpanosta: se alkaa imagen oletusarvosta joka kerta, kun kontti luodaan. Siksi käsin kubectl exec ... sysctl -w:llä tehty korjaus katoaa seuraavassa uudelleenkäynnistyksessä ja palaa vikana, joka näyttää ajoittaiselta.
Ottaa se käyttöön, jotta manifesti pitää sen
Kestävä vaihtoehto on init-kontti, joka ajetaan samassa pod sandboxissa ja kirjoittaa arvon ennen VPN-kontin käynnistymistä. Podin kontit jakavat verkkonamespacen, joten asetus siirtyy pääkonttiin.
initContainers:
- name: enable-forwarding
image: busybox:1.36
command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
securityContext:
privileged: true
Juuri privileged: true on rivi, jota arvioijat vastustavat, ja he ovat oikeassa. Sysctlin kirjoittaminen vaatii joko oikeuden tai kapeasti rajattavan kyvyn, ja rajoitetun Pod Security Standardin klusteri voi hylätä etuoikeutetun init-kontin kokonaan. Jos admission hylkää podin, tiedät sen luontihetkellä, mikä on ainakin rehellistä ja helppolukuista.
Siistimpi vaihtoehto on podin tason securityContext.sysctls-lista, joka antaa kubeletin soveltaa nimiavaruudellisia sysctlejä antamatta oikeuksia yhdellekään kontille. Se kattaa vain klusterin sallittujen listalla olevat nimet. Onko net.ipv4.ip_forward sillä listalla, riippuu siitä, miten kubelet on määritetty, ja pod, joka pyytää sysctliä sen ulkopuolelta, hylätään admissionissa tai jää jumiin CreateContainerConfigError:iin, kun sandboxia yritetään uudelleen. Tarkista sallittujen lista ennen kuin oletat kentän olevan rikki.
Ennen kuin rakennat kumpaakaan lähestymistapaa käsin, katso, tarjoaako chart jo kytkimen, usein jotain kuten ipForwardInitContainer: true. Chartin arvon käyttäminen pitää override-tiedostosi pienenä ja kestää seuraavan päivityksen, mitä käsin paikatut Deployment-muutokset eivät tee.
Toinen puoli: paluureitti ja käytäntö
Päällä oleva välitys on välttämätöntä, ei riittävää. Jos asiakkaat käyttävät yksityistä poolia, jolle klusterin verkolla ei ole reittiä, vastaukset eivät löydä takaisin tunneliin, ja podin on maskaroitava tämä liikenne kohti kohdettaan.
Käytäntö istuu sen päällä. NetworkPolicy-objektit ja pilven palomuurisäännöt arvioidaan lähdeosoitetta vasten, jonka paketti kantaa käännöksen jälkeen, joten asiakaspoolille kirjoitettu sääntö voi hiljaa lakkautua täsmäämästä, kun maskarointi otetaan käyttöön.
Kun asiakkaiden tarvitsee päästä vain klusterin sisäisiin palveluihin, VPN:n päättäminen palvelun VIP:hen on pienempi suunnittelu kuin pod-verkkoon reitittäminen. Se pitää asiakaspoolin myös kokonaan poissa CNI:n reititystaulusta.
Erottele epäonnistuva hyppy asiakkaasta
Työskentele ulospäin ja pysähdy ensimmäisellä hiljaisella askelmalla. Aloita VPN-peeristä, kokeile sitten jonkin podin osoitetta, sitten palvelun VIP:tä ja vasta sen jälkeen julkista kohdetta. Jokainen onnistuminen siirtää rajaa yhdellä hypyllä, ja jokainen epäonnistuminen nimeää kerroksen, jota kannattaa tutkia. Minkä tahansa jakelun jälkeen mene sisään ja lue sysctl uudelleen, koska korvattu pod alkaa imagen oletuksesta ja korjaus, joka ei koskaan ollut manifestissa, on jo poissa.
Kubernetesin dokumentaatio sysctlien käytöstä klusterissa luettelee, mitkä nimet voidaan asettaa podin tietoturvakontekstin kautta, ja se on ensimmäinen paikka, josta katsoa, kun admission hylkää muutoksen.