Megfelelő összehasonlítás a Kubernetes Apply, Replace és Patch műveletei között

A Kubernetes számára több lehetőség van az erőforrások frissítésére: apply, edit, patch és replace. Az, hogy mindez mit csinál és mikor alkalmazzuk őket, sokakban zűrzavart kelt. Nézzük meg alaposabban.

Megfelelő összehasonlítás a Kubernetes Apply, Replace és Patch műveletei között

Ha keressünk a Google-ben kifejezést "kubernetes apply vs replace", találunk választ a StackOverflow-on, ami nem helyes. Keresés során "kubernetes apply vs patch" az első link — dokumentáció a kubectl patch, amely nem tartalmaz összehasonlítást apply és patch. Ebben a cikkben különböző lehetőségeket fogunk megvizsgálni, valamint az egyes lehetőségek helyes használatát.

A Kubernetes erőforrás életciklusa (szolgáltatás, deployment, ingress stb.) során néha szükséges megváltoztatni, hozzáadni vagy eltávolítani bizonyos tulajdonságokat. Például megjegyzést hozzáadni, a replikák számát növelni vagy csökkenteni.

Kubernetes CLI

Ha már dolgozik Kubernetes klaszterekkel a CLI-n keresztül, akkor már ismerős a apply és szerkesztés. A parancs apply a fájlból olvassa ki az erőforrás specifikációját, és végez egy "upsert"-et a Kubernetes klaszterben, azaz létrehozza az erőforrást, ha az még nem létezik, és frissíti, ha létezik. A parancs szerkesztés az API-n keresztül olvassa ki az erőforrást, majd a helyi fájlba írja az erőforrás specifikációját, amelyet ezután egy szövegszerkesztőben nyithat meg. Miután szerkesztette és elmentette a fájlt, kubectl visszaküldi a módosításokat az API-n keresztül, amely gondoskodik arról, hogy ezek a változtatások alkalmazásra kerüljenek az erőforráson.

Nem mindenki ismeri a parancsokat patch és kicserél. A parancs patch amely lehetővé teszi az erőforrás specifikációjának egy részének megváltoztatását, a parancssorba csak a módosított részt megadva. A parancs kicserél ugyanúgy működik, mint a szerkesztés, de mindent manuálisan kell megtenni: le kell tölteni az erőforrás aktuális specifikációját, például a kubectl get -o yaml, szerkeszteni kell, majd használni a kicserél az erőforrás frissítésére a módosított specifikációval. A parancs kicserél nem fog működni, ha az erőforrás olvasása és cseréje között bármilyen változás történt.

Kubernetes API

Valószínűleg ismeri a CoreV1().Pods().Update(), replaceNamespacedService vagy patch_namespaced_deployment, ha klaszterekkel dolgozik a Kubernetes API-hoz kapcsolódó kliens könyvtárral valamely programozási nyelven. A könyvtár ezeket a módszereket HTTP protokollon keresztül kezeli, a PUT és PATCHmetódusokat használva. Eközben update és kicserél use PUT, és patch, bármennyire is banálisan hangzik, használja a PATCH.

Érdemes megjegyezni, hogy kubectl szintén dolgozik klaszterekkel az API-n keresztül. Más szóval, kubectl– egy Go-nyelvű klienskönyvtár feletti réteg, amely jelentősen lehetővé teszi, hogy a parancsokat kompaktabb és olvashatóbb formában nyújtsa a szokásos API-funkciók mellett. Például, ahogyan már észlelhettétek, a metódus apply nem volt említve a fenti bekezdésben. Jelenleg (2020 május, jegyzet: fordító) a logika kubectl apply, azaz a nem létező erőforrások létrehozása és a meglévők frissítése, teljesen a kód oldalán működik kubectl. Erőfeszítések történnek a logika apply átvitelére az API oldalára, de ez még mindig bétatesztelési fázisban van. Részletesebben alább írok.

Alapértelmezett patch

Legjobban alkalmazni patch, ha frissíteni szeretné a forrást. Így működnek a Kubernetes API feletti klienskönyvtárak, valamint kubectl (nem meglepő, hiszen ez egy klienskönyvtár burka, jegyzet: fordító).

Stratégiai szinten működni

Minden parancs kubectl apply, szerkesztés és patch azt a metódust alkalmazza PATCH HTTP-kérésekben a meglévő forrás frissítésére. Ha részletesebben megvizsgáljuk a parancsok megvalósítását, akkor mindegyiknél a strategic-merge patching megközelítést használják a források frissítésére, bár a parancs patch más megközelítéseket is alkalmazhat (erről részletesebben alább). A strategic-merge patching megközelítés megpróbálja "helyesen csinálni" a megadott specifikáció és a meglévő specifikáció egyesítését. Konkrétabban próbálja ötvözni mind az objektumokat, mind a tömböket, ami azt jelenti, hogy a módosítások jellemzően aditívak. Például egy parancs futtatása patch új környezeti változóval a pod konténer specifikációjában azt eredményezi, hogy ez a környezeti változó hozzáadódik a meglévő környezeti változókhoz, nem felülírja azokat. Ezen megközelítés használatával történő törléshez a paraméter értékét nullra kell állítani a megadott specifikációban. Mely parancsok kubectl a legjobban alkalmasak a frissítéshez?

Ha saját forrásaikat a kubectl applysegítségével hozza létre és kezeli őket, frissítéskor mindig érdemes használni kubectl applykülönböző kulcsokat adhasson meg minden egyes sugárzáskor. Az egyik lehetőség, hogy kubectl a konfiguráció kezelésére és a kérelmezett változások nyomon követésére alkalmazásonként. Azt, hogy mindig érdemes használni apply azért, mert nyomon követi az előzőleg alkalmazott specifikációt, lehetővé teszi számára, hogy tudja, mikor törlik kifejezetten a specifikáció tulajdonságait és a tömb elemeit. Ez lehetővé teszi a használatát apply a tömb tulajdonságainak és elemeinek eltávolítására, míg a szokásos stratégiai egyesítés nem fog működni. Parancsok szerkesztés és patch nem frissítik a megjegyzéseket, amelyeket kubectl apply használ a módosításainak nyomon követésére, ezért bármely módosítás, ami nyomon követett és az API-n keresztül történt, de parancsokkal lett végrehajtva szerkesztés és patch, a későbbi parancsok számára láthatatlan. applysorok és 1 oszlop: apply nem távolítja el őket, még akkor sem, ha nem szerepelnek a belső specifikációban a apply (A dokumentáció szerint szerkesztés és patch frissítik a megjegyzéseket, amelyeket apply, de a gyakorlatban – nem).

Ha nem használod a parancsot apply, akkor használható mint szerkesztés, valamint patch, kiválasztva azt a parancsot, amely jobban megfelel a végrehajtott módosításnak. A specifikációs tulajdonságok hozzáadásakor és módosításakor mindkét megközelítés körülbelül hasonló. A specifikációs tulajdonságok vagy tömb elemek eltávolítása szerkesztés az egyetlen végrehajtásként működik, apply, beleértve azt is, hogy nyomon követi, mi volt a specifikáció a módosítás előtt és után, így kifejezetten eltávolíthatók a tulajdonságok és a tömb elemei az erőforrásból. A tulajdonság értékét tisztára kell állítani a specifikációban a patch, hogy eltávolíthasd az erőforrásból. A tömb elemének eltávolítása stratégiai egyesítéssel bonyolultabb, mivel egyesítési direktívák használata szükséges. Lásd az alábbi frissítési megközelítéseket, hogy választhass elfogadhatóbb alternatívákat.

A kliens könyvtárban az olyan frissítési módszerek megvalósításához, amelyek viselkednek, mint a fent említett parancsok kubectl, a kérésekben be kell állítani content-type be. application/strategic-merge-patch+json. Ha el szeretnéd távolítani a tulajdonságokat a specifikációból, kifejezetten null-ra kell őket állítani, hasonlóan kubectl patch. Ha tömbelemeket kell eltávolítani, figyelembe kell venni az egyesítési direktívákat a frissítési specifikációban, vagy más frissítési megközelítést kell használni.

Más frissítési megközelítések

A Kubernetesben két másik frissítési megközelítés érhető el: JSON egyesítő patch és JSON patch. A JSON merge patch megközelítés részleges Kubernetes-specifikációt fogad el bemenetként, és hasonlóan működik, mint a strategic-merge patching objektumok összevonásakor. A két megközelítés közötti különbség, hogy az csak tömbök cseréjét támogatja, beleértve a konténer tömböt a pod specifikációban. Ez azt jelenti, hogy a JSON merge patch használatakor teljes specifikációkat kell megadnia minden konténer esetében, ha bármely konténer bármely tulajdonságát módosítja. Ennek a megközelítésnek az hasznos a tömb elemek eltávolítására a specifikációból. A parancssori felületen a JSON merge patch-et a következőképpen választhatja ki kubectl patch --type=merge. A Kubernetes API-val való munka során a kérés metódusát kell használni PATCH és törléshez content-type be. application/merge-patch+json.

A JSON patch megközelítése, ahelyett hogy a forrásról részleges specifikációt adna meg, a módosítások listáját használja, amelyeket a forráshoz kíván hozzáadni, ahol minden tömbelem egy módosítás leírását képviseli. Ez a megközelítés rugalmasabb és hatékonyabb módja a végrehajtott módosítások kifejezésének, azonban az egyedi módosítási lista külső, nem Kubernetes formátumban történik, ahelyett, hogy részleges specifikációt küldene a forrásról. A kubectl JSON patch-et a következőképpen választhatja ki kubectl patch --type=json. A Kubernetes API használata esetén ez a megközelítés a kérés metódusával működik PATCH és törléshez content-type be. application/json-patch+json.

Biztosra akar menni - használja a replace-t

Néhány esetben biztosnak kell lennie abban, hogy a forrás nem módosul a forrás olvasásának és frissítésének ideje között. Más szóval, meg kell győződnie arról, hogy minden módosítás atomikus. Ilyen esetben a források frissítéséhez a kicserél. Például, ha van egy ConfigMap egy számlálóval, amelyet több forrás frissít, biztosra kell menni, hogy a két forrás nem frissíti egyszerre a számlálót, ami frissítési veszteséget okoz. A szekvencia bemutatásához képzelje el, hogyan történik a rendezés az patch:

  • A és B megkapja a forrás aktuális állapotát az API-ból
  • Mindkettő helyben frissíti a specifikációt, növelve a számlálót egy egységgel, és hozzátéve "A" vagy "B" a "updated-by" megjegyzéshez
  • A kicsit gyorsabban frissíti a forrást
  • B frissíti a forrást

Az A frissítés eredményeképpen elveszett. Utolsó művelet patch nyer, a számláló egy helyett kettővel nő, és az "updated-by" megjegyzés értéke "B"-vel végződik és nem tartalmazza az "A"-t. Hasonlítsuk össze a fenti állítást azzal, ami történik, amikor frissítéseket végrehajtunk a megközelítés használatával kicserél:

  • A és B megkapja a forrás aktuális állapotát az API-ból
  • Mindkettő helyben frissíti a specifikációt, növelve a számlálót egy egységgel, és hozzátéve "A" vagy "B" a "updated-by" megjegyzéshez
  • A kicsit gyorsabban frissíti a forrást
  • B megpróbálja frissíteni az erőforrást, de a frissítést az API elutasítja, mert a specifikációban szereplő erőforrás verziója kicserél nem egyezik a Kubernetes aktuális erőforrás verziójával, mivel az erőforrás verziója megnőtt az A általi replace művelet végrehajtása során.

A fenti esetben B-nek újra le kell kérnie az erőforrást, módosítania kell az új állapotban, majd újra meg kell próbálnia kicserél. Ennek eredményeként a számláló két egységgel fog növekedni, és az "updated-by" megjegyzés "AB"-t fog tartalmazni a végén.

A fent látható példa azt feltételezi, hogy a végrehajtás során kicserél teljes cserét végeznek az összes erőforráson. A specifikáció, amelyet használnak kicserél, nem lehet részleges, vagy részekből mint a apply, hanem teljes, beleértve a ) már feldolgozásra került a watch által; hozzáadását a specifikáció metadatához. Ha nem adtad meg ) már feldolgozásra került a watch által; vagy az általad megadott verzió nem aktuális, a csere el lesz utasítva. Így a legjobb megközelítés kicserél az, hogy a forrást leolvassuk, frissítjük, majd azonnal kicseréljük. Használva kubectl, ez így nézhet ki:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "új érték"' 
    | kubectl replace -f -

Érdemes megjegyezni, hogy a következő két parancs egymás után végrehajtva sikeresen fog teljesülni, mivel deployment.yaml nem tartalmazza a 'metadata.resourceVersion' attribútumot. $ kubectl create -f deployment.yaml $ kubectl replace -f deployment.yaml

Első pillantásra úgy tűnhet, hogy ez ellentmond a fent említetteknek, például "a specifikáció metadatájához való hozzáadás". Ez így van? Nem, nem így van, mivel ha

észreveszi, hogy nem adta meg ) már feldolgozásra került a watch által; , akkor meg fogja olvasni az erőforrást, és hozzáadja a megadott specifikációhoz, és csak ezt követően hajtja végre kubectl . Mivel ez potenciálisan veszélyes, ha az atomaritásra támaszkodunk, ez a varázslat teljesen a ) már feldolgozásra került a watch által;felén működik, nem érdemes rá támaszkodni API-t kezelő klienskönyvtárak használatakor. Ebben az esetben le kell kérnie az aktuális erőforrás specifikációt, frissítenie kell azt, majd végrehajtania kell kicseréla kérést. kubectlNem lehet patch – csere végrehajtva PUT запрос.

Нельзя сделать patch – делаем replace

Néha szükség lehet olyan módosításokra, amelyeket az API nem tud kezelni. Ilyen esetekben kényszeríthetjük az erőforrás cseréjét azzal, hogy töröljük és újra létrehozzuk azt. Ezt a következő paranccsal lehet megtenni: kubectl replace --force. A parancs azonnal eltávolítja az erőforrásokat, majd újból létrehozza azokat a megadott specifikációval. Az API-ban nincs \ gracePeriodSeconds nullára (0) állítva és propagationPolicy a \

Figyelem: ez a megközelítés potenciálisan veszélyes, és határozatlan állapothoz vezethet

A szerveroldalon

Ahogy már említettük, a Kubernetes fejlesztői dolgoznak az API logikájának megvalósításán. apply a kubectl A logika apply elérhető a Kubernetes 1.18-as verziójában a kubectl apply --server-side vagy az API-n keresztül, a következő módszer alkalmazásával: PATCH a content-type application/apply-patch+YAML.

Megjegyzés: A JSON szintén érvényes YAML, így a specifikációt JSON formában is elküldheti, még akkor is, ha content-type lesz application/apply-patch+yaml.

Ezen kívül a logika kubectl elérhetővé válik mindenki számára az API-n keresztül, apply a szerveroldalon nyomon követi a specifikációs mezők felelőseit, ezáltal biztosítva a biztonságos többszörös hozzáférést a konfliktusmentes szerkesztéshez. Más szóval, ha apply a szerveroldalon széles körben elérhetővé válik, egy univerzális biztonságos erőforráskezelő interfész jön létre különböző kliensek számára, például kubectl, Pulumi vagy Terraform, GitOps, valamint egyedi szkriptek, amelyek kliens könyvtárakat használnak.

Összegzés

Remélem, hogy ez a rövid áttekintés a klaszterek erőforrásainak frissítési módjairól hasznos volt az Ön számára. Jó tudni, hogy a különbségek nem csupán az apply és a replace között állnak fenn, hiszen az erőforrást frissítheti apply, edit, patch vagy replace segítségével is. Elvileg mindegyik megközelítésnek megvan a maga alkalmazási területe. Atomi módosításokhoz a replace a preferált, más esetekben strategikus egyesítési patch alkalmazása ajánlott apply mellett. Végső soron remélem, hogy megértette, hogy nem érdemes a Google-re vagy a StackOverflow-ra támaszkodni a \

Megfelelő összehasonlítás a Kubernetes Apply, Replace és Patch műveletei között

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