Kontinuierliches Deployment in der Google Kubernetes Engine (GKE) mit Cloud Build

1. Übersicht

In diesem Lab erfahren Sie, wie Sie mit Cloud Build eine Continuous Delivery-Pipeline für GKE einrichten. In diesem Lab wird gezeigt, wie Sie Cloud Build-Jobs für verschiedene Git-Ereignisse auslösen und wie Sie automatisierte Canary-Releases in GKE implementieren.

Gehen Sie dazu so vor:

  • GKE-Anwendung erstellen
  • Bereitstellungen für Git-Zweige automatisieren
  • Bereitstellungen für den Git-Hauptzweig automatisieren
  • Bereitstellungen für Git-Tags automatisieren

2. Hinweis

Für diese Referenzanleitung benötigen Sie ein Google Cloud-Projekt. Sie können ein neues Projekt erstellen oder ein vorhandenes Projekt auswählen:

  1. Wählen Sie ein Google Cloud-Projekt aus oder erstellen Sie eines.

ZUR PROJEKTAUSWAHL

  1. Aktivieren Sie die Abrechnung für Ihr Projekt.

Abrechnung aktivieren

3. Umgebung vorbereiten

  1. Erstellen Sie Umgebungsvariablen, die Sie in dieser Anleitung verwenden:
    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
    
    export ZONE=us-central1-b
    export CLUSTER=gke-progression-cluster
    export APP_NAME=myapp
    
  2. Aktivieren Sie die folgenden APIs:
    • Resource Manager
    • GKE
    • Cloud Source Repositories
    • Cloud Build
    • Container Registry
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        sourcerepo.googleapis.com \
        cloudbuild.googleapis.com \
        containerregistry.googleapis.com \
        --async
    
  3. Klonen Sie den Beispielquellcode und wechseln Sie in das Lab-Verzeichnis:
    git clone https://github.com/GoogleCloudPlatform/software-delivery-workshop.git gke-progression
    
    cd gke-progression/labs/gke-progression
    rm -rf ../../.git
    
  4. Ersetzen Sie Platzhalterwerte im Beispiel-Repository durch Ihre PROJECT_ID:In diesem Schritt erstellen Sie Instanzen der verschiedenen Konfigurationsdateien, die für Ihre aktuelle Umgebung eindeutig sind.Wenn Sie sich ein Beispiel für die Aktualisierung der Vorlagen ansehen möchten, führen Sie den folgenden Befehl aus.
    cat k8s/deployments/dev/frontend-dev.yaml.tmpl
    
    Führen Sie die Variablensubstitution mit dem folgenden Befehl aus.
    for template in $(find . -name '*.tmpl'); do envsubst '${PROJECT_ID} ${ZONE} ${CLUSTER} ${APP_NAME}' < ${template} > ${template%.*}; done
    
    Wenn Sie sich ein Beispiel für die Datei nach der Ersetzung ansehen möchten, führen Sie den folgenden Befehl aus.
    cat k8s/deployments/dev/frontend-dev.yaml
    
  5. Wenn Sie Git noch nicht über Cloud Shell verwendet haben, legen Sie die Werte für user.name und user.email fest, die Sie verwenden möchten:
    git config --global user.email "YOUR_EMAIL_ADDRESS"
    git config --global user.name "YOUR_USERNAME"
    
  6. Speichern Sie den Code aus dem Beispiel-Repository in Cloud Source Repositories:
    gcloud source repos create gke-progression
    git init
    git config credential.helper gcloud.sh
    git remote add gcp https://source.developers.google.com/p/$PROJECT_ID/r/gke-progression
    git branch -m main
    git add . && git commit -m "initial commit"
    git push gcp main
    
  7. Erstellen Sie Ihren GKE-Cluster.
    gcloud container clusters create ${CLUSTER} \
        --project=${PROJECT_ID} \
        --zone=${ZONE}
    
  8. Cloud Build-Berechtigungen für Ihren Cluster erteilen: Cloud Build stellt die Anwendung in Ihrem GKE-Cluster bereit und benötigt dazu Berechtigungen.
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
        --role=roles/container.developer
    

Ihre Umgebung ist bereit.

4. GKE-Anwendung erstellen

In diesem Abschnitt erstellen Sie die erste Produktionsanwendung, die Sie in dieser Anleitung verwenden, und stellen sie bereit.

  1. Erstellen Sie die Anwendung mit Cloud Build:
    gcloud builds submit --tag gcr.io/$PROJECT_ID/$APP_NAME:1.0.0 src/
    
  2. Manuelle Bereitstellung in Canary- und Produktionsumgebungen:Erstellen Sie die Produktions- und Canary-Deployments und -Dienste mit den kubectl apply-Befehlen.
    kubectl create ns production
    kubectl apply -f k8s/deployments/prod -n production
    kubectl apply -f k8s/deployments/canary -n production
    kubectl apply -f k8s/services -n production
    
    Der hier bereitgestellte Dienst leitet den Traffic sowohl an das Canary- als auch an das Produktions-Deployment weiter.
  3. Anzahl der ausgeführten Pods prüfenPrüfen Sie, ob vier Pods für das Frontend ausgeführt werden, darunter drei für den Produktionstraffic und einer für Canary-Releases. Änderungen am Canary-Release betreffen daher nur einen von vier Nutzern (25%).
    kubectl get pods -n production -l app=$APP_NAME -l role=frontend
    
  4. Rufen Sie die externe IP-Adresse für die Produktionsdienste ab.
    kubectl get service $APP_NAME -n production
    
    Fahren Sie mit dem nächsten Schritt fort, sobald der Load-Balancer die IP-Adresse zurückgibt.
  5. Speichern Sie die externe IP-Adresse zur späteren Verwendung.
    export PRODUCTION_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=production services $APP_NAME)
    
  6. Überprüfen Sie die Anwendung. Prüfen Sie die Serviceversion. Es sollte „Hello World v1.0“ angezeigt werden.
    curl http://$PRODUCTION_IP
    

Glückwunsch! Sie haben die Beispiel-App bereitgestellt. Als Nächstes richten Sie Trigger für die kontinuierliche Bereitstellung Ihrer Änderungen ein.

5. Bereitstellungen für Git-Zweige automatisieren

In diesem Abschnitt richten Sie einen Trigger ein, der einen Cloud Build-Job bei einem Commit in einem anderen Branch als main ausführt. Mit der hier verwendeten Cloud Build-Datei werden automatisch ein Namespace und eine Bereitstellung für alle vorhandenen oder neuen Branches erstellt. So können Entwickler ihren Code in der Vorschau ansehen, bevor er in den Haupt-Branch integriert wird.

  1. Trigger einrichten:Die Schlüsselkomponente dieses Triggers ist die Verwendung des Parameters branchName, um main abzugleichen, und des Parameters invertRegex, der auf „true“ gesetzt ist und das branchName-Muster so ändert, dass alles abgeglichen wird, was nicht main ist. Die folgenden Zeilen finden Sie in build/branch-trigger.json.
      "branchName": "main",
      "invertRegex": true
    
    Außerdem wird in den letzten Zeilen der Cloud Build-Datei, die mit diesem Trigger verwendet wird, ein Namespace erstellt, der nach dem Branch benannt ist, der den Job ausgelöst hat. Anschließend werden die Anwendung und der Dienst im neuen Namespace bereitgestellt. Die folgenden Zeilen finden Sie in build/branch-cloudbuild.yaml:
      kubectl get ns ${BRANCH_NAME} || kubectl create ns ${BRANCH_NAME}
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/deployments/dev
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/services
    
    Nachdem Sie die verwendeten Mechanismen verstanden haben, erstellen Sie den Trigger mit dem folgenden gcloud-Befehl.
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/branch-trigger.json
    
  2. Rufen Sie zum Prüfen des Triggers die Cloud Build-Seite „Trigger” in der Console auf.Zu Triggers
  3. So erstellen Sie einen neuen Zweig:
    git checkout -b new-feature-1
    
  4. Code ändern, um v1.1 anzugebenBearbeiten Sie src/app.py und ändern Sie die Antwort von 1.0 zu 1.1.
    @app.route('/')
    def hello_world():
        return 'Hello World v1.1'
    
  5. Führen Sie für die Änderung einen Commit durch und übertragen Sie sie per Push an das Remote-Repository:
    git add . && git commit -m "updated" && git push gcp new-feature-1
    
  6. Zum Prüfen des laufenden Builds rufen Sie in der Console die Cloud Build-Seite „Verlauf“ auf.Zu den BuildsFahren Sie nach Abschluss des Builds mit dem nächsten Schritt fort.
  7. Rufen Sie die externe IP-Adresse für den neu bereitgestellten Branch-Dienst ab.
    kubectl get service $APP_NAME -n new-feature-1
    
    Fahren Sie mit dem nächsten Schritt fort, sobald der Load-Balancer die IP-Adresse zurückgibt.
  8. Speichern Sie die externe IP-Adresse zur späteren Verwendung.
    export BRANCH_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=new-feature-1 services $APP_NAME)
    
  9. Überprüfen Sie die Anwendung. Es sollte „Hello World v1.0“ angezeigt werden.
    curl http://$BRANCH_IP
    

6. Bereitstellungen für den Git-Hauptzweig automatisieren

Bevor Code für die Produktion freigegeben wird, ist es üblich, Code für eine kleine Teilmenge des Live-Traffics freizugeben, bevor der gesamte Traffic zur neuen Codebasis migriert wird.

In diesem Abschnitt implementieren Sie einen Trigger, der aktiviert wird, wenn Code an den Haupt-Branch übergeben wird. Der Trigger stellt das Canary-Deployment bereit, das 25% des gesamten Live-Traffics an die neue Überarbeitung weiterleitet.

  1. Richten Sie den Trigger für den Hauptzweig ein:
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/main-trigger.json
    
  2. Rufen Sie in der Console die Cloud Build-Seite „Trigger” auf, um den neuen Trigger zu prüfen.Zu „Trigger“
  3. Führen Sie den Branch mit der Hauptzeile zusammen und übertragen Sie ihn per Push an das Remote-Repository:
    git checkout main
    git merge new-feature-1
    git push gcp main
    
  4. Zum Prüfen des laufenden Builds rufen Sie in der Console die Cloud Build-Seite „Verlauf“ auf.Zu „Builds“Fahren Sie nach Abschluss des Builds mit dem nächsten Schritt fort.
  5. Mehrere Antworten vom Server prüfen: Führen Sie den folgenden Befehl aus und beachten Sie, dass in etwa 25% der Antworten die neue Antwort von Hello World v1.1 angezeigt wird.
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    Wenn Sie fortfahren möchten, drücken Sie Ctrl+c, um die Schleife zu beenden.

7. Bereitstellungen für Git-Tags automatisieren

Nachdem das Canary-Deployment mit einer kleinen Teilmenge des Traffics validiert wurde, geben Sie das Deployment für den Rest des Live-Traffics frei.

In diesem Abschnitt richten Sie einen Trigger ein, der aktiviert wird, wenn Sie ein Tag im Repository erstellen. Der Trigger kennzeichnet das Bild mit dem entsprechenden Tag und stellt die Updates dann in der Produktionsumgebung bereit. So wird sichergestellt, dass 100% des Traffics auf das getaggte Bild zugreifen.

  1. Tag-Trigger einrichten:
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/tag-trigger.json
    
  2. Rufen Sie in der Console die Cloud Build-Seite „Trigger” auf, um den neuen Trigger zu prüfen.Zu „Trigger“
  3. Erstellen Sie ein neues Tag und übertragen Sie es per Push in das Remote-Repository:
    git tag 1.1
    git push gcp 1.1
    
  4. Zum Prüfen des laufenden Builds rufen Sie in der Console die Cloud Build-Seite „Verlauf“ auf.Zu „Builds“
  5. Mehrere Antworten vom Server prüfenFühren Sie den folgenden Befehl aus und beachten Sie, dass in 100% der Antworten die neue Antwort „Hello World v1.1“ angezeigt wird. Das kann einen Moment dauern, da die neuen Pods bereitgestellt und in GKE Systemdiagnosen durchgeführt werden.
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    Wenn Sie bereit sind, drücken Sie Ctrl+c, um die Schleife zu verlassen.Herzlichen Glückwunsch! Sie haben in Cloud Build CI/CD-Trigger für Zweige und Tags erstellt, um Ihre Anwendungen in GKE bereitzustellen.

8. Bereinigen

Projekt löschen

  1. Wechseln Sie in der Cloud Console zur Seite Ressourcen verwalten.
  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Beenden, um das Projekt zu löschen.