Problém „chytrého“ čištění obrázků kontejnerů a jeho řešení ve werf

Problém „chytrého“ čištění obrázků kontejnerů a jeho řešení ve werf

Článek pojednává o problémech čištění obrazů, které se hromadí v registrech kontejnerů (Docker Registry a jeho analogy) v realitě moderních CI/CD potrubí pro cloudové nativní aplikace dodávané do Kubernetes. Jsou uvedena hlavní kritéria pro relevanci obrázků az toho plynoucí obtíže při automatizaci čištění, úspoře místa a plnění potřeb týmů. Nakonec vám na příkladu konkrétního Open Source projektu řekneme, jak lze tyto potíže překonat.

úvod

Počet obrázků v registru kontejnerů může rychle narůstat, zabírat více úložného prostoru a výrazně tak zvyšovat jeho náklady. Pro kontrolu, omezení nebo udržení přijatelného růstu prostoru obsazeného v registru je akceptováno:

  1. používat pevný počet značek pro obrázky;
  2. obrázky nějakým způsobem vyčistit.


První omezení je někdy přijatelné pro malé týmy. Pokud mají vývojáři dostatek trvalých značek (latest, main, test, boris atd.), registr se nezvětší a po dlouhou dobu nebudete muset vůbec přemýšlet o jeho čištění. Všechny nepodstatné obrázky se totiž vymažou a na úklid prostě nezbude práce (vše dělá běžný popelář).

Tento přístup však značně omezuje vývoj a je zřídka použitelný na moderní projekty CI/CD. Nedílnou součástí vývoje bylo automatizace, která umožňuje mnohem rychleji testovat, nasazovat a poskytovat uživatelům nové funkce. Například ve všech našich projektech se s každým potvrzením automaticky vytvoří kanál CI. V něm se obraz sestaví, otestuje, zavede do různých obvodů Kubernetes pro ladění a zbývající kontroly, a pokud je vše v pořádku, změny se dostanou ke koncovému uživateli. A to už není žádná raketová věda, ale každodenní jev pro mnohé - s největší pravděpodobností pro vás, protože čtete tento článek.

Vzhledem k tomu, že oprava chyb a vývoj nových funkcí probíhá paralelně a vydání lze provádět několikrát denně, je zřejmé, že vývojový proces je doprovázen značným počtem revizí, což znamená velké množství obrázků v registru. V důsledku toho vyvstává otázka organizace efektivního čištění registru, tzn. odstranění irelevantních obrázků.

Jak ale vůbec určit, zda je obrázek relevantní?

Kritéria relevance obrázku

V naprosté většině případů budou hlavními kritérii:

1. První (nejviditelnější a nejkritičtější ze všech) jsou obrázky, které aktuálně používaný v Kubernetes. Odstranění těchto obrazů může vést ke značným nákladům na prostoje ve výrobě (například obrazy mohou být vyžadovány pro replikaci) nebo zmařit úsilí týmu při ladění kterékoli ze smyček. (Z tohoto důvodu jsme dokonce udělali speciální Vývozci Prometheus, která sleduje nepřítomnost takových obrázků v jakémkoli clusteru Kubernetes.)

2. Druhý (méně zřejmý, ale také velmi důležitý a opět souvisí s vykořisťováním) - obrazy, které nutné pro vrácení zpět v případě zjištění závažných problémů v aktuální verzi. Například v případě Helmu se jedná o obrázky, které se používají v uložených verzích vydání. (Mimochodem, ve výchozím nastavení je v Helmu limit 256 revizí, ale je nepravděpodobné, že by někdo skutečně potřeboval uložit takový velké množství verzí?..) Koneckonců verze ukládáme především proto, abychom je mohli použít později, tzn. v případě potřeby se k nim „vrátit zpět“.

3. Třetí - vývojářské potřeby: Všechny obrázky související s jejich aktuální prací. Pokud například uvažujeme o PR, pak má smysl ponechat obrázek odpovídající poslednímu commitu a řekněme předchozímu commitu: vývojář se tak může rychle vrátit k jakémukoli úkolu a pracovat s nejnovějšími změnami.

4. Za čtvrté - obrázky, které odpovídají verzím naší aplikace, tj. jsou konečným produktem: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra atd.

Pozn.: Zde definovaná kritéria byla formulována na základě zkušeností z interakce s desítkami vývojových týmů z různých společností. Tato kritéria se však samozřejmě mohou lišit v závislosti na specifikách ve vývojových procesech a použité infrastruktuře (například se nepoužívá Kubernetes).

Způsobilost a stávající řešení

Oblíbené služby s kontejnerovými registry zpravidla nabízejí vlastní zásady čištění obrazu: v nich můžete definovat podmínky, za kterých je značka odstraněna z registru. Tyto podmínky jsou však omezeny parametry, jako jsou názvy, čas vytvoření a počet značek*.

* Závisí na konkrétních implementacích registru kontejnerů. Zvažovali jsme možnosti následujících řešení: Azure CR, Docker Hub, ECR, GCR, GitHub Packages, GitLab Container Registry, Harbor Registry, JFrog Artifactory, Quay.io - od září 2020.

Tato sada parametrů zcela postačuje ke splnění čtvrtého kritéria – tedy k výběru obrázků, které odpovídají verzím. U všech ostatních kritérií je však nutné zvolit nějaké kompromisní řešení (tvrdší nebo naopak mírnější politiku) – v závislosti na očekávání a finančních možnostech.

Například třetí kritérium – související s potřebami vývojářů – lze vyřešit organizací procesů v rámci týmů: specifické pojmenování obrázků, udržování speciálních seznamů povolených a interních dohod. Ale nakonec je stále potřeba automatizovat. A pokud možnosti hotových řešení nestačí, musíte udělat něco vlastního.

Situace s prvními dvěma kritérii je podobná: nelze je uspokojit bez příjmu dat z externího systému – toho, kde jsou nasazeny aplikace (v našem případě Kubernetes).

Ilustrace pracovního postupu v Gitu

Řekněme, že v Gitu pracujete s něčím takovým:

Problém „chytrého“ čištění obrázků kontejnerů a jeho řešení ve werf

Ikona s hlavičkou v diagramu označuje obrázky kontejnerů, které jsou aktuálně nasazeny v Kubernetes pro libovolné uživatele (koncové uživatele, testeři, manažeři atd.) nebo je používají vývojáři pro ladění a podobné účely.

Co se stane, když zásady čištění umožňují pouze zachovat obrázky (ne odstranit) podle názvů daných značek?

Problém „chytrého“ čištění obrázků kontejnerů a jeho řešení ve werf

Je zřejmé, že takový scénář nikoho nepotěší.

Co se změní, pokud zásady umožní nesmazat obrázky? podle daného časového intervalu / počtu posledních commitů?

Problém „chytrého“ čištění obrázků kontejnerů a jeho řešení ve werf

Výsledek je mnohem lepší, ale k ideálu má stále daleko. Koneckonců stále máme vývojáře, kteří potřebují obrázky v registru (nebo dokonce nasazené v K8) k odladění chyb...

Abychom shrnuli současnou situaci na trhu: funkce dostupné v registrech kontejnerů nenabízejí dostatečnou flexibilitu při čištění a hlavním důvodem je žádný způsob interakce s vnějším světem. Ukazuje se, že týmy, které vyžadují takovou flexibilitu, jsou nuceny samostatně implementovat odstranění obrazu „zvenčí“ pomocí Docker Registry API (nebo nativního API odpovídající implementace).

Hledali jsme však univerzální řešení, které by automatizovalo čištění obrazu pro různé týmy pomocí různých registrů...

Naše cesta k univerzálnímu čištění obrazu

Odkud tato potřeba pochází? Faktem je, že nejsme samostatná skupina vývojářů, ale tým, který slouží mnoha z nich najednou a pomáhá komplexně řešit problematiku CI/CD. A hlavním technickým nástrojem k tomu je utilita Open Source werf. Jeho zvláštností je, že neplní jedinou funkci, ale doprovází nepřetržité procesy dodávání ve všech fázích: od montáže až po nasazení.

Publikování obrázků do registru* (ihned po jejich vytvoření) je samozřejmou funkcí takového nástroje. A protože jsou tam obrázky umístěny pro uložení, pak - pokud vaše úložiště není neomezené - musíte být zodpovědní za jejich následné čištění. Jak jsme v tomto dosáhli úspěchu při splnění všech zadaných kritérií, bude diskutováno dále.

* Přestože samotné registry mohou být odlišné (Docker Registry, GitLab Container Registry, Harbor atd.), jejich uživatelé se potýkají se stejnými problémy. Univerzální řešení v našem případě nezávisí na implementaci registru, protože běží mimo samotné registry a nabízí stejné chování pro všechny.

Přestože jako příklad implementace používáme werf, doufáme, že použité přístupy budou užitečné pro další týmy, které čelí podobným potížím.

Tak jsme se zaměstnali vnější implementace mechanismu pro čištění obrazů - namísto těch schopností, které jsou již zabudovány do registrů pro kontejnery. Prvním krokem bylo použití Docker Registry API k vytvoření stejných primitivních politik pro počet značek a dobu jejich vytvoření (zmíněno výše). Přidáno k nim seznam povolených na základě obrázků používaných v nasazené infrastruktuře, tj. Kubernetes. U toho druhého stačilo použít Kubernetes API k iteraci všech nasazených zdrojů a získání seznamu hodnot image.

Toto triviální řešení vyřešilo nejkritičtější problém (kritérium č. 1), ale bylo pouze začátkem naší cesty ke zlepšení čisticího mechanismu. Dalším – a mnohem zajímavějším – krokem bylo rozhodnutí asociovat publikované obrázky s historií Git.

Schémata značení

Pro začátek jsme zvolili přístup, ve kterém by konečný obrázek měl uchovávat potřebné informace pro čištění, a postavili jsme proces na schématech značkování. Při publikování obrázku uživatel vybral konkrétní možnost označení (git-branch, git-commit nebo git-tag) a použila odpovídající hodnotu. V systémech CI byly tyto hodnoty nastaveny automaticky na základě proměnných prostředí. Ve skutečnosti konečný obrázek byl spojen s konkrétním primitivem Git, uložení potřebných dat pro čištění do štítků.

Tento přístup vyústil v sadu zásad, které umožnily použití Gitu jako jediného zdroje pravdy:

  • Při mazání větve/značky v Gitu byly automaticky smazány související obrázky v registru.
  • Počet obrázků přidružených ke značkám Git a odevzdáním lze řídit počtem značek použitých ve vybraném schématu a časem, kdy bylo přidružené potvrzení vytvořeno.

Celkově výsledná implementace uspokojila naše potřeby, ale brzy nás čekala nová výzva. Faktem je, že při používání schémat označování založených na Git primitivech jsme narazili na řadu nedostatků. (Jelikož jejich popis přesahuje rámec tohoto článku, může se každý seznámit s podrobnostmi zde.) Proto, když jsme se rozhodli přejít na efektivnější přístup k tagování (označování založené na obsahu), museli jsme přehodnotit implementaci čištění obrazu.

Nový algoritmus

Proč? Díky tagování založenému na obsahu může každý tag splnit několik potvrzení v Gitu. Při čištění obrázků už nemůžete předpokládat pouze z potvrzení, kde byla nová značka přidána do registru.

U nového čisticího algoritmu bylo rozhodnuto opustit schémata označování a sestavit proces metaobrazu, z nichž každý ukládá spoustu:

  • potvrzení, na kterém byla publikace provedena (nezáleží na tom, zda byl obrázek přidán, změněn nebo zůstal stejný v registru kontejnerů);
  • a náš interní identifikátor odpovídající sestavenému obrazu.

Jinými slovy, bylo poskytnuto propojení publikovaných značek s commity v Gitu.

Konečná konfigurace a obecný algoritmus

Při konfiguraci čištění mají nyní uživatelé přístup k zásadám, které vybírají aktuální obrazy. Každá taková politika je definována:

  • mnoho referencí, tzn. Git tagy nebo Git větve, které se používají během skenování;
  • a limit vyhledaných obrázků pro každý odkaz ze sady.

Pro ilustraci, takto začala vypadat výchozí konfigurace zásad:

cleanup:
  keepPolicies:
  - references:
      tag: /.*/
      limit:
        last: 10
  - references:
      branch: /.*/
      limit:
        last: 10
        in: 168h
        operator: And
    imagesPerReference:
      last: 2
      in: 168h
      operator: And
  - references:  
      branch: /^(main|staging|production)$/
    imagesPerReference:
      last: 10

Tato konfigurace obsahuje tři zásady, které splňují následující pravidla:

  1. Uložte obrázek pro posledních 10 značek Git (podle data vytvoření značky).
  2. Neukládejte více než 2 obrázky publikované za poslední týden pro maximálně 10 vláken s aktivitou za poslední týden.
  3. Uložte 10 obrázků pro větve main, staging и production.

Konečný algoritmus se scvrkává na následující kroky:

  • Načítání manifestů z registru kontejnerů.
  • S výjimkou obrázků používaných v Kubernetes, protože Již jsme je předem vybrali pomocí dotazování K8s API.
  • Skenování historie Git a vyloučení obrázků na základě specifikovaných zásad.
  • Odstraňování zbývajících obrázků.

Vrátíme-li se k naší ilustraci, toto se stane s werf:

Problém „chytrého“ čištění obrázků kontejnerů a jeho řešení ve werf

I když však nepoužíváte werf, podobný přístup k pokročilému čištění obrázků – v té či oné implementaci (podle preferovaného přístupu k označování obrázků) – lze aplikovat na jiné systémy/utility. K tomu stačí pamatovat si vzniklé problémy a najít ve svém zásobníku ty příležitosti, které vám umožní integrovat jejich řešení co nejplynuleji. Doufáme, že cesta, kterou jsme prošli, vám pomůže podívat se na váš konkrétní případ s novými detaily a myšlenkami.

Závěr

  • Dříve nebo později se většina týmů potýká s problémem přetečení registru.
  • Při hledání řešení je nejprve nutné určit kritéria relevance obrázku.
  • Nástroje nabízené oblíbenými službami registru kontejnerů vám umožňují organizovat velmi jednoduché čištění, které nebere v úvahu „vnější svět“: obrázky používané v Kubernetes a zvláštnosti pracovních postupů týmu.
  • Flexibilní a efektivní algoritmus musí rozumět procesům CI/CD a pracovat nejen s obrazovými daty Docker.

PS

Přečtěte si také na našem blogu:

Zdroj: www.habr.com

Přidat komentář