Anwendung „x86“ in GKE für mehrere Architekturen mit Arm migrieren


In dieser Anleitung wird beschrieben, wie eine Anwendung, die für Knoten mit einem x86-Prozessor (Intel oder AMD) in einem Google Kubernetes Engine (GKE)-Cluster erstellt wurde, in eine Anwendung mit mehreren Architekturen migriert wird, die entweder auf x86- oder Arm-Knoten ausgeführt wird. Die Zielgruppe für diese Anleitung sind Plattformadministratoren, Anwendungsoperatoren und Anwendungsentwickler, die ihre vorhandenen x86-kompatiblen Arbeitslasten auf Arm ausführen möchten.

Mit GKE-Clustern können Sie Arbeitslasten auf Arm-Knoten mithilfe der C4A-Maschinenserie oder der Tau T2A-Maschinenserie ausführen. In dieser Anleitung werden C4A-Knoten verwendet, die wie T2A-Knoten in Ihrem GKE-Cluster wie jeder andere Knoten mit x86-Prozessoren (Intel oder AMD) ausgeführt werden können. C4A-Knoten bieten eine konstant hohe Leistung auf Arm-Basis für Ihre Arbeitslasten.

Weitere Informationen finden Sie unter Arm-Arbeitslasten in GKE.

In dieser Anleitung wird davon ausgegangen, dass Sie mit Kubernetes und Docker vertraut sind. In dieser Anleitung werden Google Kubernetes Engine und Artifact Registry verwendet.

Ziele

In dieser Anleitung führen Sie die folgenden Aufgaben aus:

  • Container-Images mit Docker in Artifact Registry speichern.
  • Eine mit x86 kompatible Arbeitslast in einem GKE-Cluster bereitstellen.
  • Eine x86-kompatible Arbeitslast neu erstellen, die auf Arm ausgeführt wird.
  • Einem vorhandenen Cluster einen Arm-Knotenpool hinzufügen.
  • Eine Arm-kompatible Arbeitslast bereitstellen, die auf einem Arm-Knoten ausgeführt werden soll.
  • Ein Image für mehrere Architekturen erstellen, um eine Arbeitslast in mehreren Architekturen auszuführen.
  • Arbeitslasten in mehreren Architekturen in einem GKE-Cluster ausführen.

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweise

Führen Sie folgende Schritte aus, um die Kubernetes Engine API zu aktivieren:
  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Enable the APIs

Nach Abschluss dieser Anleitung können Sie weitere Kosten durch Löschen von erstellten Ressourcen vermeiden. Weitere Informationen finden Sie unter Bereinigen.

Cloud Shell starten

In dieser Anleitung verwenden Sie Cloud Shell, eine Shell-Umgebung für die Verwaltung von Ressourcen, die in Google Cloud gehostet werden.

Die Google Cloud CLI und das kubectl-Befehlszeilentool sind in Cloud Shell vorinstalliert. die gcloud-CLI ist die primäre Befehlszeile für Google Cloud und kubectl ist die primäre Befehlszeile zum Ausführen von Befehlen für Kubernetes-Cluster.

Cloud Shell aufrufen

  1. Öffnen Sie die Google Cloud Console.

    Google Cloud Console

  2. Klicken Sie in der oberen rechten Ecke der Console auf die Schaltfläche Cloud Shell aktivieren:

In der Console wird eine Cloud Shell-Sitzung angezeigt. In dieser Shell führen Sie gcloud- und kubectl-Befehle aus.

Umgebung vorbereiten

In diesem Abschnitt bereiten Sie Ihre Umgebung für die Anleitung vor.

Standardeinstellungen für die gcloud CLI festlegen

Legen Sie Umgebungsvariablen für Ihre Projekt-ID, die Zone und den Namen des neuen Clusters fest.

export PROJECT_ID=PROJECT_ID
export ZONE=us-central1-a
export CLUSTER_NAME=my-cluster

Ersetzen Sie PROJECT_ID durch die Projekt-ID, die Sie für diese Anleitung im Abschnitt Vorbereitung ausgewählt haben.

In dieser Anleitung erstellen Sie Ressourcen in der Region „us-central1-a“. Eine vollständige Liste der Verfügbarkeit der Maschinentypen C4A-Maschinen finden Sie unter Verfügbare Regionen und Zonen.

Git-Repository klonen

  1. Klonen Sie das Repository:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  2. Ändern Sie das aktuelle Arbeitsverzeichnis in das im vorherigen Schritt geklonte Repository:

    cd kubernetes-engine-samples/workloads/migrate-x86-app-to-multi-arch/
    

GKE-Cluster erstellen und x86-Anwendung bereitstellen

Im ersten Teil dieser Anleitung erstellen Sie einen Cluster mit x86-Knoten und stellen eine x86-Anwendung bereit. Die Beispielanwendung ist ein Dienst, der auf HTTP-Anfragen reagiert. Sie wird mit der Programmiersprache Golang erstellt.

Diese Einrichtung stellt eine typische Clusterumgebung dar, in der x86-kompatible Anwendungen und x86-Knoten verwendet werden.

GKE-Cluster erstellen

Erstellen Sie zuerst eine GKE mithilfe von Knoten mit x86-Prozessoren. Mit dieser Konfiguration erstellen Sie eine typische Clusterumgebung zum Ausführen von x86-Anwendungen.

Erstellen Sie den Cluster:

gcloud container clusters create $CLUSTER_NAME \
    --release-channel=rapid \
    --zone=$ZONE \
    --machine-type=e2-standard-2 \
    --num-nodes=1 \
    --async

Für diesen Cluster ist Autoscaling deaktiviert, um in späteren Schritten bestimmte Funktionen zu zeigen.

Es kann einige Minuten dauern, bis der Cluster erstellt ist. Mit dem Flag --async kann dieser Vorgang im Hintergrund ausgeführt werden, während Sie die nächsten Schritte ausführen.

Sie können Cluster nur mit Arm-Knoten erstellen. Für diese Anleitung erstellen Sie jedoch zuerst einen Cluster mit nur x86-Knoten, um zu erfahren, wie Sie x86-basierte Anwendungen mit Arm kompatibel machen.

Artifact Registry-Docker-Repository erstellen

  1. Erstellen Sie in Artifact Registry ein Repository, um Docker-Images zu speichern:

    gcloud artifacts repositories create docker-repo \
          --repository-format=docker \
          --location=us-central1 \
          --description="Docker repository"
    
  2. Konfigurieren Sie das Docker-Befehlszeilentool für die Authentifizierung bei diesem Repository in Artifact Registry:

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

x86-Image erstellen und in Artifact Registry übertragen

  1. Erstellen Sie die x86-kompatible Version der Anwendung:

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1 . 
    
  2. Übertragen Sie das Image per Push an Artifact Registry.

    docker push us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1
    

x86-Anwendung bereitstellen

  1. Prüfen Sie mit dem folgenden Script, ob der Cluster bereit ist:

    echo
    echo -ne "Waiting for GKE cluster to finish provisioning"
    gke_status=""
    while [ -z $gke_status ]; do
       sleep 2
       echo -ne '.'   
       gke_status=$(gcloud container clusters list --format="value(STATUS)" --filter="NAME=$CLUSTER_NAME AND STATUS=RUNNING")
    done
    echo
    echo "GKE Cluster '$CLUSTER_NAME' is $gke_status" 
    echo
    

    Wenn der Cluster bereit ist, sollte die Ausgabe in etwa so aussehen:

    GKE Cluster 'my-cluster' is RUNNING
    
  2. Rufen Sie die Clusteranmeldedaten ab, damit kubectl eine Verbindung zur Kubernetes API für den Cluster herstellen kann:

    gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID
    
  3. Aktualisieren Sie das Image mit kustomize und stellen Sie die x86-Anwendung bereit:

    $(cd k8s/overlays/x86 && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/x86
    
  4. Stellen Sie einen Dienst bereit, um die Anwendung im Internet freizugeben:

    kubectl apply -f k8s/hello-service.yaml
    
  5. Prüfen Sie, ob die externe IP-Adresse für den Dienst hello-service bereitgestellt wurde:

    echo
    echo -ne "Waiting for External IP to be provisioned"
    external_ip=""
    while [ -z $external_ip ]; do
       sleep 2
       echo -ne '.'
       external_ip=$(kubectl get svc hello-service --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}")
    done
    echo
    echo "External IP: $external_ip"
    echo
    

    Nachdem die externe IP-Adresse bereitgestellt wurde, sollte die Ausgabe in etwa so aussehen:

    External IP: 203.0.113.0
    
  6. Senden Sie eine HTTP-Anfrage, um zu testen, ob die Bereitstellung wie erwartet funktioniert:

    curl -w '\n' http://$external_ip
    

    Die Ausgabe sieht etwa so aus:

    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64
    

    Die Ausgabe zeigt, dass diese x86-kompatible Bereitstellung auf einem Knoten im Standardknotenpool der amd64-Architektur ausgeführt wird. Die Knoten im Standardknotenpool des Clusters haben x86-Prozessoren (Intel oder AMD).

Arm-Knoten zum Cluster hinzufügen

Im nächsten Teil dieser Anleitung fügen Sie Ihrem vorhandenen Cluster Arm-Knoten hinzu. Auf diesen Knoten wird die Arm-kompatible Version Ihrer Anwendung bereitgestellt, wenn sie für die Ausführung auf Arm neu erstellt wird.

Checkpoint

Bisher haben Sie die folgenden Ziele erreicht:

  • Einen GKE-Cluster mit x86-Knoten erstellen.
  • Ein x86-kompatibles Container-Image mit Docker in Artifact Registry speichern.
  • Eine mit x86 kompatible Arbeitslast in einem GKE-Cluster bereitstellen.

Eine Clusterumgebung mit x86-Knoten und einer x86-kompatiblen Arbeitslast konfigurieren. Diese Konfiguration ähnelt Ihren vorhandenen Clusterumgebungen, wenn Sie derzeit keine Arm-Knoten und Arm-kompatible Arbeitslasten verwenden.

Ihrem Cluster einen Arm-Knotenpool hinzufügen

Fügen Sie Ihrem vorhandenen Cluster einen Arm-Knotenpool hinzu:

gcloud container node-pools create arm-pool \
    --cluster $CLUSTER_NAME \
    --zone $ZONE \
    --machine-type=c4a-standard-2 \
    --num-nodes=1

Der Maschinentyp c4a-standard-2 ist eine ARM-VM aus der C4A-Maschinenreihe.

Sie erstellen einen Knotenpool mit Arm-Knoten auf die gleiche Weise wie einen Knotenpool mit x86-Knoten. Nachdem dieser Knotenpool erstellt wurde, werden in diesem Cluster sowohl x86-Knoten als auch Arm-Knoten ausgeführt.

Weitere Informationen zum Hinzufügen von Arm-Knotenpools zu vorhandenen Clustern finden Sie unter Arm-Knotenpool zu einem GKE-Cluster hinzufügen.

Vorhandene Anwendung skalieren, die auf x86-basierten Knoten ausgeführt wird

Knoten mehrerer Architekturtypen können nahtlos in einem Cluster zusammenarbeiten. GKE plant vorhandene Arbeitslasten die auf x86-Knoten ausgeführt werden, nicht auf Arm-Knoten im Cluster ein, da auf Arm-Knoten automatisch eine Markierung platziert wird. Skalieren Sie Ihre vorhandene Anwendung, um dies zu sehen.

  1. Aktualisieren Sie die Arbeitslast und skalieren Sie sie auf 6 Replikate:

    $(cd k8s/overlays/x86_increase_replicas && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/x86_increase_replicas/
    
  2. Warten Sie 30 Sekunden und führen Sie dann den folgenden Befehl aus, um den Status der Bereitstellung zu überprüfen:

    kubectl get pods -l="app=hello" --field-selector="status.phase=Pending"
    

    Die Ausgabe sollte in etwa so aussehen:

    NAME                                    READY   STATUS    RESTARTS   AGE
    x86-hello-deployment-6b7b456dd5-6tkxd   0/1     Pending   0          40s
    x86-hello-deployment-6b7b456dd5-k95b7   0/1     Pending   0          40s
    x86-hello-deployment-6b7b456dd5-kc876   0/1     Pending   0          40s
    

    Diese Ausgabe zeigt Pods mit dem Status „Ausstehend“, da auf den x86-basierten Knoten kein Platz mehr vorhanden ist. Da Cluster Autoscaler deaktiviert ist und die Arm-Knoten markiert sind, werden die Arbeitslasten auf keinem der verfügbaren Arm-Knoten bereitgestellt. Diese Markierung verhindert, dass GKE x86-Arbeitslasten auf Arm-Knoten plant. Damit eine Bereitstellung auf Arm-Knoten möglich ist, müssen Sie angeben, dass die Bereitstellung mit Arm-Knoten kompatibel ist.

  3. Prüfen Sie die Pods mit dem Status „Wird ausgeführt“:

    kubectl get pods -l="app=hello" --field-selector="status.phase=Running" -o wide
    

    Die Ausgabe sollte in etwa so aussehen:

    NAME                                    READY   STATUS    RESTARTS   AGE   IP            NODE                                        NOMINATED NODE   READINESS GATES
    x86-hello-deployment-6b7b456dd5-cjclz   1/1     Running   0          62s   10.100.0.17   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    x86-hello-deployment-6b7b456dd5-mwfkd   1/1     Running   0          34m   10.100.0.11   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    x86-hello-deployment-6b7b456dd5-n56rg   1/1     Running   0          62s   10.100.0.16   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    

    In dieser Ausgabe gibt die Spalte NODE an, dass alle Pods aus der Bereitstellung nur im Standardpool ausgeführt werden. Die x86-kompatiblen Pods werden also nur für die x86-Knoten geplant. Der ursprüngliche Pod, der bereits vor dem Erstellen des Arm-Knotenpools geplant wurde, wird noch auf demselben Knoten ausgeführt.

  4. Führen Sie den folgenden Befehl aus, um auf den Dienst zuzugreifen und die Ausgabe zu sehen:

    for i in $(seq 1 6); do curl -w '\n' http://$external_ip; done
    

    Die Ausgabe sieht etwa so aus:

    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64
    

    Diese Ausgabe zeigt, dass alle Pods, die Anfragen verarbeiten, auf x86-Knoten ausgeführt werden. Einige Pods können nicht antworten, da sie sich noch im Status „Ausstehend“ befinden, da auf den vorhandenen x86-Knoten kein Speicherplatz vorhanden ist und sie nicht für Arm-Knoten geplant werden.

Anwendung für die Ausführung auf Arm neu erstellen

Im vorherigen Abschnitt haben Sie einen Arm-Knotenpool zu Ihrem vorhandenen Cluster hinzugefügt. Wenn Sie die vorhandene x86-Anwendung jedoch hochskaliert haben, wurden keine Arbeitslasten für die Arm-Knoten geplant. In diesem Abschnitt erstellen Sie die Anwendung neu, damit sie Arm-kompatibel ist, damit diese Anwendung auf den Arm-Knoten im Cluster ausgeführt werden kann.

Führen Sie für dieses Beispiel diese Schritte mit docker build aus. Dieser zweistufige Ansatz umfasst:

  • Erste Phase: Den Code für ARM erstellen.
  • Zweite Phase: Die ausführbare Datei in einen schlanken Container kopieren.

Nach dem Ausführen dieser Schritte haben Sie zusätzlich zum x86-kompatiblen Image ein Arm-kompatibles Image.

Der zweite Schritt, das Kopieren der ausführbaren Datei in einen anderen Container, folgt einer der Best Practices für die Erstellung eines Containers, nämlich das Erstellen des kleinstmöglichen Images.

In dieser Anleitung wird eine Beispielanwendung verwendet, die mit der Programmiersprache Golang erstellt wurde. Mit Golang können Sie eine Anwendung auf verschiedene Betriebssysteme und CPU-Plattformen kompilieren. Dazu stellen Sie die Umgebungsvariablen GOOS bzw. GOARCH bereit.

  1. Führen Sie cat Dockerfile_arm aus, um das für Arm geschriebene Dockerfile anzusehen:

    #
    # Build: 1st stage
    #
    FROM golang:1.18-alpine as builder 
    WORKDIR /app
    COPY go.mod .
    COPY hello.go .
    RUN GOARCH=arm64 go build -o /hello && \
       apk add --update --no-cache file && \
       file /hello
    

    Das hier gezeigte Snippet zeigt nur die erste Phase. Die Datei enthält beide Phasen.

    In dieser Datei weist die Einstellung GOARCH=arm64 den Go-Compiler an, die Anwendung für den Arm-Befehlssatz zu erstellen. Sie müssen GOOS nicht festlegen, da das Basis-Image in der ersten Phase ein Linux Alpine-Image ist.

  2. Erstellen Sie den Code für Arm und übertragen Sie ihn per Push in Artifact Registry:

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1 -f Dockerfile_arm .
    docker push us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1
    

Arm-Version Ihrer Anwendung bereitstellen

Nachdem die Anwendung für die Ausführung auf Arm-Knoten erstellt wurde, können Sie sie auf den Arm-Knoten in Ihrem Cluster bereitstellen.

  1. Prüfen Sie die Datei add_arm_support.yaml mit dem Befehl cat k8s/overlays/arm/add_arm_support.yaml:

    Die Ausgabe sieht etwa so aus:

       nodeSelector:
          kubernetes.io/arch: arm64
    

    Dieser nodeSelector gibt an, dass die Arbeitslast nur auf den Arm-Knoten ausgeführt werden soll. Wenn Sie den nodeSelector verwenden, fügt GKE eine Toleranz hinzu, die der Markierung auf Arm-Knoten entspricht, sodass GKE die Arbeitslast auf diesen Knoten planen kann. Weitere Informationen zum Festlegen dieses Felds finden Sie unter Arm-Arbeitslast für die Bereitstellung vorbereiten.

  2. Stellen Sie ein Replikat der ARM-kompatiblen Version der Anwendung bereit:

    $(cd k8s/overlays/arm && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/arm
    
  3. Warten Sie fünf Sekunden und prüfen Sie dann, ob die Arm-Bereitstellung curl-Anfragen beantwortet:

    for i in $(seq 1 6); do curl -w '\n' http://$external_ip; done
    

    Die Ausgabe sieht etwa so aus:

    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:arm-hello-deployment-69b4b6bdcc-n5l28, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64
    

    Diese Ausgabe sollte Antworten von den x86-kompatiblen und Arm-kompatiblen Anwendungen enthalten, die auf die curl-Anfrage antworten.

Image mit mehreren Architekturen erstellen, um eine Arbeitslast architekturübergreifend auszuführen

Sie können zwar die im vorherigen Abschnitt beschriebene Strategie verwenden und separate Arbeitslasten für x86 und Arm bereitstellen, dafür müssen Sie jedoch zwei Build-Prozesse und zwei Container-Images verwalten und organisieren.

Im Idealfall möchten Sie Ihre Anwendung nahtlos auf x86- und Arm-Plattformen erstellen und ausführen. Wir empfehlen diesen Ansatz. Um Ihre Anwendung mit einem Manifest auf mehreren Architekturplattformen auszuführen, müssen Sie Images mit mehreren Architekturen verwenden. Weitere Informationen zu Images mit mehreren Architekturen finden Sie unter Images mit mehreren Architekturen für Arm-Arbeitslasten erstellen.

Wenn Sie Images mit mehreren Architekturen verwenden möchten, müssen Sie dafür sorgen, dass Ihre Anwendung die folgenden Voraussetzungen erfüllt:

  • Ihre Anwendung hat keine Architektur-spezifischen Abhängigkeiten.
  • Alle Abhängigkeiten müssen für mehrere Architekturen oder zumindest für die Zielplattformen erstellt werden.

Die in dieser Anleitung verwendete Beispielanwendung erfüllt beide dieser Voraussetzungen. Wir empfehlen Ihnen jedoch, Ihre eigenen Anwendungen beim Erstellen ihrer Images für mehrere Architekturen zu testen, bevor Sie sie für die Produktion bereitstellen.

Images mit mehreren Architekturen erstellen und übertragen

Sie können Images mit mehreren Architekturen mit Docker Buildx erstellen, wenn Ihre Arbeitslast die folgenden Voraussetzungen erfüllt:

  • Das Basis-Image unterstützt mehrere Architekturen. Prüfen Sie dies durch Ausführen von docker manifest inspect für das Basis-Image und prüfen Sie die Liste der Architekturplattformen. Am Ende dieses Abschnitts finden Sie ein Beispiel für die Prüfung eines Images.
  • Die Anwendung erfordert keine speziellen Build-Schritte für jede Architekturplattform. Wenn spezielle Schritte erforderlich waren, reichte Buildx möglicherweise nicht aus. Sie benötigen ein separates Dockerfile für jede Plattform und erstellen das Manifest manuell mit docker manifest create.

Das Basis-Image der Beispielanwendung ist Alpine, das mehrere Architekturen unterstützt. Es gibt auch keine plattformspezifischen Schritte, sodass Sie das Image für mehrere Architekturen mit Buildx erstellen können.

  1. Prüfen Sie das Dockerfile mit cat Dockerfile:

    # This is a multi-stage Dockerfile. 
    # 1st stage builds the app in the target platform
    # 2nd stage create a lean image coping the binary from the 1st stage
    
    #
    # Build: 1st stage
    #
    FROM golang:1.18-alpine as builder 
    ARG BUILDPLATFORM    
    ARG TARGETPLATFORM
    RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM"  
    WORKDIR /app
    COPY go.mod .
    COPY hello.go .
    RUN go build -o /hello && \
       apk add --update --no-cache file && \
       file /hello   
    
    #
    # Release: 2nd stage
    #
    FROM alpine
    WORKDIR /
    COPY --from=builder /hello /hello
    CMD [ "/hello" ]
    

    Dieses Dockerfile definiert zwei Phasen: die Build-Phase und die Release-Phase. Sie verwenden dasselbe Dockerfile, das zum Erstellen der x86-Anwendung verwendet wird.

  2. Führen Sie den folgenden Befehl aus, um einen neuen docker buildx-Builder zu erstellen und zu verwenden:

    docker buildx create --name multiarch --use --bootstrap
    

    Nachdem Sie diesen neuen Builder erstellt haben, können Sie ein Image erstellen und mit dem Flag --platform kompatibel machen, das sowohl mit linux/amd64 als auch mit linux/arm64 kompatibel ist. Für jede mit dem Flag bereitgestellte Plattform erstellt Buildx ein Image auf der Zielplattform. Wenn Buildx das Image linux/arm64 erstellt, werden arm64-Basis-Images heruntergeladen. In der ersten Phase wird die Binärdatei auf dem Image arm64 golang:1.18-alpine für arm64 erstellt. In der zweiten Phase wird das Alpine Linux-Image arm64 heruntergeladen und die Binärdatei in eine Ebene dieses Images kopiert.

  3. Erstellen Sie das Image und übertragen Sie es per Push:

    docker buildx build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1 -f Dockerfile --platform linux/amd64,linux/arm64 --push .
    

    Die Ausgabe sieht etwa so aus:

    => [linux/arm64 builder x/x] ..
    => [linux/amd64 builder x/x] ..
    

    Diese Ausgabe zeigt, dass zwei Images generiert werden, eines für linux/arm64 und eines für linux/amd64.

  4. Prüfen Sie das Manifest Ihres neuen Images für mehrere Architekturen:

    docker manifest inspect us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1
    

    Die Ausgabe sieht etwa so aus:

    {
       "schemaVersion": 2,
       "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
       "manifests": [
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 739,
             "digest": "sha256:dfcf8febd94d61809bca8313850a5af9113ad7d4741edec1362099c9b7d423fc",
             "platform": {
                "architecture": "amd64",
                "os": "linux"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 739,
             "digest": "sha256:90b637d85a93c3dc03fc7a97d1fd640013c3f98c7c362d1156560bbd01f6a419",
             "platform": {
                "architecture": "arm64",
                "os": "linux"
             }
          }
       ]
    

    In dieser Ausgabe enthält der Abschnitt manifests zwei Manifeste, eines mit der Plattformarchitektur amd64 und das andere mit der Plattformarchitektur arm64.

    Wenn Sie dieses Container-Image in Ihrem Cluster bereitstellen, lädt GKE automatisch nur das Image herunter, das der Architektur des Knotens entspricht.

Version für mehrere Architekturen Ihrer Anwendung bereitstellen

  1. Löschen Sie die ursprünglichen Arbeitslasten, bevor Sie das Image für mehrere Architekturen bereitstellen:

    kubectl delete deploy x86-hello-deployment arm-hello-deployment
    
  2. Prüfen Sie das Kustomize-Overlay add_multiarch_support.yaml mit dem Befehl cat k8s/overlays/multiarch/add_multiarch_support.yaml:

    Die Ausgabe enthält den folgenden Toleranzsatz:

       tolerations:
          - key: kubernetes.io/arch
             operator: Equal
             value: arm64
             effect: NoSchedule
    

    Diese Toleranz ermöglicht die Ausführung der Arbeitslast auf den Arm-Knoten in Ihrem Cluster, da die Toleranz mit der Markierung auf allen Arm-Knoten übereinstimmt. Da diese Arbeitslast jetzt auf jedem Knoten im Cluster ausgeführt werden kann, ist nur die Toleranz erforderlich. Nur mit der Toleranz kann GKE die Arbeitslast für x86- und Arm-Knoten planen. Wenn Sie angeben möchten, wo GKE Arbeitslasten planen kann, verwenden Sie Knotenselektoren und Knotenaffinitätsregeln. Weitere Informationen zum Festlegen dieser Felder finden Sie unter Arm-Arbeitslast für die Bereitstellung vorbereiten.

  3. Stellen Sie das Container-Image für mehrere Architekturen mit 6 Replikaten bereit:

    $(cd k8s/overlays/multiarch && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1) 
    kubectl apply -k k8s/overlays/multiarch
    
  4. Warten Sie 10 Sekunden und prüfen Sie dann, ob alle Replikate der Anwendung ausgeführt werden:

    kubectl get pods -l="app=hello" -o wide
    

    Die Ausgabe sieht etwa so aus:

    NAME                                         READY   STATUS    RESTARTS   AGE   IP            NODE                                        NOMINATED NODE   READINESS GATES
    multiarch-hello-deployment-65bfd784d-5xrrr   1/1     Running   0          95s   10.100.1.5    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-7h94b   1/1     Running   0          95s   10.100.1.4    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-7qbkz   1/1     Running   0          95s   10.100.1.7    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-7wqb6   1/1     Running   0          95s   10.100.1.6    gke-my-cluster-arm-pool-e172cff7-shwc       <none>           <none>
    multiarch-hello-deployment-65bfd784d-h2g2k   1/1     Running   0          95s   10.100.0.19   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    multiarch-hello-deployment-65bfd784d-lc9dc   1/1     Running   0          95s   10.100.0.18   gke-my-cluster-default-pool-32019863-b41t   <none>           <none>
    

    Diese Ausgabe enthält eine NODE-Spalte, die angibt, dass die Pods sowohl auf den Knoten im Arm-Knotenpool als auch auf anderen Knoten im Standard-Knotenpool (x86) laufen.

  5. Führen Sie den folgenden Befehl aus, um auf den Dienst zuzugreifen und die Ausgabe zu sehen:

    for i in $(seq 1 6); do curl -w '\n' http://$external_ip; done
    

    Die Ausgabe sieht etwa so aus:

    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7qbkz, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:multiarch-hello-deployment-65bfd784d-lc9dc, CPU PLATFORM:linux/amd64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-5xrrr, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7wqb6, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7h94b, CPU PLATFORM:linux/arm64
    Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7wqb6, CPU PLATFORM:linux/arm64
    

    Sie sollten sehen, dass Pods, die auf Architekturplattformen ausgeführt werden, die Anfragen beantworten.

Sie haben ein Image für mehrere Architekturen erstellt und bereitgestellt, um eine Arbeitslast nahtlos über mehrere Architekturen auszuführen.

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.

Nachdem Sie die Anleitung abgeschlossen haben, können Sie die von Ihnen erstellten Ressourcen bereinigen, um die Kontingentnutzung zu reduzieren und die Abrechnungsgebühren zu stoppen. In den folgenden Abschnitten erfahren Sie, wie Sie diese Ressourcen löschen oder deaktivieren.

Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten durch Löschen des für die Anleitung erstellten Projekts.

So löschen Sie das Projekt:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Dienst, Cluster und Repository löschen

Wenn Sie nicht das gesamte Projekt löschen möchten, löschen Sie den Cluster und das Repository, das Sie für die Anleitung erstellt haben:

  1. Löschen Sie den Dienst der Anwendung mit kubectl delete:

    kubectl delete service hello-service
    

    Dieser Befehl löscht den Compute Engine-Load-Balancer, den Sie beim Freigeben der Bereitstellung erstellt haben.

  2. Löschen Sie den Cluster mit gcloud container clusters delete:

    gcloud container clusters delete $CLUSTER_NAME --zone $ZONE
    
  3. Löschen Sie das Repository:

    gcloud artifacts repositories delete docker-repo —location=us-central1 --async
    

Nächste Schritte