OpenVPN-pod in Kubernetes stuur niks deur nie? Kyk na ip_forward
Kliënte ping die VPN-pod en niks daarna nie. Die naamruimte het forwardering af, en die oplossing moet toelating, herstarts en die terugpad oorleef.
Jou skootrekenaar wys 'n groen tonnel, die kliëntlog sê dat roetes gestoot is, en die enigste adres wat antwoord is die VPN-bediener se eie tonnel-IP. Pings verby dit sterf maak nie saak wat jy teiken nie, hetsy dit 'n ClusterIP, 'n ander pod se adres of 'n publieke gasheernaam is. Daardie kombinasie is diagnosties eerder as vaag: ontsluiting werk, en die tweede hop nie.
Ek het dit teëgekom op 'n Debian-nodus met 'n OpenVPN-beeld wat deur 'n chart geïnstalleer is, en die tonnel was die maklike deel. Die kliënt het 'n 10.8.0.x-huurkontrak gekry, 10.8.0.1 het geantwoord, en 10.96.0.10, die cluster-DNS-diens, het uitgetel. Niks in die bedienerlog het ongesond gelyk nie, en dit is juis waarom mense iptables-reëls begin herskryf wat hulle nooit nodig gehad het nie.
'n VPN-pod is 'n router, en dit is die moeite werd om dit reguit te sê. Geënkripteerde pakkette kom aan, word in die pod se eie netwerknaamruimte oopgemaak, en moet dan deur 'n ander koppelvlak vertrek. Linux weier daardie tweede stap tensy forwardering binne daardie selfde naamruimte geaktiveer is.
Wat die kliënt kan en nie kan bereik nie
Die adres wat antwoord, behoort aan die tonnel-eindpunt, en die VPN-proses besit dit plaaslik, so geen forwardering is hoegenaamd betrokke nie. Al die res, insluitend 'n ander pod, 'n diens-VIP of die internet, benodig die kern om 'n pakket van tun0 na eth0 te skuif. Wanneer daardie skuif geweier word, is die simptoom eenvormige stilte eerder as 'n verwerping, want niks genereer 'n ICMP-fout terug in die tonnel nie. Jy kry uittye, nie onbereikbare boodskappe nie, en dit is die leidraad dat niemand hoegenaamd roeteer nie.
Twee minute se klassifikasie vernou die laag. As DNS-name misluk terwyl rou pings na 'n diens-IP slaag, is die probleem DNS-loodgietery, nie forwardering nie. As elke bestemming anderkant die peer-adres uittyd, insluitend 'n kaal IP, begin by die naamruimte.
Lees die instelling binne die naamruimte
Elke pod kry sy eie netwerknaamruimte, en net.ipv4.ip_forward is 'n sysctl per naamruimte. Om dit op die nodus te verander sê niks oor die houer nie, en dit is 'n betroubare manier om 'n middag op die verkeerde masjien te spandeer.
kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0
'n Nul bevestig die diagnose. Die waarde word ook nie van die nodus se looptydkonfigurasie geërf nie: dit begin elke keer wanneer 'n houer geskep word by die beeldverstek. 'n Regstelling wat met die hand met kubectl exec ... sysctl -w toegepas is, verdwyn dus by die volgende herstart en kom terug as 'n fout wat wisselvallig lyk.
Dit aktiveer sodat die manifes dit behou
Die duursame opsie is 'n inis-houer wat in dieselfde pod-sandbox loop en die waarde skryf voordat die VPN-houer begin. Houers in 'n pod deel 'n netwerknaamruimte, so die instelling dra oor na die hoofhouer.
initContainers:
- name: enable-forwarding
image: busybox:1.36
command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
securityContext:
privileged: true
Daardie privileged: true is die reël waarop resensente terugdruk, en hulle is reg. Om 'n sysctl te skryf vereis óf voorreg óf 'n nou-omlynde vermoë, en 'n cluster wat die beperkte Pod Security Standard gebruik, kan 'n bevoorregte inis-houer heeltemal weier. As toelating die pod verwerp, leer jy dit by die skeppingstyd, wat ten minste eerlik en maklik leesbaar is.
Die skoner alternatief is die pod-vlak securityContext.sysctls-lys, wat die kubelet toelaat om naamruimte-sysctls toe te pas sonder om voorreg aan enige houer te gee. Dit dek net name op die cluster se toelatingslys. Of net.ipv4.ip_forward op daardie lys is, hang af van hoe die kubelet opgestel is, en 'n pod wat 'n sysctl buite dit vra, word by toelating geweier of sit vas in CreateContainerConfigError terwyl die sandbox herprobeer word. Kontroleer die toelatingslys voordat jy aanvaar die veld is stukkend.
Voordat jy enige van die twee benaderings met die hand bou, kyk of die chart die skakelaar reeds blootstel, dikwels as iets soos ipForwardInitContainer: true. Om die chart-waarde te gebruik hou jou oorheersingslêer klein en oorleef die volgende opgradering, wat met die hand gepakte Deployment-wysigings nie doen nie.
Die tweede helfte: terugpad en beleid
Forwardering aan is nodig, nie voldoende nie. As kliënte 'n privaat poel gebruik waarvoor die cluster-netwerk geen roete het nie, kan antwoorde nie terug in die tonnel vind nie, en moet die pod daardie verkeer na sy bestemming masjineer.
Beleid sit bo-op dit. NetworkPolicy-objekte en wolk-brandmuurreëls word teen die bronadres wat 'n pakket na vertaling dra, geëvalueer, so 'n reël wat vir die kliëntpoel geskryf is, kan stilweg ophou pas sodra masjinerie geaktiveer is.
Wanneer kliënte net dienste binne die cluster hoef te bereik, is dit 'n kleiner ontwerp om die VPN by die diens-VIP te laat termineer as om in die pod-netwerk te roeteer. Dit hou ook die kliëntpoel heeltemal uit die CNI se roetetabel.
Isoleer die mislukkende hop van die kliënt
Werk uitwaarts en stop by die eerste stille stap. Begin met die VPN-peer, probeer dan een of ander pod se adres, dan 'n diens-VIP, en eers daarna 'n publieke bestemming. Elke sukses skuif die grens een hop, en elke mislukking noem die laag wat die moeite werd is om te ondersoek. Na enige uitrol, exec in en lees die sysctl weer, want 'n vervangde pod begin by die beeldverstek en 'n regstelling wat nooit in die manifes was nie, is reeds weg.
Die Kubernetes-dokumentasie oor die gebruik van sysctls in 'n cluster lys watter name deur die pod-sekuriteitskonteks gestel kan word, en dit is die eerste plek om te kyk wanneer toelating die verandering weier.