Inhaltsbasiertes Tagging im werf Builder: Warum und wie funktioniert es?

Inhaltsbasiertes Tagging im werf Builder: Warum und wie funktioniert es?

Hof ist unser Open-Source-GitOps-CLI-Dienstprogramm zum Erstellen und Bereitstellen von Anwendungen für Kubernetes. IN Veröffentlichung v1.1 Im Bildersammler wurde eine neue Funktion eingeführt: Bilder nach Inhalt oder Tag markieren Inhaltsbasiertes Tagging. Bisher umfasste das typische Tagging-Schema in werf das Markieren von Docker-Images per Git-Tag, Git-Branch oder Git-Commit. Alle diese Schemata haben jedoch Nachteile, die durch die neue Tagging-Strategie vollständig behoben werden. Details darüber und warum es so gut ist, finden Sie unten.

Einführung einer Reihe von Microservices aus einem Git-Repository

Es kommt häufig vor, dass eine Anwendung in viele mehr oder weniger unabhängige Dienste aufgeteilt ist. Veröffentlichungen dieser Dienste können unabhängig voneinander erfolgen: Ein oder mehrere Dienste können gleichzeitig veröffentlicht werden, während der Rest ohne Änderungen weiter funktionieren muss. Aus Sicht der Codespeicherung und des Projektmanagements ist es jedoch bequemer, solche Anwendungsdienste in einem einzigen Repository zu speichern.

Es gibt Situationen, in denen Dienste wirklich unabhängig und nicht mit einer einzelnen Anwendung verknüpft sind. In diesem Fall befinden sie sich in separaten Projekten und ihre Veröffentlichung erfolgt über separate CI/CD-Prozesse in jedem der Projekte.

In der Realität teilen Entwickler jedoch häufig eine einzelne Anwendung in mehrere Microservices auf, doch die Erstellung eines separaten Repositorys und Projekts für jeden Microservice ist eindeutig übertrieben. Auf diese Situation wird weiter eingegangen: Mehrere solcher Microservices befinden sich in einem einzigen Projekt-Repository und Releases erfolgen über einen einzigen Prozess in CI/CD.

Tagging nach Git-Zweig und Git-Tag

Nehmen wir an, dass die am häufigsten verwendete Tagging-Strategie verwendet wird: Tag-oder-Zweig. Bei Git-Zweigen werden Bilder mit dem Namen des Zweigs getaggt. Für einen Zweig gibt es jeweils nur ein veröffentlichtes Bild mit dem Namen dieses Zweigs. Bei Git-Tags werden Bilder entsprechend dem Tag-Namen getaggt.

Wenn ein neues Git-Tag erstellt wird – beispielsweise wenn eine neue Version veröffentlicht wird – wird ein neues Docker-Tag für alle Projekt-Images in der Docker-Registrierung 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 werden über Helm-Vorlagen an die Kubernetes-Konfiguration übergeben. Beim Starten der Bereitstellung mit dem Befehl werf deploy Feld wird aktualisiert image in Kubernetes-Ressourcenmanifesten und Neustart der entsprechenden Ressourcen aufgrund des geänderten Imagenamens.

Problem: Wenn sich der Inhalt des Bildes seit dem letzten Rollout (Git-Tag) tatsächlich nicht geändert hat, sondern nur sein Docker-Tag, passiert dies überflüssig Ein Neustart dieser Anwendung und dementsprechend ist eine gewisse Ausfallzeit möglich. Obwohl es keinen wirklichen Grund gab, diesen Neustart durchzuführen.

Infolgedessen ist es beim aktuellen Tagging-Schema notwendig, mehrere separate Git-Repositorys abzugrenzen, und es entsteht das Problem, den Rollout dieser mehreren Repositorys zu organisieren. Im Allgemeinen erweist sich ein solches Schema als überladen und komplex. Es ist besser, viele Dienste in einem einzigen Repository zusammenzufassen und Docker-Tags zu erstellen, damit es nicht zu unnötigen Neustarts kommt.

Tagging durch Git-Commit

werf verfügt außerdem über eine Tagging-Strategie für Git-Commits.

Git-Commit ist eine Kennung für den Inhalt eines Git-Repositorys und hängt vom Bearbeitungsverlauf der Dateien im Git-Repository ab. Daher erscheint es logisch, es zum Markieren von Bildern in der Docker-Registrierung zu verwenden.

Allerdings hat das Tagging per Git-Commit die gleichen Nachteile wie das Tagging per Git-Branches oder Git-Tags:

  • Es könnte ein leerer Commit erstellt werden, der keine Dateien ändert, aber das Docker-Tag des Images wird geändert.
  • Es könnte ein Merge-Commit erstellt werden, der die Dateien nicht ändert, aber das Docker-Tag des Images wird geändert.
  • Es könnte ein Commit durchgeführt werden, der diejenigen Dateien in Git ändert, die nicht in das Image importiert werden, und das Docker-Tag des Images wird erneut geändert.

Das Markieren des Namens des Git-Zweigs spiegelt nicht die Bildversion wider

Es gibt ein weiteres Problem im Zusammenhang mit der Tagging-Strategie für Git-Zweige.

Das Markieren nach Zweignamen funktioniert, solange die Commits für diesen Zweig nacheinander in chronologischer Reihenfolge erfasst werden.

Wenn der Benutzer im aktuellen Schema mit der Neuerstellung eines alten Commits beginnt, der einem bestimmten Zweig zugeordnet ist, schreibt werf das Image mithilfe des entsprechenden Docker-Tags mit einer neu erstellten Version des Images für den alten Commit neu. Bei Bereitstellungen, die dieses Tag verwenden, besteht von nun an das Risiko, dass beim Neustart von Pods eine andere Version des Images abgerufen wird, wodurch unsere Anwendung die Verbindung zum CI-System verliert und desynchronisiert wird.

Darüber hinaus kann es bei aufeinanderfolgenden Pushs in einen Zweig mit kurzem Zeitabstand dazu kommen, dass der alte Commit später kompiliert wird als der neuere: Die alte Version des Images überschreibt die neue mithilfe des Git-Branch-Tags. Solche Probleme können durch ein CI/CD-System gelöst werden (z. B. wird in GitLab CI die Pipeline des letzteren für eine Reihe von Commits gestartet). Allerdings unterstützen nicht alle Systeme dies und es muss einen zuverlässigeren Weg geben, um solch ein grundlegendes Problem zu verhindern.

Was ist inhaltsbasiertes Tagging?

Was ist also inhaltsbasiertes Tagging – das Markieren von Bildern nach Inhalt?

Um Docker-Tags zu erstellen, werden keine Git-Primitive (Git-Zweig, Git-Tag...) verwendet, sondern eine Prüfsumme, die mit Folgendem verknüpft ist:

  • Inhalt des Bildes. Das Bild-ID-Tag spiegelt seinen Inhalt wider. Beim Erstellen einer neuen Version ändert sich diese Kennung nicht, sofern sich die Dateien im Image nicht geändert haben.
  • Geschichte der Erstellung dieses Bildes in Git. Bilder, die über werf mit verschiedenen Git-Zweigen und unterschiedlichem Build-Verlauf verknüpft sind, haben unterschiedliche ID-Tags.

Ein solches Erkennungsetikett ist das sogenannte Bildbühnensignatur.

Jedes Bild besteht aus einer Reihe von Phasen: from, before-install, git-archive, install, imports-after-install, before-setup, ... git-latest-patch usw. Jede Stufe hat eine Kennung, die ihren Inhalt widerspiegelt Bühnensignatur (Bühnensignatur).

Das endgültige Bild, bestehend aus diesen Stufen, wird mit der sogenannten Signatur der Menge dieser Stufen versehen – Bühnensignatur, - was für alle Phasen des Bildes verallgemeinernd ist.

Für jedes Bild aus der Konfiguration werf.yaml Im Allgemeinen gibt es eine eigene Signatur und dementsprechend ein Docker-Tag.

Die Bühnensignatur löst all diese Probleme:

  • Resistent gegen leere Git-Commits.
  • Resistent gegen Git-Commits, die Dateien ändern, die für das Image nicht relevant sind.
  • Führt nicht zu dem Problem einer Überarbeitung der aktuellen Version des Images, wenn Builds für alte Git-Commits eines Zweigs neu gestartet werden.

Dies ist jetzt die empfohlene Tagging-Strategie und die Standardeinstellung in werf für alle CI-Systeme.

So aktivieren und verwenden Sie in werf

Der Befehl verfügt nun über eine entsprechende Option werf publish: --tag-by-stages-signature=true|false

In einem CI-System wird die Tagging-Strategie durch den Befehl angegeben werf ci-env. Zuvor wurde der Parameter dafür definiert werf ci-env --tagging-strategy=tag-or-branch. Nun, wenn Sie angeben werf ci-env --tagging-strategy=stages-signature oder geben Sie diese Option nicht an, werf verwendet standardmäßig die Tagging-Strategie stages-signature. Mannschaft werf ci-env setzt automatisch die erforderlichen Flags für den Befehl werf build-and-publish (oder werf publish), sodass für diese Befehle keine zusätzlichen Optionen angegeben werden müssen.

Zum Beispiel der Befehl:

werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature

...kann folgende Bilder erstellen:

  • registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d
  • registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6

Hier 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d ist eine Signatur der Stadien des Bildes backendUnd f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 - Signatur von Bildstufen frontend.

Bei Verwendung von Sonderfunktionen werf_container_image и werf_container_env An den Helm-Vorlagen muss nichts geändert werden: Diese Funktionen generieren automatisch die richtigen Bildnamen.

Beispielkonfiguration in einem 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:

Insgesamt

  • Neue Option werf publish --tag-by-stages-signature=true|false.
  • Neuer Optionswert werf ci-env --tagging-strategy=stages-signature|tag-or-branch (Wenn nicht angegeben, wird die Standardeinstellung verwendet stages-signature).
  • Wenn Sie zuvor die Tagging-Optionen für Git-Commits verwendet haben (WERF_TAG_GIT_COMMIT oder Option werf publish --tag-git-commit COMMIT), dann stellen Sie sicher, dass Sie zur Tagging-Strategie wechseln Stufen-Signatur.
  • Es ist besser, neue Projekte sofort auf das neue Tagging-Schema umzustellen.
  • Bei der Umstellung auf werf 1.1 empfiehlt es sich, alte Projekte auf das neue Tagging-Schema umzustellen, jedoch auf das alte Tag-oder-Zweig wird weiterhin unterstützt.

Inhaltsbasiertes Tagging löst alle im Artikel behandelten Probleme:

  • Widerstand des Docker-Tag-Namens gegen leere Git-Commits.
  • Widerstandsfähigkeit des Docker-Tag-Namens gegenüber Git-Commits, die für das Image irrelevante Dateien ändern.
  • Führt nicht zu dem Problem, die aktuelle Version des Images zu überarbeiten, wenn Builds für alte Git-Commits für Git-Zweige neu gestartet werden.

Benutze es! Und vergessen Sie nicht, uns zu besuchen GitHubum ein Problem zu erstellen oder ein bestehendes zu finden, ein Plus hinzuzufügen, eine PR zu erstellen oder einfach die Entwicklung des Projekts zu beobachten.

PS

Lesen Sie auch auf unserem Blog:

Source: habr.com

Kommentar hinzufügen