
— onze GitOps CLI-tool met open source voor het bouwen en leveren van applicaties in Kubernetes. In is een nieuwe functie gepresenteerd in de image builder: tags voor images op basis van inhoud of content-based tagging. Tot nu toe was de typische tagging-strategie in werf het taggen van Docker-images op git-tag, git-branch of git-commit. Maar al deze schema's hebben nadelen die volledig worden opgelost door de nieuwe tagging-strategie. Meer details daarover en wat het zo goed maakt — verderop.
De uitrol van een set microservices vanuit één Git-repository
Het komt vaak voor dat een applicatie is opgesplitst in meerdere meer of minder onafhankelijke services. De releases van deze services kunnen onafhankelijk plaatsvinden: in één keer kan één of meerdere services worden vrijgegeven, terwijl de andere zonder enige wijziging moeten blijven werken. Maar vanuit het oogpunt van codemanagement en projectbeheer is het handiger om dergelijke services in één repository te houden.
Er zijn situaties waarin services echt onafhankelijk zijn en niet zijn verbonden aan één applicatie. In dat geval zullen ze zich in aparte projecten bevinden en zal hun release via afzonderlijke CI/CD-processen in elk van de projecten plaatsvinden.
In de praktijk splitsen ontwikkelaars vaak een enkele applicatie op in verschillende microservices, maar het aanmaken van een aparte repository en project voor elk… — is duidelijk overkill. Dit artikel behandelt precies deze situatie: verschillende microservices bevinden zich in één enkele projectrepository en releases vinden plaats via één proces in CI/CD.
Taggen op Git-branch en Git-tag
Laten we de meest voorkomende tagging-strategie gebruiken — tag-or-branch. Voor Git-branches worden images getagd met de naam van de branch, voor één branch bestaat er op elk moment slechts één gepubliceerde image met de naam van deze branch. Voor Git-tags worden images overeenkomstig de naam van de tag getagd.
Bij het aanmaken van een nieuwe Git-tag — bijvoorbeeld bij de uitgave van een nieuwe versie — zal voor alle images van het project in de Docker Registry een nieuwe Docker-tag worden aangemaakt:
-
myregistry.org/myproject/frontend:v1.1.10 -
myregistry.org/myproject/myservice1:v1.1.10 -
myregistry.org/myproject/myservice2:v1.1.10 -
myregistry.org/myproject/myservice3:v1.1.10 -
myregistry.org/myproject/myservice4:v1.1.10 -
myregistry.org/myproject/myservice5:v1.1.10 -
myregistry.org/myproject/database:v1.1.10
Deze nieuwe afbeeldingsnamen worden via Helm-templates in de configuratie van Kubernetes opgenomen. Bij het uitvoeren van de deployment met het commando werf deploy wordt het veld afbeelding in de manifesten van Kubernetes-resources bijgewerkt en worden de bijbehorende resources opnieuw opgestart vanwege de gewijzigde afbeeldingsnaam.
Probleem: in het geval dat de inhoud van de afbeelding niet is gewijzigd sinds de vorige release (Git-tag), maar alleen de Docker-tag, vindt er onnodig herstarten van deze applicatie plaats en kan er dus enige downtime optreden. Hoewel er geen echte redenen waren om deze herstart uit te voeren.
Als gevolg hiervan moet bij de huidige tagstrategie verschillende aparte Git-repositories worden opgezet en rijst het probleem van de organisatie van de releases van deze verschillende repositories. Over het algemeen lijkt deze aanpak overbelast en complex. Het is beter om meerdere services in één enkele repository te combineren en Docker-tags te creëren om onnódige herstarts te voorkomen.
Tagging op basis van Git-commits
In werf is er ook een taggingstrategie die verband houdt met Git-commits.
Een Git-commit is een identificatie van de inhoud van de Git-repository en is afhankelijk van de bewerkingsgeschiedenis van bestanden in de Git-repository, daarom lijkt het logisch om deze te gebruiken voor het taggen van afbeeldingen in de Docker Registry.
Echter, tagging op basis van Git-commits heeft dezelfde nadelen als tagging op basis van Git-branches of Git-tags:
- Er had een lege commit kunnen worden gemaakt die geen bestanden wijzigt, maar de Docker-tag van de afbeelding zal worden gewijzigd.
- Er had een merge-commit kunnen worden gemaakt die geen bestanden wijzigt, maar de Docker-tag van de afbeelding zal worden gewijzigd.
- Er had een commit kunnen worden gemaakt die de bestanden in Git wijzigt die niet in de afbeelding zijn geïmporteerd, en de Docker-tag van de afbeelding zal opnieuw worden gewijzigd.
Tagging op basis van de naam van de Git-branch weerspiegelt niet de versie van de afbeelding.
Er is ook nog een probleem dat verband houdt met de taggingstrategie op basis van Git-branches.
Tagging op basis van de naam van de branch werkt zolang de commits van deze branch sequentieel in chronologische volgorde worden verzameld.
Als in de huidige opzet de gebruiker een opnieuw opbouwen van een oude commit, verbonden met een bepaalde branch, start, zal werf de afbeelding verversen op basis van de overeenkomstige Docker-tag met de opnieuw gebouwde versie van de afbeelding voor de oude commit. Deployments die deze tag gebruiken, lopen vanaf dat moment het risico tijdens het opnieuw opstarten van pods een andere versie van de afbeelding te pullen, waardoor onze toepassing de verbinding met het CI-systeem verliest en desynchroniseert.
Bovendien kan bij opeenvolgende pushs naar dezelfde branch met een korte tijdsinterval tussen hen, een oude commit later worden opgebouwd dan een nieuwere: de oude versie van de afbeelding overschrijft de nieuwe op de Git-branch tag. Dergelijke problemen kunnen worden opgelost door een CI/CD-systeem (bijvoorbeeld in GitLab CI wordt voor een reeks commits de pipeline van de laatste gestart). Niet alle systemen ondersteunen dit en er moet een betrouwbaardere manier zijn om zo'n fundamenteel probleem te voorkomen.
Wat is content-based tagging?
Dus wat is content-based tagging - het taggen van afbeeldingen op basis van hun inhoud.
Voor het creëren van Docker-tags worden geen primitieve Git-elementen (Git-branch, Git-tag...) gebruikt, maar een controlegetal dat gerelateerd is aan:
- de inhoud van de afbeelding. De tag-identificator van de afbeelding weerspiegelt zijn inhoud. Bij het samenstellen van een nieuwe versie verandert deze identificator niet, als de bestanden in de afbeelding niet zijn gewijzigd;
- de geschiedenis van het creëren van deze afbeelding in Git. Afbeeldingen die zijn gekoppeld aan verschillende Git-branches en verschillende bouwgeschiedenissen via werf, zullen verschillende tag-identificatoren hebben.
Als zo'n tag-identificator fungeert de zogenaamde fase-signatuur van de afbeelding.
Elke afbeelding bestaat uit een set fasen: van, before-install, git-archive, install, imports-after-install, before-setup,… git-latest-patch enzovoort. Elke fase heeft een identificator die zijn inhoud weerspiegelt, - de fase-signatuur (stage signature).
De uiteindelijke afbeelding, die bestaat uit deze fasen, wordt getagd met de zogenaamde signatuur van deze set fasen - stages signature, - die een algemeen beeld geeft van alle fasen van de afbeelding.
Elke afbeelding uit de configuratie werf.yaml zal in het algemeen zijn eigen zo'n signatuur hebben en bijgevolg een Docker-tag.
De fase-signatuur lost al deze genoemde problemen op:
- Is resistent tegen lege Git-commits.
- Is resistent tegen Git-commits die bestanden wijzigen die niet relevant zijn voor de afbeelding.
- Veroorzaakt geen probleem met het overschrijven van de huidige versie van de afbeelding bij het opnieuw opstarten van builds voor oude Git-commits van de branch.
Dit is nu de aanbevolen taggingstrategie en wordt standaard gebruikt in werf voor alle CI-systemen.
Hoe in te schakelen en te gebruiken in werf
De relevante optie is toegevoegd aan het commando werf publish: --tag-by-stages-signature=true|false
In het CI-systeem wordt de taggingstrategie ingesteld met het commando werf ci-env. Eerder werd hiervoor een parameter gedefinieerd werf ci-env --tagging-strategy=tag-or-branch. Nu, als je opgeeft werf ci-env --tagging-strategy=stages-signature of deze optie niet op te geven, zal werf standaard de tagging-strategie gebruiken stages-signature. De opdracht werf ci-env zal automatisch de benodigde vlaggen voor het commando instellen werf build-and-publish (of werf publish), dus er zijn geen extra opties nodig voor deze commando's.
Bijvoorbeeld, het commando:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature… kan de volgende beelden aanmaken:
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Hier 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — dit is de signature van de beeldfase backend, met behulp van 1 bit, gelijk aan 0, f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — signature van de beeldfase frontend.
Bij het gebruik van speciale functies werf_container_image en werf_container_env hoeven er in de Helm-sjablonen niets te worden gewijzigd: deze functies zullen automatisch de juiste namen voor de beelden genereren.
Voorbeeldconfiguratie in het CI-systeem:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployMeer informatie over de configuratie is beschikbaar in de documentatie:
- ;
- ;
- .
Total
- Nieuwe optie
werf publish --tag-by-stages-signature=true|false. - Nieuwe waarde voor optie
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(als niet opgegeven, is het standaardstages-signature). - Als eerder taggingopties op basis van Git-commits zijn gebruikt (
WERF_TAG_GIT_COMMITof optiewerf publish --tag-git-commit COMMIT), dan moet de taggingstrategie worden gewijzigd stages-signature. - Nieuwe projecten kunnen beter meteen worden omgeschakeld naar het nieuwe tagging-schema.
- Oude projecten die naar werf 1.1 worden overgezet, moeten idealiter worden omgeschakeld naar het nieuwe tagging-schema, maar het oude tag-or-branch wordt nog steeds ondersteund.
Content-based tagging lost alle in het artikel besproken problemen op:
- De robuustheid van de Docker-tagnaam tegen lege Git-commits.
- De robuustheid van de Docker-tagnaam tegen Git-commits die irrelevante bestanden voor het beeld wijzigen.
- Leidt niet tot problemen met het overschrijven van de actuele versie van het beeld bij het opnieuw starten van builds voor oude Git-commits voor Git-takken.
Gebruik het! En vergeet niet om bij ons te kijken op , om een issue te creëren of een bestaand te vinden, een plus te geven, een PR te maken of gewoon het project te volgen.
P.S.
Lees ook op onze blog:
- «»
- «»
- «»;
- Een cyclus van notities over de innovaties in werf:
- «»;
- «»;
- «»;
- «».
Bron: habr.com
