Het probleem van het "slim" opschonen van containerafbeeldingen en de oplossing ervan op de werf

Het probleem van het "slim" opschonen van containerafbeeldingen en de oplossing ervan op de werf

Het artikel bespreekt de problemen van het opschonen van afbeeldingen die zich ophopen in containerregisters (Docker Registry en zijn analogen) in de realiteit van moderne CI/CD-pijplijnen voor cloud-native applicaties die aan Kubernetes worden geleverd. De belangrijkste criteria voor de relevantie van afbeeldingen en de daaruit voortvloeiende problemen bij het automatiseren van het schoonmaken, het besparen van ruimte en het voldoen aan de behoeften van teams worden gegeven. Ten slotte zullen we u, aan de hand van het voorbeeld van een specifiek Open Source-project, vertellen hoe deze moeilijkheden kunnen worden overwonnen.

Introductie

Het aantal images in een containerregister kan snel groeien, waardoor meer opslagruimte in beslag wordt genomen en de kosten aanzienlijk stijgen. Om de aanvaardbare groei van de ruimte die in het register wordt ingenomen te controleren, beperken of handhaven, wordt het volgende aanvaard:

  1. gebruik een vast aantal tags voor afbeeldingen;
  2. maak de afbeeldingen op de een of andere manier schoon.


De eerste beperking is soms acceptabel voor kleine teams. Als ontwikkelaars voldoende permanente tags hebben (latest, main, test, boris enz.), zal het register niet groter worden en hoeft u lange tijd niet na te denken over het opschonen ervan. Alle irrelevante afbeeldingen worden immers gewist en er is simpelweg geen werk meer om op te ruimen (alles wordt gedaan door een gewone vuilnisman).

Deze aanpak beperkt de ontwikkeling echter enorm en is zelden toepasbaar op moderne CI/CD-projecten. Een integraal onderdeel van de ontwikkeling was automatisering, waarmee u nieuwe functionaliteit veel sneller kunt testen, implementeren en aan gebruikers kunt leveren. In al onze projecten wordt bijvoorbeeld bij elke commit automatisch een CI-pijplijn aangemaakt. Daarin wordt het image samengesteld, getest, uitgerold naar verschillende Kubernetes-circuits voor debugging en overige controles, en als alles goed gaat, bereiken de wijzigingen de eindgebruiker. En dit is niet langer rocket science, maar voor velen een alledaagse gebeurtenis - waarschijnlijk ook voor jou, aangezien je dit artikel leest.

Omdat het oplossen van bugs en het ontwikkelen van nieuwe functionaliteit parallel worden uitgevoerd en releases meerdere keren per dag kunnen worden uitgevoerd, is het duidelijk dat het ontwikkelingsproces gepaard gaat met een aanzienlijk aantal commits, wat betekent een groot aantal afbeeldingen in het register. Als gevolg hiervan ontstaat de kwestie van het organiseren van een effectieve opschoning van het register, d.w.z. het verwijderen van irrelevante afbeeldingen.

Maar hoe bepaal je eigenlijk of een afbeelding relevant is?

Criteria voor de relevantie van het beeld

In de overgrote meerderheid van de gevallen zullen de belangrijkste criteria zijn:

1. De eerste (de meest voor de hand liggende en meest kritische van allemaal) zijn de beelden die momenteel gebruikt in Kubernetes. Het verwijderen van deze afbeeldingen kan resulteren in aanzienlijke kosten voor downtime van de productie (de afbeeldingen kunnen bijvoorbeeld nodig zijn voor replicatie) of kan de inspanningen van het team bij het debuggen van een van de lussen teniet doen. (Om deze reden hebben we zelfs een special gemaakt Prometheus-exporteurs, die de afwezigheid van dergelijke afbeeldingen in elk Kubernetes-cluster bijhoudt.)

2. Ten tweede (minder voor de hand liggend, maar ook erg belangrijk en heeft opnieuw betrekking op uitbuiting) - beelden die vereist voor het terugdraaien in geval van detectie van ernstige problemen in de huidige versie. In het geval van Helm zijn dit bijvoorbeeld afbeeldingen die worden gebruikt in opgeslagen versies van de release. (Trouwens, in Helm is de limiet standaard 256 revisies, maar het is onwaarschijnlijk dat iemand echt moet opslaan zo een een groot aantal versies?..) Wij slaan immers vooral versies op, zodat we ze later kunnen gebruiken, d.w.z. “roll back” naar hen indien nodig.

3. Derde - behoeften van de ontwikkelaar: Alle afbeeldingen die gerelateerd zijn aan hun huidige werk. Als we bijvoorbeeld een PR overwegen, is het zinvol om een ​​afbeelding achter te laten die overeenkomt met de laatste commit en bijvoorbeeld de vorige commit: op deze manier kan de ontwikkelaar snel terugkeren naar elke taak en werken met de laatste wijzigingen.

4. Ten vierde - afbeeldingen die komen overeen met de versies van onze applicatie, d.w.z. zijn het eindproduct: v1.0.0, 20.04.01/XNUMX/XNUMX, sierra, enz.

NB: De hier gedefinieerde criteria zijn geformuleerd op basis van ervaring in de interactie met tientallen ontwikkelingsteams van verschillende bedrijven. Afhankelijk van de specifieke kenmerken van de ontwikkelingsprocessen en de gebruikte infrastructuur (Kubernetes wordt bijvoorbeeld niet gebruikt) kunnen deze criteria uiteraard verschillen.

Geschiktheid en bestaande oplossingen

Populaire services met containerregisters bieden in de regel hun eigen beleid voor het opschonen van afbeeldingen: daarin kunt u de voorwaarden definiëren waaronder een tag uit het register wordt verwijderd. Deze voorwaarden worden echter beperkt door parameters zoals namen, aanmaaktijd en aantal tags*.

* Afhankelijk van specifieke implementaties van containerregisters. We hebben de mogelijkheden van de volgende oplossingen overwogen: Azure CR, Docker Hub, ECR, GCR, GitHub Packages, GitLab Container Registry, Harbor Registry, JFrog Artifactory, Quay.io - vanaf september 2020.

Deze reeks parameters is voldoende om aan het vierde criterium te voldoen, dat wil zeggen om afbeeldingen te selecteren die overeenkomen met de versies. Voor alle andere criteria moet men echter een soort compromisoplossing kiezen (een strenger of, omgekeerd, soepeler beleid) – afhankelijk van de verwachtingen en de financiële mogelijkheden.

Het derde criterium – gerelateerd aan de behoeften van ontwikkelaars – kan bijvoorbeeld worden opgelost door processen binnen teams te organiseren: specifieke naamgeving van afbeeldingen, het bijhouden van speciale acceptatielijsten en interne afspraken. Maar uiteindelijk moet het toch geautomatiseerd worden. En als de mogelijkheden van kant-en-klare oplossingen niet voldoende zijn, moet je zelf iets doen.

De situatie met de eerste twee criteria is vergelijkbaar: ze kunnen niet worden vervuld zonder gegevens te ontvangen van een extern systeem - het systeem waarop applicaties worden ingezet (in ons geval Kubernetes).

Illustratie van de werkstroom in Git

Laten we zeggen dat je zoiets in Git werkt:

Het probleem van het "slim" opschonen van containerafbeeldingen en de oplossing ervan op de werf

Het pictogram met een kop in het diagram geeft containerimages aan die momenteel in Kubernetes worden geïmplementeerd voor alle gebruikers (eindgebruikers, testers, managers, enz.) of die door ontwikkelaars worden gebruikt voor foutopsporing en soortgelijke doeleinden.

Wat gebeurt er als het opschoonbeleid alleen toestaat dat afbeeldingen worden bewaard (niet verwijderd) op basis van opgegeven tagnamen?

Het probleem van het "slim" opschonen van containerafbeeldingen en de oplossing ervan op de werf

Het is duidelijk dat een dergelijk scenario niemand gelukkig zal maken.

Wat zal er veranderen als het beleid toestaat dat afbeeldingen niet worden verwijderd? volgens een bepaald tijdsinterval / aantal laatste commits?

Het probleem van het "slim" opschonen van containerafbeeldingen en de oplossing ervan op de werf

Het resultaat is veel beter geworden, maar nog verre van ideaal. We hebben tenslotte nog steeds ontwikkelaars die afbeeldingen in het register nodig hebben (of zelfs geïmplementeerd in K8s) om bugs te debuggen...

Om de huidige marktsituatie samen te vatten: de functies die beschikbaar zijn in containerregisters bieden niet voldoende flexibiliteit bij het opschonen, en de belangrijkste reden hiervoor is geen enkele manier om met de buitenwereld te communiceren. Het blijkt dat teams die dergelijke flexibiliteit nodig hebben, gedwongen worden om zelfstandig het verwijderen van afbeeldingen “van buitenaf” te implementeren, met behulp van de Docker Registry API (of de native API van de overeenkomstige implementatie).

We waren echter op zoek naar een universele oplossing die het opschonen van afbeeldingen zou automatiseren voor verschillende teams die verschillende registers gebruiken...

Ons pad naar universele beeldreiniging

Waar komt deze behoefte vandaan? Feit is dat we geen afzonderlijke groep ontwikkelaars zijn, maar een team dat velen van hen tegelijk bedient en helpt bij het volledig oplossen van CI/CD-problemen. En het belangrijkste technische hulpmiddel hiervoor is het Open Source-hulpprogramma werf. Het bijzondere is dat het niet één enkele functie vervult, maar continue leveringsprocessen in alle fasen begeleidt: van montage tot implementatie.

Het publiceren van images naar het register* (onmiddellijk nadat ze zijn gebouwd) is een voor de hand liggende functie van een dergelijk hulpprogramma. En aangezien de afbeeldingen daar worden geplaatst voor opslag, moet u - als uw opslag niet onbeperkt is - verantwoordelijk zijn voor de daaropvolgende schoonmaak ervan. Hoe we hierin succes hebben geboekt en aan alle gestelde criteria hebben voldaan, zal verder worden besproken.

* Hoewel de registers zelf verschillend kunnen zijn (Docker Registry, GitLab Container Registry, Harbor, enz.), worden hun gebruikers met dezelfde problemen geconfronteerd. De universele oplossing is in ons geval niet afhankelijk van de implementatie van het register, omdat draait zelf buiten de registers en biedt voor iedereen hetzelfde gedrag.

Hoewel we werf als voorbeeldimplementatie gebruiken, hopen we dat de gebruikte aanpak nuttig zal zijn voor andere teams die met soortgelijke problemen worden geconfronteerd.

Dus we zijn druk bezig geweest extern implementatie van een mechanisme voor het opschonen van afbeeldingen - in plaats van de mogelijkheden die al in registers voor containers zijn ingebouwd. De eerste stap was het gebruik van de Docker Registry API om hetzelfde primitieve beleid te creëren voor het aantal tags en het tijdstip waarop ze werden aangemaakt (hierboven vermeld). Aan hen toegevoegd lijst met toegestane gebruikers op basis van afbeeldingen die worden gebruikt in de geïmplementeerde infrastructuur, d.w.z. Kubernetes. Voor dit laatste was het voldoende om de Kubernetes API te gebruiken om alle geïmplementeerde bronnen te doorlopen en een lijst met waarden te verkrijgen image.

Deze triviale oplossing loste het meest kritische probleem op (criterium nr. 1), maar was slechts het begin van onze reis om het reinigingsmechanisme te verbeteren. De volgende – en veel interessantere – stap was de beslissing koppel gepubliceerde afbeeldingen aan Git-geschiedenis.

Tagging-schema's

Om te beginnen kozen we voor een aanpak waarbij het uiteindelijke beeld de benodigde informatie voor het opschonen zou moeten opslaan, en bouwden we het proces op tagging-schema's. Bij het publiceren van een afbeelding heeft de gebruiker een specifieke taggingoptie geselecteerd (git-branch, git-commit of git-tag) en gebruikte de overeenkomstige waarde. In CI-systemen werden deze waarden automatisch ingesteld op basis van omgevingsvariabelen. In werkelijkheid de uiteindelijke afbeelding werd geassocieerd met een specifieke Git-primitief, waarbij de benodigde gegevens voor het reinigen in labels worden opgeslagen.

Deze aanpak resulteerde in een reeks beleidsregels die het mogelijk maakten Git te gebruiken als de enige bron van waarheid:

  • Bij het verwijderen van een branch/tag in Git werden de bijbehorende afbeeldingen in het register automatisch verwijderd.
  • Het aantal afbeeldingen dat is gekoppeld aan Git-tags en commits kan worden bepaald door het aantal tags dat in het geselecteerde schema wordt gebruikt en het tijdstip waarop de bijbehorende commit is gemaakt.

Over het geheel genomen voldeed de resulterende implementatie aan onze behoeften, maar al snel wachtte ons een nieuwe uitdaging. Feit is dat we bij het gebruik van tagging-schema's gebaseerd op Git-primitieven een aantal tekortkomingen tegenkwamen. (Aangezien hun beschrijving buiten het bestek van dit artikel valt, kan iedereen zich vertrouwd maken met de details hier.) Daarom moesten we, nadat we hadden besloten om over te stappen op een efficiëntere benadering van tagging (op inhoud gebaseerde tagging), de implementatie van het opschonen van afbeeldingen heroverwegen.

Nieuw algoritme

Waarom? Met op inhoud gebaseerde tagging kan elke tag aan meerdere commits in Git voldoen. Bij het opschonen van afbeeldingen kun je er niet meer vanuit gaan alleen van de commit waar de nieuwe tag aan het register is toegevoegd.

Voor het nieuwe opschoonalgoritme werd besloten om af te stappen van tagging-schema's en te bouwen meta-beeldproces, die elk een aantal bevatten:

  • de commit waarop de publicatie is uitgevoerd (het maakt niet uit of de afbeelding is toegevoegd, gewijzigd of hetzelfde is gebleven in het containerregister);
  • en onze interne identificatie die overeenkomt met de samengestelde afbeelding.

Met andere woorden, het werd verstrekt gepubliceerde tags koppelen aan commits in Git.

Definitieve configuratie en algemeen algoritme

Bij het configureren van het opschonen hebben gebruikers nu toegang tot beleid dat huidige afbeeldingen selecteert. Elk dergelijk beleid wordt gedefinieerd:

  • veel referenties, d.w.z. Git-tags of Git-vertakkingen die worden gebruikt tijdens het scannen;
  • en de limiet van gezochte afbeeldingen voor elke referentie uit de set.

Ter illustratie: dit is hoe de standaardbeleidsconfiguratie er begon uit te zien:

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

Deze configuratie bevat drie beleidsregels die voldoen aan de volgende regels:

  1. Bewaar de afbeelding voor de laatste 10 Git-tags (op basis van de aanmaakdatum van de tag).
  2. Bewaar niet meer dan 2 afbeeldingen die de afgelopen week zijn gepubliceerd voor niet meer dan 10 discussies met activiteit in de afgelopen week.
  3. Bewaar 10 afbeeldingen voor takken main, staging и production.

Het uiteindelijke algoritme komt neer op de volgende stappen:

  • Manifesten ophalen uit het containerregister.
  • Exclusief afbeeldingen gebruikt in Kubernetes, omdat We hebben ze al vooraf geselecteerd door de K8s API te pollen.
  • Git-geschiedenis scannen en afbeeldingen uitsluiten op basis van gespecificeerd beleid.
  • Resterende afbeeldingen verwijderen.

Terugkerend naar ons voorbeeld, dit is wat er gebeurt met werf:

Het probleem van het "slim" opschonen van containerafbeeldingen en de oplossing ervan op de werf

Maar zelfs als u werf niet gebruikt, kan een vergelijkbare aanpak voor het geavanceerd opschonen van afbeeldingen - in een of andere implementatie (volgens de voorkeursaanpak voor het taggen van afbeeldingen) - worden toegepast op andere systemen/hulpprogramma's. Om dit te doen, volstaat het om de problemen die zich voordoen te onthouden en die kansen in uw stapel te vinden waarmee u hun oplossing zo soepel mogelijk kunt integreren. We hopen dat het pad dat we hebben afgelegd u zal helpen om met nieuwe details en gedachten naar uw specifieke geval te kijken.

Conclusie

  • Vroeg of laat worden de meeste teams geconfronteerd met het probleem van registeroverflow.
  • Bij het zoeken naar oplossingen is het eerst nodig om de criteria voor de relevantie van het beeld te bepalen.
  • Met de tools die worden aangeboden door populaire containerregistratiediensten kunt u een zeer eenvoudige opschoning organiseren waarbij geen rekening wordt gehouden met de ‘buitenwereld’: de afbeeldingen die in Kubernetes worden gebruikt en de eigenaardigheden van de workflows van het team.
  • Een flexibel en efficiënt algoritme moet inzicht hebben in CI/CD-processen en niet alleen met Docker-beeldgegevens werken.

PS

Lees ook op onze blog:

Bron: www.habr.com

Voeg een reactie