3-way merge a werf: telepítés Kubernetesbe Helm 'szteroidokon'

Megvalósult az, amire mi (és nem csak mi) régóta vártunk: werf, 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.

3-way merge a werf: telepítés Kubernetesbe Helm 'szteroidokon'

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=IMAGE
    kubectl scale
  • parancsot — a replikák számának módosítása: kubectl scale --replicas=3 deployment/mysql
    Ez a megközelítés elsőre kényelmesnek tűnhet. Azonban vannak problémák:
  • stb.

Nehéz

  1. automatizálni a konfigurációt.
  2. Mint Git-ben? Hogyan lehet átnézni a klaszteren bekövetkező változásokat? Hogyan biztosítsuk
  3. 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.
  4. …

A create, get, replace és delete műveletek GitOps 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 optimista zárolás é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ép a Deployment-ben értéket kap: ubuntu:18.04.
  • A felhasználó a kubectl edit mező értékét megváltoztatta ubuntu:19.04-ra..
  • A chart Helm újratelepítésekor nem generál javítást, mert a mező kép a kiadás korábbi verziójában és a jelenlegi chartban azonos.
  • Az újratelepítés után kép marad ubuntu:19.04-ra., bár a chartban az szerepel, hogy ubuntu: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 3-way-merge patch: 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 v1.0.5-alpha.19verziótól kezdve készült el, míg a beta csatornán — a v1.0.4-beta.20.

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 egyéb).

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 HPA és VPA.

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: #6031, #3275"werf.io/allow-adoption-by-release": RELEASE_NAME kubectl edit):

"werf.io/allow-adoption-by-release": RELEASE_NAME

Most 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 dokumentáció.

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ó: ezeken a dokumentációs oldalakon.

Helm 3

Külön figyelmet érdemel nemrégiben megjelent ú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ó migrációt 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 sok egyéb, 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. itt). Egyébként a Helm 3 időközben stabilizálódni fog.

P.S.

Olvasson további információkat a blogunkban:

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster