Sziasztok, rögtön az elején tisztáznám, nem production rendszerről van szó, laptopomon futó Minikube klaszterrel dolgozok, tanulás és kísérletezés a cél.
Kind és Minikube több "alap" CNI plugint is támogat, pl. Calico, Flannel, Cilium, stb. Flannel ha jól látom lightweightebb, másik kettő sok funkciót implementál. Amit szeretnék, hogy transzparens módon egy saját CNI plugint futtassak AZ UTÁN, hogy az "alap" CNI plugin végzett a teendőivel. Ez a saját plugin pár dolgot beállítana az interfészeken, egy futtatható fájl az egész, ha kézzel futtatom a konténereken akkor megcsinálja amit kell. Ha jól értem, az alapműködés az, hogy DaemonSet-ként fut az alap CNI plugin, vannak saját image-i, mikor készül egy pod akkor a CNI plugin init konténere lefut, az image-ben ott vannak a configok és binárisok (/etc/cni/net.d/*.conflist és /opt/cni/bin/) amiket lefuttat, aztán jön a pod saját initje.
Kérdés: hogyan lehetne kiterjeszteni ezzel a saját pluginnal az "alap" CNI plugint anélkül, hogy azok image-ébe belenyúlok?
Hozzászólások
A "multus" nevű projectet találták neked ki.
https://github.com/k8snetworkplumbingwg/multus-cni
ezekkel a pluginnekkel remekül működik együtt:
https://www.cni.dev/plugins/current/
Elvileg igen, de azért volt vele pár gondunk.
* Egy CNI plugin csak egy interface-t kezelt, azaz a multus által hívott első (primary) plugin a containerbeli eth0-át konfigurálta, a második a net1-et, a harmadik a net2-t stb. A legtöbb CNI plugin úgy van megírva hogy létre is hozza a veth párt és emiatt egy már létező interface-re nem tudod ráengedni.
* Emiatt a Kubernetes (kubelet) csak az első, eth0, interface IP címeit látja és állítja be a podhoz az apiserveren (etcd-ben).
* A Service kezelés emiatt nehézkes mert a controller-manager az apiservertől kéri le a podok címeit. Így csak olyan Service-t tudsz csinálni ami container elsődleges interface-ere esik be.
* Van egy multus-service projekt is, de amikor néztem akkor még az volt a README.md-ben hogy nem production ready, le sem írják hogy miképp telepítsd és hogy ne is kérdezz ha bármi gondod lenne vele. Ez lehet azóta változott.
* Személyes meglátás, de a multus-cni doksija nem igazán volt ténylegesen használható, sok mindent trial and error módon kellett összekalapálnom.
Mivel nekünk csak pár extra konfiguráció kellett az elsődleges interface-en (dual-stack support aws-vpc-cni-hez amit official nem tud), így egy rövid wrapper scriptet írtam rá ami megcsinálta azt amit kellett. Ez nem teljesen multi-CNI, de mint kiderült az nem is kellett a mi esetünkben.
Én utoljára kb 1 éve néztem a multus-t ha azóta a fenti pontok közül valami már nem áll fenn akkor kérlek javítsatok ki.
Multust én is néztem és felületes megértésem alapján nekem ezekből a pontokból főleg az első és részben a második a gondom. Már alapból van egy veth amit létrehozott az alap CNI, erre jönnek mindenféle routing, bridgeing esetleg tűzfal, egress/ingress policy okosságok, és Multus ezekre tekintet nélkül ad egy másik veth-et. Ez majdhogynem balckbox a klaszter számára, menedzselésre és konfigra szorul az alap CNI-n felül. Amennyire megértettem, Multus akkor jó amikor eleve valami kubernetesbe nehezen integrálható hálózat van, főleg kernel-bypassal pl. DPDK, AF_XDP esetleg SR-IOV VF-ek: ezekkel amúgy sem tud mit kezdeni a CRI/kubelet és jó hogy ott a Multus amivel ezek bevihetők menedzselhető formában a podokba.
Köszi a szempont listát, tényleg nagyon hasznos és örülök neki!
- abban igazad van, hogy a macvlan, ipvlan, bridge, sriov cni pluginek tényleg hozhatnak létre új interfacet, akár veth párral. Viszont vannak a meta pluginek, amik nem hoznak létre új interfacet, hanem egy meglévőt állítanak át/be. gondolok itt leginkább a tuning, meg az sbr pluginekre.
- igen, a másodlagos interface-ekkel nem akar foglalkozni a k8s (még, bár van rá sig)
- egyetértek, a dokis kifejezetten pocsék. De szerencsére tényleg nem csinál mást a multus, mint hogy a kubelettől érkező cni hívásokat multiplexeli a bekonfigurált többi cni-hez.
Hat ez csodalatos! Tobb, mint 4 eve hagytam ott a cloudos termekcsaladunkat, de mar akkor is arra vartunk, hogy majd nemsokara kesz lesz. Addig meg majdcsak kibirjuk mindenfele CNI trukkozessel...
IPv4/v6 dual-stack stabil mar vegre?
A dual-stack stabil, legalábbis mi már jó ideje használjuk és nem volt vele gondunk.
Amit én csináltam.
* Beraktam egy üres CNI konfig állományt, hogy a kubelet ne állítsa a node-ot Ready-re induláskor.
* Egy rövid script/systemd unit várt amíg az official CNI plugin le nem generálta a konfig állományát az /etc/cni/net.d alá.
* Módosítottam úgy hogy egy proxy scriptet hívjon meg és felül írtam vele az üres konfigot. Ehhez elég csak kicserélni egy értéket a JSON-ban.
* A proxy script visszaalakította a konfigot röptében és azzal meghívta az eredeti CNI binárist. Elmentette az eredményt, megcsinálta az amit még kellett, főleg ip netns exec használatával, majd módosította a választ (egy új IP címet adtam hozza, szintén JSON) és visszaküldte a kubeletnek.
* Így a kubelet és a Kubernetes látta az összes IP címet, működött minden egyéb rendesen.
Kb ennyi volt az egész. Nem triviális, de azért nem is túl nehéz, ha értesz magához a hálózati részéhet. A CNI spec az elég egyszerű.
Érdemes még megnézni a bash-cni (vagy shell-cni) projektet. Abban szépen látszik hogy hogyan is működik ez az egész.
Köszönöm a részletes leírást. Jól értem, hogy itt azért lett proxy script, hogy az eredeti CNI plugin ELŐTT tudjon lefutni? Vagy ugyanezt csinálnád akkor is, ha utána kellene hogy lefusson?
"bash-cni"-t olvasd együtt a https://www.cni.dev/docs/spec/#cni-operations doksival, és akkor kitalálhatod, hogy neked is elég-e a wrapper, vagy írsz egy meta plugint, és multus-on keresztül használod.
Köszi!
Utána kellett a saját cuccnak lefutnia.
A primary CNI, az én esetemben, mindenáron maga akarta a veth pairt létrehozni, így csak az utólagos mókolás jöhetett szóba, de még az előtt hogy a Kubernetes értesülne az eredményről.
Ahogy dromie írta nézd meg a CNI specet és a bash-cni implementációt. Tényleg nem túl bonyolult és sokat lehet belőle tanulni.
Köszönöm, néztem/kipróbáltam bash-cni implementációt, szépen kiírt mindent ami érdekelt. A libcni-t is nézegettem, látszik hogy a .conf és .conflist fájlokon végighalad a CNI conf folderben név szerint rendezve.
Ami érdekes, hogy kind és minikube is azt csinálja, hogy lefuttatja az első .conflist-re végződő fájlban lévő plugineket. Ez után alapbeállítás szerint (azt nem találom ezt hol lehet könnyen módosítani) nem olvas be újabb .conf vagy .conflist fájlokat. KIVÉVE HA az van amit írsz, hogy az első fájlban van valami hiba (syntax vagy valamelyik plugin a listából nem 0-val tér vissza).
Végül mivel csak egy apró, paraméter nélküli pluginem van, azt csináltam, hogy csekkolom az elso .conflist fájlt /etc/cni/net.d-ből egy DaemonSettel, és ha nincs benne a pluginem, akkor jq-val beinjektálom a plugin lista JSON végére: így akkor fut le, ha előtte kindnet már lefutott (minikube meg kind is kindnet CNI-t használ default).