Problem "pametnog" čišćenja slika spremnika i njegovo rješenje u werfu

Problem "pametnog" čišćenja slika spremnika i njegovo rješenje u werfu

U članku se raspravlja o problemima čišćenja slika koje se nakupljaju u registrima spremnika (Docker Registry i njegovi analozi) u stvarnosti modernih CI/CD cjevovoda za izvorne aplikacije u oblaku isporučene Kubernetesu. Dati su glavni kriteriji za relevantnost slika i poteškoće koje iz toga proizlaze u automatizaciji čišćenja, uštedi prostora i zadovoljavanju potreba timova. Na kraju ćemo vam na primjeru konkretnog Open Source projekta reći kako se ove poteškoće mogu prevladati.

Uvod

Broj slika u registru spremnika može brzo rasti, zauzimajući više prostora za pohranu i time značajno povećavajući njegovu cijenu. Za kontrolu, ograničavanje ili održavanje prihvatljivog rasta prostora zauzetog u registru, prihvaća se:

  1. koristite fiksni broj oznaka za slike;
  2. očistiti slike na neki način.


Prvo ograničenje ponekad je prihvatljivo za male timove. Ako programeri imaju dovoljno trajnih oznaka (latest, main, test, boris itd.), registar se neće povećati i dugo vremena uopće nećete morati razmišljati o njegovom čišćenju. Uostalom, sve nevažne slike se brišu, a za čišćenje jednostavno nema posla (sve radi obični sakupljač smeća).

Međutim, ovaj pristup uvelike ograničava razvoj i rijetko je primjenjiv na moderne CI/CD projekte. Sastavni dio razvoja bio je automatizacija, što vam omogućuje mnogo brže testiranje, implementaciju i dostavu novih funkcija korisnicima. Na primjer, u svim našim projektima, CI cjevovod se automatski stvara sa svakim predanjem. U njemu se slika sastavlja, testira, izbacuje u razne Kubernetes sklopove radi otklanjanja pogrešaka i preostalih provjera, a ako je sve u redu, promjene dolaze do krajnjeg korisnika. I to više nije raketna znanost, već svakodnevica za mnoge - vjerojatno i za vas, budući da čitate ovaj članak.

Budući da se ispravljanje grešaka i razvoj novih funkcionalnosti odvija paralelno, a izdanja se mogu izvoditi nekoliko puta dnevno, očito je da razvojni proces prati značajan broj commitova, što znači veliki broj slika u registru. Kao rezultat toga, postavlja se pitanje organiziranja učinkovitog čišćenja registra, tj. uklanjanje nebitnih slika.

Ali kako uopće odrediti je li slika relevantna?

Kriteriji za relevantnost slike

U velikoj većini slučajeva glavni kriteriji bit će:

1. Prvi (najočitiji i najkritičniji od svih) su slike koje trenutno se koristi u Kubernetesu. Uklanjanje ovih slika može rezultirati značajnim troškovima zastoja u proizvodnji (na primjer, slike mogu biti potrebne za replikaciju) ili poništiti napore tima za otklanjanje pogrešaka na bilo kojoj od petlji. (Iz tog razloga smo čak napravili poseban Prometejski izvoznici, koji prati odsutnost takvih slika u bilo kojem Kubernetes klasteru.)

2. Drugo (manje očito, ali također vrlo važno i opet se odnosi na iskorištavanje) - slike koje potreban za vraćanje u prethodno stanje u slučaju otkrivanja ozbiljnih problema u trenutnoj verziji. Na primjer, u slučaju Helma, to su slike koje se koriste u spremljenim verzijama izdanja. (Usput, prema zadanim postavkama u Helmu ograničenje je 256 revizija, ali malo je vjerojatno da itko stvarno treba spremati takav veliki broj verzija?..) Uostalom, mi posebno spremamo verzije kako bismo ih kasnije mogli koristiti, tj. "vratiti" na njih ako je potrebno.

3. Treće - potrebe programera: Sve slike koje se odnose na njihov trenutni rad. Na primjer, ako razmišljamo o PR-u, onda ima smisla ostaviti sliku koja odgovara zadnjem obvezivanju i, recimo, prethodnom obvezivanju: na taj način se programer može brzo vratiti na bilo koji zadatak i raditi s najnovijim promjenama.

4. Četvrto – slike koje odgovaraju verzijama naše aplikacije, tj. su konačni proizvod: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra itd.

NB: Ovdje definirani kriteriji formulirani su na temelju iskustva u interakciji s desecima razvojnih timova iz različitih tvrtki. No, naravno, ovisno o specifičnostima u razvojnim procesima i korištenoj infrastrukturi (primjerice, ne koristi se Kubernetes), ti se kriteriji mogu razlikovati.

Podobnost i postojeća rješenja

Popularne usluge s registrima spremnika u pravilu nude vlastita pravila čišćenja slike: u njima možete definirati uvjete pod kojima se oznaka uklanja iz registra. Međutim, ti su uvjeti ograničeni parametrima kao što su imena, vrijeme stvaranja i broj oznaka*.

* Ovisi o specifičnim implementacijama registra spremnika. Razmotrili smo mogućnosti sljedećih rješenja: Azure CR, Docker Hub, ECR, GCR, GitHub Packages, GitLab Container Registry, Harbor Registry, JFrog Artifactory, Quay.io - od rujna'2020.

Ovaj skup parametara sasvim je dovoljan da se zadovolji četvrti kriterij - da se izaberu slike koje odgovaraju verzijama. No, za sve druge kriterije treba izabrati nekakvo kompromisno rješenje (tvrđu ili, obrnuto, blažu politiku) - ovisno o očekivanjima i financijskim mogućnostima.

Na primjer, treći kriterij – vezan uz potrebe programera – može se riješiti organiziranjem procesa unutar timova: specifičnim imenovanjem slika, održavanjem posebnih lista dopuštenih i internih dogovora. Ali u konačnici to ipak treba automatizirati. A ako mogućnosti gotovih rješenja nisu dovoljne, morate učiniti nešto svoje.

Situacija s prva dva kriterija je slična: oni se ne mogu zadovoljiti bez primanja podataka iz vanjskog sustava - onog u kojem su aplikacije postavljene (u našem slučaju Kubernetes).

Ilustracija tijeka rada u Gitu

Recimo da radite nešto poput ovoga u Gitu:

Problem "pametnog" čišćenja slika spremnika i njegovo rješenje u werfu

Ikona s glavom u dijagramu označava slike spremnika koje su trenutno raspoređene u Kubernetesu za sve korisnike (krajnje korisnike, testere, upravitelje itd.) ili ih programeri koriste za otklanjanje pogrešaka i slične svrhe.

Što se događa ako pravila čišćenja dopuštaju samo zadržavanje (ne brisanje) slika prema zadanim imenima oznaka?

Problem "pametnog" čišćenja slika spremnika i njegovo rješenje u werfu

Očito, takav scenarij nikoga neće usrećiti.

Što će se promijeniti ako pravila dopuštaju da se slike ne brišu? prema zadanom vremenskom intervalu / broju zadnjih obveza?

Problem "pametnog" čišćenja slika spremnika i njegovo rješenje u werfu

Rezultat je postao mnogo bolji, ali je još uvijek daleko od idealnog. Uostalom, još uvijek imamo programere koji trebaju slike u registru (ili čak postavljene u K8s) za otklanjanje grešaka...

Da rezimiramo trenutnu situaciju na tržištu: funkcije dostupne u registrima spremnika ne nude dovoljno fleksibilnosti prilikom čišćenja, a glavni razlog za to je nema načina za interakciju s vanjskim svijetom. Ispada da su timovi koji zahtijevaju takvu fleksibilnost prisiljeni samostalno implementirati brisanje slika "izvana", koristeći Docker Registry API (ili izvorni API odgovarajuće implementacije).

Međutim, tražili smo univerzalno rješenje koje bi automatiziralo čišćenje slika za različite timove koji koriste različite registre...

Naš put do univerzalnog čišćenja slike

Odakle ta potreba? Činjenica je da mi nismo zasebna grupa programera, već tim koji opslužuje mnoge od njih odjednom, pomažući u sveobuhvatnom rješavanju problema CI/CD. A glavni tehnički alat za to je uslužni program Open Source werf. Njegova je osobitost što ne obavlja samo jednu funkciju, već prati kontinuirane procese isporuke u svim fazama: od montaže do postavljanja.

Objavljivanje slika u registru* (odmah nakon što su izgrađene) očita je funkcija takvog uslužnog programa. A budući da se slike tamo stavljaju radi pohrane, tada - ako vaša pohrana nije neograničena - morate biti odgovorni za njihovo naknadno čišćenje. Kako smo u tome uspjeli, zadovoljivši sve zadane kriterije, bit će riječi u nastavku.

* Iako sami registri mogu biti različiti (Docker Registry, GitLab Container Registry, Harbor itd.), njihovi se korisnici suočavaju s istim problemima. Univerzalno rješenje u našem slučaju ne ovisi o implementaciji registra, jer radi izvan samih registara i nudi isto ponašanje za sve.

Iako koristimo werf kao primjer implementacije, nadamo se da će korišteni pristupi biti korisni drugim timovima koji se suočavaju sa sličnim poteškoćama.

Pa smo se zauzeli vanjski implementacija mehanizma za čišćenje slika - umjesto onih mogućnosti koje su već ugrađene u registre za spremnike. Prvi korak bio je korištenje Docker Registry API-ja za stvaranje istih primitivnih pravila za broj oznaka i vrijeme njihove izrade (gore spomenuto). Dodano im popis dopuštenih na temelju slika korištenih u postavljenoj infrastrukturi, tj. Kubernetes. Za potonje je bilo dovoljno upotrijebiti Kubernetes API za iteraciju kroz sve raspoređene resurse i dobiti popis vrijednosti image.

Ovo trivijalno rješenje riješilo je najkritičniji problem (kriterij br. 1), ali je bilo samo početak našeg puta ka poboljšanju mehanizma za čišćenje. Sljedeći - i mnogo zanimljiviji - korak bila je odluka pridružite objavljene slike Git povijesti.

Sheme označavanja

Za početak smo odabrali pristup u kojem bi konačna slika trebala pohraniti potrebne informacije za čišćenje, a proces smo izgradili na shemama označavanja. Prilikom objave slike korisnik je odabrao određenu opciju označavanja (git-branch, git-commit ili git-tag) i upotrijebio odgovarajuću vrijednost. U CI sustavima te su vrijednosti postavljene automatski na temelju varijabli okruženja. Zapravo konačna slika bila je povezana s određenom Git primitivom, pohranjujući potrebne podatke za čišćenje u naljepnicama.

Ovaj je pristup rezultirao skupom pravila koja su omogućila korištenje Gita kao jedinog izvora istine:

  • Prilikom brisanja grane/oznake u Gitu, pridružene slike u registru automatski su izbrisane.
  • Broj slika povezanih s Git oznakama i obvezama može se kontrolirati brojem oznaka korištenih u odabranoj shemi i vremenom u kojem je pridružena obveza stvorena.

Sve u svemu, dobivena implementacija zadovoljila je naše potrebe, no ubrzo nas je čekao novi izazov. Činjenica je da smo tijekom korištenja shema označavanja temeljenih na Git primitivima naišli na brojne nedostatke. (Budući da je njihov opis izvan okvira ovog članka, svatko se može upoznati s detaljima здесь.) Stoga smo, nakon što smo odlučili prijeći na učinkovitiji pristup označavanju (označavanje temeljeno na sadržaju), morali ponovno razmotriti implementaciju čišćenja slike.

Novi algoritam

Zašto? Uz označavanje temeljeno na sadržaju, svaka oznaka može zadovoljiti više obveza u Gitu. Kad čistite slike, više ne možete pretpostaviti samo iz urezivanja gdje je nova oznaka dodana u registar.

Za novi algoritam čišćenja odlučeno je odmaknuti se od shema označavanja i izgraditi proces meta-slike, od kojih svaki pohranjuje hrpu:

  • commit na kojem je izvršena objava (nije bitno je li slika dodana, promijenjena ili je ostala ista u registru spremnika);
  • i naš interni identifikator koji odgovara sastavljenoj slici.

Drugim riječima, bilo je osigurano povezivanje objavljenih oznaka s obvezama u Gitu.

Konačna konfiguracija i opći algoritam

Prilikom konfiguriranja čišćenja korisnici sada imaju pristup pravilima koja odabiru trenutne slike. Svaka takva politika definirana je:

  • mnoge reference, tj. Git oznake ili Git grane koje se koriste tijekom skeniranja;
  • i ograničenje traženih slika za svaku referencu iz skupa.

Za ilustraciju, ovako je počela izgledati zadana konfiguracija pravila:

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

Ova konfiguracija sadrži tri pravila koja su u skladu sa sljedećim pravilima:

  1. Spremite sliku za zadnjih 10 Git oznaka (prema datumu izrade oznake).
  2. Spremite ne više od 2 slike objavljene prošli tjedan za ne više od 10 niti s aktivnostima u prošlom tjednu.
  3. Sačuvajte 10 slika za grane main, staging и production.

Konačni algoritam svodi se na sljedeće korake:

  • Dohvaćanje manifesta iz registra spremnika.
  • Isključujući slike koje se koriste u Kubernetesu, jer Već smo ih unaprijed odabrali ispitivanjem K8s API-ja.
  • Skeniranje Git povijesti i izuzimanje slika na temelju navedenih pravila.
  • Uklanjanje preostalih slika.

Vraćajući se našoj ilustraciji, ovo se događa s werfom:

Problem "pametnog" čišćenja slika spremnika i njegovo rješenje u werfu

Međutim, čak i ako ne koristite werf, sličan pristup naprednom čišćenju slike - u jednoj ili drugoj implementaciji (prema preferiranom pristupu označavanju slike) - može se primijeniti na druge sustave/uslužne programe. Da biste to učinili, dovoljno je sjetiti se problema koji se pojavljuju i pronaći one mogućnosti u svom nizu koje vam omogućuju da integrirate njihovo rješenje što je moguće glatko. Nadamo se da će vam put kojim smo prošli pomoći da sagledate svoj slučaj s novim detaljima i razmišljanjima.

Zaključak

  • Prije ili kasnije, većina timova naiđe na problem prekoračenja registra.
  • Pri traženju rješenja najprije je potrebno odrediti kriterije relevantnosti slike.
  • Alati koje nude popularne usluge registra spremnika omogućuju vam da organizirate vrlo jednostavno čišćenje koje ne uzima u obzir "vanjski svijet": slike koje se koriste u Kubernetesu i osobitosti tijeka rada tima.
  • Fleksibilan i učinkovit algoritam mora imati razumijevanje CI/CD procesa i raditi ne samo s Docker slikovnim podacima.

PS

Pročitajte i na našem blogu:

Izvor: www.habr.com

Dodajte komentar