werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Am 27. Mai im Hauptsaal der DevOpsConf 2019, die im Rahmen des Festivals stattfindet, RIT++ 2019, im Rahmen der Sektion „Continuous Delivery“, hielt ich einen Vortrag über „werf – unser Tool für CI/CD in Kubernetes“. Dabei geht es um die Herausforderungen und Probleme, mit denen jeder beim Deployment in Kubernetes konfrontiert wird, sowie um die Feinheiten, die nicht sofort offensichtlich sind. Bei der Untersuchung möglicher Lösungswege zeigen wir, wie dies im Open-Source-Tool werf.

Seit meinem Vortrag hat unsere Utility (ehemals bekannt als dapp) einen historischen Meilenstein von 1000 Sternen auf GitHub erreicht — wir hoffen, dass die wachsende Community der Nutzer vielen DevOps-Ingenieuren das Leben erleichtert.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Vorhang auf für das Video mit dem Vortrag (~47 Minuten, deutlich informativer als der Artikel) sowie die Hauptausschnitte in Textform. Los geht's!

Code-Deployment in Kubernetes

Im Vortrag geht es nicht mehr um werf, sondern um CI/CD in Kubernetes, wobei vorausgesetzt wird, dass unsere Software in Docker-Containern verpackt ist (darüber habe ich in meinem Vortrag aus dem Jahr 2016)von K8s verwendet wird, um sie in der Produktion auszuführen (dazu mehr — in 2017).

Wie sieht das Deployment in Kubernetes aus?

  • Es gibt ein Git-Repository mit Code und Anleitungen zur Erstellung. Die Anwendung wird in ein Docker-Image gepackt und im Docker Registry veröffentlicht.
  • Im selben Repository finden sich auch Anleitungen zum Deployen und Ausführen der Anwendung. Während des Deployments werden diese Anleitungen an Kubernetes gesendet, das das benötigte Image aus dem Registry abruft und es startet.
  • Zusätzlich gibt es normalerweise Tests. Einige davon können während der Veröffentlichung des Images durchgeführt werden. Zudem kann (mit denselben Anleitungen) eine Kopie der Anwendung (in einem separaten K8s-Namensraum oder einem separaten Cluster) bereitgestellt und dort getestet werden.
  • Schließlich wird ein CI-System benötigt, das Ereignisse aus Git (oder Tastendrucke) empfängt und alle festgelegten Stufen aufruft: Build, Publish, Deploy, Test.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Hier sind einige wichtige Anmerkungen:

  1. Da wir eine unveränderbare Infrastruktur haben (immutable infrastructure), muss das Anwendungs-Image, das in allen Phasen (Staging, Produktion usw.) verwendet wird, einheitlich sein. Detaillierte Informationen dazu mit Beispielen habe ich bereits hier.
  2. Da wir dem Ansatz Infrastruktur als Code folgen (IaC), sollten der Anwendungs-Code, die Anleitungen zu seiner Erstellung und Ausführung genau in einem Repository liegen. Detaillierte Informationen dazu finden Sie in derselben Präsentation..
  3. Lieferkette (Lieferung) typischerweise sehen wir das so: die Anwendung wurde erstellt, getestet und veröffentlicht (Release-Phase) und das war's – die Lieferung hat stattgefunden. Aber in Wirklichkeit erhält der Nutzer das, was Sie bereitgestellt haben, nicht erst zu dem Zeitpunkt, wenn Sie es in die Produktion gebracht haben und er darauf zugreifen konnte und die Produktion lief. Daher denke ich, dass die Lieferkette nur in der Betriebsphase endet (Betrieb), genauer gesagt sogar in dem Moment, in dem der Code aus der Produktion entfernt wurde (ersetzt durch neuen).

Kehren wir zu dem oben erwähnten Kubernetes-Liefermodell zurück: Es wurde nicht nur von uns erfunden, sondern von praktisch jedem, der sich mit diesem Problem beschäftigt hat. Tatsächlich wird dieses Muster heute als GitOps bezeichnet (mehr über den Begriff und die ihn zugrunde liegenden Ideen können Sie lesen hier)). Schauen wir uns die Phasen des Modells an.

Build-Phase

Was kann man im Jahr 2019 über den Aufbau von Docker-Images erzählen, wenn alle in der Lage sind, Dockerfiles zu schreiben und auszuführen? docker build?.. Вот нюансы, на которые хотелось бы обратить внимание:

  1. Die Größe des Images ist wichtig, daher verwenden Sie Multi-Stage, um nur das Nötigste für den Betrieb der Anwendung im Image zu belassen.
  2. Die Anzahl der Schichten sollte minimiert werden, indem sinnvolle Befehlsketten zusammengefasst werden. RUN-Team nach Bedeutung.
  3. Das führt jedoch zu Problemen bei der Fehlersuche, da man bei einem Build-Absturz das benötigte Kommando in der Kette finden muss, das das Problem verursacht hat.
  4. Die Buildgeschwindigkeit ist wichtig, weil wir Änderungen schnell ausrollen und die Ergebnisse sehen möchten. Zum Beispiel möchten wir bei jeder Anwendungskompilierung nicht die Abhängigkeiten der Programmiersprachen neu bauen müssen.
  5. Oft werden aus einem Git-Repository viele Images, was durch eine Sammlung von Dockerfiles (oder benannten Stufen in einer Datei) und einem Bash-Skript zur sequenziellen Erstellung gelöst werden kann.

Das war nur die Spitze des Eisbergs, mit der jeder konfrontiert wird. Aber es gibt auch andere Probleme, insbesondere:

  1. Häufig müssen wir in der Build-Phase etwas einbinden zum Beispiel, um das Ergebnis eines apt-Befehls in ein externes Verzeichnis zwischenzuspeichern.
  2. Wir möchten Ansible anstatt in Shell zu programmieren.
  3. Wir möchten ohne Docker bauen (warum sollten wir eine zusätzliche virtuelle Maschine einrichten, in der wir alles dafür konfigurieren müssen, wenn wir bereits ein Kubernetes-Cluster haben, in dem wir Container ausführen können?).
  4. Paralleles Bauen, die unterschiedlich interpretiert werden kann: verschiedene Befehle aus einem Dockerfile (wenn multi-stage verwendet wird), mehrere Commits eines Repositories, mehrere Dockerfiles.
  5. Verteilte Kompilierung: wir möchten etwas in Pods kompilieren, die "ephemer" sind, da sie den Cache verlieren, was bedeutet, dass er irgendwo separat gespeichert werden muss.
  6. Schließlich habe ich die Spitze der Wünsche genannt Automagie: es wäre ideal, in das Repository zu gehen, einen Befehl einzugeben und ein fertiges Image zu erhalten, das mit dem Verständnis erstellt wurde, wie und was richtig zu tun ist. Ich bin mir jedoch persönlich nicht sicher, ob alle Nuancen so vorhergesehen werden können.

Und da gibt es Projekte:

  • moby/buildkit – der Compiler von Docker Inc. (bereits in den aktuellen Docker-Versionen integriert), der versucht, all diese Probleme zu lösen;
  • kaniko – ein Compiler von Google, der das Kompilieren ohne Docker ermöglicht;
  • Buildpacks.io – ein Versuch der CNCF, Automagie zu schaffen und insbesondere eine interessante Lösung mit Rebase für Schichten anzubieten;
  • und eine ganze Reihe anderer Tools wie buildah, genuinetools/img

… und sehen Sie, wie viele Sterne sie auf GitHub haben. Das heißt, einerseits docker build gibt es Möglichkeiten, etwas zu tun, aber in der Realität ist die Frage noch nicht vollständig gelöst. Dies zeigt sich auch im parallel verlaufenden Wachstum alternativer Build-Tools, von denen jedes eine Teilmenge der Probleme löst.

Der Build in werf

So sind wir zu werf (früher bekannten wie dapp) gekommen. Dies ist ein Open Source-Tool der Firma „Flant“, an dem wir bereits seit vielen Jahren arbeiten. Alles begann vor etwa 5 Jahren mit Bash-Skripten, die das Erstellen von Dockerfiles optimierten, und in den letzten 3 Jahren wird die Entwicklung im Rahmen eines Projekts mit eigenem Git-Repository in vollem Umfang vorangetrieben. (zunächst in Ruby, dann neu geschrieben in Go und gleichzeitig umbenannt).Welche Build-Probleme werden in werf gelöst?

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Die in Blau markierten Probleme sind bereits umgesetzt, die parallele Erstellung wurde innerhalb eines Hosts realisiert, und die in Gelb markierten Fragen planen wir bis Ende des Sommers zu bearbeiten.

Phase der Veröffentlichung im Registry (publish)

Wir haben gesammelt docker push… — was könnte so schwierig daran sein, ein Image in das Registry hochzuladen? Und hier stellt sich die Frage: „Welches Tag soll dem Image zugewiesen werden?“ Diese Frage entsteht, weil wir über Gitflow (oder eine andere Git-Strategie) und Kubernetes verfügen, und die Branche strebt danach, dass das, was in Kubernetes passiert, mit dem, was in Git gemacht wird, übereinstimmt. Denn Git ist unsere einzige Quelle der Wahrheit.

Was ist daran so kompliziert? Reproduzierbarkeit garantieren: vom Commit in Git, der von Natur aus unveränderlich ist (unveränderlich), bis zum Docker-Image, das ebenfalls gleich bleiben sollte.

Es ist uns auch wichtig, die Herkunft zu bestimmen, denn wir möchten verstehen, aus welchem Commit die Anwendung in Kubernetes gebaut wurde (dann können wir Diffs machen und ähnliche Dinge).

Tagging-Strategien

Die erste ist ein einfacher git tag.Wir haben ein Registry mit einem Image, das als 1.0getaggt ist. In Kubernetes gibt es Stage und Production, wo dieses Image bereitgestellt wird. In Git machen wir Commits und setzen irgendwann ein Tag 2.0. Wir bauen es gemäß den Anweisungen aus dem Repository und platzieren es in der Registry mit dem Tag 2.0. Wir rollen es auf Stage aus und, wenn alles gut läuft, dann auf Production.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Das Problem dieses Ansatzes ist, dass wir zuerst den Tag gesetzt und dann getestet und ausgerollt haben. Warum? Erstens, es ist einfach unlogisch: Wir geben eine Version der Software heraus, die wir noch nicht einmal überprüft haben (wir können es nicht anders machen, da wir zunächst den Tag setzen müssen, um zu testen). Zweitens passt dieser Weg nicht zu Gitflow.

Die zweite Option ist git commit + tag.Im Master-Zweig gibt es einen Tag 1.0; für ihn im Registry — ein Image, das auf der Produktionsumgebung bereitgestellt wurde. Darüber hinaus gibt es im Kubernetes-Cluster die Umgebungen für Preview und Staging. Anschließend folgen wir Gitflow: im Hauptzweig für die Entwicklung (develop) erstellen wir neue Features, was zu einem Commit mit der ID #c1. Wir bauen es und veröffentlichen es im Registry, indem wir diese ID (#c1) verwenden. Mit derselben ID rollen wir auf Preview aus. Gleiches machen wir mit den Commits. #c2 und #c3.

Wenn wir feststellen, dass es genügend Features gibt, beginnen wir mit der Stabilisierung. Im Git erstellen wir einen Branch release_1.1 (basierend auf #c3 von develop). Dieses Release muss nicht gebaut werden, da dies in der vorherigen Phase bereits erledigt wurde. Daher können wir es einfach auf Staging ausrollen. Wir beheben Bugs in #c4 und rollen ebenfalls auf Staging aus. Gleichzeitig läuft die Entwicklung in develop, wo gelegentlich Änderungen aus release_1.1übernommen werden. Irgendwann erhalten wir einen gesammelten und auf Staging ausgerollten Commit, mit dem wir zufrieden sind (#c25).

. Dann führen wir einen Merge (mit Fast-Forward) des Release-Branches (release_1.1) in den Master durch. Wir setzen ein Tag mit der neuen Version auf diesen Commit (1.1). Da dieses Image bereits im Registry gebaut wurde, fügen wir einfach ein zweites Tag zum vorhandenen Image hinzu (jetzt hat es im Registry Tags) #c25 und 1.1). Danach stellen wir es in die Produktion bereit.

Es gibt einen Nachteil, dass auf Staging ein Image bereitgestellt wurde (#c25), während in der Produktion – wie es scheint – ein anderes (1.1) verwendet wird. Aber wir wissen, dass es „physisch“ dasselbe Image aus dem Registry ist.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Der eigentliche Nachteil ist, dass es keine Unterstützung für Merge-Commits gibt; man muss Fast-Forward machen.

Man kann weiter gehen und einen Trick machen… Lassen Sie uns ein einfaches Dockerfile-Beispiel betrachten:

FROM ruby:2.3 as assets
RUN mkdir -p /app
WORKDIR /app
COPY . ./
RUN gem install bundler && bundle install
RUN bundle exec rake assets:precompile
CMD bundle exec puma -C config/puma.rb

FROM nginx:alpine
COPY --from=assets /app/public /usr/share/nginx/www/public

Wir werden eine Datei basierend auf folgendem Prinzip erstellen, dass wir nehmen:

  • SHA256 von den Identifikatoren der verwendeten Images (ruby:2.3 und nginx:alpine), die Prüfziffern ihres Inhalts sind;
  • alle Befehle (RUN, CMD usw.);
  • SHA256 von den Dateien, die hinzugefügt wurden.

… und wir nehmen die Prüfziffer (wieder SHA256) von dieser Datei. Das ist die Signatur von allem, was den Inhalt des Docker-Images definiert.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Kehren wir zum Schema zurück und werden wir anstelle von Commits solche Signaturen verwenden, d.h. wir versehen die Images mit Signaturen.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Jetzt, wenn wir beispielsweise Änderungen aus dem Release in den Master-Branch mergen müssen, können wir einen echten Merge-Commit durchführen: Er hat eine andere ID, aber dieselbe Signatur. Mit dieser ID werden wir das Image auch in die Produktion bringen.

Der Nachteil ist, dass wir jetzt nicht mehr feststellen können, welcher Commit in die Produktion überführt wurde – die Hash-Prüfziffern funktionieren nur in eine Richtung. Dieses Problem wird durch eine zusätzliche Schicht mit Metadaten gelöst – dazu sage ich später mehr.

Tagging in werf

In werf sind wir noch weiter gegangen und bereiten den Aufbau eines verteilten Builds mit einem Cache vor, der nicht auf einer einzelnen Maschine gespeichert wird… Also, wir erstellen Docker-Images von zwei Typen, die wir nennen Kanal "stage" und image.

Im Git-Repository von werf befinden sich spezifische Anweisungen für den Build, die verschiedene Schritte des Builds beschreiben (beforeInstall, install, beforeSetup, setup). Zunächst erstellen wir ein Stage-Image mit einer Signatur, die als Prüfziffer der ersten Schritte definiert ist. Danach fügen wir den Quellcode hinzu; für das neue Stage-Image berechnen wir die Prüfziffer… Diese Vorgänge wiederholen sich für alle Stufen, wodurch wir eine Sammlung von Stage-Images erhalten. Anschließend erstellen wir ein finales Image, das auch Metadaten über seine Herkunft enthält. Und dieses Image kennzeichnen wir auf verschiedene Weisen (Details folgen später).

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Angenommen, es gibt einen neuen Commit, in dem nur der Anwendungscode geändert wurde. Was passiert dann? Für die Codeänderungen wird ein Patch erstellt und ein neues Stage-Image vorbereitet. Seine Signatur wird als Prüfziffer des alten Stage-Images und des neuen Patches definiert. Aus diesem Image wird dann ein neues finales Image erstellt. Ein ähnliches Verhalten tritt bei Änderungen in anderen Phasen auf.

So sind Stage-Images ein Cache, der verteilt gespeichert werden kann, während die aus ihnen erstellten Images in das Docker Registry hochgeladen werden.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Registry bereinigen

Es geht hier nicht um die Entfernung von Schichten, die nach dem Löschen von Tags übrig geblieben sind - das ist eine Standardfunktion des Docker Registry. Es handelt sich um die Situation, in der sich zahlreiche Docker-Tags ansammeln und wir erkennen, dass wir einen Teil davon nicht mehr benötigen, sie aber Platz beanspruchen (und/oder wir dafür bezahlen).

Welche Strategien zur Bereinigung gibt es?

  1. Man kann einfach nichts bereinigen. Manchmal ist es tatsächlich einfacher, etwas für zusätzlichen Speicherplatz zu zahlen, als das riesige Knäuel von Tags zu entwirren. Aber das funktioniert nur bis zu einem bestimmten Punkt.
  2. Vollständiger Reset. Wenn man alle Images löscht und nur die aktuellen im CI-System neu erstellt, kann es zu Problemen kommen. Wenn der Container in der Produktion neu gestartet wird, lädt er ein neues Image herunter - eines, das noch von niemandem getestet wurde. Das widerspricht der Idee einer unveränderlichen Infrastruktur.
  3. Blue-green. Wenn ein Registry überquillt, laden wir die Images in einen anderen hoch. Das gleiche Problem wie bei der vorherigen Methode: Wann kann der Registry, der überquillt, gereinigt werden?
  4. Nach Zeit. Alle Images, die älter als 1 Monat sind, löschen? Es wird mit Sicherheit einen Dienst geben, der einen ganzen Monat lang nicht aktualisiert wurde...
  5. Manuell festlegen, was bereits entfernt werden kann.

Es gibt zwei wirklich praktikable Optionen: entweder nicht reinigen oder eine Kombination aus Blue-Green und manuellem Vorgehen. Im letzteren Fall bedeutet das Folgendes: Wenn Sie feststellen, dass es Zeit ist, das Registry zu reinigen, erstellen Sie ein neues und fügen Sie alle neuen Images über einen Zeitraum von beispielsweise einem Monat hinzu. Nach einem Monat überprüfen Sie, welche Pods in Kubernetes weiterhin das alte Registry verwenden, und migrieren diese ebenfalls zum neuen Registry.

Zu dem, was wir gekommen sind, werf? Мы собираем:

  1. Git-Head: alle Tags, alle Branches – vorausgesetzt, alles, was in Git getaggt ist, benötigen wir auch in den Images (und falls nicht, muss es im Git entfernt werden);
  2. alle Pods, die momentan in Kubernetes bereitgestellt sind;
  3. alte ReplicaSets (die kürzlich bereitgestellt wurden), sowie planen wir, Helm-Releases zu scannen und die neuesten Images dort auszuwählen.

... und erstellen aus diesem Satz eine Whitelist – eine Liste von Images, die wir nicht löschen werden. Alles andere reinigen wir, und danach finden wir verwaiste Stage-Images und entfernen diese ebenfalls.

Deploy-Stadium

Zuverlässige Deklarativität

Der erste Punkt, auf den ich beim Deployment hinweisen möchte, ist die Bereitstellung der aktualisierten Ressourcenkonfiguration, die deklarativ definiert wurde. Das ursprüngliche YAML-Dokument, das die Kubernetes-Ressourcen beschreibt, unterscheidet sich stark von dem, was tatsächlich im Cluster funktioniert. Denn Kubernetes fügt der Konfiguration hinzu:

  1. IDs;
  2. metainformationen;
  3. viele Standardwerte;
  4. einen Abschnitt mit dem aktuellen Status;
  5. Änderungen, die im Rahmen der Arbeit des Admission Webhooks vorgenommen wurden;
  6. das Ergebnis der Arbeit verschiedener Controller (und Scheduler).

Daher können wir, wenn eine neue Ressourcenkonfiguration erscheint (neu), nicht einfach die aktuelle, „lebende“ Konfiguration (Live-) überschreiben. Dafür müssen wir neu mit der zuvor angewendeten Konfiguration (last-applied) vergleichen und das Live- erhaltene Patch anwenden.

Dieser Ansatz wird als 2-way mergebezeichnet. Er wird beispielsweise in Helm verwendet.

Es gibt auch einen 3-way merge, der sich dadurch unterscheidet, dass:

  • wir beim Vergleich sehen, was entfernt wurde; last-applied und neuwir prüfen, was hinzugefügt oder geändert wurde;
  • wir beim Vergleich sehen, was entfernt wurde; neu und Live-wir den summierten Patch anwenden auf
  • Den kumulierten Patch wenden wir auf Live-.

Wir setzen über 1000 Anwendungen mit Helm ein, deshalb leben wir eigentlich mit 2-Wege-Merge. Allerdings gibt es dabei einige Probleme, die wir mit unseren Patches gelöst haben, um Helm eine reibungslose Funktion zu ermöglichen.

Aktueller Status des Rollouts

Nachdem unser CI-System nach einem bestimmten Ereignis eine neue Konfiguration für Kubernetes generiert hat, wird diese zur Anwendung (apply) im Cluster – entweder über Helm oder kubectl apply. Danach erfolgt der bereits beschriebene N-Wege-Merge, auf den das Kubernetes-API der CI-Anwendung zustimmt, und diese gibt das Feedback an den Nutzer weiter.

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Es gibt jedoch ein großes Problem: Eine erfolgreiche Anwendung bedeutet nicht unbedingt einen erfolgreichen Rollout. Wenn Kubernetes die Änderungen, die anzuwenden sind, verstanden hat und sie anwendet, wissen wir noch nicht, was das Ergebnis sein wird. Beispielsweise kann das Update und der Neustart der Pods im Frontend erfolgreich verlaufen, während es im Backend scheitert, was uns zu unterschiedlichen Versionen der laufenden Anwendungsimages führt.

Um alles korrekt zu machen, braucht es in diesem Schema eine zusätzliche Komponente – einen speziellen Tracker, der Informationen über den Status vom Kubernetes API erhält und diese für eine weitere Analyse des tatsächlichen.state überträgt. Wir haben eine Open Source-Bibliothek in Go erstellt – kubedog (siehe die Ankündigung) hier), — die dieses Problem löst und in werf integriert ist.

Das Verhalten dieses Trackers auf der werf-Ebene wird durch Annotationen eingestellt, die auf Deployments oder StatefulSets angewendet werden. Die Hauptannotation ist fail-mode — versteht die folgenden Werte:

  • IgnoreAndContinueDeployProcess — ignoriert Probleme beim Rollout dieses Komponenten und fährt mit dem Deployment fort;
  • FailWholeDeployProcessImmediately — ein Fehler in diesem Komponenten stoppt den Deploy-Prozess;
  • HopeUntilEndOfDeployProcess — wir hoffen, dass dieses Komponente bis zum Ende des Deployments funktioniert.

Zum Beispiel eine solche Kombination von Ressourcen und Werten der Annotation fail-mode:

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Wenn wir zum ersten Mal deployen, könnte die Datenbank (MongoDB) noch nicht bereit sein — die Deployments werden fehlschlagen. Aber wir können den Moment abwarten, bis sie gestartet wird, und das Deployment wird trotzdem erfolgreich sein.

Es gibt noch zwei Annotationen für kubedog in werf:

  • failures-allowed-per-replica — die Anzahl der erlaubten Ausfälle pro Replik;
  • show-logs-until — regelt den Moment, bis zu dem werf Logs aus allen ausgerollten Pods anzeigt (im stdout). Standardmäßig ist dies PodIsReady — (um Nachrichten zu ignorieren, die wir wahrscheinlich nicht benötigen, wenn der Pod mit Traffic beginnt), jedoch sind auch die Werte ControllerIsReady und EndOfDeploy.

Was wollen wir sonst noch vom Deployment?

Neben den bereits beschriebenen zwei Punkten möchten wir:

  • sehen Logs — und zwar nur die benötigten, nicht alle auf einmal;
  • den Fortschritt überwachen, denn wenn ein Job mehrere Minuten "stumm" hängt, ist es wichtig zu verstehen, was dort passiert;einen automatischen Rollback
  • für den Fall, dass etwas schiefgeht (und daher ist es entscheidend, den aktuellen Status des Deployments zu kennen). Der Rollout sollte atomar sein: Er muss entweder vollständig durchgeführt werden oder alles wird in den vorherigen Zustand zurückversetzt. Als Unternehmen benötigen wir für die Umsetzung aller beschriebenen Aspekte in den verschiedenen Phasen der Bereitstellung (Build, Publish, Deploy) lediglich ein CI-System und ein Tool. Zur abschließenden Bemerkung:

Ergebnisse

Mit werf haben wir große Fortschritte bei der Lösung einer Vielzahl von Problemen für DevOps-Engineers gemacht und freuen uns, wenn die breitere Gemeinschaft dieses Tool zumindest einmal im Einsatz ausprobiert. Gemeinsam werden wir einfacher zu guten Ergebnissen kommen. werf.

Video des Vortrags (~47 Minuten):

werf — unser Tool für CI/CD in Kubernetes (Übersicht und Video des Vortrags)

Weitere Vorträge über Kubernetes in unserem Blog:

Videos und Folien

(Dmitrij Stoljaro; 27. April 2019 auf "Stachka")

Video abspielen

Präsentation des Vortrags:

P.S.

Erweiterung und Ergänzung von Kubernetes

Quelle: habr.com

Kaufen 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