Content-basiertes Tagging im Werfer: Warum und wie funktioniert das?

Content-basiertes Tagging im Werfer: Warum und wie funktioniert das?

werf — unser GitOps CLI-Tool mit offenem Quellcode zum Erstellen und Bereitstellen von Anwendungen in Kubernetes. In der Version v1.1 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, installieren, 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|deploy

Weitere 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Ă€ĂŸig stages-signature).
  • Wenn zuvor die Tagging-Optionen nach Git-Commits verwendet wurden (WERF_TAG_GIT_COMMIT oder die Option werf 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 GitHub, 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:

Quelle: habr.com

Erwerben Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server đŸ”„ Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster