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:
- 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.
- Wenn Änderungen an Projektdateien vorgenommen werden, muss der Builder schnell eine neue Ebene erstellen, indem er einen Patch auf die geänderten Dateien anwendet.
- 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 YAMLDer 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?
- 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). - 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 ) . - 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:
- 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. .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.- 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) .“