Kontinuierliches Deployment in Google Kubernetes Engine mit Jenkins

In dieser Anleitung wird beschrieben, wie Sie die im nachstehenden Diagramm dargestellte Continuous Delivery-Pipeline mit Jenkins und Google Kubernetes Engine (GKE) einrichten können.

Jenkins: Continuous Delivery-Architektur.

Ziele

  • Beispielanwendung verstehen
  • Anwendung in GKE bereitstellen
  • Code in Cloud Source Repositories hochladen
  • Deployment-Pipelines in Jenkins erstellen
  • Entwicklungsumgebungen bereitstellen
  • Canary-Release bereitstellen
  • Produktionsumgebungen bereitstellen

Kosten

In dieser Anleitung werden kostenpflichtige Komponenten von Google Cloud verwendet, darunter:

  • Compute Engine
  • Google Kubernetes Engine
  • Cloud Build

Sie können mithilfe des Preisrechners eine Kostenschätzung für Ihre voraussichtliche Nutzung erstellen. Neuen GCP-Nutzern steht gegebenenfalls eine kostenlose Testversion zur Verfügung.

Vorbereitung

  1. Melden Sie sich bei Ihrem Google Cloud-Konto an. Wenn Sie mit Google Cloud noch nicht vertraut sind, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.

    Zur Projektauswahl

  3. Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für Ihr Projekt aktiviert ist.

  4. Compute Engine, GKE, and Cloud Build APIs aktivieren.

    Aktivieren Sie die APIs

  5. Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.

    Zur Projektauswahl

  6. Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für Ihr Projekt aktiviert ist.

  7. Compute Engine, GKE, and Cloud Build APIs aktivieren.

    Aktivieren Sie die APIs

Umgebung vorbereiten

  1. Arbeiten Sie die Anleitung zum Einrichten von Jenkins in GKE durch. In GKE sollte dann eine funktionierende Jenkins-Installation ausgeführt werden.

  2. Klonen Sie den Beispielcode in Cloud Shell.

    git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes
    cd continuous-deployment-on-kubernetes/sample-app
    
  3. Weisen Sie dem Jenkins-Dienstkonto die Rolle cluster-admin zu:

    kubectl create clusterrolebinding jenkins-deploy \
        --clusterrole=cluster-admin --serviceaccount=default:cd-jenkins
    

    Für diese Anleitung benötigt das Jenkins-Dienstkonto cluster-admin-Berechtigungen, damit es Kubernetes-Namespaces und andere Ressourcen erstellen kann, die für die Anwendung notwendig sind. In einer Produktionsumgebung sollten Sie die erforderlichen Berechtigungen zusammenstellen und sie dem Dienstkonto einzeln zuweisen.

Anwendung verstehen

Sie stellen die Beispielanwendung gceme in Ihrer kontinuierlichen Deployment-Pipeline bereit. Die Anwendung ist in der Sprache Go geschrieben und befindet sich im Verzeichnis sample-app des Repositorys. Wenn Sie die Binärdatei gceme auf einer Compute Engine-Instanz ausführen, zeigt die Anwendung die Metadaten der Instanz auf einer Infokarte an.

gceme info card

Die Anwendung simuliert einen Mikrodienst durch Unterstützung von zwei Betriebsmodi:

  • Im Back-End-Modus beobachtet gceme Port 8080 und gibt Metadaten der Compute Engine-Instanz im JSON-Format zurück.

  • Im Front-End-Modus fragt gceme den Back-End-Dienst gceme ab und rendert die resultierenden JSON-Daten in der Benutzeroberfläche.

    gceme-Architektur

Die Front- und Back-End-Modi unterstützen zwei weitere URLs:

  • /version gibt die aktuelle Version aus.
  • /healthz meldet den Status der Anwendung. Wenn das Back-End erreichbar ist, wird im Front-End-Modus der Status als OK angezeigt.

Beispielanwendung in Kubernetes erstellen

Stellen Sie das Front-End und Back-End von gceme in Kubernetes mithilfe von Manifestdateien bereit, die die Deployment-Umgebung beschreiben. Die Dateien verwenden ein Standard-Image, das weiter unten in dieser Anleitung aktualisiert wird.

Stellen Sie die Anwendungen in zwei Umgebungen bereit.

  • Produktion. Die Live-Website, auf die Ihre Nutzer zugreifen.

  • Canary. Eine Website mit geringerer Kapazität, die einen Teil Ihres Nutzertraffics empfängt. Verwenden Sie diese Umgebung zur Integritätsprüfung Ihrer Software mit Live-Traffic, bevor sie in der Live-Umgebung freigeschaltet wird.

Erstellen Sie Ihre Anwendung zuerst in der Produktionsumgebung, um funktionstüchtigen Code in der Pipeline zu haben.

  1. Erstellen Sie den Kubernetes-Namespace, um das Produktions-Deployment logisch zu isolieren:

    kubectl create ns production
    
  2. Erstellen Sie die Canary- und Produktions-Deployments und -Dienste.

    kubectl --namespace=production apply -f k8s/production
    kubectl --namespace=production apply -f k8s/canary
    kubectl --namespace=production apply -f k8s/services
    
  3. Skalieren Sie die Front-Ends der Produktionsumgebung hoch:

    kubectl --namespace=production scale deployment gceme-frontend-production --replicas=4
    
  4. Rufen Sie die externe IP-Adresse für die Produktionsdienste ab. Es kann einige Minuten dauern, bis die IP-Adresse des Load-Balancers angezeigt wird.

    kubectl --namespace=production get service gceme-frontend
    

    Nach Abschluss des Vorgangs wird in der Spalte EXTERNAL-IP eine IP-Adresse angezeigt.

    NAME             TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
    gceme-frontend   LoadBalancer   10.35.254.91   35.196.48.78   80:31088/TCP   1m
    
  5. Speichern Sie die Load-Balancer-IP-Adresse des Front-End-Dienstes in einer Umgebungsvariablen:

    export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=production services gceme-frontend)
    
  6. Sie können prüfen, ob beide Dienste ausgeführt werden, wenn Sie die externe Front-End-IP-Adresse in Ihrem Browser öffnen.

  7. Öffnen Sie ein separates Terminal und fragen Sie die /version-URL des Produktionsendpunkts ab, damit Sie im nächsten Abschnitt Rolling Updates beobachten können:

    while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1;  done
    

Repository zum Hosten des Quellcodes der Beispielanwendung erstellen

Erstellen Sie als Nächstes eine Kopie der Beispielanwendung gceme und übertragen Sie sie in Cloud Source Repositories.

  1. Erstellen Sie das Repository in Cloud Source Repositories:

    gcloud source repos create gceme
    
  2. Initialisieren Sie das lokale Git-Repository:

    git init
    git config credential.helper gcloud.sh
    export PROJECT_ID=$(gcloud config get-value project)
    git remote add origin https://source.developers.google.com/p/$PROJECT_ID/r/gceme
    
  3. Legen Sie den Nutzernamen und die E-Mail-Adresse für Ihre Git-Commits in diesem Repository fest. Ersetzen Sie [EMAIL_ADDRESS] durch Ihre Git-E-Mail-Adresse und [USERNAME] durch Ihren Git-Nutzernamen:

    git config --global user.email "[EMAIL_ADDRESS]"
    git config --global user.name "[USERNAME]"
    
  4. Fügen Sie die Dateien hinzu, führen Sie den Commit durch und laden Sie die Dateien hoch:

    git add .
    git commit -m "Initial commit"
    git push origin master
    

Pipeline erstellen

Verwenden Sie Jenkins, um eine Pipeline zum Testen, Erstellen und für das Deployment der Kopie von gceme in Ihrem Kubernetes-Cluster zu definieren und auszuführen.

Anmeldedaten für das Dienstkonto hinzufügen

Konfigurieren Sie Ihre Anmeldedaten, damit Jenkins auf das Code-Repository zugreifen kann.

  1. Klicken Sie in der Jenkins-Benutzeroberfläche im linken Navigationsbereich auf Credentials (Anmeldedaten).
  2. Klicken Sie in der Tabelle Credentials (Anmeldedaten) auf den Link Jenkins.

    Jenkins-Anmeldedatengruppe

  3. Klicken Sie auf Global Credentials (Globale Anmeldedaten).

  4. Klicken Sie im linken Navigationsbereich auf Add Credentials (Anmeldedaten hinzufügen).

  5. Wählen Sie in der Drop-down-Liste Kind (Art) die Option Google Service Account from metadata (Google-Dienstkonto aus Metadaten) aus.

  6. Klicken Sie auf OK.

Es gibt jetzt zwei globale Anmeldedaten. Notieren Sie sich für die spätere Verwendung in dieser Anleitung den Namen des zweiten Anmeldedatums.

Jenkins-Anmeldedaten

Jenkins-Job erstellen

Verwenden Sie dann die Funktion Jenkins Pipeline, um die Build-Pipeline zu konfigurieren. Jenkins-Pipeline-Dateien werden mithilfe einer Groovy-ähnlichen Syntax erstellt.

Gehen Sie zur Jenkins-Benutzeroberfläche und folgen Sie den Schritten, um einen Pipeline-Job zu konfigurieren.

  1. Klicken Sie oben links in der Benutzeroberfläche auf den Link Jenkins.
  2. Klicken Sie in der linken Navigationsleiste auf den Link New Item (Neues Element).
  3. Geben Sie dem Projekt sample-app einen Namen, wählen Sie die Option Multibranch Pipeline (Mehrzweigige Pipeline) aus und klicken Sie auf OK.
  4. Klicken Sie auf der nächsten Seite auf Add Source (Quelle hinzufügen) und wählen Sie git aus.
  5. Fügen Sie in Cloud Source Repositories die HTTPS-Klon-URL Ihres Repositorys sample-app in das Feld Project Repository (Projekt-Repository) ein. Ersetzen Sie dabei [PROJECT_ID] durch Ihre Projekt-ID.

    https://source.developers.google.com/p/[PROJECT_ID]/r/gceme
    
  6. Wählen Sie in der Drop-down-Liste Credentials (Anmeldedaten) den Namen der Anmeldedaten aus, die Sie beim Hinzufügen Ihres Dienstkontos erstellt haben.

  7. Klicken Sie im Abschnitt Scan Multibranch Pipeline (Mehrzweigige Pipeline scannen) auf das Kästchen Periodically if not otherwise run (Regelmäßig, wenn nicht anders ausgeführt). Legen Sie unter Interval (Intervall) den Wert "1 Minute" fest.

  8. Klicken Sie auf Speichern.

    Jenkins-Jobeinstellungen erstellen

Nach Abschluss dieser Schritte wird ein Job mit dem Namen "Branch indexing" ausgeführt. Dieser Meta-Job ermittelt die Branches in Ihrem Repository und stellt sicher, dass in vorhandenen Branches keine Änderungen vorgenommen wurden. Wenn Sie Jenkins aktualisieren, wird im Zweig master dieser Job angezeigt.

Die erste Ausführung des Jobs schlägt fehl, bis Sie im nächsten Schritt einige Codeänderungen vornehmen.

Pipelinedefinition ändern

Erstellen Sie einen Zweig mit dem Namen canary für die Canary-Umgebung.

git checkout -b canary

Der Jenkinsfile-Container, der diese Pipeline definiert, wird in der Jenkins Pipeline Groovy-Syntax geschrieben. Mit einem Jenkinsfile kann eine vollständige Build-Pipeline in einer einzigen Datei ausgedrückt werden, die neben Ihrem Quellcode besteht. Pipelines unterstützen leistungsstarke Funktionen wie Parallelisierung und erfordern eine manuelle Nutzergenehmigung.

Ändern Sie das Jenkinsfile so, dass sie Ihre Produkt-ID in Zeile 1 enthält.

Canary-Release bereitstellen

Nachdem die Pipeline ordnungsgemäß konfiguriert wurde, können Sie die Anwendung gceme ändern und die Pipeline testen, verpacken und bereitstellen.

Die Canary-Umgebung wird als Canary-Release eingerichtet. Dadurch wird Ihre Änderung nur für einen kleinen Prozentsatz der Pods hinter dem Lastenausgleichsmodul in der Produktionsumgebung freigegeben. Dies wird in Kubernetes durch die Beibehaltung mehrerer Bereitstellungen mit den gleichen Labels bewerkstelligt. Für diese Anwendung erfolgt das Load-Balancing der gceme-frontend- Dienste für alle Pods mit den Labels app: gceme und role: frontend. Die Canary-Manifestdatei k8s/frontend-canary.yaml legt die Replikate auf 1 fest und enthält die für den Dienst gceme-frontend erforderlichen Labels.

Aktuell führt einer von fünf der Front-End-Pods den Canary-Code und die anderen vier führen den Produktionscode aus. Dadurch wird sichergestellt, dass sich der Canary-Code nicht negativ auf Nutzer auswirkt, bevor die Einführung für Ihre gesamte Pod-Flotte erfolgt.

  1. Öffnen Sie html.go und ersetzen Sie die beiden Instanzen von blue durch orange.
  2. Öffnen Sie main.go und ändern Sie die Versionsnummer von 1.0.0 in 2.0.0:

    const version string = "2.0.0"
    
  3. Fügen Sie diese Dateien dann Ihrem lokalen Repository hinzu und führen Sie einen Commit aus:

    git add Jenkinsfile html.go main.go
    git commit -m "Version 2"
    
  4. Laden Sie Ihre Änderungen schließlich auf den Remote-Git-Server hoch:

    git push origin canary
    
  5. Wechseln Sie nach dem Hochladen der Änderung in das Git-Repository zur Jenkins-Benutzeroberfläche, wo Sie sehen können, dass Ihr Build gestartet wurde.

    Ansicht: erster Jenkins-Build

  6. Nachdem der Build ausgeführt wurde, klicken Sie im linken Navigationsbereich auf den Pfeil nach unten neben dem Build und wählen Sie Console Output (Konsolenausgabe) aus.

    Navigation Jenkins-Konsole

  7. Beobachten Sie die Ausgabe des Builds einige Minuten lang und warten Sie, bis die Ausgabe der Nachrichten kubectl --namespace=production apply... beginnt. Prüfen Sie beim Start das Terminal, das die Produktions-URL /version abgefragt hat, und beobachten Sie, ob sich einige der Anfragen ändern. Sie haben diese Änderung nun für eine Teilgruppe der Nutzer eingeführt.

  8. Nach dem Deployment der Änderung in der Canary-Umgebung können Sie sie für die übrigen Nutzer einführen. Führen Sie dazu den Code mit dem Zweig master zusammen und übertragen Sie Ihn auf den Git-Server:

    git checkout master
    git merge canary
    git push origin master
    
  9. Ungefähr eine Minute später startet im Ordner sample-app der Job master.

    Jenkins-Masterjob

  10. Klicken Sie auf den Link master, um die Phasen Ihrer Pipeline sowie Pass/Fail-Informationen und Zeitmerkmale anzeigen zu lassen.

    Produktion in der Jenkins-Pipeline

  11. Fragen Sie die Produktions-URL ab, um zu bestätigen, dass die neue Version 2.0.0 bereitgestellt wurde und Anfragen von allen Nutzern sendet.

    export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
    while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1;  done
    

Sie können den Workflow im Jenkinsfile im Projekt sehen.

Entwicklungszweig bereitstellen

Manchmal müssen Sie mit nicht herkömmlichen Änderungen arbeiten, die nicht direkt in die Canary-Umgebung hochgeladen werden können. Entwicklungszweige sind Umgebungen, die von Entwicklern zum Testen von Codeänderungen verwendet werden, bevor der Code in die Live-Website eingebunden wird. Diese Umgebungen sind vereinfachte Versionen Ihrer Anwendung, werden aber mit den gleichen Mechanismen wie die Live-Umgebung bereitgestellt.

Laden Sie den Branch auf den Git-Server hoch und lassen Sie die Umgebung dann mit Jenkins bereitstellen, um eine Entwicklungsumgebung über einen Funktions-Branch zu erstellen. In einem Entwicklungsszenario würden Sie keinen öffentlichen Load-Balancer verwenden. Zum Sichern Ihrer Anwendung können Sie den kubectl-Proxy verwenden. Der Proxy authentifiziert sich bei der Kubernetes API und leitet Anfragen von Ihrem lokalen Rechner an den Dienst im Cluster weiter, ohne Ihren Dienst im Internet verfügbar zu machen.

  1. Erstellen Sie einen weiteren Zweig und laden Sie ihn auf den Git-Server hoch.

    git checkout -b new-feature
    git push origin new-feature
    

    Ein neuer Job und Ihre Entwicklungsumgebung werden erstellt. Unten in der Konsolenausgabe des Jobs wird beschrieben, wie Sie auf Ihre Umgebung zugreifen können.

  2. Starten Sie den Proxy im Hintergrund:

    kubectl proxy &
    
  3. Prüfen Sie, ob mit localhost auf Ihre Anwendung zugegriffen werden kann:

    curl http://localhost:8001/api/v1/namespaces/new-feature/services/gceme-frontend:80/proxy/
    
  4. Sie können nun Code auf diesen Branch hochladen, um Ihre Entwicklungsumgebung zu aktualisieren. Wenn Sie fertig sind, führen Sie Ihren Zweig wieder mit canary zusammen, um diesen Code in der Canary-Umgebung bereitzustellen.

    git checkout canary
    git merge new-feature
    git push origin canary
    
  5. Wenn Sie sicher sind, dass Ihr Code keine Probleme in der Produktionsumgebung verursacht, führen Sie den Zweig canary mit dem Zweig master zusammen, um das Deployment zu starten:

    git checkout master
    git merge canary
    git push origin master
    
  6. Wenn Sie mit dem Entwicklungszweig fertig sind, löschen Sie ihn vom Server und löschen Sie die Umgebung aus dem Kubernetes-Cluster:

    git push origin :new-feature
    kubectl delete ns new-feature
    

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten, wenn Sie das zum Ausführen der Anleitung erstellte Projekt löschen.

So löschen Sie das Projekt:

  1. Wechseln Sie in der Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Nächste Schritte