Aufbau einer Continuous-Delivery-Pipeline mit GitHub und Helm zur Bereitstellung von Magnolia in Kubernetes
Feb. 9, 2021
--
Continuous delivery with Kubernetes 656x400

Aufbau einer Continuous-Delivery-Pipeline mit GitHub und Helm zur Bereitstellung von Magnolia in Kubernetes

Die Containerisierung einer Anwendung und ihre Bereitstellung in Kubernetes über eine Continuous-Delivery-Pipeline (CD) vereinfacht die Wartung und ermöglicht schnellere und einfachere Updates.

Dieser Artikel führt Sie durch die Schritte zur Containerisierung von Magnolia mit Docker (Dockerizing) und zur Einrichtung einer kompletten CD-Pipeline für einen Kubernetes (K8s)-Cluster.

Die Pipeline erstellt ein Magnolia-Bündel, erstellt ein Docker-Image, überträgt es an die GitHub Container Registry und stellt Helm Chart mit dem Docker-Image in Kubernetes bereit. Als Ergebnis werden wir eine containerisierte Magnolia-Version in einem lokalen Kubernetes-Cluster ausführen.

Key-Components

Nachstehend finden Sie ein Flussdiagramm der CD-Pipeline mit den wichtigsten Komponenten:

Chart

Kubernetes

Kubernetes (K8s) ist ein Open-Source-Container-Orchestrierungssystem, mit dem Sie die Bereitstellung, Skalierung und Verwaltung von containerisierten Anwendungen automatisieren können. Es bietet ein gemeinsames Framework, mit dem Sie verteilte Systeme ausführen können, sodass Entwicklungsteams eine konsistente, unnachgiebige Infrastruktur von der Entwicklung bis zur Produktion erhalten.

Steuerkarte

Helm ist ein Paketmanager für Kubernetes. Er verwendet ein Paketformat namens Charts. Helm-Diagramme definieren, installieren und aktualisieren Kubernetes-Anwendungen.

GitHub-Aktionen

Durch die Automatisierung Ihrer Softwareentwicklungs-Workflows ermöglicht GitHub Actions die einfache Einrichtung von Continuous Integration (CI) und Continuous Deployment (CD) direkt in Ihrem Repository - ohne die Hilfe anderer CI/CD-Systeme.

Ein Workflow ist ein automatisierter Prozess, den Sie in Ihrem GitHub-Repository einrichten. Sie können jedes GitHub-Projekt mithilfe eines Workflows erstellen, testen, verpacken, freigeben oder bereitstellen. Er besteht aus verschiedenen Aufgaben, die als Aktionen bezeichnet werden und bei bestimmten Ereignissen automatisch ausgeführt werden können, z. B. bei der Zusammenführung einer Pull-Anfrage oder einem Git-Push.

GitHub Container-Registrierung

MitGitHub Container Registry können Sie Docker-Container-Images in Ihrer Organisation oder einem persönlichen Benutzerkonto auf GitHub hosten und verwalten. Sie können auch konfigurieren, wer Pakete verwalten und darauf zugreifen darf, indem Sie fein abgestufte Berechtigungen vergeben.

Voraussetzungen

Um die Pipeline zu erstellen, installieren wir mehrere Befehlszeilenschnittstellen-Tools (CLI), richten einen lokalen Kubernetes-Cluster und ein GitHub-Repository ein, das unsere Bereitstellungsdateien und die Pipeline enthält.

minikube

Mitminikube können Sie einen Kubernetes-Cluster mit einem einzigen Knoten auf einer virtuellen Maschine (VM) auf Ihrem Computer betreiben. Sie können es verwenden, um Kubernetes zu testen oder für Ihre tägliche Entwicklungsarbeit.

Wenn Sie bereits einen Kubernetes-Cluster haben, den Sie verwenden können, z. B. AWS EKS oder Google GKE, können Sie diesen Schritt überspringen. Andernfalls installieren Sie bitte minikube, indem Sie der Dokumentation folgen.

Wenn minikube auf Ihrem Rechner installiert ist, können Sie den Cluster mit einer bestimmten Kubernetes-Version starten:

Java
  
$ minikube start --kubernetes-version=1.16.0 😄 minikube v1.6.2 auf Darwin 10.14.5 ✨ Automatisch den 'virtualbox'-Treiber ausgewählt (Alternativen: []) 🔥 Virtualbox-VM erstellen (CPUs=2, Memory=2000MB, Disk=20000MB) ... 🐳 Vorbereiten von Kubernetes v1.16.0 auf Docker '19.03.5' ... 💾 Herunterladen von kubeadm v1.16.0 💾 Herunterladen von kubelet v1.16.0 🚜 Ziehen von Images ... 🚀 Starten von Kubernetes ... 
⌛ Warten darauf, dass der Cluster online geht ... 🏄 Fertig! kubectl ist jetzt für die Verwendung von "minikube" konfiguriert

kubectl

kubectl ist ein Kubernetes-Befehlszeilen-Tool zur Ausführung von Befehlen für einen Kubernetes-Cluster. Es kann verwendet werden, um Anwendungen bereitzustellen, Cluster-Ressourcen zu prüfen und zu verwalten und Protokolle anzuzeigen.

Installieren Sie kubectl und verifizieren Sie Ihren Minikube-Cluster:

Java
  $ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE coredns-5644d7b6d9-nq48z 1/1 Läuft 1 3h27m coredns-5644d7b6d9-sqgrb 1/1 Läuft 1 3h27m etcd-minikube 1/1 Läuft 1 3h26m kube-addon-manager-minikube 1/1 Läuft 1 3h26m kube-apiserver-minikube 1/1 läuft 1 3h26m kube-controller-manager-minikube 1/1 läuft 2 3h26m kube-proxy-zw787 1/1 läuft 1 3h27m kube-scheduler-minikube 1/1 läuft 2 3h26m storage-provisioner 1/1 läuft 1 3h27m  

Da unser Kubernetes-Cluster in einer VM läuft, verwenden wir auch kubectl proxy, um einen Proxy von Ihrer localhost-Adresse zum Kubernetes-API-Server in Ihrer VM zu senden.

Java
  $ kubectl proxy --port=8080 --accept-hosts='.*\.ngrok.io $' & [1] 30147 $ Start der Bereitstellung auf 127.0.0.1:8080  

ngrok

Da wir später über GitHub-Aktionen auf den Kubernetes-Cluster zugreifen werden, benötigen wir einen öffentlichen Proxy, der Anfragen an Ihren Kubernetes-API-Server weiterleitet. Sie können ngrok, ein kostenloses Tunnelsystem, verwenden, um Ihre lokalen Dienste nach außen hin sichtbar zu machen.

Es dauert nur ein paar Minuten, um sich für ein Konto zu registrieren und einen Tunnel zu localhost einzurichten. Um Ihre lokalen Dienste mit ngrok zu verbinden, folgen Sie bitte der Dokumentation.

Java
  $ ngrok http http://127.0.0.1:8080 ngrok by @inconshreveable (Ctrl+C zum Beenden) Session Status online Account Do Hoang Khiem (Plan: Free) Version 2.3.35 Region Vereinigte Staaten (us)  
Java
  Verbindungen ttl opn rt1 rt5 p50 p90 295 0 0,00 0,00 8,84 46,03  

Helm

Helm ist ein wichtiges Tool für die Arbeit mit Kubernetes. Es ist nicht erforderlich, um diese Bereitstellung abzuschließen, aber es ist dennoch gut, es auf Ihrem lokalen Rechner zu haben, um Ihre Bereitstellung am Ende zu überprüfen und zu validieren.

Sie können den Paketmanager Helm 3 installieren, indem Sie der Dokumentation folgen.

Prüfen Sie die Helm-Version nach der Installation.

Java
  $ helm version version.BuildInfo{Version: "v3.2.4", GitCommit: "0ad800ef43d3b826f31a5ad8dfbb4fe05d143688", GitTreeState: "dirty", GoVersion: "go1.14.3"}  

GitHub-Repository

Sie müssen ein GitHub-Repository, eine GitHub-Container-Registrierung und ein persönliches Zugriffstoken einrichten.

GitHub_fork

2. Aktivieren Sie die GitHub Container Registry

Um die GitHub Container Registry zu nutzen, müssen Sie die verbesserte Container-Unterstützung aktivieren. Navigieren Sie zu "Funktionsvorschau" im Menü oben rechts unter Ihrem Kontoprofil und aktivieren Sie dann die verbesserte Container-Unterstützung.

GitHub_feature_preview

3. Generieren Sie ein persönliches GitHub-Zugangs-Token

Wir müssen ein GitHub Personal Access Token verwenden, um Docker-Images in die GitHub Container Registry zu pushen. Sie können ein neues Token über Einstellungen → Entwicklereinstellungen → Persönliche Zugriffstokens generieren. Klicken Sie auf "Generate new token":

GitHub_access_token

Wählen Sie auf dem nächsten Bildschirm mindestens die Bereiche write:packages und delete:packages aus:

GitHub_access_token_scopes

Kopieren Sie das Token, sobald es erstellt ist, da es nicht mehr sichtbar sein wird.

4. Konfigurieren Sie Secrets in Ihrem magnolia-Docker-Repository

Gehen Sie zurück zu Ihrem Repository und konfigurieren Sie Ihre Secrets unter Einstellungen → Secrets:

GitHub_secrets

Erstellen Sie für jedes der folgenden Schlüssel-Wert-Paare ein Geheimnis:

  • PACKAGE_USER: Ihr GitHub-Benutzername

  • PACKAGE_TOKEN: Ihr persönliches Zugangs-Token

  • KUBECONFIG : Ihre Kubernetes-Konfiguration für den Zugriff auf Ihren Cluster

Wenn Sie von Ihrem lokalen Rechner aus auf den Cluster zugreifen, können Sie die Konfigurationsdatei unter ~/.kube/config finden, oder Sie können kubectl config view verwenden, um die aktuelle Konfiguration anzuzeigen.

Wenn Sie ein Attribut wie certificate-authority, client-certificate, oder client-key in der Konfigurationsdatei sehen, das einen Pfad zu einer .crt oder .key-Datei angibt, müssen Sie es durch certificate-authority-data, client-certificate-data, client-key-data ersetzen und den Dateipfad durch den base64-kodierten Wert des .crt- oder .key-Inhalts ersetzen.

Zum Beispiel, um den base64-kodierten Wert von certificate-authority-data zu erhalten:

cat ~/.minikube/ca.crt | base64

Nachfolgend finden Sie ein Beispiel für KUBECONFIG (cert und key base64 sind gekürzt). Der ngrok-Endpunkt wird für den Parameter cluster verwendet.

Für diese Demonstration können wir insecure-skip-tls-verify:true verwenden, um nicht vertrauenswürdige Zertifikate zu ignorieren:

Java
  apiVersion: v1 clusters: - cluster: server: https://66ab386be8b6.ngrok.io insecure-skip-tls-verify: true name: minikube contexts: - context: cluster: minikube user: minikube name: minikube current-context: minikube kind: Konfig-Einstellungen: {} users: - name: minikube user: client-certificate-data: LS0tLS1CRUdJTi... client-key-data: LS0tLS1CRUdJ...  
GitHub_secrets2

Magnolia in a Can: Containerization with Magnolia

Learn how to deploy Magnolia as a Docker container based on best practices from our professional services team

Magnolia-Docker Image

In diesem Beispiel verwenden wir das magnolia-empty-webapp-Bundle aus den öffentlichen Magnolia-Releases auf Nexus, zusammen mit dem magnolia-rest-services-Modul für Liveness- und Readiness-Endpunkte. Erstellen Sie das folgende POM im webapp-Verzeichnis:

Java
  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
   <groupId>info.magnolia.sre</groupId>
   <artifactId>magnolia-docker-bundle-parent</artifactId>
   <version>1.0-SNAPSHOT</version>
   <relativePath>../pom.xml</relativePath>
 </parent>

 <artifactId>magnolia-docker-bundle-webapp</artifactId>
 <name>Magnolia Docker Image Bundle Webapp</name>
 <packaging>war</packaging>

 <dependencies>
   <dependency>
     <groupId>info.magnolia</groupId>
     <artifactId>magnolia-leere-webapp</artifactId>
     <type>war</type>
   </dependency>
   <dependency>
     <groupId>info.magnolia</groupId>
     <artifactId>magnolia-leere-webapp</artifactId>
     <type>pom</type>
   </dependency>

   <!-- Contains the liveness/readiness end point: .rest/status -->
   <dependency>
     <groupId>info.magnolia.rest</groupId>
     <artifactId>magnolia-rest-services</artifactId>
   </dependency>
 </dependencies>

 <build>
   <finalName>ROOT</finalName>

   <plugins>
     <plugin>
       <groupId>io.fabric8</groupId>
       <artifactId>docker-maven-plugin</artifactId>
       <configuration>
         <skip>true</skip>
       </configuration>
     </plugin>
   </plugins>
 </build>
</project>

Sie können die Erstellung eines Magnolia-Bundles lokal testen, indem Sie diesen Befehl vom Stammverzeichnis aus ausführen:

$ mvn package -B -U

Das Bundle wird dann verwendet, um ein Docker-Image zu erstellen, das auf dem Tomcat 9 mit OpenJDK 11 slim-Image basiert. Dies ist das Dockerfile das sich unter src/main/docker:

Java
  ---------------------------------------------------------- # Magnolia Docker Image # ---------------------------------------------------------- # FROM tomcat:9.0.38-jdk11-openjdk-slim MAINTAINER sre@magnolia-cms.com ENV JAVA_OPTS="-Dmagnolia.home=/opt/magnolia -Dmagnolia.resources.dir=/opt/magnolia -Dmagnolia.update.auto=true -Dmagnolia.author.key.location=/opt/magnolia/activation-key/magnolia-activation-keypair.properties" # Tomcat setenv.sh kopieren COPY src/main/docker/tomcat-setenv.sh $CATALINA_HOME/bin/setenv.sh RUN chmod +x $CATALINA_HOME/bin/setenv.sh # Dieses Verzeichnis wird für die Magnolia-Eigenschaft "magnolia.home" verwendet RUN mkdir /opt/magnolia RUN chmod 755 /opt/magnolia RUN rm -rf $CATALINA_HOME/webapps/ROOT COPY webapp/target/ROOT.war $CATALINA_HOME/webapps/  

Sie können die Erstellung eines Docker-Images lokal im Stammverzeichnis des Projekts testen:

$ mvn -B docker:build

Magnolia Helm Chart

Magnolia Helm Chart befindet sich im Verzeichnis helm-chart. Nachfolgend ist die Struktur der Karte dargestellt:

Java
  . ├── Chart.yaml ├── templates │ ├── configmap.yaml │ ├── _helpers.tpl │ ├── ingress.yaml │ ├── service.yaml │ ├── statefulset.yaml │ └── tests │ └── test-connection.yaml └── values.yaml 2 Verzeichnisse, 8 Dateien  

Diagramm.yaml

Diese Datei definiert Diagrammparameter wie Name, Beschreibung, Typ, Version und appVersion.

Werte.yaml

Die Datei liefert die Werte, die in den Vorlagen zu ersetzen sind. Wir können das Bild, den Tag, die pullPolicy, die Service-Ports, die Ingress-Hostnamen, die Ressourcenlimits und benutzerdefinierte App-Konfigurationen wie JAVA_OPTS definieren.

templates/statefulset.yaml

Diese Datei definiert die Arbeitslast für die Anwendung. Für diesen Einsatz verwenden wir 2 StatefulSets, die Magnolia author und public repräsentieren. Mit StatefulSet können wir persistente Namen - Sticky Identities - vergeben und Pods in einer bestimmten Reihenfolge verwalten. In der Pod-Spezifikation von StatefulSet definieren wir Container, Volumes und Probes.

vorlage/dienst.yaml

Diese Datei definiert die Dienste für die Magnolia-Autoren- und Public-Instanzen, die den Lastausgleich und den Zugriff auf Anwendungen in den darunter liegenden Pods ermöglichen.

Ausführen von GitHub-Aktionen Workflow

Workflow-Konfiguration

Der GitHub Actions-Workflow wird in .github/workflows/pipeline.yml. definiert. Wenn er ausgelöst wird, sucht GitHub Actions automatisch nach .yml- oder .yaml-Dateien im Verzeichnis .github/workflows

Java
  name: Bauen und Veröffentlichen on: push: branches: [ master ] jobs: build: name: 'Maven: Build and upload artifact' runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: 11 - name: Build Magnolia bundle run: mvn package -B -U - name: Build Magnolia Docker Image run: mvn -B -Dgithub-registry=${{github.repository_owner}} docker:build - name: Push Magnolia Docker Image ausführen: mvn -B -Ddocker.username=${{secrets.PACKAGES_USER}} -Ddocker.passwort=${{geheimnisse.PACKAGES_TOKEN}} -Dgithub-registry=${{github.repository_owner}} docker:push helm-lint: name: Helm lint and release läuft auf: ubuntu-latest benötigt: build steps: - verwendet: actions/checkout@v2 - name: Helm Lint verwendet: WyriHaximus/github-action-helm3@v2 mit: exec: helm lint ./helm-chart - name: Helm install uses: WyriHaximus/github-action-helm3@v2 mit: exec: helm upgrade --install github-magnolia-docker ./helm-chart kubeconfig: '${{ secrets.KUBECONFIG }}'  

Am Anfang der Datei wird das Ereignis definiert, das den Workflow auslöst, z. B. ein Push-Ereignis für den Master-Zweig.

Die Datei konfiguriert dann 2 Aufträge, die auf einem von GitHub gehosteten Runner, einer vorkonfigurierten virtuellen Umgebung, unter Verwendung der neuesten Ubuntu-Version "ubuntu-latest" ausgeführt werden.

1. Maven: Artefakte erstellen und hochladen

Dieser Job checkt das Git-Repository auf den Runner aus, installiert JDK 11 und erstellt das Magnolia-Bundle und das Docker-Image. Schließlich wird das Image in die GitHub Container Registry gepusht.

2. Helm fusseln und loslassen

Dieser Job führt helm lint aus, um zu überprüfen, ob die Karte wohlgeformt ist, und installiert dann die Karte über Helm.

Workflow auslösen

Der Workflow wird ausgelöst, indem eine Änderung in den Master-Zweig des Repositorys übertragen wird:

Workflow1
Workflow2

Einsatz überprüfen

Nachdem die Bereitstellung der Pipeline erfolgreich abgeschlossen ist, können Sie Helm verwenden, um die Freigabe in Kubernetes zu überprüfen.

Java
  $ helm list NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION github-magnolia-docker default 1 2020-11-18 07:42:32.240781604 +0000 UTC deployed magnolia-0.1.0 6.2.3      

Die Ausgabe zeigt, dass wir eine github-magnolia-docker-Version im Cluster bereitgestellt haben, die das magnolia-0.1.0-Diagramm verwendet. Die App-Version ist 6.2.3.

Um mehr Details über die zugrunde liegenden Objekte zu erfahren, können wir den Befehl kubectl verwenden:

Java
  $ kubectl get statefulset NAME READY AGE github-magnolia-docker-author 1/1 21h github-magnolia-docker-public 1/1 21h $ kubectl get pods NAME READY STATUS RESTARTS AGE github-magnolia-docker-author-0 1/1 Läuft 0 21h github-magnolia-docker-public-0 1/1 Läuft 0 21h $ kubectl get svc NAME TYP CLUSTER-IP EXTERNAL-IP PORT(S) AGE github-magnolia-docker-author ClusterIP 10.110.231.225 <none> 80/TCP 21h github-magnolia-docker-public ClusterIP 10.98.85.7 <none> 80/TCP 21h  

Sie können die Portweiterleitung nutzen, um über localhost auf Ihre Magnolia-Dienste zuzugreifen, zum Beispiel auf den Magnolia-Autorendienst:

Java
  $ kubectl port-forward svc/github-magnolia-docker-author 8888:80  

Öffnen Sie http://localhost:8888 in einem Browser und melden Sie sich mit superuser/superuser an.

Magnolia_login

Magnolias Containerisierung auf die nächste Stufe heben

Magnolien in Containern zu pflanzen ist cool, nicht wahr? Aber das ist nicht die ganze Geschichte. Sie können Magnolia in einen CI/CD-Workflow einbinden, der nahtlos mit GitHub und Ihrem Kubernetes-Cluster zusammenarbeitet. CI/CD ist ein wesentlicher Aspekt der DevOps-Kultur und muss unbedingt richtig gemacht werden.

GitHub Actions erweist sich als effizientes und einfach zu bedienendes Werkzeug, um die Dinge in der Realität umzusetzen. Von hier aus können Sie der Pipeline weitere Aktionen hinzufügen, z. B. Testschritte, die Aktualisierung des Bundle-Deskriptors oder Dienstdefinitionen im Helm-Diagramm.

Aktualisierungen und Beiträge finden Sie in unserem GitHub-Repository.

Über den autor

Khiem Do Hoang

Senior Site Reliability Engineer, Magnolia

Khiem works on Magnolia’s Site Reliability Engineering (SRE) team. As an SRE he helps to ensure that Magnolia deploys smoothly and reliably on cloud infrastructure. He is involved in the design and implementation of automation processes, CI/CD, Infrastructure as Code (IaC), monitoring, and logging. Khiem is also interested in designing systems to take advantage of the automation and scalability of cloud-native, microservice-oriented, and containerized environments using technology such as Docker and Kubernetes.