
— unser GitOps CLI-Tool mit offenem Quellcode zum Erstellen und Bereitstellen von Anwendungen in Kubernetes. In wurde eine neue Funktion im Image-Builder eingeführt: die Tagging-Möglichkeit basierend auf dem Inhalt oder inhaltsbasiertes Tagging. Bislang bestand das typische Tagging-Schema in werf darin, Docker-Images nach Git-Tag, Git-Branch oder Git-Commit zu taggen. Doch alle diese Ansätze haben Mängel, die durch die neue Tagging-Strategie vollständig behoben werden. Weitere Details dazu und warum sie so vorteilhaft ist — im Folgenden.
Deployment eines Satzes von Microservices aus einem Git-Repository
Es kommt häufig vor, dass eine Anwendung in mehrere mehr oder weniger unabhängige Dienste unterteilt ist. Die Releases dieser Dienste können unabhängig voneinander stattfinden: Es kann gleichzeitig ein oder mehrere Dienste released werden, während die anderen weiterhin ohne Änderungen funktionieren müssen. Aus Sicht der Codeverwaltung und Projektorganisation ist es jedoch sinnvoller, solche Dienste der Anwendung in einem einzigen Repository zu halten.
Es gibt Situationen, in denen Dienste tatsächlich unabhängig sind und nicht mit einer einzigen Anwendung verbunden sind. In diesem Fall werden sie in separaten Projekten platziert, und ihre Veröffentlichung erfolgt über separate CI/CD-Prozesse in jedem der Projekte.
In Wirklichkeit teilen Entwickler jedoch oft eine gesamte Anwendung in mehrere Mikrodienste auf, und es wäre ein klarer Overkill, für jeden einzelnen einen separaten Repository und ein Projekt zu erstellen... Genau um diese Situation wird es im Folgenden gehen: Mehrere solcher Mikrodienste liegen in einem einzigen Repository des Projekts, und die Veröffentlichungen erfolgen über einen einzigen Prozess in CI/CD.
Tagging nach Git-Branch und Git-Tag
Angenommen, die am weitesten verbreitete Tagging-Strategie wird verwendet — tag-or-branch. Für Git-Branches werden die Images mit dem Namen des Branches getaggt, zu einem bestimmten Zeitpunkt existiert für einen Branch nur ein veröffentlichtes Image mit diesem Namen. Für Git-Tags werden die Images entsprechend dem Namen des Tags getaggt.
Beim Erstellen eines neuen Git-Tags — beispielsweise beim erscheinen 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 Image-Namen gelangen über Helm-Vorlagen in die Kubernetes-Konfiguration. Beim Starten des Deployments mit dem Befehl werf deploy wird das Feld image in den Ressourcen-Manifests von Kubernetes aktualisiert und die entsprechenden Ressourcen aufgrund des geänderten Image-Namens neu gestartet.
Das Problem: wenn sich der Inhalt des Images im Vergleich zur vorherigen Version (Git-Tag) tatsächlich nicht geändert hat, sondern nur das Docker-Tag, kommt es zu einem unnötigen Neustart dieser Anwendung und somit kann es zu einem gewissen Stillstand kommen. Obwohl es keine wirklichen Gründe gab, diesen Neustart durchzuführen.
Folglich muss man bei dem aktuellen Tagging-Schema mehrere separate Git-Repositories verwalten, und es entsteht das Problem der Organisation der Bereitstellung dieser mehreren Repositories. Insgesamt wird ein solches Schema überladen und kompliziert. Es ist besser, viele Dienste in einem einzigen Repository zu bündeln und Docker-Tags zu erstellen, um unnötige Neustarts zu vermeiden.
Tagging nach Git-Commit
In werf gibt es auch eine Tagging-Strategie, die mit Git-Commits verbunden ist.
Ein Git-Commit ist eine Identifikation des Inhalts eines Git-Repositorys und hängt von der Historie der Dateiänderungen im Git-Repository ab. Daher erscheint es sinnvoll, ihn zum Taggen von Images im Docker-Registry zu verwenden.
Das Taggen nach Git-Commits hat jedoch die gleichen Nachteile wie das Taggen 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 Images geändert wird.
- Es könnte ein Merge-Commit erstellt worden sein, der keine Dateien ändert, während der Docker-Tag des Images geändert wird.
- Es könnte ein Commit erstellt worden sein, der die Dateien in Git ändert, die nicht im Image importiert werden, während der Docker-Tag des Images erneut geändert wird.
Das Taggen nach dem Namen des Git-Branches spiegelt nicht die Version des Images wider.
Es gibt ein weiteres Problem, das mit der Tagging-Strategie nach Git-Branches verbunden ist.
Das Taggen nach dem Namen des Branches funktioniert, solange die Commits dieses Branches chronologisch aufeinanderfolgend gesammelt werden.
Wenn der Benutzer in der aktuellen Konfiguration eine Neuassemblierung eines alten Commits, der mit einem bestimmten Branch verbunden ist, startet, wird werf das Image mit dem entsprechenden Docker-Tag durch die neu gebaute Version des Images für den alten Commit überschreiben. Deployments, die dieses Tag verwenden, laufen ab diesem Zeitpunkt das Risiko, beim Neustart der Pods eine andere Version des Images zu ziehen, was dazu führt, dass unsere Anwendung die Verbindung zum CI-System verliert und desynchronisiert wird.
Außerdem kann bei aufeinanderfolgenden Pushs in einen Branch mit nur kurzem Abstand zwischen ihnen der alte Commit später gebaut werden als der neuere: Die alte Version des Images überschreibt die neue unter dem Git-Branch-Tag. Solche Probleme kann ein CI/CD-System lösen (zum Beispiel wird in GitLab CI für eine Serie von Commits der letzte Pipeline-Job gestartet). Allerdings unterstützen nicht alle Systeme dies, und es sollte einen zuverlässigeren Weg geben, um ein so fundamentales Problem zu verhindern.
Was ist content-based tagging?
Also, was ist content-based tagging – das Tagging von Images basierend auf ihrem Inhalt.
Für die Erstellung von Docker-Tags werden nicht die primitiven Git-Objekte (Git-Branch, Git-Tag …) verwendet, sondern eine Prüfziffer, die mit verbunden ist:
- dem Inhalt des Images. Die Image-Tag-ID spiegelt dessen Inhalt wider. Bei der Erstellung einer neuen Version ändert sich diese ID nicht, sofern die Dateien im Image unverändert bleiben.
- die Historie dieser Image in Git. Images, die mit unterschiedlichen Git-Branches und verschiedenen Erstellungs-Historien über werf verbunden sind, werden unterschiedliche Tag-IDs haben.
Als solche Tag-ID fungiert sozusagen die Signatur der Image-Stufen.
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 finale Image, das aus diesen Stufen besteht, wird mit der sogenannten Signatur dieser Stufen getaggt — Stages signature, — die für alle Stufen des Images eine Zusammenfassung darstellt.
Jedes Image aus der Konfiguration werf.yaml wird im Allgemeinen eine eigene solche Signatur und entsprechend einen Docker-Tag haben.
Die Stufensignatur löst alle genannten Probleme:
- Sie ist resistent gegen leere Git-Commits.
- Sie ist resistent gegen Git-Commits, die Dateien verändern, die für das Image nicht relevant sind.
- Führt nicht zu Problemen beim Überschreiben der aktuellen Version des Images beim Neustart von Builds für alte Git-Commits des Branches.
Jetzt ist dies 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 ist im Befehl hinzugekommen werf publish: --tag-by-stages-signature=true|false
In CI-Systemen wird die Tagging-Strategie durch den Befehl festgelegt werf ci-env. Zuvor wurde dafür ein Parameter festgelegt werf ci-env --tagging-strategy=tag-or-branch. Jetzt, unabhängig davon, ob diese Option angegeben wird oder nicht, verwendet werf standardmäßig die Tagging-Strategie werf ci-env --tagging-strategy=stages-signature setzt automatisch die erforderlichen Flags für den Befehl stages-signature. Der Befehl werf ci-env ), daher müssen keine zusätzlichen Optionen für diese Befehle angegeben werden. werf build-and-publish (oder werf publishZum Beispiel der Befehl:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature
… kann folgende Images erstellen:registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d
-
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 -
4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d
Hier — das ist die Sigantur der Stufen des Images f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 backend, und — Sigantur der Stufen des Images Bei der Nutzung spezieller Funktionen Frontend.
werf_container_image werf_container_env und werf_container_env In den Helm-Vorlagen sind keine Änderungen erforderlich: Diese Funktionen generieren automatisch die richtigen Bildnamen.
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:
- ;
- ;
- .
Gesamt
- 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, ist standardmäßigstages-signature). - Wenn zuvor die Tagging-Optionen nach Git-Commits verwendet wurden (
WERF_TAG_GIT_COMMIToder die Optionwerf publish --tag-git-commit COMMIT), muss unbedingt auf die Tagging-Strategie umgeschaltet werden. stages-signature. - Neue Projekte sollten sofort auf das neue Tagging-Schema umgestellt werden.
- Alte Projekte sollten beim Umstieg auf werf 1.1 ebenfalls auf das neue Tagging-Schema umgeschaltet werden, allerdings wird das alte tag-or-branch weiterhin unterstützt.
Content-basiertes Tagging löst alle in dem Artikel angesprochenen Probleme:
- Die Stabilität des Docker-Tag-Namens bei leeren Git-Commits.
- Die Stabilität des Docker-Tag-Namens bei Git-Commits, die irrelevante Dateien für das Image ändern.
- Es führt nicht zu Problemen beim Überschreiben der aktuellen Version des Images beim Neustart von Builds für alte Git-Commits in Git-Branches.
Nutzen Sie es! Und vergessen Sie nicht, bei uns vorbei zu schauen auf , um ein Issue zu erstellen oder ein bereits bestehendes zu finden, einen Pluspunkt zu vergeben, einen PR zu erstellen oder einfach die Entwicklung des Projekts zu beobachten.
P.S.
Lesen Sie auch in unserem Blog:
- «»
- «»
- «»;
- Notizen zu den Neuerungen in werf:
- «»;
- «»;
- «»;
- «».
Quelle: habr.com
