Problemet med "smart" rensning av containeravbilder och dess lösning i werf

Problemet med "smart" rensning av containeravbilder och dess lösning i werf

I artikeln diskuteras problematiken kring rensning av avbilder som samlas i containerregistren (Docker Registry och dess motsvarigheter) i dagens CI/CD-pipelines för cloud native-applikationer som distribueras i Kubernetes. Huvudkriterier för avbilders aktualitet beskrivs, liksom de svÄrigheter som uppstÄr vid automatisering av rensning, utnyttjande av utrymme och tillfredsstÀllande av teamens behov. Slutligen, genom ett specifikt Open Source-projekt, förklarar vi hur dessa utmaningar kan övervinnas.

Introduktion

Antalet avbilder i containerregistret kan snabbt vÀxa och ta upp mer utrymme i lagringen, vilket i sin tur kan öka kostnaden avsevÀrt. För att kontrollera, begrÀnsa eller upprÀtthÄlla en acceptabel tillvÀxt av det utrymme som upptas i registret, görs följande:

  1. anvÀnda ett fast antal taggar för avbilder;
  2. pÄ nÄgot sÀtt rensa avbilder.


Den första begrÀnsningen Àr ibland acceptabel för smÄ team. Om utvecklarna klarar sig med fasta taggar (latest, main, test, boris och sÄ vidare), kommer registret inte att svÀlla i storlek och under lÄng tid behöver man inte ens tÀnka pÄ rensning. Alla obehövliga avbilder ÄsidosÀtts och det finns helt enkelt inget arbete kvar att göra för rensning (allt hanteras av den vanliga skrÀpbilen).

Trots detta begrÀnsar en sÄdan strategi utvecklingen kraftigt och Àr sÀllan tillÀmpbar inom CI/CD i moderna projekt. Automatisering har blivit en integrerad del av utvecklingsprocessen, som möjliggör snabbare testning, distribution och leverans av ny funktionalitet till anvÀndarna. Till exempel skapas det i alla vÄra projekt automatiskt en CI-pipeline vid varje commit. I den byggs en avbild, testas, distribueras till olika Kubernetes-miljöer för felsökning och vidare kontroller, och om allt gÄr bra - nÄr förÀndringarna slutligen anvÀndaren. Detta Àr inte lÀngre raketvetenskap, utan en vanlig företeelse för mÄnga - förmodligen Àven för dig, eftersom du lÀser denna artikel.Eftersom buggar fixas och ny funktionalitet utvecklas parallellt, och med flera releaser som kan ske varje dag, Àr det uppenbart att utvecklingsprocessen Ätföljs av ett betydande antal commits, vilket innebÀr -

ett stort antal avbilder i registret. ett stort antal av bilder i registret. Som ett resultat uppstÄr en akut frÄga om hur man organiserar en effektiv rengöring av registret, dvs. att ta bort inaktuella avbilder.

Men hur kan man överhuvudtaget avgöra om en avbild Àr aktuell?

Kriterier för aktuell avbild

I övervÀldigande fall kommer de viktigaste kriterierna att vara följande:

1. Det första (det mest uppenbara och mest kritiska av alla) Àr avbilder som just nu anvÀnds i Kubernetes. Att ta bort dessa avbilder kan leda till betydande kostnader relaterade till stillestÄnd i produktionen (till exempel kan avbilder behövas vid replikering) eller helt enkelt förstöra teamets insatser som arbetar med felsökning pÄ nÄgot av konturerna. (Av denna anledning har vi Àven skapat en speciell Prometheus exporter, som övervakar avsaknaden av sÄdana avbilder i alla Kubernetes-kluster.)

2. Det andra (mindre uppenbart, men ocksÄ mycket viktigt och Äterigen relaterat till drift) Àr avbilder som krÀvs för att ÄtergÄ i hÀndelse av allvarliga problem i den aktuella versionen. Till exempel, i fallet med Helm handlar det om avbilder som anvÀnds i sparade versioner av en release. (För övrigt, som standard gÀller en grÀns pÄ 256 revisioner i Helm, men fÄ mÀnniskor har nog faktiskt behov av att spara sÄ mycket versioner?..) Faktum Àr att vi, bland annat, sparar versioner sÄ att vi sedan kan anvÀnda dem, dvs. "ÄtergÄ" till dem vid behov.

3. Det tredje — utvecklarbehoven: alla avbilder som Ă€r kopplade till deras nuvarande arbeten. Till exempel, om vi granskar ett PR kan det vara meningsfullt att behĂ„lla avbilden som motsvarar den senaste commit och, sĂ€g, den föregĂ„ende commit: pĂ„ sĂ„ sĂ€tt kan utvecklaren snabbt Ă„tervĂ€nda till vilken uppgift som helst och arbeta med de senaste Ă€ndringarna.

4. Det fjĂ€rde — avbilder som motsvarar versionerna av vĂ„r applikation, dvs. som Ă€r den slutliga produkten: v1.0.0, 20.04.01, sierra osv.

NB: Kriterierna som anges hÀr har formulerats utifrÄn erfarenheter av samarbete med tiotals utvecklarteam frÄn olika företag. Men naturligtvis, beroende pÄ egenskaperna i utvecklingsprocesserna och den anvÀnda infrastrukturen (t.ex. om Kubernetes inte anvÀnds), kan dessa kriterier variera.

ÖverensstĂ€mmelse med kriterier och befintliga lösningar

PopulÀra tjÀnster med container registry erbjuder vanligtvis sina egna policyer för rensning av bilder: i dem kan du definiera villkor under vilka en tagg tas bort frÄn registry. Men möjligheterna med dessa villkor begrÀnsas av parametrar som namn, skapelsedatum och antal taggar*.

* Beror pÄ specifika implementationer av container registry. Vi har övervÀgt möjligheterna hos följande lösningar: Azure CR, Docker Hub, ECR, GCR, GitHub Packages, GitLab Container Registry, Harbor Registry, JFrog Artifactory, Quay.io - fram till september 2020.

Dessa parametrar Àr helt tillrÀckliga för att uppfylla det fjÀrde kriteriet - att vÀlja bilder som motsvarar versioner. Men för alla andra kriterier mÄste man vÀlja nÄgon form av kompromisslösning (en mer strikt eller Ä sin sida mer tolerant politik) - beroende pÄ förvÀntningar och ekonomiska möjligheter.

Till exempel kan det tredje kriteriet - som rör utvecklarnas behov - lösas genom att organisera processer inom team: specifik namngivning av bilder, upprÀtta speciella allow lists och interna avtal. Men i slutÀndan mÄste det ÀndÄ automatiseras. Och om de fÀrdiga lösningarna inte rÀcker till, mÄste man göra nÄgot eget.

Situationen med de tvÄ första kriterierna Àr liknande: de kan inte uppfyllas utan att fÄ data frÄn ett externt system - det system dÀr applikationerna distribueras (i vÄrt fall Àr det Kubernetes).

Illustration av arbetsflödet i Git

Anta att du arbetar efter ett mönster i Git:

Problemet med "smart" rensning av containeravbilder och dess lösning i werf

Ikonen med huvudet pÄ diagrammet markerar de containerbilder som för nÀrvarande Àr distribuerade i Kubernetes för vissa anvÀndare (slutanvÀndare, testare, chefer etc.) eller anvÀnds av utvecklare för debugging och liknande ÀndamÄl.

Vad hÀnder om rensningspolicyerna tillÄter att bilder kvarstÄr (inte tas bort) enbart enligt angivna taggnamn?

Problemet med "smart" rensning av containeravbilder och dess lösning i werf

Uppenbarligen blir ett sÄdant scenario ingen glad.

Vad Àndras om policyerna tillÄter att inte ta bort bilder enligt ett angivet tidsintervall / antal senaste commits?

Problemet med "smart" rensning av containeravbilder och dess lösning i werf

Resultatet blev avsevÀrt bÀttre, men Àr fortfarande lÄngt ifrÄn idealet. För vi har fortfarande utvecklare som behöver bilder i registret (eller till och med distribuerade i K8s) för att debugga buggar...

Sammanfattningsvis, den nuvarande situationen pÄ marknaden: de tillgÀngliga funktionerna i containerrregister erbjuder inte tillrÀcklig flexibilitet för rensning, och den frÀmsta orsaken Àr att det inte finns nÄgot sÀtt att interagera med omvÀrlden. Det innebÀr att team som behöver denna flexibilitet tvingas implementera borttagning av bilder "utifrÄn" genom att anvÀnda Docker Registry API (eller det inhemska API:et för den aktuella implementeringen).

Vi har dock sökt efter en universell lösning som automatiserar rensningen av bilder för olika team som anvĂ€nder olika register


VÄr vÀg till universell rensning av bilder

Varför finns det ett sÄdant behov? Det Àr sÄ att vi inte Àr en separat grupp utvecklare, utan ett team som stödjer mÄnga sÄdana grupper, och hjÀlper till att lösa CI/CD-frÄgor pÄ ett omfattande sÀtt. Och det viktigaste tekniska verktyget för detta Àr en Open Source-verktyg werf. Dess sÀrskildhet ligger i att den inte utför en enda funktion, utan följer processerna för kontinuerlig leverans i alla steg: frÄn byggande till deployment.

Publiceringen av bilder i registret* (omedelbart efter deras byggande) Àr en uppenbar funktion för ett sÄdant verktyg. Eftersom bilderna lagras dÀr behöver man, om ditt lagringsutrymme inte Àr oÀndligt, ocksÄ ta ansvar för deras efterföljande rensning. Hur vi lyckades med detta, och tillfredsstÀllde alla angivna kriterier, kommer att diskuteras vidare.

* Även om sjĂ€lva registren kan vara olika (Docker Registry, GitLab Container Registry, Harbor osv.), sĂ„ möter deras anvĂ€ndare samma problem. Den universella lösningen i vĂ„rt fall Ă€r oberoende av registerens implementation, eftersom den utförs utanför sjĂ€lva registren och erbjuder samma beteende för alla.

Trots att vi anvÀnder werf som exempel pÄ implementation, hoppas vi att de anvÀnda tillvÀgagÄngssÀtten kommer att vara anvÀndbara för andra team som stÄr inför liknande svÄrigheter.

SĂ„ vi började med extern implementeringen av en mekanism för att rensa bilder — istĂ€llet för de funktioner som redan Ă€r inbyggda i registren för containrar. Det första steget var att anvĂ€nda Docker Registry API för att skapa just dessa primitiva policyer baserade pĂ„ antalet taggar och deras skapelsedatum (nĂ€mnda ovan). Dessa kompletterades med en allow list baserad pĂ„ bilder som anvĂ€nds i den distribuerade infrastrukturen, dvs. Kubernetes. För det sistnĂ€mnda rĂ€ckte det att anvĂ€nda Kubernetes API för att iterera över alla distribuerade resurser och fĂ„ en lista med vĂ€rden. bild.

Denna triviala lösning löste det mest kritiska problemet (kriterium nr 1), men var bara början pĂ„ vĂ„r vĂ€g mot att förbĂ€ttra stĂ€dprocessen. NĂ€sta — och mycket mer intressanta — steg var att lösa knyta de publicerade bilderna till Git-historiken..

Taggningsscheman

För att börja valde vi ett tillvÀgagÄngssÀtt dÀr den slutliga bilden skulle lagra den nödvÀndiga informationen för stÀdning, och vi byggde processen pÄ taggningsscheman. NÀr anvÀndaren publicerade en bild valde hen ett visst alternativ för taggning (git-gren, git-commit eller git-tag) och anvÀnde motsvarande vÀrde. I CI-system sattes dessa vÀrden automatiskt baserat pÄ miljövariabler. I grund och botten sÄ knöts den slutliga bilden till en viss Git-primitiv,, som lagrade nödvÀndig data för stÀdning i etiketter.

Inom detta tillvÀgagÄngssÀtt uppstod en uppsÀttning policyer som gjorde det möjligt att anvÀnda Git som den enda sanningskÀllan:

  • Vid borttagning av en gren/tagg i Git togs Ă€ven de relaterade bilderna automatiskt bort frĂ„n registret.
  • Antalet bilder kopplade till Git-taggar och commits kunde regleras med antalet taggar som anvĂ€ndes i den valda schemat, samt tidpunkten för den relaterade committen.

Överlag uppfyllde den resulterande implementationen vĂ„ra behov, men snart vĂ€ntade en ny utmaning. Problemet var att under tiden vi anvĂ€nde taggningsscheman baserade pĂ„ Git-primitiver stötte vi pĂ„ ett antal nackdelar. (Eftersom deras beskrivning gĂ„r utanför Ă€mnet för denna artikel, kan alla intresserade fĂ„ detaljerna hĂ€r.) DĂ€rför, efter att ha beslutat att gĂ„ över till ett mer effektivt tillvĂ€gagĂ„ngssĂ€tt för taggning (innehĂ„llsbaserad taggning), var vi tvungna att ompröva Ă€ven vĂ„r stĂ€dimplementation.

Den nya algoritmen

Varför? Vid taggning inom ramen för innehÄllsbaserad kan varje tagg motsvara flera commits i Git. Vid stÀdning av bilder kan man inte lÀngre utgÄ bara frÄn committen dÀr den nya taggen lades till i registret.

För den nya stÀdalgoritmen beslutades det att lÀmna taggningsscheman och bygga processen pÄ meta-bilder,, dÀr varje bild lagrar en koppling av:

  • commit som publiceringen utfördes (det spelar ingen roll om bilden lades till, Ă€ndrades eller förblev densamma i containerregistret);
  • och vĂ„r interna identifierare som motsvarar den byggda bilden.

Med andra ord, sÀkerstÀlldes kopplingen mellan de publicerade etiketterna och commits i Git..

Den slutgiltiga konfigurationen och den övergripande algoritmen

AnvÀndare i konfigurationen av stÀdningen har nu tillgÄng till policys som avgör hur aktuella bilder vÀljs. Varje sÄdan policy definieras av:

  • ett antal referenser, dvs. Git-taggar eller Git-grenar, som anvĂ€nds vid skanning;
  • och en grĂ€ns för antalet bilder som ska sökas för varje referens frĂ„n mĂ€ngden.

Som en illustration — sĂ„ hĂ€r har konfigurationen av standardpolicys sett ut:

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

Denna konfiguration innehÄller tre policys som motsvarar följande regler:

  1. BehÄll bilden för de 10 senaste Git-taggarna (baserat pÄ datum för taggning).
  2. BehÄll högst 2 bilder publicerade under den senaste veckan för högst 10 grenar som haft aktivitet den senaste veckan.
  3. BehÄll 10 bilder för grenarna main, staging och production.

Den slutgiltiga algoritmen sammanfattas i följande steg:

  • InhĂ€mta manifest frĂ„n container-registret.
  • Exkludera bilder som anvĂ€nds i Kubernetes, eftersom vi redan har filtrerat ut dem genom att frĂ„ga K8s API.
  • Skanna Git-historiken och exkludera bilder enligt de angivna policys.
  • Ta bort de Ă„terstĂ„ende bilderna.

ÅtergĂ„r vi till vĂ„r illustration, sĂ„ hĂ€r ser det ut med werf:

Problemet med "smart" rensning av containeravbilder och dess lösning i werf

Men Ă€ven om du inte anvĂ€nder werf, kan en liknande metod för avancerad stĂ€dning av bilder — i en eller annan implementation (enligt den föredragna metoden för attetagningar av bilder) — tillĂ€mpas i andra system/verktyg. Det Ă€r nog att komma ihĂ„g de problem som uppstĂ„r och hitta de möjligheter i din stack som lĂ„ter dig integrera deras lösning sĂ„ smidigt som möjligt. Vi hoppas att den vĂ€g vi har gĂ„tt kan hjĂ€lpa dig att se pĂ„ ditt specifika fall med nya detaljer och tankar.

Slutsats

  • SĂ„ smĂ„ningom möter nĂ€stan alla team problemet med att register blir överfulla.
  • Vid sökandet efter lösningar Ă€r det först och frĂ€mst nödvĂ€ndigt att faststĂ€lla kriterierna för relevansen av bilden.
  • Verktygen som erbjuds av populĂ€ra container registry-tjĂ€nster gör det möjligt att organisera en mycket enkel rengöring, som inte tar hĂ€nsyn till "den yttre vĂ€rlden": bilder som anvĂ€nds i Kubernetes och sĂ€rskildheterna i arbetsflöden inom teamet.
  • En flexibel och effektiv algoritm mĂ„ste ha en uppfattning om CI/CD-processer och hantera inte bara data frĂ„n Docker-bilder.

P.S.

LÀs Àven i vÄr blogg:

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster