3-cestné zlúčenie do werf: nasadenie do Kubernetes s Helmom „na steroidoch“

Stalo sa to, na čo sme (a nielen my) dlho čakali: werf, naša utilita s otvoreným zdrojovým kódom na vytváranie aplikácií a ich doručovanie do Kubernetes, teraz podporuje aplikovanie zmien pomocou 3-cestných opráv na zlúčenie! Okrem toho je možné prijať existujúce zdroje K8 do verzií Helm bez toho, aby ste tieto zdroje prebudovali.

3-cestné zlúčenie do werf: nasadenie do Kubernetes s Helmom „na steroidoch“

Ak je to veľmi krátke, potom dáme WERF_THREE_WAY_MERGE=enabled — dostaneme nasadenie „ako v kubectl apply“, kompatibilný s existujúcimi inštaláciami Helm 2 a ešte o niečo viac.

Začnime však teóriou: čo presne sú 3-way-merge patche, ako ľudia prišli na prístup k ich generovaniu a prečo sú dôležité v procesoch CI/CD s infraštruktúrou založenou na Kubernetes? A potom sa pozrime, čo je trojcestné zlúčenie vo werf, aké režimy sa štandardne používajú a ako to spravovať.

Čo je to 3-cestná záplata?

Začnime teda úlohou uvedenia zdrojov popísaných v manifestoch YAML do Kubernetes.

Na prácu so zdrojmi ponúka Kubernetes API tieto základné operácie: vytvorenie, oprava, nahradenie a odstránenie. Predpokladá sa, že s ich pomocou je potrebné skonštruovať pohodlné kontinuálne zavádzanie zdrojov do klastra. Ako?

kubectl imperatívne príkazy

Prvým prístupom k správe objektov v Kubernetes je použitie imperatívnych príkazov kubectl na vytvorenie, úpravu a odstránenie týchto objektov. Jednoducho povedané:

  • tímom kubectl run môžete spustiť Deployment alebo Job:
    kubectl run --generator=deployment/apps.v1 DEPLOYMENT_NAME --image=IMAGE
  • tímom kubectl scale — zmeniť počet replík:
    kubectl scale --replicas=3 deployment/mysql
  • atď

Tento prístup sa môže zdať na prvý pohľad pohodlný. Existujú však problémy:

  1. Je to ťažké automatizovať.
  2. Ako odrážať konfiguráciu v Git? Ako skontrolovať zmeny, ku ktorým dochádza v klastri?
  3. Ako poskytnúť reprodukovateľnosť konfigurácie pri reštarte?
  4. ...

Je jasné, že tento prístup sa nehodí k ukladaniu aplikácií a infraštruktúry ako kódu (IaC; alebo dokonca GitOps ako modernejšia možnosť, ktorá si získava na popularite v ekosystéme Kubernetes). Preto tieto príkazy nedostali ďalší vývoj v kubectl.

Vytvorte, získajte, nahraďte a odstráňte operácie

S primárom tvorba je to jednoduché: pošlite manifest do prevádzky create kube api a zdroj bol vytvorený. YAML reprezentácia manifestu môže byť uložená v Git a vytvorená pomocou príkazu kubectl create -f manifest.yaml.

С odstránenie také jednoduché: nahradiť to isté manifest.yaml z Gitu do tímu kubectl delete -f manifest.yaml.

Operácie replace umožňuje úplne nahradiť konfiguráciu zdroja novou, bez opätovného vytvárania prostriedku. To znamená, že pred vykonaním zmeny zdroja je logické spýtať sa na aktuálnu verziu pomocou operácie get, zmeňte ho a aktualizujte pomocou operácie replace. kube apiserver je zabudovaný optimistické zamykanie a ak po operácii get objekt sa zmenil, potom operácia replace nebude to fungovať.

Ak chcete uložiť konfiguráciu v systéme Git a aktualizovať ju pomocou funkcie nahradiť, musíte vykonať operáciu get, zlúčte konfiguráciu z Git s tým, čo sme dostali, a spustite replace. V predvolenom nastavení vám kubectl umožňuje použiť iba príkaz kubectl replace -f manifest.yamlKde manifest.yaml — už plne pripravený (v našom prípade zlúčený) manifest, ktorý je potrebné nainštalovať. Ukazuje sa, že používateľ potrebuje implementovať manifesty zlúčenia, a to je netriviálna záležitosť...

Za zmienku tiež stojí, že hoci manifest.yaml a je uložený v Git, nemôžeme vopred vedieť, či je potrebné vytvoriť objekt alebo ho aktualizovať - ​​to musí urobiť používateľský softvér.

Celkom: môžeme vybudovať nepretržité zavádzanie iba pomocou vytvoriť, nahradiť a odstrániť, čím sa zabezpečí, že konfigurácia infraštruktúry je uložená v Git spolu s kódom a pohodlným CI/CD?

V zásade môžeme... Za toto budete musieť implementovať operáciu zlúčenia manifesty a nejaký druh väzby, že:

  • kontroluje prítomnosť objektu v klastri,
  • vykoná počiatočné vytvorenie zdroja,
  • aktualizuje alebo vymaže.

Pri aktualizácii si to uvedomte zdroj sa mohol zmeniť od minula get a automaticky riešiť prípad optimistického uzamykania - opakujte pokusy o aktualizáciu.

Prečo však znovu vynájsť koleso, keď kube-apiserver ponúka iný spôsob aktualizácie zdrojov: operáciu patch, ktorý zbaví užívateľa niektorých z popísaných problémov?

Náplasť

Teraz sa dostaneme k náplastiam.

Opravy sú primárnym spôsobom, ako aplikovať zmeny na existujúce objekty v Kubernetes. Prevádzka patch funguje to takto:

  • používateľ kube-apiserver musí poslať opravu vo formáte JSON a špecifikovať objekt,
  • a samotný apiserver sa bude zaoberať aktuálnym stavom objektu a dovedie ho do požadovanej podoby.

Optimistické uzamykanie nie je v tomto prípade potrebné. Táto operácia je skôr deklaratívna ako nahradiť, aj keď sa to na prvý pohľad môže zdať naopak.

Týmto spôsobom:

  • pomocou operácie create vytvoríme objekt podľa manifestu z Gitu,
  • skrz delete — vymazať, ak už objekt nie je potrebný,
  • skrz patch — zmeníme objekt a uvedieme ho do podoby opísanej v Git.

Aby ste to však dosiahli, musíte vytvoriť správna záplata!

Ako fungujú záplaty v Helm 2: 2-way-merge

Keď prvýkrát nainštalujete vydanie, Helm vykoná operáciu create pre zdroje grafov.

Pri aktualizácii vydania Helm pre každý zdroj:

  • zohľadňuje opravu medzi verziou zdroja z predchádzajúceho grafu a aktuálnou verziou grafu,
  • aplikuje túto záplatu.

Tento patch budeme nazývať 2-way merge patch, pretože na jeho tvorbe sa podieľajú 2 manifesty:

  • manifest prostriedkov z predchádzajúceho vydania,
  • manifest zdroja z aktuálneho zdroja.

Pri odstraňovaní prevádzky delete v kube apiserver sa volá pre prostriedky, ktoré boli deklarované v predchádzajúcom vydaní, ale nie sú deklarované v aktuálnom.

Prístup opráv obojsmerného zlúčenia má problém: vedie k nesynchronizované so skutočným stavom prostriedku v klastri a manifestom v Git.

Ilustrácia problému s príkladom

  • V systéme Git je v grafe uložený manifest, v ktorom je pole image Na nasadení záleží ubuntu:18.04.
  • Používateľ cez kubectl edit zmenil hodnotu tohto poľa na ubuntu:19.04.
  • Pri opätovnom nasadení mapy Helm nevygeneruje záplatu, pretože pole image v predchádzajúcej verzii vydania a v aktuálnom grafe sú rovnaké.
  • Po opätovnom nasadení image zvyšky ubuntu:19.04, aj keď graf hovorí ubuntu:18.04.

Dostali sme desynchronizáciu a stratili sme deklaratívnosť.

Čo je synchronizovaný zdroj?

Všeobecne povedané plne Nie je možné získať zhodu medzi manifestom prostriedku v spustenom klastri a manifestom z Gitu. Pretože v skutočnom manifeste môžu byť anotácie/návestia služby, ďalšie kontajnery a ďalšie údaje, ktoré niektoré radiče pridávajú a odstraňujú zo zdroja dynamicky. Tieto údaje nemôžeme a ani nechceme uchovávať v systéme Git. Chceme však, aby polia, ktoré sme explicitne špecifikovali v Git, nadobudli po zavedení príslušné hodnoty.

Ukazuje sa to tak všeobecne pravidlo synchronizovaného zdroja: pri zavádzaní zdroja môžete zmeniť alebo odstrániť iba tie polia, ktoré sú explicitne špecifikované v manifeste z Git (alebo boli špecifikované v predchádzajúcej verzii a teraz sú odstránené).

3-way merge patch

ústredné myšlienkou 3-way merge patch: vygenerujte opravu medzi poslednou použitou verziou manifestu z Gitu a cieľovou verziou manifestu z Gitu, pričom sa zohľadní aktuálna verzia manifestu zo spusteného klastra. Výsledná oprava musí byť v súlade s pravidlom synchronizovaných zdrojov:

  • nové polia pridané do cieľovej verzie sa pridávajú pomocou opravy;
  • predtým existujúce polia v poslednej použitej verzii a neexistujúce v cieľovej verzii sa resetujú pomocou opravy;
  • polia v aktuálnej verzii objektu, ktoré sa líšia od cieľovej verzie manifestu, sa aktualizujú pomocou opravy.

Práve na tomto princípe generuje záplaty kubectl apply:

  • posledná použitá verzia manifestu je uložená v anotácii samotného objektu,
  • cieľ - prevzatý zo špecifikovaného súboru YAML,
  • aktuálny je z bežiaceho klastra.

Teraz, keď sme vyriešili teóriu, je čas povedať vám, čo sme robili vo werf.

Aplikovanie zmien na werf

Predtým werf, podobne ako Helm 2, používal záplaty s obojsmerným zlúčením.

Opravte náplasť

Aby sme mohli prejsť na nový typ záplat - 3-way-merge - ako prvý krok sme zaviedli tzv. opravné záplaty.

Pri nasadzovaní sa používa štandardná oprava 2-way-merge, ale werf dodatočne vygeneruje opravu, ktorá by synchronizovala skutočný stav zdroja s tým, čo je napísané v Git (takáto oprava je vytvorená pomocou rovnakého pravidla synchronizovaného prostriedku opísaného vyššie) .

Ak dôjde k desynchronizácii, na konci nasadenia používateľ dostane VAROVANIE so zodpovedajúcou správou a opravou, ktorú je potrebné použiť, aby sa zdroj dostal do synchronizovanej podoby. Tento patch je zaznamenaný aj v špeciálnej anotácii werf.io/repair-patch. Predpokladá sa, že ruky užívateľa sám použije túto opravu: werf ju nebude aplikovať vôbec.

Generovanie opravných opráv je dočasné opatrenie, ktoré vám umožňuje skutočne otestovať vytváranie opráv na základe princípu trojcestného zlúčenia, ale tieto opravy neaplikujte automaticky. V súčasnosti je tento prevádzkový režim štandardne povolený.

3-way-merge patch len pre nové vydania

Od 1. decembra 2019 začínajú beta a alfa verzie werf v predvolenom nastavení použite plnohodnotné 3-way-merge patche na aplikovanie zmien len na nové vydania Helm zavedené cez werf. Existujúce vydania budú naďalej používať prístup obojsmerného zlúčenia + opravy.

Tento prevádzkový režim je možné aktivovať explicitne nastavením WERF_THREE_WAY_MERGE_MODE=onlyNewReleases teraz.

Poznámka: funkcia sa objavila vo werf počas niekoľkých vydaní: v alfa kanáli bola pripravená s verziou v1.0.5-alpha.19a v beta kanáli - s v1.0.4-beta.20.

3-way-merge patch pre všetky vydania

Od 15. decembra 2019 začnú beta a alfa verzie werf štandardne používať úplné záplaty trojcestného zlúčenia, aby sa zmeny aplikovali na všetky vydania.

Tento prevádzkový režim je možné aktivovať explicitne nastavením WERF_THREE_WAY_MERGE_MODE=enabled teraz.

Čo robiť s automatickým škálovaním zdrojov?

V Kubernetes existujú 2 typy automatického škálovania: HPA (horizontálne) a VPA (vertikálne).

Horizontálne automaticky vyberie počet replík, vertikálne - počet zdrojov. Počet replík aj požiadavky na prostriedky sú špecifikované v manifeste prostriedku (pozri Manifest prostriedkov). spec.replicas alebo spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory и ostatné).

Problém: Ak používateľ nakonfiguruje zdroj v grafe tak, aby špecifikoval určité hodnoty pre zdroje alebo repliky a pre tento zdroj sú povolené automatické škálovače, potom pri každom nasadení werf obnoví tieto hodnoty na to, čo je napísané v manifeste grafu. .

Existujú dve riešenia problému. Na začiatok je najlepšie vyhnúť sa explicitnému zadávaniu hodnôt s automatickou mierkou v manifeste grafu. Ak táto možnosť nie je z nejakého dôvodu vhodná (napríklad preto, že je vhodné nastaviť počiatočné limity zdrojov a počet replík v grafe), werf ponúka nasledujúce anotácie:

  • werf.io/set-replicas-only-on-creation=true
  • werf.io/set-resources-only-on-creation=true

Ak je takáto anotácia prítomná, werf nezresetuje zodpovedajúce hodnoty pri každom nasadení, ale nastaví ich len pri prvotnom vytvorení prostriedku.

Bližšie informácie nájdete v projektovej dokumentácii k HPA и VPA.

Zakážte používanie 3-cestnej náplasti

Používateľ môže v súčasnosti zakázať používanie nových záplat vo werf pomocou premennej prostredia WERF_THREE_WAY_MERGE_MODE=disabled. Avšak počnúc Od 1 už tento zákaz nebude platiť. a bude možné použiť iba 3-way-merge patche.

Prijatie zdrojov v werf

Zvládnutie metódy aplikovania zmien pomocou záplat 3-way-merge nám umožnilo okamžite implementovať takú funkciu, ako je prijatie zdrojov existujúcich v klastri do vydania Helm.

Helm 2 má problém: nemôžete pridať zdroj do manifestov grafu, ktorý už existuje v klastri, bez toho, aby ste tento zdroj znova vytvorili od začiatku (pozri. # 6031, # 3275). Naučili sme werf akceptovať existujúce zdroje na uvoľnenie. Ak to chcete urobiť, musíte nainštalovať anotáciu na aktuálnu verziu prostriedku z bežiaceho klastra (napríklad pomocou kubectl edit):

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

Teraz musí byť zdroj opísaný v tabuľke a keď werf nabudúce nasadí vydanie s príslušným názvom, existujúci zdroj bude prijatý do tohto vydania a zostane pod jeho kontrolou. Okrem toho v procese prijímania prostriedku na uvoľnenie werf prenesie aktuálny stav prostriedku z bežiaceho klastra do stavu opísaného v grafe pomocou rovnakých opráv 3-cestného zlúčenia a pravidla synchronizovaného prostriedku.

Poznámka: nastavenie WERF_THREE_WAY_MERGE_MODE neovplyvňuje adopciu zdrojov - v prípade adopcie sa vždy používa 3-way-merge patch.

Podrobnosti - v dokumentáciu.

Závery a plány do budúcnosti

Dúfam, že po tomto článku je už jasnejšie, čo sú 3-way-merge patche a prečo k nim prišli. Z praktického hľadiska vývoja projektu werf bola ich implementácia ďalším krokom k zlepšeniu nasadenia podobného Helmu. Teraz môžete zabudnúť na problémy so synchronizáciou konfigurácie, ktoré často vznikali pri používaní Helm 2. Zároveň bola do vydania Helm pridaná nová užitočná funkcia preberania už stiahnutých zdrojov Kubernetes.

Stále existujú určité problémy a výzvy s nasadením podobným Helm, ako je napríklad používanie šablón Go, ktorým sa budeme aj naďalej venovať.

Informácie o spôsoboch aktualizácie zdrojov a ich prijatí nájdete aj na túto dokumentačnú stránku.

Kormidlo 3

Hodné osobitnej poznámky prepustený len nedávno nová hlavná verzia Helm - v3 - ktorá tiež používa 3-way-merge patche a zbavuje sa Tillera. Vyžaduje sa nová verzia Helm migrácia existujúce inštalácie, aby ste ich skonvertovali do formátu úložiska nového vydania.

Werf sa momentálne zbavil používania Tiller, prešiel na trojcestné zlúčenie a pridal oveľa viac, pričom zostáva kompatibilný s existujúcimi inštaláciami Helm 2 (nie je potrebné spúšťať žiadne migračné skripty). Preto kým werf neprejde na Helm 3, používatelia werf nestrácajú hlavné výhody Helm 3 oproti Helmu 2 (má ich aj werf).

Prechod werf na kódovú základňu Helm 3 je však nevyhnutný a stane sa tak v blízkej budúcnosti. Pravdepodobne to bude werf 1.1 alebo werf 1.2 (v súčasnosti je hlavnou verziou werf 1.0; viac informácií o zariadení na vytváranie verzií werf nájdete na tu). Počas tejto doby bude mať Helm 3 čas na stabilizáciu.

PS

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár