Unsere Implementierung von Continuous Deployment auf der Plattform des Kunden

Wir bei True Engineering haben einen Prozess zur kontinuierlichen Bereitstellung von Updates an Kundenserver eingerichtet und möchten diese Erfahrung teilen.

Zunächst haben wir für den Kunden ein Online-System entwickelt und dieses in unserem eigenen Kubernetes-Cluster bereitgestellt. Jetzt ist unsere Hochlastlösung auf die Plattform des Kunden umgezogen, für die wir einen vollautomatischen Continuous Deployment-Prozess eingerichtet haben. Dadurch haben wir die Markteinführungszeit – die Bereitstellung von Änderungen an der Produktumgebung – beschleunigt.

In diesem Artikel werden wir über alle Phasen des Continuous Deployment (CD)-Prozesses oder der Bereitstellung von Updates für die Plattform des Kunden sprechen:

  1. Wie beginnt dieser Prozess?
  2. Synchronisierung mit dem Git-Repository des Kunden,
  3. Montage von Backend und Frontend,
  4. automatische Anwendungsbereitstellung in einer Testumgebung,
  5. automatische Bereitstellung für Prod.

Wir teilen Ihnen unterwegs die Einrichtungsdetails mit.

Unsere Implementierung von Continuous Deployment auf der Plattform des Kunden

1. CD starten

Die kontinuierliche Bereitstellung beginnt damit, dass der Entwickler Änderungen im Release-Zweig unseres Git-Repositorys durchführt.

Unsere Anwendung läuft auf einer Microservice-Architektur und alle ihre Komponenten werden in einem Repository gespeichert. Dadurch werden alle Microservices erfasst und installiert, auch wenn sich einer davon geändert hat.

Wir haben die Arbeit aus mehreren Gründen über ein Repository organisiert:

  • Einfache Entwicklung – die Anwendung wird aktiv weiterentwickelt, sodass Sie mit dem gesamten Code auf einmal arbeiten können.
  • Eine einzige CI/CD-Pipeline, die garantiert, dass die Anwendung als einzelnes System alle Tests besteht und an die Produktionsumgebung des Kunden geliefert wird.
  • Wir beseitigen Verwirrung bei Versionen – wir müssen keine Karte der Microservice-Versionen speichern und deren Konfiguration für jeden Microservice in Helm-Skripten beschreiben.

2. Synchronisierung mit dem Git-Repository des Quellcodes des Kunden

Vorgenommene Änderungen werden automatisch mit dem Git-Repository des Kunden synchronisiert. Dort wird die Anwendungsassembly konfiguriert, die nach der Aktualisierung des Zweigs und der Bereitstellung für die Fortsetzung gestartet wird. Beide Prozesse stammen in ihrer Umgebung aus einem Git-Repository.

Wir können nicht direkt mit dem Repository des Kunden arbeiten, da wir unsere eigenen Umgebungen für Entwicklung und Tests benötigen. Für diese Zwecke nutzen wir unser Git-Repository – es ist mit ihrem Git-Repository synchronisiert. Sobald ein Entwickler Änderungen im entsprechenden Zweig unseres Repositorys veröffentlicht, leitet GitLab diese Änderungen sofort an den Kunden weiter.

Unsere Implementierung von Continuous Deployment auf der Plattform des Kunden

Danach müssen Sie die Montage durchführen. Es besteht aus mehreren Phasen: Backend- und Frontend-Montage, Test und Lieferung an die Produktion.

3. Zusammenbau von Backend und Frontend

Der Aufbau des Backends und des Frontends sind zwei parallele Aufgaben, die im GitLab Runner-System ausgeführt werden. Die ursprüngliche Baugruppenkonfiguration befindet sich im selben Repository.

Tutorial zum Schreiben eines YAML-Skripts zum Erstellen in GitLab.

GitLab Runner entnimmt den Code aus dem erforderlichen Repository, stellt ihn mit dem Java-Anwendungs-Build-Befehl zusammen und sendet ihn an die Docker-Registrierung. Hier bauen wir Backend und Frontend zusammen, besorgen Docker-Images, die wir auf Kundenseite in ein Repository legen. Zur Verwaltung von Docker-Images verwenden wir Gradle-Plugin.

Wir synchronisieren die Versionen unserer Bilder mit der Release-Version, die in Docker veröffentlicht wird. Für einen reibungslosen Betrieb haben wir einige Anpassungen vorgenommen:

1. Container werden zwischen der Testumgebung und der Produktionsumgebung nicht neu erstellt. Wir haben Parametrisierungen vorgenommen, damit derselbe Container mit allen Einstellungen, Umgebungsvariablen und Diensten sowohl in der Testumgebung als auch in der Produktion ohne Neuaufbau funktionieren kann.

2. Um eine Anwendung über Helm zu aktualisieren, müssen Sie deren Version angeben. Wir erstellen das Backend, das Frontend und aktualisieren die Anwendung – das sind drei verschiedene Aufgaben, daher ist es wichtig, überall die gleiche Version der Anwendung zu verwenden. Für diese Aufgabe verwenden wir Daten aus dem Git-Verlauf, da sich unsere K8S-Clusterkonfiguration und -Anwendungen im selben Git-Repository befinden.

Die Anwendungsversion erhalten wir aus den Ergebnissen der Befehlsausführung
git describe --tags --abbrev=7.

4. Automatische Bereitstellung aller Änderungen an der Testumgebung (UAT)

Der nächste Schritt in diesem Build-Skript besteht darin, den K8S-Cluster automatisch zu aktualisieren. Dies geschieht unter der Voraussetzung, dass die gesamte Anwendung erstellt wurde und alle Artefakte in der Docker-Registrierung veröffentlicht wurden. Danach beginnt das Update der Testumgebung.

Das Cluster-Update wird mit gestartet Helm-Update. Wenn dadurch etwas nicht nach Plan lief, macht Helm alle Änderungen automatisch und selbstständig rückgängig. Seine Arbeit bedarf keiner Kontrolle.

Wir liefern die K8S-Cluster-Konfiguration zusammen mit der Montage. Daher besteht der nächste Schritt darin, es zu aktualisieren: configMaps, Bereitstellungen, Dienste, Geheimnisse und alle anderen K8S-Konfigurationen, die wir geändert haben.

Anschließend führt Helm ein RollOut-Update der Anwendung selbst in der Testumgebung durch. Bevor die Anwendung in der Produktion bereitgestellt wird. Dies geschieht, damit Benutzer die Geschäftsfunktionen, die wir in die Testumgebung stellen, manuell testen können.

5. Automatische Bereitstellung aller Änderungen an Prod

Um ein Update in der Produktionsumgebung bereitzustellen, müssen Sie in GitLab nur auf eine Schaltfläche klicken – und die Container werden sofort an die Produktionsumgebung geliefert.

Dieselbe Anwendung kann in verschiedenen Umgebungen – Test- und Produktionsumgebungen – ohne Neuerstellung funktionieren. Wir verwenden dieselben Artefakte, ohne etwas an der Anwendung zu ändern, und legen die Parameter extern fest.

Die flexible Parametrisierung der Anwendungseinstellungen hängt von der Umgebung ab, in der die Anwendung ausgeführt wird. Wir haben alle Umgebungseinstellungen nach außen verschoben: Alles wird über die K8S-Konfiguration und Helm-Parameter parametrisiert. Wenn Helm eine Assembly in der Testumgebung bereitstellt, werden die Testeinstellungen darauf und die Produkteinstellungen auf die Produktionsumgebung angewendet.

Am schwierigsten war es, alle verwendeten Dienste und Variablen, die von der Umgebung abhängen, zu parametrisieren und sie in Umgebungsvariablen und Beschreibungskonfigurationen von Umgebungsparametern für Helm zu übersetzen.

Anwendungseinstellungen verwenden Umgebungsvariablen. Ihre Werte werden in Containern mithilfe der K8S-Konfigurationskarte festgelegt, die mithilfe von Go-Vorlagen erstellt wird. Das Festlegen einer Umgebungsvariablen auf den Domänennamen kann beispielsweise wie folgt erfolgen:

APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}

.Values.global.env – Diese Variable speichert den Namen der Umgebung (prod, stage, UAT).
.Values.app.properties.app_external_domain – In dieser Variablen legen wir die gewünschte Domain in der Datei .Values.yaml fest

Beim Aktualisieren einer Anwendung erstellt Helm eine configmap.yaml-Datei aus Vorlagen und füllt den APP_EXTERNAL_DOMAIN-Wert mit dem gewünschten Wert, abhängig von der Umgebung, in der das Anwendungsupdate beginnt. Diese Variable ist bereits im Container festgelegt. Da von der Anwendung aus darauf zugegriffen werden kann, hat jede Anwendungsumgebung einen anderen Wert für diese Variable.

Vor relativ kurzer Zeit erschien die K8S-Unterstützung in Spring Cloud, einschließlich der Arbeit mit configMaps: Spring Cloud Kubernetes. Während sich das Projekt aktiv weiterentwickelt und radikal verändert, können wir es nicht in der Produktion verwenden. Aber wir überwachen seinen Zustand aktiv und verwenden es in DEV-Konfigurationen. Sobald es sich stabilisiert, werden wir von der Verwendung von Umgebungsvariablen darauf umsteigen.

Insgesamt

Continuous Deployment ist also konfiguriert und funktioniert. Alle Aktualisierungen erfolgen mit einem Tastendruck. Die Übermittlung von Änderungen an der Produktumgebung erfolgt automatisch. Und was noch wichtiger ist: Updates stoppen das System nicht.

Unsere Implementierung von Continuous Deployment auf der Plattform des Kunden

Zukünftige Pläne: automatische Datenbankmigration

Wir haben darüber nachgedacht, die Datenbank zu aktualisieren und diese Änderungen rückgängig zu machen. Schließlich laufen zwei verschiedene Versionen der Anwendung gleichzeitig: Die alte läuft und die neue ist online. Und wir werden die alte Version erst dann deaktivieren, wenn wir sicher sind, dass die neue Version funktioniert. Die Datenbankmigration sollte es Ihnen ermöglichen, mit beiden Versionen der Anwendung zu arbeiten.

Daher können wir den Spaltennamen oder andere Daten nicht einfach ändern. Aber wir können eine neue Spalte erstellen, Daten aus der alten Spalte hinein kopieren und Trigger schreiben, die beim Aktualisieren der Daten diese gleichzeitig in eine andere Spalte kopieren und aktualisieren. Und nach der erfolgreichen Bereitstellung der neuen Version der Anwendung und nach Ablauf des Post-Launch-Supportzeitraums können wir die alte Spalte und den überflüssig gewordenen Trigger löschen.

Wenn die neue Version der Anwendung nicht ordnungsgemäß funktioniert, können wir auf die vorherige Version zurücksetzen, einschließlich der vorherigen Version der Datenbank. Kurz gesagt, unsere Änderungen ermöglichen es Ihnen, gleichzeitig mit mehreren Versionen der Anwendung zu arbeiten.

Wir planen, die Datenbankmigration per K8S-Job zu automatisieren und in den CD-Prozess zu integrieren. Und dieses Erlebnis werden wir auf jeden Fall auf Habré teilen.

Source: habr.com

Kommentar hinzufügen