Problemi i pastrimit "të zgjuar" të imazheve të kontejnerëve dhe zgjidhja e tij në werf

Problemi i pastrimit "të zgjuar" të imazheve të kontejnerëve dhe zgjidhja e tij në werf

Artikulli diskuton problemet e pastrimit të imazheve që grumbullohen në regjistrat e kontejnerëve (Docker Registry dhe analogët e tij) në realitetet e tubacioneve moderne CI/CD për aplikacionet vendase të cloud të dorëzuara në Kubernetes. Janë dhënë kriteret kryesore për rëndësinë e imazheve dhe vështirësitë që rezultojnë në automatizimin e pastrimit, kursimin e hapësirës dhe plotësimin e nevojave të ekipeve. Së fundi, duke përdorur shembullin e një projekti specifik me burim të hapur, ne do t'ju tregojmë se si mund të kapërcehen këto vështirësi.

Paraqitje

Numri i imazheve në regjistrin e kontejnerëve mund të rritet me shpejtësi, duke zënë më shumë hapësirë ​​ruajtëse dhe duke rritur ndjeshëm koston e tij. Për të kontrolluar, kufizuar ose ruajtur rritjen e pranueshme të hapësirës së zënë në regjistër, pranohet:

  1. përdorni një numër fiks etiketash për imazhet;
  2. pastroni imazhet në një farë mënyre.


Kufizimi i parë ndonjëherë është i pranueshëm për ekipet e vogla. Nëse zhvilluesit kanë mjaft etiketa të përhershme (latest, main, test, boris etj.), regjistri nuk do të rritet në madhësi dhe për një kohë të gjatë nuk do të duhet të mendoni fare për pastrimin e tij. Në fund të fundit, të gjitha imazhet e parëndësishme fshihen dhe thjesht nuk ka mbetur punë për pastrim (gjithçka bëhet nga një mbledhës i rregullt i mbeturinave).

Megjithatë, kjo qasje kufizon shumë zhvillimin dhe rrallë është e zbatueshme për projektet moderne CI/CD. Një pjesë integrale e zhvillimit ishte automatizim, i cili ju lejon të testoni, vendosni dhe ofroni funksionalitete të reja te përdoruesit shumë më shpejt. Për shembull, në të gjitha projektet tona, një tubacion CI krijohet automatikisht me çdo angazhim. Në të, imazhi mblidhet, testohet, shpërndahet në qarqe të ndryshme Kubernetes për korrigjimin dhe kontrollet e mbetura, dhe nëse gjithçka është mirë, ndryshimet arrijnë te përdoruesi përfundimtar. Dhe kjo nuk është më shkencë raketash, por një dukuri e përditshme për shumë - me shumë mundësi për ju, pasi po lexoni këtë artikull.

Meqenëse rregullimi i gabimeve dhe zhvillimi i funksionalitetit të ri kryhet paralelisht, dhe lëshimet mund të kryhen disa herë në ditë, është e qartë se procesi i zhvillimit shoqërohet nga një numër i konsiderueshëm detyrimesh, që do të thotë një numër i madh imazhesh në regjistër. Si rezultat, lind çështja e organizimit të pastrimit efektiv të regjistrit, d.m.th. heqja e imazheve të parëndësishme.

Por si mund të përcaktoni nëse një imazh është i rëndësishëm?

Kriteret për rëndësinë e imazhit

Në shumicën dërrmuese të rasteve, kriteret kryesore do të jenë:

1. E para (më e dukshme dhe më kritike nga të gjitha) janë imazhet që aktualisht përdoret në Kubernetes. Heqja e këtyre imazheve mund të rezultojë në kosto të konsiderueshme joproduktive të prodhimit (për shembull, imazhet mund të kërkohen për riprodhim) ose të mohojë përpjekjet e ekipit për korrigjimin e gabimeve në cilindo prej sytheve. (Për këtë arsye kemi bërë edhe një speciale Eksportues i Prometeut, i cili gjurmon mungesën e imazheve të tilla në çdo grupim Kubernetes.)

2. E dyta (më pak e dukshme, por edhe shumë e rëndësishme dhe përsëri lidhet me shfrytëzimin) - imazhe që kërkohet për rikthim në rast të zbulimit të problemeve serioze në versionin aktual. Për shembull, në rastin e Helm, këto janë imazhe që përdoren në versionet e ruajtura të lëshimit. (Nga rruga, si parazgjedhje në Helm kufiri është 256 rishikime, por nuk ka gjasa që dikush me të vërtetë të ketë nevojë të kursejë kjo një numër i madh versionesh?..) Në fund të fundit, ne, veçanërisht, i ruajmë versionet në mënyrë që t'i përdorim ato më vonë, d.m.th. "Kthehuni përsëri" tek ata nëse është e nevojshme.

3. E treta - nevojat e zhvilluesit: Të gjitha imazhet që lidhen me punën e tyre aktuale. Për shembull, nëse po shqyrtojmë një PR, atëherë ka kuptim të lëmë një imazh që korrespondon me kryerjen e fundit dhe, të themi, kryerjen e mëparshme: në këtë mënyrë zhvilluesi mund të kthehet shpejt në çdo detyrë dhe të punojë me ndryshimet më të fundit.

4. E katërta – imazhe që korrespondojnë me versionet e aplikacionit tonë, d.m.th. janë produkti përfundimtar: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra, etj.

NB: Kriteret e përcaktuara këtu u formuluan bazuar në përvojën e ndërveprimit me dhjetëra ekipe zhvillimi nga kompani të ndryshme. Sidoqoftë, natyrisht, në varësi të specifikave në proceset e zhvillimit dhe infrastrukturës së përdorur (për shembull, Kubernetes nuk përdoret), këto kritere mund të ndryshojnë.

Pranueshmëria dhe zgjidhjet ekzistuese

Shërbimet e njohura me regjistrat e kontejnerëve, si rregull, ofrojnë politikat e tyre të pastrimit të imazhit: në to mund të përcaktoni kushtet në të cilat një etiketë hiqet nga regjistri. Megjithatë, këto kushte kufizohen nga parametra të tillë si emrat, koha e krijimit dhe numri i etiketave*.

* Varet nga zbatimet specifike të regjistrit të kontejnerëve. Ne shqyrtuam mundësitë e zgjidhjeve të mëposhtme: Azure CR, Docker Hub, ECR, GCR, Paketat GitHub, Regjistri i kontejnerëve GitLab, Regjistri i Harbour, JFrog Artifactory, Quay.io - që nga shtatori '2020.

Ky grup parametrash është mjaft i mjaftueshëm për të përmbushur kriterin e katërt - domethënë, për të zgjedhur imazhe që korrespondojnë me versionet. Megjithatë, për të gjitha kriteret e tjera, duhet zgjedhur një lloj zgjidhje kompromisi (një politikë më e ashpër ose, anasjelltas, më e butë) - në varësi të pritshmërive dhe aftësive financiare.

Për shembull, kriteri i tretë - i lidhur me nevojat e zhvilluesve - mund të zgjidhet duke organizuar procese brenda ekipeve: emërtimi specifik i imazheve, mbajtja e listave speciale të lejeve dhe marrëveshjeve të brendshme. Por në fund të fundit ende duhet të automatizohet. Dhe nëse aftësitë e zgjidhjeve të gatshme nuk janë të mjaftueshme, duhet të bëni diçka tuajën.

Situata me dy kriteret e para është e ngjashme: ato nuk mund të kënaqen pa marrë të dhëna nga një sistem i jashtëm - ai ku vendosen aplikacionet (në rastin tonë, Kubernetes).

Ilustrimi i rrjedhës së punës në Git

Le të themi se jeni duke punuar diçka si kjo në Git:

Problemi i pastrimit "të zgjuar" të imazheve të kontejnerëve dhe zgjidhja e tij në werf

Ikona me një kokë në diagram tregon imazhet e kontejnerit që janë vendosur aktualisht në Kubernetes për çdo përdorues (përdorues fundor, testues, menaxherë, etj.) ose përdoren nga zhvilluesit për korrigjimin e gabimeve dhe qëllime të ngjashme.

Çfarë ndodh nëse politikat e pastrimit lejojnë që vetëm imazhet të mbahen (jo të fshihen) nga emrat e etiketave të dhëna?

Problemi i pastrimit "të zgjuar" të imazheve të kontejnerëve dhe zgjidhja e tij në werf

Natyrisht, një skenar i tillë nuk do të bëjë askënd të lumtur.

Çfarë do të ndryshojë nëse politikat lejojnë që imazhet të mos fshihen? sipas një intervali kohor të caktuar / numrit të kryerjeve të fundit?

Problemi i pastrimit "të zgjuar" të imazheve të kontejnerëve dhe zgjidhja e tij në werf

Rezultati është bërë shumë më i mirë, por është ende larg idealit. Në fund të fundit, ne kemi ende zhvillues që kanë nevojë për imazhe në regjistër (ose edhe të vendosura në K8) për të korrigjuar gabimet...

Për të përmbledhur situatën aktuale të tregut: funksionet e disponueshme në regjistrat e kontejnerëve nuk ofrojnë fleksibilitet të mjaftueshëm gjatë pastrimit, dhe arsyeja kryesore për këtë është asnjë mënyrë për të ndërvepruar me botën e jashtme. Rezulton se ekipet që kërkojnë një fleksibilitet të tillë detyrohen të zbatojnë në mënyrë të pavarur fshirjen e imazhit "nga jashtë", duke përdorur API-në e Regjistrit Docker (ose API-në amtare të zbatimit përkatës).

Sidoqoftë, ne po kërkonim një zgjidhje universale që do të automatizonte pastrimin e imazhit për ekipe të ndryshme duke përdorur regjistra të ndryshëm...

Rruga jonë drejt pastrimit universal të imazhit

Nga vjen kjo nevojë? Fakti është se ne nuk jemi një grup i veçantë zhvilluesish, por një ekip që u shërben shumë prej tyre menjëherë, duke ndihmuar në zgjidhjen e plotë të çështjeve CI/CD. Dhe mjeti kryesor teknik për këtë është mjeti me burim të hapur werf. E veçanta e tij është se nuk kryen një funksion të vetëm, por shoqëron proceset e vazhdueshme të shpërndarjes në të gjitha fazat: nga montimi në vendosje.

Publikimi i imazheve në regjistër* (menjëherë pasi ato janë ndërtuar) është një funksion i dukshëm i një programi të tillë. Dhe meqenëse imazhet vendosen atje për ruajtje, atëherë - nëse ruajtja juaj nuk është e pakufizuar - duhet të jeni përgjegjës për pastrimin e tyre të mëvonshëm. Se si arritëm sukses në këtë, duke plotësuar të gjitha kriteret e specifikuara, do të diskutohet më tej.

* Edhe pse vetë regjistrat mund të jenë të ndryshëm (Docker Registry, GitLab Container Registry, Harbor, etj.), përdoruesit e tyre përballen me të njëjtat probleme. Zgjidhja universale në rastin tonë nuk varet nga zbatimi i regjistrit, sepse funksionon jashtë vetë regjistrave dhe ofron të njëjtën sjellje për të gjithë.

Edhe pse ne po përdorim werf si një shembull zbatimi, ne shpresojmë që qasjet e përdorura do të jenë të dobishme për ekipet e tjera që përballen me vështirësi të ngjashme.

Kështu që ne u zënë të jashtme zbatimi i një mekanizmi për pastrimin e imazheve - në vend të atyre aftësive që janë ndërtuar tashmë në regjistrat e kontejnerëve. Hapi i parë ishte përdorimi i Docker Registry API për të krijuar të njëjtat politika primitive për numrin e etiketave dhe kohën e krijimit të tyre (përmendur më sipër). Shtuar atyre lejojë listën e bazuar në imazhet e përdorura në infrastrukturën e vendosur, d.m.th. Kubernetes. Për këtë të fundit, mjaftonte përdorimi i Kubernetes API për të përsëritur të gjitha burimet e vendosura dhe për të marrë një listë vlerash image.

Kjo zgjidhje e parëndësishme zgjidhi problemin më kritik (kriteri nr. 1), por ishte vetëm fillimi i rrugëtimit tonë për të përmirësuar mekanizmin e pastrimit. Hapi tjetër - dhe shumë më interesant - ishte vendimi shoqëroni imazhet e publikuara me historinë e Git.

Skemat e etiketimit

Për të filluar, ne zgjodhëm një qasje në të cilën imazhi përfundimtar duhet të ruajë informacionin e nevojshëm për pastrim dhe e ndërtuam procesin në skemat e etiketimit. Kur publikon një imazh, përdoruesi zgjodhi një opsion specifik etiketimi (git-branch, git-commit ose git-tag) dhe përdori vlerën përkatëse. Në sistemet CI, këto vlera u vendosën automatikisht bazuar në variablat e mjedisit. Në fakt imazhi përfundimtar u shoqërua me një primitiv specifik Git, duke ruajtur të dhënat e nevojshme për pastrim në etiketa.

Kjo qasje rezultoi në një sërë politikash që lejuan që Git të përdoret si burimi i vetëm i së vërtetës:

  • Kur fshini një degë/etiketë në Git, imazhet e lidhura në regjistër u fshinë automatikisht.
  • Numri i imazheve të lidhura me etiketat dhe angazhimet Git mund të kontrollohet nga numri i etiketave të përdorura në skemën e përzgjedhur dhe koha në të cilën është krijuar kryerja e lidhur.

Në përgjithësi, zbatimi rezultues i plotësoi nevojat tona, por së shpejti na priste një sfidë e re. Fakti është se gjatë përdorimit të skemave të etiketimit të bazuara në primitivët Git, ne hasëm një sërë mangësish. (Meqenëse përshkrimi i tyre është përtej qëllimit të këtij artikulli, të gjithë mund të njihen me detajet këtu.) Prandaj, pasi vendosëm të kalonim në një qasje më efikase për etiketimin (etiketimi i bazuar në përmbajtje), na u desh të rishikonim zbatimin e pastrimit të imazhit.

Algoritëm i ri

Pse? Me etiketimin e bazuar në përmbajtje, çdo etiketë mund të plotësojë disa angazhime në Git. Kur pastroni imazhet, nuk mund të supozoni më vetëm nga commit ku u shtua etiketa e re në regjistër.

Për algoritmin e ri të pastrimit, u vendos që të largohej nga skemat e etiketimit dhe të ndërtohej procesi i meta-imazhit, secila prej të cilave ruan një grup të:

  • angazhimi mbi të cilin është kryer publikimi (nuk ka rëndësi nëse imazhi është shtuar, ndryshuar ose ka mbetur i njëjtë në regjistrin e kontejnerit);
  • dhe identifikuesin tonë të brendshëm që korrespondon me imazhin e mbledhur.

Me fjalë të tjera, u dha lidhja e etiketave të publikuara me angazhimet në Git.

Konfigurimi përfundimtar dhe algoritmi i përgjithshëm

Kur konfiguroni pastrimin, përdoruesit tani kanë qasje në politikat që zgjedhin imazhet aktuale. Çdo politikë e tillë përcaktohet:

  • shumë referenca, d.m.th. Etiketat Git ose degët Git që përdoren gjatë skanimit;
  • dhe kufiri i imazheve të kërkuara për çdo referencë nga grupi.

Për të ilustruar, kjo është se si filloi të dukej konfigurimi i parazgjedhur i politikës:

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

Ky konfigurim përmban tre politika që përputhen me rregullat e mëposhtme:

  1. Ruani imazhin për 10 etiketat e fundit Git (sipas datës së krijimit të etiketës).
  2. Ruani jo më shumë se 2 imazhe të publikuara javën e fundit për jo më shumë se 10 tema me aktivitet në javën e fundit.
  3. Ruani 10 imazhe për degë main, staging и production.

Algoritmi përfundimtar zbret në hapat e mëposhtëm:

  • Marrja e manifesteve nga regjistri i kontejnerëve.
  • Duke përjashtuar imazhet e përdorura në Kubernetes, sepse Ne i kemi para-zgjedhur tashmë duke anketuar API-në e K8s.
  • Skanimi i historisë së Git dhe përjashtimi i imazheve bazuar në politikat e specifikuara.
  • Heqja e imazheve të mbetura.

Duke u kthyer te ilustrimi ynë, kjo është ajo që ndodh me werf:

Problemi i pastrimit "të zgjuar" të imazheve të kontejnerëve dhe zgjidhja e tij në werf

Megjithatë, edhe nëse nuk përdorni werf, një qasje e ngjashme me pastrimin e avancuar të imazhit - në një zbatim ose në një tjetër (sipas qasjes së preferuar për etiketimin e imazheve) - mund të zbatohet për sisteme/shërbime të tjera. Për ta bërë këtë, mjafton të mbani mend problemet që lindin dhe të gjeni ato mundësi në pirgun tuaj që ju lejojnë të integroni zgjidhjen e tyre sa më mirë. Shpresojmë që rruga që kemi përshkuar do t'ju ndihmojë të shikoni rastin tuaj të veçantë me detaje dhe mendime të reja.

Përfundim

  • Herët a vonë, shumica e ekipeve ndeshen me problemin e tejmbushjes së regjistrit.
  • Kur kërkoni për zgjidhje, së pari është e nevojshme të përcaktohen kriteret për rëndësinë e imazhit.
  • Mjetet e ofruara nga shërbimet e njohura të regjistrit të kontejnerëve ju lejojnë të organizoni një pastrim shumë të thjeshtë që nuk merr parasysh "botën e jashtme": imazhet e përdorura në Kubernetes dhe veçoritë e rrjedhave të punës së ekipit.
  • Një algoritëm fleksibël dhe efikas duhet të ketë një kuptim të proceseve CI/CD dhe të funksionojë jo vetëm me të dhënat e imazhit Docker.

PS

Lexoni edhe në blogun tonë:

Burimi: www.habr.com

Shto një koment