
â unser GitOps-CLI-Tool mit offenem Quellcode zur Erstellung und Bereitstellung von Anwendungen in Kubernetes. In wurde eine neue Funktion im Image-Building vorgestellt: das Tagging von Images basierend auf dem Inhalt oder content-based tagging. Bisher war das typische Tagging-Schema in werf, dass Docker-Images anhand des Git-Tags, des Git-Zweigs oder des Git-Commits getaggt wurden. Doch alle diese Schemata haben Nachteile, die durch die neue Tagging-Strategie vollstĂ€ndig gelöst werden. Details dazu und was sie so gut macht, finden Sie darunter.
Die Bereitstellung eines Satzes von Mikroservices aus einem einzelnen Git-Repository
Es gibt hĂ€ufig Situationen, in denen eine Anwendung in mehrere mehr oder weniger unabhĂ€ngige Dienste aufgeteilt ist. Die Bereitstellungen dieser Dienste können unabhĂ€ngig voneinander erfolgen: auf einmal kann ein oder mehrere Dienste bereitgestellt werden, wĂ€hrend die anderen weiterhin ohne Ănderungen arbeiten mĂŒssen. Aus der Sicht der Codeverwaltung und des Projektmanagements ist es jedoch praktischer, solche Dienste in einem einzigen Repository zu halten.
Es gibt Situationen, in denen die Dienste tatsĂ€chlich unabhĂ€ngig sind und nicht zu einer einzigen Anwendung gehören. In diesem Fall befinden sie sich in separaten Projekten, und die Bereitstellung erfolgt ĂŒber separate CI/CD-Prozesse in jedem dieser Projekte.
In der RealitĂ€t jedoch zerlegen Entwickler oft eine einheitliche Anwendung in mehrere Mikroservices, aber fĂŒr jeden einen separaten Repository und ein Projekt anzulegen, wĂ€re ... ein offensichtlicher Overkill. Genau ĂŒber diese Situation wird im Folgenden gesprochen: mehrere solche Mikroservices liegen in einem einzigen Repository des Projekts und die Bereitstellungen erfolgen ĂŒber einen einzigen CI/CD-Prozess.
Tagging nach Git-Zweig und Git-Tag
Angenommen, es wird die am weitesten verbreitete Tagging-Strategie verwendet â tag-or-branch. FĂŒr Git-Zweige werden Images mit dem Namen des Zweigs getaggt, fĂŒr einen Zweig existiert zu einem Zeitpunkt nur ein veröffentlichtes Image mit dem Namen dieses Zweigs. FĂŒr Git-Tags werden die Images entsprechend dem Tag-Namen getaggt.
Bei der Erstellung eines neuen Git-Tags â zum Beispiel bei der Veröffentlichung einer neuen Version â wird fĂŒr alle Images des Projekts im Docker-Registry ein neuer Docker-Tag erstellt:
-
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
Diese neuen Bildnamen gelangen ĂŒber Helm-Templates in die Kubernetes-Konfiguration. Bei der AusfĂŒhrung des Deployments mit dem Befehl werf deploy erfolgt eine Aktualisierung des Feldes Image in den Manifesten der Kubernetes-Ressourcen und ein Neustart der entsprechenden Ressourcen aufgrund des geĂ€nderten Bildnamens.
Problem: falls sich der Inhalt des Images seit dem letzten Rollout (Git-Tag) tatsĂ€chlich nicht geĂ€ndert hat, sondern nur dessen Docker-Tag, findet ein ĂŒberflĂŒssiger Neustart dieser Anwendung statt, wodurch möglicherweise eine Unterbrechung entsteht. Obwohl es keine wirklichen GrĂŒnde gab, fĂŒr diesen Neustart.
Folglich muss bei dem aktuellen Taggingschema mehrere separate Git-Repositorys erstellt werden, und es entsteht das Problem, diese mehreren Repositorys auszuspielen. Insgesamt fĂŒhrt ein solches Schema zu einer Ăberlastung und KomplexitĂ€t. Es ist besser, viele Dienste in einem einzigen Repository zu bĂŒndeln und Docker-Tags so zu setzen, dass ĂŒberflĂŒssige Neustarts vermieden werden.
Tagging nach Git-Commit
In werf gibt es auch eine Tagging-Strategie, die mit Git-Commits verbunden ist.
Ein Git-Commit ist der Identifier fĂŒr den Inhalt des Git-Repositorys und hĂ€ngt von der Ănderungs-Historie der Dateien im Git-Repository ab, daher erscheint es logisch, ihn fĂŒr das Tagging von Bildern im Docker-Registry zu verwenden.
Allerdings hat das Tagging nach Git-Commit die gleichen Nachteile wie das Tagging nach Git-Branches oder Git-Tags:
- Es könnte ein leerer Commit erstellt worden sein, der keine Dateien Àndert, wÀhrend der Docker-Tag des Bildes geÀndert wird.
- Es könnte ein Merge-Commit erstellt worden sein, der keine Dateien Àndert, wÀhrend der Docker-Tag des Bildes geÀndert wird.
- Es könnte ein Commit erstellt worden sein, der die Dateien in Git Àndert, die nicht im Image importiert werden, und der Docker-Tag des Bildes wird erneut geÀndert.
Tagging nach dem Namen des Git-Branches spiegelt nicht die Version des Images wider
Es gibt noch ein weiteres Problem, das mit der Tagging-Strategie nach Git-Branches verbunden ist.
Tagging nach dem Namen des Branches funktioniert, solange die Commits dieses Branches chronologisch aufeinanderfolgend gesammelt werden.
Wenn der Benutzer im aktuellen Schema eine Neubau des alten Commits, der mit einem bestimmten Branch verbunden ist, startet, wird werf das Image gemÀà dem entsprechenden Docker-Tag mit der neu gebauten Version des Images fĂŒr den alten Commit ĂŒberschreiben. Die Deployments, die dieses Tag verwenden, laufen ab diesem Moment Gefahr, beim Neustart der Pods eine andere Version des Images zu ziehen, was dazu fĂŒhren kann, dass unsere Anwendung die Verbindung zum CI-System verliert und desynchronisiert wird.
DarĂŒber hinaus kann bei aufeinanderfolgenden Pushes in einen Branch mit geringen ZeitabstĂ€nden zwischen ihnen der alte Commit spĂ€ter gebaut werden als der neuere: Die alte Version des Images ĂŒberschreibt die neue nach dem Git-Branch-Tag. Solche Probleme können von einem CI/CD-System (z. B. wird in GitLab CI fĂŒr eine Reihe von Commits das Pipeline des letzten Commits gestartet) gelöst werden. Allerdings unterstĂŒtzen nicht alle Systeme dies, und es sollte eine zuverlĂ€ssigere Methode zur Vermeidung eines so fundamentalen Problems geben.
Was ist Content-based Tagging?
Also, was ist Content-based Tagging â das Tagging von Images basierend auf deren Inhalt.
Zur Erstellung von Docker-Tags werden nicht die primitiven Git-Elemente (Git-Branch, Git-TagâŠ) verwendet, sondern eine PrĂŒfziffer, die verbunden ist mit:
- dem Inhalt des Images. Die Tag-ID des Images spiegelt dessen Inhalt wider. Bei der Erstellung einer neuen Version wird diese ID nicht verÀndert, sofern sich die Dateien im Image nicht geÀndert haben;
- der Historie der Erstellung dieses Images in Git. Images, die mit verschiedenen Git-Branches und unterschiedlichen Bauhistorien ĂŒber werf verbunden sind, haben unterschiedliche Tag-IDs.
So eine Tag-ID ist die sogenannte Stufensignatur des Images.
Jedes Image besteht aus einer Reihe von Stufen: from, before-install, git-archive, install, imports-after-install, before-setup,⊠git-latest-patch usw. Jede Stufe hat eine ID, die ihren Inhalt widerspiegelt, â Stufensignatur (stage signature).
Das endgĂŒltige Bild, das aus diesen Stufen besteht, wird mit der sogenannten Signatur der Stufensammlung getaggt â stages signature, â die verallgemeinernd fĂŒr alle Stufen des Images ist.
Jedes Image aus der Konfiguration werf.yaml wird im Allgemeinen eine solche Signatur und damit einen entsprechenden Docker-Tag haben.
Die Stufensignatur löst alle genannten Probleme:
- Ist resistent gegen leere Git-Commits.
- Ist resistent gegen Git-Commits, die Dateien verĂ€ndern, die nicht relevant fĂŒr das Image sind.
- FĂŒhrt nicht zu einem Problem mit der Ăberschreibung der aktuellen Version des Images beim Neustart von Builds fĂŒr alte Git-Commits des Branches.
Dies ist jetzt die empfohlene Tagging-Strategie und wird standardmĂ€Ăig in werf fĂŒr alle CI-Systeme verwendet.
Wie man es in werf aktiviert und verwendet
Die entsprechende Option wurde im Befehl hinzugefĂŒgt werf publish: --tag-by-stages-signature=true|false
In der CI-System wird die Tagging-Strategie durch den Befehl festgelegt werf ci-env. Zuvor wurde dafĂŒr der Parameter definiert werf ci-env --tagging-strategy=tag-or-branch. Wenn nun werf ci-env --tagging-strategy=stages-signature oder diese Option weggelassen wird, verwendet werf standardmĂ€Ăig die Tagging-Strategie stages-signature. Der Befehl werf ci-env stellt automatisch die erforderlichen Flags fĂŒr den Befehl ein werf build-and-publish (oder werf publish), daher mĂŒssen fĂŒr diese Befehle keine zusĂ€tzlichen Optionen angegeben werden.
Beispielsweise der Befehl:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature⊠kann die folgenden Images erstellen:
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Hier 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d â das ist die Signatur der Stufen des Images backend, und f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 â Signatur der Stufen des Images frontend.
Bei der Verwendung spezieller Funktionen werf_container_image und werf_container_env muss im Helm-Template nichts geÀndert werden: diese Funktionen generieren automatisch die korrekten Image-Namen.
Beispielkonfiguration im CI-System:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployWeitere Informationen zur Konfiguration finden Sie in der Dokumentation:
- ;
- ;
- .
Insgesamt
- Neue Option
werf publish --tag-by-stages-signature=true|false. - Neuer Wert der Option
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(wenn nicht angegeben, wird standardmĂ€Ăigstages-signature). - Wenn zuvor Tags nach Git-Commits verwendet wurden (
WERF_TAG_GIT_COMMIToder die Optionwerf publish --tag-git-commit COMMIT), muss unbedingt auf die Tagging-Strategie umgestellt werden. stages-signature. - Neue Projekte sollten sofort auf das neue Tagging-System umgestellt werden.
- Alte Projekte sollten beim Ăbergang zu werf 1.1 idealerweise auf das neue Tagging-System umgestellt werden, jedoch wird die alte tag-or-branch weiterhin unterstĂŒtzt.
Content-basiertes Tagging löst alle im Artikel angesprochenen Probleme:
- Widerstandsvermögen des Docker-Tag-Namens gegen leere Git-Commits.
- Widerstandsvermögen des Docker-Tag-Namens gegen Git-Commits, die irrelevante Dateien fĂŒr das Image Ă€ndern.
- FĂŒhrt nicht zu Problemen beim Ăberschreiben der aktuellen Version des Images bei einem Neustart von Builds fĂŒr alte Git-Commits in Git-Zweigen.
Nutzen Sie es! Und vergessen Sie nicht, uns auf , um ein Issue zu erstellen oder ein bereits bestehendes zu finden, einen Daumen hoch zu geben, einen PR zu erstellen oder einfach den Fortschritt des Projekts zu beobachten.
P.S.
Lesen Sie auch in unserem Blog:
- «»
- «»
- «»;
- Eine Serie von Notizen zu neuen Funktionen in werf:
- «»;
- «»;
- «»;
- «».
Quelle: habr.com
