Migrer l'application x86 sur GKE vers multi-arch avec Arm


Ce tutoriel explique comment migrer une application créée pour les nœuds à l'aide d'un processeur x86 (Intel ou AMD) dans un cluster Google Kubernetes Engine (GKE) vers une application multi-architecture (multi-arch) exécutée sur l'un des x86 ou nœuds Arm. L'audience visée pour ce tutoriel est constituée des administrateurs de plate-forme, des opérateurs d'application et des développeurs d'applications qui souhaitent exécuter leurs charges de travail existantes compatibles x86 sur Arm.

Avec les clusters GKE, vous pouvez exécuter des charges de travail sur les nœuds Arm à l'aide de la série de machines Arm Tau T2A. Les nœuds T2A peuvent s'exécuter dans votre cluster GKE comme n'importe quel autre nœud utilisant des processeurs x86 (Intel ou AMD). Ils constituent un bon choix pour les charges de travail évolutives et intensives.

Pour en savoir plus, consultez la section Charges de travail Arm sur GKE.

Dans ce tutoriel, nous partons du principe que vous maîtrisez Kubernetes et Docker. Ce tutoriel utilise Google Kubernetes Engine et Artifact Registry.

Objectifs

Dans ce tutoriel, vous allez effectuer les tâches suivantes :

  • Stocker des images de conteneurs avec Docker dans Artifact Registry
  • Déployer une charge de travail compatible x86 sur un cluster GKE
  • Recompilez une charge de travail compatible x86 pour l'exécuter sur Arm.
  • Ajoutez un pool de nœuds Arm à un cluster existant.
  • Déployez une charge de travail compatible avec Arm pour une exécution sur un nœud Arm.
  • Créez une image multi-arch pour exécuter une charge de travail sur plusieurs architectures.
  • Exécutez des charges de travail sur plusieurs architectures dans un même cluster GKE.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

Pour activer l'API Kubernetes Engine, procédez comme suit :
  1. Connectez-vous à votre compte Google Cloud. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits gratuits pour exécuter, tester et déployer des charges de travail.
  2. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  4. Activer les API Artifact Registry and Google Kubernetes Engine.

    Activer les API

  5. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  6. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  7. Activer les API Artifact Registry and Google Kubernetes Engine.

    Activer les API

Une fois que vous avez terminé ce tutoriel, évitez de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir, plus, consultez la section Effectuer un nettoyage.

Lancer Cloud Shell

Dans ce tutoriel, vous allez utiliser Cloud Shell, un environnement shell permettant de gérer les ressources hébergées sur Google Cloud.

Cloud Shell est préinstallé avec Google Cloud CLI et l'outil de ligne de commande kubectl. gcloud CLI est l'interface de ligne de commande principale utilisée sur Google Cloud, et kubectl fournit l'interface de ligne de commande principale permettant d'exécuter des commandes sur les clusters Kubernetes.

Lancez Cloud Shell :

  1. Accédez à Google Cloud Console.

    Google Cloud Console

  2. Dans l'angle supérieur droit de la console, cliquez sur le bouton Activer Cloud Shell :

Une session Cloud Shell apparaît dans la console. Ce shell vous permet d'exécuter les commandes gcloud et kubectl.

Préparer votre environnement

Dans cette section, vous allez préparer votre environnement au tutoriel.

Configurez les paramètres par défaut de gcloud CLI

Définissez des variables d'environnement pour l'ID de votre projet, la zone et le nom de votre nouveau cluster.

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

Remplacez PROJECT_ID par l'ID de projet que vous avez choisi pour ce tutoriel dans la section Avant de commencer.

Dans ce tutoriel, vous allez créer des ressources dans us-central1-a. Pour obtenir la liste complète des zones où la série de machines Tau T2A est disponible, consultez la page Régions et zones disponibles.

Cloner le dépôt Git

Ce tutoriel utilise les ressources du dépôt GitHub Arm on GKE.

  1. Clonez le dépôt :

    git clone https://github.com/GoogleCloudPlatform/gke-arm
    
  2. Remplacez votre répertoire de travail actuel par gke-arm/migrate-x86-app-to-multi-arch/ à partir du dépôt cloné à l'étape précédente:

    cd gke-arm/migrate-x86-app-to-multi-arch/
    

Créer un cluster GKE et déployer l'application x86

Dans la première partie de ce tutoriel, vous allez créer un cluster avec des nœuds x86 et déployer une application x86. L'exemple d'application est un service qui répond aux requêtes HTTP. Il est conçu à l'aide du langage de programmation Golang.

Cette configuration représente un environnement de cluster type, avec des applications compatibles x86 et des nœuds x86.

Créer un cluster GKE

Tout d'abord, créez un cluster GKE à l'aide de nœuds avec des processeurs x86. Avec cette configuration, vous créez un environnement de cluster type pour exécuter des applications x86.

Créez le cluster :

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

L'autoscaling est désactivé sur ce cluster afin de démontrer des fonctionnalités spécifiques lors des étapes ultérieures.

La création du cluster peut prendre plusieurs minutes. L'option --async permet d'exécuter cette opération en arrière-plan pendant que vous effectuez les étapes suivantes.

Vous pouvez créer des clusters avec uniquement des nœuds Arm. Toutefois, dans le cadre de ce tutoriel, vous allez commencer par créer un cluster ne comportant que des nœuds x86 pour en savoir plus sur le processus permettant de rendre des applications x86 uniquement compatibles avec Arm.

Créer le dépôt Docker Artifact Registry

  1. Créez un dépôt dans Artifact Registry pour stocker les images Docker:

    gcloud artifacts repositories create docker-repo \
          --repository-format=docker \
          --location=us-central1 \
          --description="Docker repository"
    
  2. Configurez l'outil de ligne de commande Docker pour qu'il s'authentifie auprès de ce dépôt dans Artifact Registry:

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

Créer l'image x86 et la transférer vers Artifact Registry

  1. Créez la version compatible x86 de l'application:

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1 .
    
  2. Transférez l'image vers Artifact Registry :

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

Déployer l'application x86

  1. Vérifiez que le cluster est prêt en exécutant le script suivant:

    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
    

    Lorsque le cluster est prêt, le résultat doit ressembler à ce qui suit:

    GKE Cluster 'my-cluster' is RUNNING
    
  2. Récupérez les identifiants du cluster afin que kubectl puisse se connecter à l'API Kubernetes pour le cluster:

    gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID
    
  3. Mettez à jour l'image à l'aide de kustomize et déployez l'application x86:

    $(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. Déployez un service pour exposer l'application à Internet:

    kubectl apply -f k8s/hello-service.yaml
    
  5. Vérifiez que le provisionnement de l'adresse IP externe pour le service, hello-service, est terminé:

    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
    

    Une fois l'adresse IP externe provisionnée, le résultat doit ressembler à ce qui suit:

    External IP: 203.0.113.0
    
  6. Envoyez une requête HTTP pour vérifier que le déploiement fonctionne comme prévu:

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

    Le résultat ressemble à ce qui suit :

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

    Le résultat indique que ce déploiement compatible x86 est exécuté sur un nœud du pool de nœuds par défaut dans l'architecture amd64. Les nœuds du pool par défaut de votre cluster disposent de processeurs x86 (Intel ou AMD).

Ajouter des nœuds Arm au cluster

Dans la partie suivante de ce tutoriel, ajoutez des nœuds Arm à votre cluster existant. Ces nœuds se trouvent là où la version de l'application compatible avec Arm est déployée lorsqu'elle est recréée sur Arm.

Check Point

Jusqu'à présent, vous avez atteint les objectifs suivants:

  • Créer un cluster GKE avec des nœuds x86
  • stocker une image de conteneur compatible x86 avec Docker dans Artifact Registry.
  • Déployer une charge de travail compatible x86 sur un cluster GKE

Vous avez configuré un environnement de cluster avec des nœuds x86 et une charge de travail compatible x86. Cette configuration est semblable à vos environnements de cluster existants si vous n'utilisez pas actuellement de nœuds Arm et de charges de travail compatibles Arm.

Ajouter un pool de nœuds Arm à votre cluster

Ajoutez un pool de nœuds Arm à un cluster existant:

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

Le type de machine t2a-standard-2 est une VM Arm de la série de machines Tau T2A (version bêta).

Vous créez un pool de nœuds avec des nœuds Arm de la même manière qu'un pool de nœuds x86. Une fois ce pool de nœuds créé, vos nœuds x86 et Arm s'exécuteront dans ce cluster.

Pour en savoir plus sur l'ajout de pools de nœuds Arm à des clusters existants, consultez la page Ajouter un pool de nœuds Arm à un cluster GKE.

Effectuez un scaling à la hausse de l'application existante s'exécutant sur des nœuds x86

Les nœuds de plusieurs types d'architecture peuvent fonctionner en synergie dans un même cluster. GKE ne programme pas les charges de travail existantes exécutées sur les nœuds x86 vers des nœuds Arm dans le cluster, car un rejet est automatiquement placé sur les nœuds Arm. Vous pouvez le voir en effectuant un scaling à la hausse de votre application existante.

  1. Mettez à jour la charge de travail en la faisant évoluer jusqu'à six instances dupliquées:

    $(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. Patientez 30 secondes, puis exécutez la commande suivante pour vérifier l'état du déploiement:

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

    Le résultat doit ressembler à ce qui suit :

    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
    

    Ce résultat montre les pods avec un état "En attente", car il n'y a plus d'espace sur les nœuds basés sur x86. Étant donné que l'autoscaler de cluster est désactivé et que les nœuds Arm sont rejetés, les charges de travail ne seront déployées sur aucun des nœuds Arm disponibles. Ce rejet empêche GKE de planifier des charges de travail x86 sur des nœuds Arm. Pour un déploiement sur des nœuds Arm, vous devez indiquer que le déploiement est compatible avec les nœuds Arm.

  3. Vérifiez les pods qui sont en cours d'exécution:

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

    Le résultat doit ressembler à ce qui suit :

    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>
    

    Dans ce résultat, la colonne NODE indique que tous les pods du déploiement ne s'exécutent que dans le pool par défaut, ce qui signifie que les pods compatibles x86 ne sont programmés que sur les nœuds x86. Le pod d'origine précédemment programmé avant la création du pool de nœuds Arm s'exécute toujours sur le même nœud.

  4. Exécutez la commande suivante pour accéder au service et afficher le résultat:

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

    Le résultat ressemble à ce qui suit :

    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
    

    Ce résultat montre que tous les pods qui diffusent des requêtes s'exécutent sur des nœuds x86. Certains pods ne peuvent pas répondre, car ils sont toujours en attente, car il n'y a pas d'espace sur les nœuds x86 existants et ils ne seront pas programmés sur des nœuds Arm.

Recompilez l'application pour l'exécuter sur Arm

Dans la section précédente, vous avez ajouté un pool de nœuds Arm à votre cluster existant. Cependant, lorsque vous avez effectué un scaling à la hausse de l'application x86 existante, elle n'a programmé aucune charge de travail sur les nœuds Arm. Dans cette section, vous allez recompiler votre application pour qu'elle soit compatible avec Arm, afin que cette application puisse s'exécuter sur les nœuds Arm du cluster.

Pour cet exemple, effectuez ces étapes à l'aide de docker build. Cette approche en deux étapes comprend les étapes suivantes:

  • Première étape: compilez le code dans Arm.
  • Deuxième étape: copiez l'exécutable dans un conteneur allégé.

Après avoir suivi ces étapes, vous obtiendrez une image compatible avec Arm en plus de l'image compatible x86.

La deuxième étape de la copie de l'exécutable dans un autre conteneur est l'une des bonnes pratiques pour la création d'un conteneur, à savoir créer la plus petite image possible.

Ce tutoriel utilise un exemple d'application créé avec le langage de programmation Golang. Avec Golang, vous pouvez compiler de manière croisée une application vers différents systèmes d'exploitation et plates-formes de processeur en fournissant respectivement des variables d'environnement, GOOS et GOARCH.

  1. Exécutez la commande cat Dockerfile_arm pour afficher le fichier Dockerfile écrit pour Arm:

    #
    # 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
    

    L'extrait de code présenté ici montre uniquement la première étape. Dans le fichier, les deux étapes sont incluses.

    Dans ce fichier, le paramètre GOARCH=arm64 indique au compilateur Go de créer l'application pour l'ensemble d'instructions Arm. Vous n'avez pas besoin de définir GOOS, car l'image de base à la première étape est une image Linux Alpine.

  2. Créez le code pour Arm, puis transférez-le vers 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
    

Déployer la version Arm de votre application

Maintenant que l'application est conçue pour s'exécuter sur des nœuds Arm, vous pouvez la déployer sur les nœuds Arm de votre cluster.

  1. Inspectez le add_arm_support.yaml en exécutant la commande cat k8s/overlays/arm/add_arm_support.yaml:

    Le résultat ressemble à ce qui suit :

       nodeSelector:
          kubernetes.io/arch: arm64
    

    Cet élément nodeSelector spécifie que la charge de travail ne doit s'exécuter que sur les nœuds Arm. Lorsque vous utilisez nodeSelector, GKE ajoute une tolérance qui correspond au rejet sur les nœuds Arm, permettant ainsi à GKE de programmer la charge de travail sur ces nœuds. Pour en savoir plus sur la définition de ce champ, consultez la page Préparer une charge de travail Arm pour le déploiement.

  2. Déployez une instance dupliquée de la version de l'application compatible avec Arm:

    $(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. Attendez 5 secondes, puis vérifiez que le déploiement Arm répond aux requêtes curl:

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

    Le résultat ressemble à ce qui suit :

    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
    

    Ce résultat doit inclure les réponses des applications compatibles x86 et Arm qui répondent à la requête curl.

Créer une image multi-architecture pour exécuter une charge de travail sur plusieurs architectures

Bien que vous puissiez utiliser la stratégie décrite dans la section précédente et déployer des charges de travail distinctes pour x86 et Arm, vous devrez alors gérer et garder deux processus de compilation et deux images de conteneur.

Idéalement, vous souhaitez créer et exécuter votre application de manière fluide sur les plates-formes x86 et Arm. Nous recommandons cette approche. Pour exécuter votre application avec un fichier manifeste sur plusieurs plates-formes d'architecture, vous devez utiliser des images multi-architecture (multi-arch). Pour en savoir plus sur les images multi-architecture, consultez la page Créer des images multi-arch pour les charges de travail Arm.

Pour utiliser des images multi-architecture, vous devez vous assurer que votre application remplit les conditions préalables suivantes:

  • Votre application ne comporte aucune dépendance spécifique à une plate-forme d'architecture.
  • Toutes les dépendances doivent être conçues pour une multi-architecture ou, au minimum, les plates-formes ciblées.

L'exemple d'application utilisé dans ce tutoriel remplit ces deux conditions préalables. Toutefois, nous vous recommandons de tester vos propres applications lors de la création de leurs images multi-arch avant de les déployer en production.

Créer et transférer des images multi-architectures

Vous pouvez créer des images multi-arch avec Docker Buildx si votre charge de travail remplit les conditions préalables suivantes:

  • L'image de base accepte plusieurs architectures. Vérifiez cela en exécutant docker manifest inspect sur l'image de base et en vérifiant la liste des plates-formes d'architecture. Consultez un exemple d'inspection d'une image à la fin de cette section.
  • L'application ne nécessite pas d'étapes de compilation spéciales pour chaque plate-forme d'architecture. Si des étapes spéciales étaient nécessaires, Buildx peut ne pas être suffisant. Vous devez disposer d'un fichier Dockerfile distinct pour chaque plate-forme et créer le fichier manifeste manuellement avec docker manifest create.

L'image de base de l'exemple d'application est Alpine, qui accepte plusieurs architectures. Il n'existe pas non plus d'étapes spécifiques à une plate-forme d'architecture. Vous pouvez donc créer l'image multi-arch avec Buildx.

  1. Inspectez le fichier Dockerfile en exécutant 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" ]
    

    Ce fichier Dockerfile définit deux étapes: l'étape de compilation et l'étape de release. Vous allez utiliser le même fichier Dockerfile que celui utilisé pour créer l'application x86. Si vous suivez les bonnes pratiques pour la création de conteneurs, vous pourrez peut-être recréer vos propres images de conteneurs sans apporter aucune modification.

  2. Exécutez la commande suivante pour créer et utiliser un nouveau compilateur docker buildx:

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

    Maintenant que vous avez créé ce compilateur, vous pouvez créer et transférer une image compatible avec linux/amd64 et linux/arm64 à l'aide de l'option --platform. Pour chaque plate-forme fournie avec l'option, Buildx crée une image sur la plate-forme cible. Lorsque Buildx crée l'image linux/arm64, il télécharge les images de base arm64. Dans un premier temps, il crée le binaire sur l'image arm64 golang:1.18-alpine pour arm64. Ensuite, l'image Alpine Linux arm64 est téléchargée et le binaire est copié sur une couche de cette image.

  3. Créez et transférez l'image:

    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 .
    

    Le résultat ressemble à ce qui suit :

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

    Ce résultat montre que deux images sont générées, une pour linux/arm64 et une pour linux/amd64.

  4. Inspectez le fichier manifeste de votre nouvelle image multi-arch:

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

    Le résultat ressemble à ce qui suit :

    {
       "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"
             }
          }
       ]
    

    Dans ce résultat, la section manifests inclut deux fichiers manifestes, l'un avec l'architecture de la plate-forme amd64 et l'autre avec l'architecture de la plate-forme arm64.

    Lorsque vous déployez cette image de conteneur sur votre cluster, GKE ne télécharge automatiquement que l'image correspondant à l'architecture du nœud.

Déployer la version multi-arch de votre application

  1. Avant de déployer l'image multi-arch, supprimez les charges de travail d'origine:

    kubectl delete deploy x86-hello-deployment arm-hello-deployment
    
  2. Inspectez la superposition kustomize add_multiarch_support.yaml en exécutant cat k8s/overlays/multiarch/add_multiarch_support.yaml:

    Le résultat inclut l'ensemble de tolérances suivant:

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

    Cette tolérance permet à la charge de travail de s'exécuter sur les nœuds Arm de votre cluster, car elle correspond au rejet défini sur tous les nœuds Arm. Comme cette charge de travail peut maintenant être exécutée sur n'importe quel nœud du cluster, seule la tolérance est nécessaire. Avec la tolérance uniquement, GKE peut planifier la charge de travail sur les nœuds x86 et Arm. Si vous souhaitez spécifier où GKE peut planifier des charges de travail, utilisez des sélecteurs de nœuds et des règles d'affinité de nœuds. Pour en savoir plus sur la définition de ces champs, consultez la page Préparer une charge de travail Arm pour le déploiement.

  3. Déployez l'image de conteneur multi-arch avec six instances dupliquées:

    $(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. Attendez 10 secondes, puis vérifiez que toutes les instances dupliquées de l'application sont en cours d'exécution:

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

    Le résultat ressemble à ce qui suit :

    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>
    

    Cette sortie inclut une colonne NODE qui indique que les pods s'exécutent sur les deux nœuds du pool de nœuds Arm et d'autres dans le pool de nœuds par défaut (x86).

  5. Exécutez la commande suivante pour accéder au service et afficher le résultat:

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

    Le résultat ressemble à ce qui suit :

    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
    

    Vous devriez voir que les pods s'exécutant sur plusieurs plates-formes d'architecture répondent aux requêtes.

Vous avez créé et déployé une image multi-arch pour exécuter de manière fluide une charge de travail dans plusieurs architectures.

Effectuer un nettoyage

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Une fois le tutoriel terminé, vous pouvez nettoyer les ressources que vous avez créées afin de réduire l'utilisation du quota et d'arrêter les frais de facturation. Dans les sections suivantes, nous allons voir comment supprimer ou désactiver ces ressources.

Supprimer le projet

Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.

Pour supprimer le projet :

  1. Dans la console Google Cloud, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Supprimer le service, le cluster et le dépôt

Si vous ne souhaitez pas supprimer l'intégralité du projet, supprimez le cluster et le dépôt que vous avez créés pour le tutoriel:

  1. Supprimez l'objet Service de l'application en exécutant la commande kubectl delete :

    kubectl delete service hello-service
    

    Cette commande supprime l'équilibreur de charge Compute Engine que vous avez créé lorsque vous avez exposé le déploiement.

  2. Supprimez votre cluster en exécutant la commande gcloud container clusters delete :

    gcloud container clusters delete $CLUSTER_NAME --zone $ZONE
    
  3. Supprimez le dépôt :

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

Étapes suivantes