Docker-Images können auch mit der üblichen Docker-Datei in werf erstellt werden

Besser spät als nie. Oder wie wir fast einen schwerwiegenden Fehler gemacht haben, weil wir nicht die Unterstützung gewöhnlicher Dockerfiles zum Erstellen von Anwendungsbildern hatten.



Wir werden über werf sprechen, ein GitOps-Dienstprogramm, das in jedes CI / CD-System integriert ist und die Kontrolle über den gesamten Anwendungslebenszyklus bietet. So können Sie:

  • Sammeln und veröffentlichen Sie Bilder
  • Stellen Sie Anwendungen in Kubernetes bereit
  • Löschen Sie nicht verwendete Bilder mithilfe spezieller Richtlinien.

Die Philosophie des Projekts besteht darin, Tools auf niedriger Ebene zu einem einzigen einheitlichen System zusammenzufassen, mit dem DevOps-Ingenieure die Kontrolle über Anwendungen haben. Nach Möglichkeit sollten vorhandene Dienstprogramme (wie Helm und Docker) einbezogen werden. Wenn es keine Lösung für ein Problem gibt, können wir alles Notwendige dafür erstellen und pflegen.

Hintergrund: Ihr Bildersammler


Das ist mit dem Bildersammler in werf passiert: Wir hatten nicht das übliche Dockerfile. Wenn Sie schnell in die Geschichte des Projekts eintauchen, manifestiert sich dieses Problem in den ersten Versionen von werf (damals noch als dapp bekannt ).

Als wir ein Tool zum Erstellen von Anwendungen in Docker-Images erstellten, stellten wir schnell fest, dass die Docker-Datei für einige sehr spezifische Aufgaben nicht geeignet war:

  1. Die Notwendigkeit, typische kleine Webanwendungen nach dem folgenden Standardschema zu erstellen:
    • Installieren Sie systemweite Anwendungsabhängigkeiten
    • Paket von Anwendungsabhängigkeitsbibliotheken installieren,
    • Vermögenswerte sammeln
    • und vor allem aktualisieren Sie den Code im Bild schnell und effizient.
  2. Wenn Änderungen an Projektdateien vorgenommen werden, muss der Builder schnell eine neue Ebene erstellen, indem er einen Patch auf die geänderten Dateien anwendet.
  3. Wenn sich bestimmte Dateien geändert haben, muss die entsprechende abhängige Phase neu erstellt werden.

Heute gibt es in unserem Sammler viele andere Möglichkeiten, aber die anfänglichen Wünsche und Triebe waren diese.

Im Allgemeinen haben wir uns ohne nachzudenken mit der verwendeten Programmiersprache (siehe unten) bewaffnet und sind losgefahren - implementieren Sie unser eigenes DSL ! Entsprechend den Aufgaben sollte der Assemblierungsprozess schrittweise beschrieben und die Abhängigkeiten dieser Phasen von Dateien ermittelt werden. Und ergänzt durch seinen eigenen Sammler , der DSL zum ultimativen Ziel gemacht hat - ein zusammengesetztes Bild. Zuerst war DSL in Ruby, und als wir zu Golang wechselten, wurde die Konfiguration unseres Sammlers in der YAML-Datei beschrieben.


Alte Konfiguration für dapp auf Ruby


Aktuelle Konfiguration für werf auf YAML

Der Mechanismus des Kollektors änderte sich ebenfalls im Laufe der Zeit. Zuerst haben wir einfach eine temporäre temporäre Docker-Datei aus unserer Konfiguration im laufenden Betrieb generiert und dann begonnen, Montageanweisungen in temporären Containern auszuführen und ein Commit durchzuführen.

NB : Im Moment hat sich unser Kollektor, der mit seiner Konfiguration (in YAML) arbeitet und als Stapel-Kollektor bezeichnet wird, bereits zu einem ziemlich leistungsfähigen Werkzeug entwickelt. Die detaillierte Beschreibung verdient separate Artikel, und die wichtigsten Details finden Sie in der Dokumentation .

Problembewusstsein


Wir haben jedoch nicht sofort festgestellt, dass wir einen Fehler gemacht haben: Wir haben nicht die Möglichkeit hinzugefügt, Bilder über die Standard-Docker-Datei zu sammeln und sie für die integrierte Anwendungsverwaltung in dieselbe Infrastruktur zu integrieren (d. H. Bilder zu sammeln, bereitzustellen und zu bereinigen). Wie können Sie ein Bereitstellungstool in Kubernetes erstellen und die Dockerfile-Unterstützung nicht implementieren, d. H. eine Standardmethode zur Beschreibung von Bildern für die meisten Projekte? ..

Anstatt eine solche Frage zu beantworten, bieten wir eine Lösung an. Was ist, wenn Sie bereits eine Docker-Datei (oder eine Reihe von Docker-Dateien) haben und werf verwenden möchten?

NB : Übrigens, warum sollten Sie überhaupt werf verwenden wollen? Die Hauptmerkmale sind wie folgt:

  • vollständiger Anwendungsverwaltungszyklus einschließlich Bildreinigung;
  • die Fähigkeit, die Zusammenstellung mehrerer Images von einer einzigen Konfiguration aus zu steuern;
  • Verbesserter Helm-kompatibler Kartenbereitstellungsprozess.

Eine vollständigere Liste finden Sie auf der Projektseite .

Wenn wir also früher vorschlagen würden, Dockerfile in unsere Konfiguration umzuschreiben, können wir jetzt gerne sagen: "Lassen Sie werf Ihre Dockerfiles erstellen!"

Wie benutzt man?


Die vollständige Implementierung dieser Funktion wurde in der Version werf v1.0.3-beta.1 veröffentlicht . Das allgemeine Prinzip ist einfach: Der Benutzer gibt den Pfad zur vorhandenen Docker-Datei in der werf-Konfiguration an und führt dann den Befehl werf build ... aus, und fertig - werf sammelt das Image. Betrachten Sie ein abstraktes Beispiel.

Dockerfile folgende Dockerfile im Stammverzeichnis des Projekts:

 FROM ubuntu:18.04 RUN echo Building ... 

Und deklarieren Sie werf.yaml , das diese Dockerfile werf.yaml verwendet:

 configVersion: 1 project: dockerfile-example --- image: ~ dockerfile: ./Dockerfile 

Das ist alles! Es bleibt noch werf build laufen zu werf build :



Darüber hinaus können Sie das folgende werf.yaml um mehrere Bilder aus verschiedenen Docker-Dateien gleichzeitig zu erstellen:

 configVersion: 1 project: dockerfile-example --- image: backend dockerfile: ./dockerfiles/Dockerfile-backend --- image: frontend dockerfile: ./dockerfiles/Dockerfile-frontend 

Schließlich unterstützt es auch die Übertragung zusätzlicher Build-Parameter - wie --build-arg und --add-host - über die werf-Konfiguration. Eine vollständige Beschreibung der Dockerfile-Image-Konfiguration finden Sie auf der Dokumentationsseite .

Wie funktioniert es


Während des Erstellungsprozesses funktioniert der Standard-Cache der lokalen Ebene in Docker. Wichtig ist jedoch, dass werf auch die Dockerfile-Konfiguration in seine Infrastruktur integriert . Was bedeutet das?

  1. Jedes aus der Docker-Datei gesammelte Bild besteht aus einer Stufe namens dockerfile (mehr darüber, welche Stufen in werf sind, können Sie hier lesen).
  2. Für die Phase berechnet dockerfile werf die Signatur, die vom Inhalt der Dockerfile-Konfiguration abhängt. Wenn die Dockerfile-Konfiguration geändert wird, dockerfile Signatur der dockerfile Stufe und werf initiiert die Neuerstellung dieser Stufe mit der neuen Dockerfile-Konfiguration. Wenn sich die Signatur nicht ändert, nimmt werf das Bild aus dem Cache (weitere Details zur Verwendung von Signaturen in werf wurden in diesem Bericht beschrieben ) .
  3. Darüber hinaus können die gesammelten Bilder werf publish Befehl werf publish (oder werf build-and-publish ) veröffentlicht und für die Bereitstellung in Kubernetes verwendet werden. Veröffentlichte Bilder in der Docker-Registrierung werden mit Standard-Werf-Reinigern bereinigt, d. H. Alte Bilder (älter als N Tage), Bilder, die nicht vorhandenen Git-Zweigen zugeordnet sind, und andere Richtlinien werden automatisch bereinigt.

Weitere Informationen zu den hier beschriebenen Punkten finden Sie in der Dokumentation:


Hinweise und Vorsichtsmaßnahmen


1. Externe URL in ADD wird nicht unterstützt


Die Verwendung einer externen URL in der ADD Direktive wird derzeit nicht unterstützt. Werf initiiert keine Neuerstellung, wenn eine Ressource auf die angegebene URL geändert wird. Bald ist geplant, diese Funktion hinzuzufügen.

2. Sie können einem Bild kein .git hinzufügen


Im Allgemeinen ist das Hinzufügen eines .git Verzeichnisses zu einem Bild eine bösartige schlechte Praxis, und hier ist der Grund dafür:

  1. Wenn .git im endgültigen Image verbleibt, verstößt dies gegen die Prinzipien der 12-Faktor-App : Da das endgültige Image einem Commit zugeordnet werden muss, sollte es nicht möglich sein, ein beliebiges Commit zu überprüfen.
  2. .git vergrößert das Bild (das Repository kann groß sein, da große Dateien einmal hinzugefügt und dann gelöscht wurden). Die Größe des Arbeitsbaums, der nur einem bestimmten Commit zugeordnet ist, hängt nicht vom Verlauf der Operationen in Git ab. Gleichzeitig funktioniert das Hinzufügen und Entfernen von .git zum endgültigen Image nicht: Das Image erhält weiterhin eine zusätzliche Ebene - so funktioniert Docker.
  3. Docker kann unnötige Neuerstellungen initiieren, selbst wenn dasselbe Commit erstellt wird, jedoch aus unterschiedlichen Arbeitsbäumen. Beispielsweise erstellt GitLab separate geklonte Verzeichnisse in /home/gitlab-runner/builds/HASH/[0-N]/yourproject wenn die parallele Assembly aktiviert ist. Die zusätzliche Neuerstellung ist darauf zurückzuführen, dass sich das .git Verzeichnis in verschiedenen geklonten Versionen desselben Repositorys unterscheidet, selbst wenn dasselbe Commit erfasst wird.

Der letzte Punkt hat eine Konsequenz bei der Verwendung von werf. Werf setzt voraus, dass der gesammelte Cache vorhanden ist, wenn bestimmte Befehle ausgeführt werden (z. B. werf deploy ). Während der Ausführung solcher Befehle berechnet werf die Stufensignaturen für die in werf.yaml angegebenen Bilder und sie müssen sich im Assemblycache befinden. Andernfalls kann das Team nicht weiterarbeiten. Wenn die Signatur der Stufen vom Inhalt von .git abhängt, erhalten wir einen Cache, der gegenüber Änderungen in irrelevanten Dateien instabil ist, und werf kann einen solchen Fehler nicht verzeihen (weitere Informationen finden Sie in der Dokumentation ).

Im Allgemeinen erhöht das Hinzufügen nur bestimmter erforderlicher Dateien über die ADD Anweisung in jedem Fall die Effizienz und Zuverlässigkeit der geschriebenen Dockerfile und verbessert auch die Stabilität des von dieser Dockerfile kompilierten Dockerfile gegen irrelevante Änderungen in Git.

Zusammenfassung


Unsere anfängliche Art, unseren eigenen Compiler für bestimmte Anforderungen zu schreiben, war schwierig, ehrlich und unkompliziert: Anstatt Krücken über der Standard-Docker-Datei zu verwenden, haben wir unsere eigene Lösung mit benutzerdefinierter Syntax geschrieben. Und das hat seine Vorteile gebracht: Der Stapelbauer kommt seiner Aufgabe perfekt nach.

Beim Schreiben unseres eigenen Sammlers haben wir jedoch die Unterstützung vorhandener Docker-Dateien übersehen. Jetzt wurde dieser Fehler behoben, und in Zukunft planen wir, die Dockerfile-Unterstützung zusammen mit unserem benutzerdefinierten Stapelkollektor für die verteilte Montage und für die Montage mit Kubernetes (d. H. Montage auf Läufern innerhalb von Kubernetes, wie in Kaniko) zu entwickeln.

Also, wenn Sie plötzlich ein paar Dockerfiles herumliegen hatten ... versuchen Sie es mit werf !

PS Liste der zugehörigen Dokumentation



Lesen Sie auch in unserem Blog: „ werf ist unser CI / CD-Tool in Kubernetes (Rezension und Videobericht) .“

Source: https://habr.com/ru/post/de463613/


All Articles