Megvalósult az, amire mi (és nem csak mi) régóta vártunk: , az Open Source alkalmazásgyűjtő és Kubernetes-be való telepítő eszközünk most már támogatja a változtatások alkalmazását 3-way-merge patch-ekkel! Ezen kívül lehetőség nyílt a meglévő K8s-erdők adopciójára Helm-kiadásokba anélkül, hogy ezeket újra létrehoznánk.

Röviden: állítsuk be WERF_THREE_WAY_MERGE=enabled — és megkapjuk a már meglévő Helm 2 telepítésekkel kompatibilis „deploy”-t, sőt egy kicsit többet is. kubectl applyDe kezdjük a teóriával: mi is az a 3-way-merge patch, hogyan jutottak el az emberek ehhez a megoldáshoz, és miért fontosak a CI/CD folyamatokban, amelyeket Kubernetes-alapú infrastruktúrával kezelünk? Aztán nézzük meg, hogy mit is jelent a 3-way-merge a werf-ben, milyen alapértelmezett módszerek állnak rendelkezésre, és hogyan tudjuk ezeket kezelni.
Mi az a 3-way-merge patch?
Tehát kezdjük azzal, hogy a Kubernetes-ben YAML-manifesztumokban leírt erőforrásokat kiadunk.
A Kubernetes API a következő alapvető műveleteket kínálja az erőforrásokkal való munkához: create, patch, replace és delete. Ezek segítségével egy kényelmes folyamatos erőforráskiadást kell megvalósítani a klaszterben. Hogyan?
Imperatív kubectl parancsok
Az első megközelítés az objektumok kezelésére a Kubernetes-ben a kubectl imperatív parancsainak használata az objektumok létrehozására, módosítására és törlésére. Egyszerűen fogalmazva:
kubectl run
- parancsot
egy Deployment vagy Job indítására használható:kubectl run --generator=deployment/apps.v1 DEPLOYMENT_NAME --image=IMAGEkubectl scale - parancsot
— a replikák számának módosítása:kubectl scale --replicas=3 deployment/mysqlEz a megközelítés elsőre kényelmesnek tűnhet. Azonban vannak problémák: - stb.
Nehéz
- automatizálni a konfigurációt.
- Mint Git-ben? Hogyan lehet átnézni a klaszteren bekövetkező változásokat? Hogyan biztosítsuk
- a reprodukálhatóságot az újraindítások során? Nyilvánvaló, hogy ez a megközelítés nem illeszkedik jól a kód mellett tárolt alkalmazásokhoz és az infrastruktúra kód formájában (IaC; vagy akár a Kubernetes ökoszisztémában népszerűbbé váló modernebb változata). Ezért a kubectl parancsoknak nem volt további fejlődésük.
- …
A create, get, replace és delete műveletek Az elsődleges
létrehozás
nagyon egyszerű: egy manifesztet küldünk a create műveletnek a kube API-n, és az erőforrás létrejön. A manifeszt YAML-reprezentációját tárolhatjuk a Git-ben, a létrehozáshoz pedig a következő parancsot használhatjuk: kubectl create -f manifest.yaml A törlés is egyszerű: ugyanazt a.
Késleltetett streaming replikációt is beállíthatunk, de van néhány csapda, amelyek a replikációs slotokkal, a forró tartalék visszajelzésével stb. kapcsolatosak. A WAL archívum lehetővé teszi, hogy elkerüljük ezeket. manifest.yaml fájlt állítjuk be a parancsban: kubectl delete -f manifest.yaml replace kubectl delete -f manifest.yaml.
Művelet replace teljes mértékben helyettesíti az erőforrás konfigurációját egy újjal, anélkül hogy újat kellene létrehozni. Ez azt jelenti, hogy mielőtt módosítanánk az erőforrást, ésszerű először lekérdezni a jelenlegi verziót egy művelettel get, módosítani azt, majd frissíteni a művelettel replace. A kube apiserverbe beépített és ha a művelet után get az objektum megváltozott, akkor a művelet replace nem fog végrehajtódni.
Ahhoz, hogy a konfigurációt Git-ben tároljuk és replace segítségével frissítsük, el kell végezni a műveletet get, össze kell olvasztani a konfigurációt a Git-ből azzal, amit kaptunk, és végrehajtani a replace. Alapértelmezetten a kubectl csak a parancs használatát teszi lehetővé kubectl replace -f manifest.yaml, ahol kubectl delete -f manifest.yaml — már teljesen előkészített (esetünkben - egyesített) manifeszt, amelyet telepíteni kell. Tehát a felhasználónak meg kell valósítania a manifeszt-összevonást, ami nem triviális feladat…
Érdemes megjegyezni, hogy bár kubectl delete -f manifest.yaml Git-ben tároljuk, nem tudhatjuk előre, hogy létre kell-e hoznunk egy objektumot vagy frissíteni azt — ezt a felhasználói szoftvernek kell megtennie.
Összesen: megvalósíthatjuk-e a folyamatos telepítést csak a create, replace és delete parancsok segítségével, biztosítva az infrastruktúra konfigurációjának Git-ben történő tárolását a kóddal együtt és kényelmes CI/CD-t?
Elvben megtehetjük… Ehhez meg kell valósítani a manifeszt-összevonást és egy olyan keretrendszert, amely:
- ellenőrzi az objektum jelenlétét a klaszterben,
- végrehajtja az erőforrás elsődleges létrehozását,
- frissíti vagy törli azt.
Frissítéskor figyelembe kell venni, hogy az erőforrás megváltozhatott az utolsó alkalom óta get és automatikusan kezelni kell az optimista zárolás esetét — meg kell próbálni a frissítést újra.
De miért találjunk fel a bikalit, amikor a kube-apiserver más módot kínál az erőforrások frissítésére: a patch, amely részben leveszi a terhet a felhasználóról?
Patch
Íme, elérkeztünk a javításokhoz.
A javítások a Kubernetes-ben létező objektumok módosításának fő módját jelentik. A művelet patch úgy működik, hogy a felhasználónak a kube-apiserverhez kell küldenie a javítást JSON formátumban, és meg kell adnia az objektumot,
- míg az apiserver automatikusan kezeli az objektum aktuális állapotát, és az szükséges formára állítja.
- Ebben az esetben az optimista zárolás nem szükséges. Ez a művelet deklaratívabb a replacehez képest, bár kezdetben ellentmondásosnak tűnhet.
Ezért:
a művelet segítségével
- létrehozzuk az objektumot a Git-ből származó manifeszt alapján,
kubectl create -f manifest.yaml— eltávolítjuk, ha az objektum már nem szükséges, - segítségével
törlés— módosítjuk az objektumot, hogy megfeleljen a Git-ben leírtaknak. - segítségével
patch— изменяем объект, приводя его к виду, описанному в Git.
Ahhoz, hogy ezt megtegyük, létre kell hozni a megfelelő javítást!
Hogyan működnek a javítások a Helm 2-ben: 2-way-merge
A Helm kiadásának első telepítésekor végrehajtja a műveletet kubectl create -f manifest.yaml a chart erőforrásaival.
A Helm kiadásának frissítésekor minden erőforráshoz:
- megszámolja a javítást a korábbi chart verziójának erőforrása és a jelenlegi chart verzió között,
- alkalmazza ezt a javítást.
Ezt a javítást nevezzük 2-way-merge patch-nek, mert a létrehozásában 2 manifeszt részt vesz:
- a korábbi kiadás erőforrásának manifesztje,
- a jelenlegi erőforrás manifesztje.
A törlés során a művelet törlés a kube apiserverben a múltban bejelentett, de a jelenlegi kiadásban nem bejelentett erőforrások számára történik.
A 2-way-merge patch megközelítésnek van egy problémája: ez ahhoz vezet, hogy az erőforrás tényleges állapota a klaszterben és a manifeszt a Git-ben eltér..
A probléma illusztrálása példával
- A Git-ben a chartban található manifesztben a következő mező
képa Deployment-ben értéket kap:ubuntu:18.04. - A felhasználó a
kubectl editmező értékét megváltoztattaubuntu:19.04-ra.. - A chart Helm újratelepítésekor nem generál javítást, mert a mező
képa kiadás korábbi verziójában és a jelenlegi chartban azonos. - Az újratelepítés után
képmaradubuntu:19.04-ra., bár a chartban az szerepel, hogyubuntu:18.04.
Elértük az eltérést és elvesztettük a deklarativitást.
Mi az a szinkronizált erőforrás?
Általánosságban elmondható, a teljes képviselete a működő klaszterben található erőforrás manifesztjének és a Git-ből származó manifesztnek nem lehetséges. Mert a valódi manifesztben lehetnek szolgáltatói annotációk/címkék, további konténerek és más adatok, amelyeket a vezérlők dinamikusan adnak hozzá vagy távolítanak el az erőforrástól. Ezeket az adatokat nem tudjuk és nem is akarjuk a Git-ben tartani. Azonban azt akarjuk, hogy a kiadás során azok a mezők, amelyeket egyértelműen megadtunk a Git-ben, a megfelelő értékeket vegyék fel.
Tehát van egy általános szabály a szinkronizált erőforrásra vonatkozóan: az erőforrás kiadása során csak azokat a mezőket lehet módosítani vagy törölni, amelyeket kifejezetten a Git-ből származó manifesztben írtak elő (vagy amelyeket az előző verzióban írtak, de most töröltek).
3-way-merge patch
A fő ötlet : javítást generálunk a Git-ben alkalmazott legutolsó verzió és a célzott verzió között, figyelembe véve a jelenlegi verziót a működő klaszterben. Az végső javításnak meg kell felelnie a szinkronizált erőforrás szabályának:
- az új mezők, amelyek a célzott verzióba kerültek, javításon keresztül kerülnek hozzáadásra;
- A korábbi, az utoljára alkalmazott verzióban lévő, és a célzott verzióban nem létező mezők nullázódnak a patch segítségével;
- A célzott verziótól eltérő mezők a jelenlegi objektum verziójában patch segítségével frissülnek.
Éppen ilyen elv szerint generál patch-eket kubectl apply:
- Az utolsó alkalmazott verzió megmarad az objektum saját annotációjában,
- a célzott verziót pedig a megadott YAML-fájlból vesszük,
- a jelenlegi verzió pedig a működő klaszterből származik.
Most, hogy megtanultuk az elméletet, ideje elmondani, mit is tettünk a werf-ben.
Változtatások alkalmazása a werf-ben
Korábban a werf, akárcsak a Helm 2, 2-way-merge patch-eket használt.
Repair patch
Ahhoz, hogy áttérjünk az új patch típusra — 3-way-merge —, első lépésként bevezettük az úgynevezett repair patch-eket.
A telepítés során a standard 2-way-merge patch-et használjuk, de a werf további patch-et generál, amely szinkronizálja a tényleges erőforrás állapotát azzal, ami a Git-ben található (ez a patch ugyanazzal a szinkronizált erőforrás szabállyal készül, amelyet fentebb írtunk le).
Ha szinkronizálási probléma merül fel, a telepítés végén a felhasználó WARNING üzenetet kap a megfelelő üzenettel és patch-el, amelyet alkalmazni kell az erőforrás szinkronizált állapotba hozatalához. Ezt a patch-et egy speciális annotációba is rögzítjük werf.io/repair-patch. Azt feltételezzük, hogy a felhasználó manuálisan maga alkalmazza ezt a patch-et: a werf ezt elvileg nem fogja automatikusan elvégezni.
A repair patch-ek generálása átmeneti intézkedés, amely lehetővé teszi a 3-way-merge elvén alapuló patch-ek létrehozásának tesztelését, de ezeket automatikusan nem alkalmazzuk. Jelenleg ez a működési mód alapértelmezés szerint be van kapcsolva.
3-way-merge patch csak új kiadásokhoz
2019. december 1-jétől a werf beta- és alpha-verziói elkezdik alapértelmezett teljes értékű 3-way-merge patch-eket használni a változtatások alkalmazására, de csak az új Helm kiadásokhoz, amelyeket a werf-en keresztül hoznak létre. A már létező kiadások továbbra is a 2-way-merge + repair patch megközelítést fogják használni.
Ezt a működési módot kifejezetten be lehet kapcsolni a WERF_THREE_WAY_MERGE_MODE=onlyNewReleases beállítással,
Megjegyzés: ez a funkció a werf-ban több kiadás során jelent meg: az alpha csatornán az verziótól kezdve készült el, míg a beta csatornán — a .
3-way-merge patch minden kiadás számára
2019. december 15-től a werf beta és alpha verziói alapértelmezés szerint teljes értékű 3-way-merge javításokat kezdenek alkalmazni a változtatások érvényesítésére minden kiadásnál.
Ezt a működési módot kifejezetten be lehet kapcsolni a WERF_THREE_WAY_MERGE_MODE=enabled beállítással,
Hogyan kezeljük az erőforrások automatikus skálázását?
A Kubernetesben kétféle automatikus skálázás létezik: HPA (horizontális) és VPA (függőleges).
A horizontális automatikusan meghatározza a példányok számát, míg a függőleges az erőforrások mennyiségét. Mind a példányok számát, mind az erőforrások követelményeit a forrásmánifestumban kell megadni (lásd. spec.replicas vagy spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory és ).
Probléma: ha a felhasználó úgy konfigurál egy erőforrást a chartban, hogy az erőforrásokra vagy példányokra vonatkozó konkrét értékek szerepelnek, és az adott erőforráshoz automatikus skálázók vannak engedélyezve, akkor a werf minden telepítéskor visszaállítja ezeket az értékeket arra, ami a chart árumanifesztjében szerepel.
A problémának két megoldása van. Először is a legjobb, ha elkerüljük az automatikusan skálázható értékek kifejezett megadását a chart árumanifesztjében. Ha azonban ez valamilyen okból nem megoldható (például, mert a chartban kényelmes megadni a kezdeti erőforráskorlátokat és a példányok számát), akkor a werf a következő annotációkat javasolja:
-
werf.io/set-replicas-only-on-creation=true -
werf.io/set-resources-only-on-creation=true
Ha van ilyen annotáció, a werf nem állítja vissza a megfelelő értékeket minden telepítéskor, hanem csak az erőforrás első létrehozásakor állítja be őket.
További részletekért lásd a projekt dokumentációjában a és .
A 3-way-merge patch használatának tiltása
A felhasználó egyelőre megtilthatja az új javítások használatát a werf-nél a környezeti változó segítségével WERF_THREE_WAY_MERGE_MODE=disabled. Azonban 2020. március 1-jétől ez a tilalom megszűnik és csak a 3-way-merge javítások használata lesz lehetséges. A werf erőforrásainak átvétele
A 3-way-merge javításokkal történő változásalkalmazás módszerének elsajátítása lehetővé tette számunkra egy olyan funkció azonnali bevezetését, mint a meglévő erőforrások átvétele a klaszterben a Helm-kiadásban.
A Helm 2-nek van egy problémája: nem lehet olyan erőforrást hozzáadni a chart manifesztumaihoz, amely már létezik a klaszterben, anélkül, hogy azt nulláról újra létrehoznánk (lásd.
). A werf-et megtanítottuk arra, hogy fogadja el a meglévő erőforrásokat a kiadásban. Ehhez az aktuális erőforrás verziójára a működő klaszterből annotációt kell beállítani (például a következő segítségével: , "werf.io/allow-adoption-by-release": RELEASE_NAME kubectl edit):
"werf.io/allow-adoption-by-release": RELEASE_NAMEMost már a forrást le kell írni a chartban, és a következő telepítés során a werf által az adott néven megjelölt kiadásban a meglévő forrás be fog kerülni, és a kiadás irányítása alatt marad. Ráadásul a forrás kiadási folyamatában a werf a működő klaszter aktuális állapotát a chartban leírt állapotra állítja, a 3-way-merge javítások és a szinkronizált forrás szabálya segítségével.
Megjegyzés: beállítás WERF_THREE_WAY_MERGE_MODE nincs hatással a források elfogadására — az elfogadás során mindig 3-way-merge javítást használnak.
További részletek itt találhatók .
Következtetések és további tervek
Remélem, hogy ez a cikk világosabbá tette, mi az a 3-way-merge javítás, és miért hozták létre. A werf projekt fejlesztésének szempontjából a megvalósításuk egy újabb lépés a Helm-szerű telepítések fejlesztésében. Mostantól elfelejthetjük a konfigurációk szinkronizálásával kapcsolatos problémákat, amelyek gyakran felmerültek a Helm 2 használata során. Ezen kívül hozzáadódott egy új hasznos funkció az elfogadott Kubernetes források Helm kiadásba való beépítésére.
A Helm-szerű telepítésekben még mindig vannak bizonyos problémák és nehézségek, például a Go sablonok használata, és ezeket továbbra is meg fogjuk oldani.
Az erőforrások frissítési módszereiről és az elfogadásról itt is található információ: .
Helm 3
Külön figyelmet érdemel új főverziója a Helmnek — v3, — amely szintén 3-way-merge javításokat használ és megszabadul a Tillertől. Az új Helm verzió igényel a már meglévő telepítések esetében, hogy átkonvertálja őket az új kiadási tárolási formátumra.
A werf a saját részéről már eltávolította a Tiller használatát, átállt a 3-way-merge-re és hozzájutott , miközben továbbra is kompatibilis a már létező Helm 2 telepítésekkel (nincs szükség migráló szkriptek futtatására). Ezért, amíg a werf nem áll át a Helm 3-ra, a werf felhasználói nem veszítenek a Helm 3 fő előnyeiből a Helm 2-höz képest (ezek a werfben is elérhetők).
Mindazonáltal a werf átállása a Helm 3 kódalapjára elkerülhetetlen, és a közeljövőben bekövetkezik. Valószínűleg a werf 1.1 vagy werf 1.2 verzióban fog megtörténni (jelenleg a werf főverziója 1.0; a werf verziókezeléséről bővebben ld. ). Egyébként a Helm 3 időközben stabilizálódni fog.
P.S.
Olvasson további információkat a blogunkban:
- A werf újdonságairól szóló jegyzetek ciklusa:
- «»;
- «»;
- «».
- «»;
- «»;
- «».
Forrás: habr.com
