Problem “pametnog” čišćenja slika kontejnera i njegovo rješenje u werfu

Problem “pametnog” čišćenja slika kontejnera i njegovo rješenje u werfu

U članku se razmatraju problemi čišćenja slika koje se akumuliraju u registrima kontejnera (Docker Registry i njegovi analozi) u stvarnosti modernih CI/CD cevovoda za Cloud izvorne aplikacije koje se isporučuju u Kubernetes. Navedeni 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. Konačno, koristeći primjer konkretnog Open Source projekta, reći ćemo vam kako se ove poteškoće mogu prevazići.

Uvod

Broj slika u registru kontejnera može brzo rasti, zauzimajući više prostora za pohranu i na taj način značajno povećavajući njegovu cijenu. Za kontrolu, ograničavanje ili održavanje prihvatljivog rasta zauzetog prostora u registru, prihvaćeno je:

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


Prvo ograničenje je ponekad prihvatljivo za male timove. Ako programeri imaju dovoljno trajnih oznaka (latest, main, test, boris itd.), registar se neće povećati u veličini i dugo vremena nećete morati uopće razmišljati o čišćenju. Uostalom, sve nebitne slike se brišu i jednostavno nema posla za čišćenje (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, koji vam omogućava mnogo brže testiranje, implementaciju i isporuku novih funkcionalnosti korisnicima. Na primjer, u svim našim projektima, CI cevovod se automatski kreira sa svakim urezivanjem. U njemu se slika sklapa, testira, razbacuje u razna Kubernetes kola za otklanjanje grešaka i preostale provjere, a ako je sve u redu, promjene stižu do krajnjeg korisnika. I ovo više nije raketna nauka, već svakodnevna pojava za mnoge - najvjerovatnije za vas, budući da čitate ovaj članak.

Budući da se ispravljanje grešaka i razvoj nove funkcionalnosti odvijaju paralelno, a izdanja se mogu izvoditi nekoliko puta dnevno, očigledno je da je proces razvoja praćen značajnim brojem urezivanja, što znači veliki broj slika u registru. Kao rezultat toga, nameće se pitanje organizovanja efikasnog čišćenja registra, tj. uklanjanje nebitnih slika.

Ali kako uopće odrediti da li je slika relevantna?

Kriterijumi za relevantnost slike

U velikoj većini slučajeva, glavni kriterijumi će biti:

1. Prva (najočiglednija i najkritičnija 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 negirati napore timskog otklanjanja grešaka na bilo kojoj od petlji. (Iz tog razloga smo čak napravili specijal Prometejevi izvoznici, koji prati odsustvo takvih slika u bilo kojem Kubernetes klasteru.)

2. Drugo (manje očigledno, ali i veoma važno i opet se odnosi na eksploataciju) - slike koje potrebno 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 sačuvanim verzijama izdanja. (Usput, prema zadanim postavkama u Helmu ograničenje je 256 revizija, ali malo je vjerovatno da itko zaista treba da sprema takva veliki broj verzija?..) Uostalom, mi, posebno, pohranjujemo verzije kako bismo ih kasnije koristili, tj. „vratiti se“ 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 posljednjem urezivanju i, recimo, prethodnom urezivanju: 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 finalni proizvod: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra, itd.

Napomena: Kriterijumi definisani ovde su formulisani na osnovu iskustva u interakciji sa desetinama razvojnih timova iz različitih kompanija. Međutim, naravno, u zavisnosti od specifičnosti razvojnih procesa i korišćene infrastrukture (na primer, Kubernetes se ne koristi), ovi kriterijumi se mogu razlikovati.

Podobnost i postojeća rješenja

Popularni servisi sa registrima kontejnera, po pravilu, nude sopstvene politike čišćenja slike: u njima možete definisati uslove pod kojima se oznaka uklanja iz registra. Međutim, ovi uvjeti su ograničeni parametrima kao što su imena, vrijeme kreiranja i broj oznaka*.

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

Ovaj skup parametara sasvim je dovoljan da zadovolji četvrti kriterij - odnosno da odaberete slike koje odgovaraju verzijama. Međutim, za sve ostale kriterijume treba izabrati neku vrstu kompromisnog rešenja (strožu ili, obrnuto, blažu politiku) – u zavisnosti od očekivanja i finansijskih mogućnosti.

Na primjer, treći kriterij – vezan za potrebe programera – može se riješiti organiziranjem procesa unutar timova: specifično imenovanje slika, održavanje posebnih lista dopuštenja i internih ugovora. Ali u konačnici to još uvijek treba automatizirati. A ako mogućnosti gotovih rješenja nisu dovoljne, morate učiniti nešto svoje.

Situacija sa prva dva kriterijuma je slična: oni se ne mogu zadovoljiti bez primanja podataka iz eksternog sistema – onog u kome se postavljaju aplikacije (u našem slučaju Kubernetes).

Ilustracija toka rada u Gitu

Recimo da radite nešto ovako u Gitu:

Problem “pametnog” čišćenja slika kontejnera i njegovo rješenje u werfu

Ikona sa glavom na dijagramu označava slike kontejnera koji su trenutno raspoređeni u Kubernetesu za sve korisnike (krajnje korisnike, testere, menadžere, itd.) ili ih koriste programeri za otklanjanje grešaka i slične svrhe.

Šta se događa ako pravila čišćenja dozvoljavaju samo zadržavanje slika (ne brisanje) prema datim nazivima oznaka?

Problem “pametnog” čišćenja slika kontejnera i njegovo rješenje u werfu

Očigledno, takav scenario nikoga neće usrećiti.

Šta će se promijeniti ako pravila dopuštaju da se slike ne brišu? prema datom vremenskom intervalu / broju zadnjih urezivanja?

Problem “pametnog” čišćenja slika kontejnera i njegovo rješenje u werfu

Rezultat je postao mnogo bolji, ali je još uvijek daleko od idealnog. Uostalom, još uvijek imamo programere kojima su potrebne slike u registru (ili čak raspoređene u K8s) za otklanjanje grešaka...

Da sumiramo trenutnu situaciju na tržištu: funkcije dostupne u registrima kontejnera ne nude dovoljno fleksibilnosti prilikom čišćenja, a glavni razlog za to je nema načina za interakciju sa vanjskim svijetom. Ispostavilo se da su timovi kojima je potrebna takva fleksibilnost primorani da samostalno implementiraju brisanje slike „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 slike za različite timove koristeći različite registre...

Naš put ka univerzalnom čišćenju slike

Odakle dolazi ova potreba? Činjenica je da mi nismo posebna grupa programera, već tim koji služi mnogima od njih odjednom, pomažući u sveobuhvatnom rješavanju CI/CD problema. A glavni tehnički alat za to je uslužni program otvorenog koda werf. Njegova posebnost je u tome što ne obavlja jednu funkciju, već prati kontinuirane procese isporuke u svim fazama: od montaže do postavljanja.

Objavljivanje slika u registru* (odmah nakon što su napravljene) očigledna je funkcija takvog uslužnog programa. A budući da su slike tamo smještene za pohranu, onda - ako vaša pohrana nije neograničena - morate biti odgovorni za njihovo naknadno čišćenje. Kako smo u tome postigli uspjeh, zadovoljavajući sve navedene kriterije, bit će riječi dalje.

* Iako se sami registri mogu razlikovati (Docker Registry, GitLab Container Registry, Harbor, itd.), njihovi korisnici se suočavaju sa istim problemima. Univerzalno rješenje u našem slučaju ne zavisi od implementacije 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.

Tako da smo bili zauzeti eksterni implementacija mehanizma za čišćenje slika - umjesto onih mogućnosti koje su već ugrađene u registre za kontejnere. Prvi korak je bio korištenje Docker Registry API-ja za kreiranje istih primitivnih politika za broj oznaka i vrijeme njihovog kreiranja (gore spomenuto). Dodato im lista dozvola zasnovana na slikama koje se koriste u raspoređenoj infrastrukturi, tj. Kubernetes. Za ovo drugo, bilo je dovoljno koristiti Kubernetes API za ponavljanje kroz sve raspoređene resurse i dobijanje liste vrijednosti image.

Ovo trivijalno rješenje riješilo je najkritičniji problem (kriterijum br. 1), ali je bilo samo početak našeg puta ka poboljšanju mehanizma čišćenja. Sljedeći - i mnogo zanimljiviji - korak bila je odluka povezati objavljene slike sa istorijom Gita.

Šeme označavanja

Za početak smo odabrali pristup u kojem bi konačna slika trebala pohraniti potrebne informacije za čišćenje i izgradili proces na šemama označavanja. Prilikom objavljivanja slike, korisnik je odabrao određenu opciju označavanja (git-branch, git-commit ili git-tag) i koristio odgovarajuću vrijednost. U CI sistemima, ove vrijednosti su postavljene automatski na osnovu varijabli okruženja. Zapravo konačna slika je bila povezana sa određenim Git primitivom, pohranjivanje potrebnih podataka za čišćenje u etikete.

Ovaj pristup je rezultirao skupom pravila koja su omogućila da se Git koristi kao jedini izvor istine:

  • Prilikom brisanja grane/oznake u Gitu, pridružene slike u registru su automatski izbrisane.
  • Broj slika povezanih sa Git oznakama i urezima mogao bi se kontrolirati brojem oznaka korištenih u odabranoj šemi i vremenom u kojem je povezano urezivanje kreirano.

Sve u svemu, rezultirajuća implementacija je zadovoljila naše potrebe, ali nas je uskoro čekao novi izazov. Činjenica je da smo prilikom korištenja shema označavanja baziranih na Git primitivima naišli na niz nedostataka. (Budući da njihov opis izlazi iz okvira ovog članka, svi se mogu upoznati s detaljima ovdje.) Stoga, nakon što smo odlučili da pređemo na efikasniji pristup označavanju (označavanje zasnovano na sadržaju), morali smo da preispitamo implementaciju čišćenja slike.

Novi algoritam

Zašto? Sa označavanjem zasnovanim na sadržaju, svaka oznaka može zadovoljiti više urezivanja u Gitu. Prilikom čišćenja slika više ne možete pretpostaviti samo iz urezivanja gdje je nova oznaka dodana u registar.

Za novi algoritam čišćenja odlučeno je da se odmakne od šema označavanja i da se gradi proces meta slike, od kojih svaki pohranjuje gomilu:

  • urezivanje na kojem je izvršeno objavljivanje (nije bitno da li je slika dodana, promijenjena ili je ostala ista u registru kontejnera);
  • i naš interni identifikator koji odgovara sastavljenoj slici.

Drugim rečima, obezbeđeno je povezivanje objavljenih oznaka sa urezima u Gitu.

Konačna konfiguracija i opći algoritam

Prilikom konfigurisanja čišćenja, korisnici sada imaju pristup politikama koje biraju trenutne slike. Svaka takva politika je definirana:

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

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

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. Sačuvajte sliku za poslednjih 10 Git oznaka (prema datumu kreiranja oznake).
  2. Sačuvajte ne više od 2 slike objavljene u prošloj sedmici za najviše 10 niti s aktivnostima u prošloj sedmici.
  3. Sačuvajte 10 slika za grane main, staging и production.

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

  • Dohvaćanje manifesta iz registra kontejnera.
  • Isključujući slike koje se koriste u Kubernetesu, jer Već smo ih unaprijed odabrali anketiranjem K8s API-ja.
  • Skeniranje Git historije i izuzimanje slika na osnovu određenih pravila.
  • Uklanjanje preostalih slika.

Da se vratimo na našu ilustraciju, evo šta se dešava sa werf-om:

Problem “pametnog” čišćenja slika kontejnera 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 slika) - može se primijeniti na druge sisteme/uslužne programe. Da biste to učinili, dovoljno je zapamtiti probleme koji se pojavljuju i pronaći one mogućnosti u svom stogu koje vam omogućavaju da integrirate njihovo rješenje što je lakše moguće. Nadamo se da će vam put koji smo prešli pomoći da sagledate svoj slučaj s novim detaljima i razmišljanjima.

zaključak

  • Prije ili kasnije, većina timova se susreće s problemom prelijevanja registra.
  • Prilikom traženja rješenja prvo je potrebno odrediti kriterije za relevantnost slike.
  • Alati koje nude popularne usluge registra kontejnera omogućavaju vam da organizirate vrlo jednostavno čišćenje koje ne uzima u obzir „spoljni svijet“: slike koje se koriste u Kubernetesu i posebnosti toka rada tima.
  • Fleksibilan i efikasan algoritam mora imati razumijevanje CI/CD procesa i raditi ne samo s podacima Docker slike.

PS

Pročitajte i na našem blogu:

izvor: www.habr.com

Dodajte komentar