Nagy méretű konfiguráció kezelése Kubernetesben

Fórumok

Sziasztok!

Egy idális világban egy szolgáltatásnak van 1 konfig fájlja, amit be tudunk tenni egy ConfigMap-be és boldogok vagyunk :) De ki hogyan kezelné azt a sziitut ha egy Pod-ba több, akár nagyobb méretű konfigurációt is be kellene tenni? Akár olyat, ami a ConfigMap méretkorlátait is túlteljesíti (pl. nagyobb mint 1Mb).

Tételezzük fel h. több ilyen Pod is van, különböző konfigokkal. ArgoCD intézi az alkalmazásokat egy Git repoból mondjuk valami olyan szerkezetben h. myrepo.example.com/app1, myrepo.example.com/app2, stb.stb.

Ha a konfigurációt is bepakolom ezekbe az app könyvtárakba, akkor pl. init-containerrel be tudom tolni a megfelelő app-nak, illetve mondjuk egy sidecarral tudom frissítgetni, de valahogy nem tűnik túl elegánsnak. Pláne h. nekem az app1 dobozba csak mondjuk az app1/config mappából kell 3Mb konfigurációt frissítgetni, így valamiféle sparse checkoutot is kellene csinálni a sidecar/init konténerekben, ami még jobban bonyolítja.

A cél az lenne h. a konfigurációkat as-is szerkeszti az üzemeltetés egy git repoban és merge-nél kellene bevinni a prod app-ba valamilyen úton módon.

Kíváncsi vagyok van-e valakinek a fenti init/sidecar megvalósításnál esetleg jobb/szebb/hatékonyabb ötlete.

Előre is köszi az ötletelést :) 

Hozzászólások

Őszintén szólva, ha tényleg több megabyte configot akarsz bemappelni valahogy a containerbe, akkor nem nagyon tudod megúszni valami "külső" (nem k8s natív) megoldás nélkül. Szóval valamilyen initcontainer-re szükséged lesz (vagy sidecar, ha menetközben kellene frissíteni is, ahogy írtad).

De azt hozzátennem, hogy 3MB (gyanítom, hogy nem 3Mb-ra gondoltál valójában, csak elírtad, mert az még beleférne a limitbe) már több mint konfiguráció, nehezen hiszem, hogy ez tényleg az a dataset, amit napi (vagy akár havi) szinten változtattok. Ha pedig nem, akkor érdemes lenne valamilyen olyan réteget azonosítanod, ami tényleg változik, a többit pedig akár default-ként berakni magába az image-be akár valami olyan megoldással, hogy egy egyszerűbb bemeneti configból generálja neked a végső nagy configot valami template alapján, vagy hasonló. De lehet, hogy ha többet tudsz mondani arról, hogy mégis mik ezek a hatalmas configok, akkor többet tudunk segíeni.

Megjegyzem, hogy ha ekkora config fájlokkal dolgozol, a git repó mérete is hamar akkora lesz, hogy már nehéz lesz vele dolgozni.

Technikailag mi történik a futó példányokkal miután a git-ben módosul a config? Azaz csak konfig csere és ezt észreveszik/felnyalják, vagy mindenképp redeploy (gondolom rolling)?

Amúgy az init/sidecar teljesen jó ötlet, nem szigszalagnak tűnik

Ekkora konfiguráció valószínűleg nem normális méret és ezt én inkább külső forrásból és applikáció szinen oldanám meg (vagy sidecar konténer).  Ezt azt jelentené, hogy lenne egy minimális konfig az Applikáció indulásakor és ezeket a beállításokat nem fáljlból venné, hanem külső forrásból. Külső forrás alatt lehet ez Git repó, Valamilyen API, ami ezt kiszolgálja, vagy egy MongoDB. Ezt igazából a konfiguráció szerkezete és/vagy a fejlesztő tudása eldönti az esetek többségében. A választott technológiától függően a konfig reload kérdés is megoldott lehet. Pl. Webhook trigger, API call stb.

Tekintve, hogy applikációnak lett nevezve, gondoltam behozom azt a szálat, hogy nem minden alkalmazás alkalmas a Kubernetes-en való futtatásra. Kubernetes esetén kis applikációk vagy micro servicek a jellemzőek. Ha ez egy nagy alkalmazás,  akkor érdemes feltenni a kérdést,  hogy tényleg a Kubernetes a legjobb futtatási környezet neki? Ha mégis ez lenne az irány, akkor van lehetőség az alkalmazás darabolására micro service-ként és úgy futtatni Kubernetesen. Ez azért szokott bennem feljönni,  mert sokszor jön az szembe, hogy mindenféle sokszor erőforrás (rengeteg CPU, RAM, Disk IO) kell a működéséhez, amivel nem épp erre az architektúrára való az adott alkalmazás. Van amire jobb a VM és van amire a Kubernetes.

Úgy érzem két lépést összemostál.

  1. Platform csere meglévő szoftver alatt, mert mondjuk kirothadt a vas
  2. Szoftver megújítás

Ezek független dolgok és a linkelt pattern szigorúan csak a másodikat szeretné megoldani:

"An alternative route is to gradually create a new system around the edges of the old, letting it grow slowly over several years until the old system is strangled."

Az új rendszerelemek már természetesen lehetnek cloud native alapon, de a régit nem feltétlen kell belefeszíteni ugyanabba a keretbe, kivéve ha szódával elmegy, de csak azzal a szoros megkötéssel, hogy nem hathat ki negatívan a futtató platformra. Pl: ne kelljen platform szintű timeout-ot feljebb venni mert percekig indul. Ne legyen olyan nagy az erőforrás igénye, hogy új worker típust kelljen bevezetni miatta. Ne fossa maga alá a logjait, ne legyen lock fájl függő, ami egy kubectl-lel újralökve jól megakadályozza hogy elinduljon, stb. Ha nem sikerül, akkor hibrid környezet. Belépő él kubernetes, azon az új funkciók, path routing stb, és external service-ként felvéve a VM-eken futó legacy rész. Így az is úgy tűnik, mintha a platform része lenne, csak nem kellett megerőszakolni. A strangler típusú pattern-ekre kb ez ma a leghasználhatóbb és legrugalmasabb környezet.

Nagyjából egyetértek, mondjuk az "új worker típust" én pont nem érzem akkora fájdalomnak.

Ha csinálsz (az egy) legacy szeméttelepnek egy worker típust (és beleraksz pár node-ot) akkor pont azt el tudod érni taintekkel meg node affinityvel  mintha külön futtatnád de mégis ökoszisztémán belül vagy. Persze ha az alkalmazás annyira szeméttelep hogy ezt nem bírja el akkor marad amit írtál.
Aminek a rugalmasságával egyetértek.

Gábriel Ákos

Szerintem teljesen terület specifikus h. mi a "normális" mérete egy konfigurációnak.

Értem a kérdéseidet, röviden válaszolva: Az alkalmazás 1 db bináris, tökéletesen alkalmas microservice-nek. A terület problémásabb, azért nincs rá különösebben szép megoldás, mert gyakorlatilag ez a szegmens (telco) nem kicsit van lemaradva a többi szegmenshez képest (pl. webapp) mind fejben, mind technológiában.

Csak h. konkretizáljuk az alkalmazást, talán segít a nagyméretű konfig megértésében: Asterisk :)

A nagy konfiguráció abból adódhat, hogy pl. van 50 ivr, aminek van egyenként 3000 soros Dialplanje. Most szándékosan túlzok, de érted. Jelenleg egy komplett konfig kb. 500kb és azért ez tud hízni.

Ezért jött az init container és sidecar container ötlet, mert pont ezt szeretném h. egy repoban van a konfig. Ott konfigol a telco mérnök és majd a sidecar intézi h. egy cloud native infrába za bekerüljön, meg megtörténjen a rasterix -x 'reload' pl.

A sidecar/init kontener helyett nem fogsz jobbat talalni ha ezt a problemat kubernetes szintjen akarod kezelni.

Ennel jobb csak az a megoldas lenne ha az applikacio tudna ezt kezelni magatol es behuzna/frissitene a konfigot gitbol.

Milyen jelleguek ezek az adatok es milyen gyakran valtoznak? Es mennyire strukturaltak, mappaba szervezettek? Github lehetne a megoldas, onnan venne fel rendszeresen vagy utolso commit alapjan (mint amit az argo csinal). 

Ekkora configot egy config management tool-ban tarolunk vagy egy nosql adatbazisban (akik szopatni akarjak magukat azok RDBMS-ben, bar postgresql jol kezeli a json fieldeket). Igy a pod configmapja es az app is csak a helyet tartalmazza ahonnan fel fogja olvasni a configot majd amit be fog tolteni, par kilobyte.

Mondjuk ha egy config tobb megabyte-nyi akkor ott valami nagyon nincs rendben softverarchitektura ugyileg :D

Fentebb már írtam, de akkor még egyszer. Adott egy telefonközpont, amiben bármi lehet konfigolva, a default 5 sorostól a 20k soros ivr-ig.

Ez teljesen rendben van, mert ez ténylegesen konfiguráció, a terminológia már más kérdés h. kicsit feljebbről nézve ez valamiféle üzleti logikánk tekinthető, amit az alkalmazás tárolhatna valami másban is és lehetne felület az állítására, nem csak egy .conf. De ez így működik 30 éve és nem holnap fogják megváltoztatni. A konfiguráció kisebb része tudna menni rdbms-ből, de attól még ez a problémakör továbbra is létezne, mert egy ivr az bizony egy konfigurációs elem és fájlban kell a PBX alá.

Ettem en, de pont az Asterisk-ben lehet include directivakat alkalmazni, azaz mehet sok kis configmap-ba ami kell es ezeket fel lehet mountolni, majd a main cofigot is, ami tartalmazza az include-okat. Ezt raadasul nagyon szepen meg lehet csinalni HELM-el, mert beelbaszod egy konyvtarba az osszes conf filest, majd a Helm meg felolvassa onnan es legyartja mind a configmap-okat, mind a main conf-ot.

Vagy tenyleg en ertek valamit nagyon felre.

Igen, erre én is gondoltam (sok kis configmap). A probléma inkább az h. változhat az include miatt h. mit is kell mountolni (ezt ki fogja lekövetni dinamikusan, pláne ha sorrend is kell pl).

Arról nem is beszélve h. olyannak is elérhetővé és érthetővé kellene tegyem a konfigurációt, aki nem feltétlenül tudja még azt sem h. mi az a helm (és sok esetben nem is akarja :( )

Az valid h. Helm chartot szeretnék csinálni belőle és példányosítom argo-val annyi példányban ahány pbx-et akar üzemeltetni a cég, egyedül a /etc/asterisk mappát kell tudnom szeparáltan kezelnem példányonként. Ezen kívül ugye a változáskor reload kell, ahogy írtam is fentebb, ez eléggé stateful app.

Azért a helm-es verziót megnézem h. hogy lehetne kivitelezni. Mert végülis lehet az h. 1 chart, a charton belül van a configurations mappa amiben az összes példány összes konfigja benne van. Ez egészen jó ötlet, csak így meg a charton tud elhízni vagy 200 megára szélsőséges esetben pl :)

En ugy csinalnam, hogy lenne egy chartom, ami szepen megcsinalna magat az asterisk telepitest es abban csak annyi lenne, hogy mount a config dir.

Ez lenne aztan dependenciaban az adott kotnyezetek helm chartjaiban, ami meg csak es kizarolag annyut csinalna, hogy legyartja a configmap-okat, meg a main configfile-t. Ebben ugye felul lehetne defiinalni az asterisk helm chartom value-it. Na ezek a customerA, customerB chart-ok tartalmaznak a git-ben a "configuratons" mappat, amiben barki szepen szerkesztheti a configokat a sajat branch-en, majd egy pull request utan mergelodnenek. Amikor mergelodik, akkor az Argo le fogja futtatni a telepitest mivel valtozott a config. Cak es kizarolag a customerX-re.

Az egyetlen dolog amit meg kell irni az egy controller, hogy ha valtozik a configmap akkor kuldjon az adott asterisk instance-nak egy szep reload-ot. Ezt meg lehetne csinalni annotation-okkel vagy label-ekkel. A CM-kban benne van a "customer-name:" meg a pbx pod-ban is. Akar python-ban is megrhato ha nem akar valaki a Go-val szenvedni.

A configmap chart amugy annyibol allna hogy  loopolod a '.Files.Glob "configurations/**.conf' -ot es belerakod a file nevet meg a tartalmat. Ez kb egy 4 soros template :D, A main config meg ugyanez csak oda meg a nevek mennenek csak bele nem a tartalmak.

Ha van egyszer idod es kedved agyik este csinalhatunk egy teams/webex/faszomtudja meetinget es megmutatom :D

Kozben eszembe jutott hogy ugyanezt csinalja a grafana helm chart is az pl a k8s-sidecar-t hasznalja, hogy felolvassa az osszes adott labellel rendelkezo configmap-ot es felmountolja oket egy adott konyvtarba. Ezzel meg egyszerubb a megoldas, mert csak a configmap-okat kell legyartanai a customerA,B,C helm chartokkal :D

A grafana nagy ötlet, mint "template", valóban ezt csinálja :)

Ezen a vonalon el tudok indulni sztem, köszi! Ez így kb. pont jó lenne és az a nyerő az egészben h. külön chartokban van a customerA,B saját vacka, de az alapkonfig meg a corpAsterisk chartban van.

Sztem meg is oldottad a gondom ezzel az ötlettel. Köszi még1x! A teams/webex/faszomtuja kártyát nem játszanám ki, de azért ha 3 hét alatt nem jön össze akkor visszatérhetünk rá? :) Előre is köszönöm!

Hat en irnek ra inkabb egy controllert akar python-ban (Go-ban sokkal tovabb tartana), mert kb picsa konnyu lenne. A hatranya hogy nem lenne generikus hanem a te adott projektedben letezo configmapokra figyelne csak es inditana ujra a podokat amiket kell.

Ha generikusra akarnam csinalni, akkor lenne egy myrestarter Kind aminek az attributumai egy lista lenne aminek az objektumai rendelkeznenek a configNamespace, configName, configLabel, secretNamespace, secretName, secretLabel, podNamespace, PodLabel attributumokkal. Ez aztan benyelne a beallitott listat es ha az API serveren elkapja hogy valamelyik config vagy secret updatelodott, akkor szepen nyomna egy pod restartot. Ja lehet az xLabel inkabb xLabels lenne :D

A kerdes hogy megerne e ennyit foglalkozni vele :D

kiwigrid sidecar-t nézd meg, ha jól értem pont erre való

Gábriel Ákos