Migrar una aplicación x86 en GKE a una multiarquitectura con Arm

En este tutorial se describe cómo migrar una aplicación creada para nodos que usan un procesador x86 (Intel o AMD) en un clúster de Google Kubernetes Engine (GKE) a una aplicación de arquitectura múltiple (multi-arch) que se ejecuta en nodos x86 o Arm. Este tutorial está dirigido a administradores de plataformas, operadores de aplicaciones y desarrolladores de aplicaciones que quieran ejecutar sus cargas de trabajo compatibles con x86 en Arm.

Con los clústeres de GKE, puedes ejecutar cargas de trabajo en nodos Arm con la serie de máquinas C4A o la serie de máquinas Tau T2A. En este tutorial se usan nodos C4A que, al igual que los nodos T2A, se pueden ejecutar en tu clúster de GKE como cualquier otro nodo que use procesadores x86 (Intel o AMD). Los nodos C4A proporcionan un rendimiento alto y constante basado en Arm para tus cargas de trabajo.

Para obtener más información, consulta Cargas de trabajo de Arm en GKE.

En este tutorial se da por hecho que tienes conocimientos de Kubernetes y Docker. En el tutorial se usan Google Kubernetes Engine y Artifact Registry.

Abrir Cloud Shell

En este tutorial, usarás Cloud Shell, un entorno de shell para gestionar recursos alojados enGoogle Cloud.

Cloud Shell tiene preinstaladas la CLI de Google Cloud y la herramienta de línea de comandos kubectl. La CLI de gcloud proporciona la interfaz de línea de comandos principal de Google Cloud, y kubectl proporciona la interfaz de línea de comandos principal para ejecutar comandos en clústeres de Kubernetes.

Abre Cloud Shell:

  1. Ve a la Google Cloud consola.

    Google Cloud console

  2. En la esquina superior derecha de la consola, haz clic en el botón Activar Cloud Shell:

Se abrirá una sesión de Cloud Shell en la consola. Esta shell se usa para ejecutar comandos gcloud y kubectl.

Prepara tu entorno

En esta sección, prepararás el entorno para seguir el tutorial.

Definir la configuración predeterminada de gcloud CLI

Define las variables de entorno del ID de tu proyecto, la ubicación de Compute Engine de tu clúster y el nombre de tu nuevo clúster.

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

Sustituye PROJECT_ID por el ID del proyecto que has elegido para este tutorial en la sección Antes de empezar.

En este tutorial, creará recursos en us-central1-a. Para ver una lista completa de las regiones y zonas en las que está disponible la serie de máquinas C4A, consulta Regiones y zonas disponibles.

Clona el repositorio de Git

  1. Clona el repositorio:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  2. Cambia el directorio de trabajo actual por el repositorio clonado en el paso anterior:

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

    Este repositorio contiene los archivos que necesitas para completar este tutorial. En este tutorial se usan implementaciones de Kubernetes. Un Deployment es un objeto de la API de Kubernetes que te permite ejecutar varias réplicas de pods distribuidas entre los nodos de un clúster.

Crear un clúster de GKE y desplegar la aplicación x86

En la primera parte de este tutorial, crearás un clúster con nodos x86 y desplegarás una aplicación x86. La aplicación de ejemplo es un servicio que responde a solicitudes HTTP. Se ha creado con el lenguaje de programación Golang.

Esta configuración representa el aspecto de un entorno de clúster típico, con aplicaciones compatibles con x86 y nodos x86.

Crear un clúster de GKE

Primero, crea un clúster de GKE con nodos que tengan procesadores x86. Con esta configuración, se crea un entorno de clúster típico para ejecutar aplicaciones x86.

Crea el clúster:

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

Este clúster tiene el autoescalado inhabilitado para mostrar una función específica en pasos posteriores.

El proceso de creación del clúster puede tardar varios minutos. La marca --async permite que esta operación se ejecute en segundo plano mientras completas los pasos siguientes.

Puedes crear clústeres solo con nodos Arm, pero en este tutorial primero crearás un clúster solo con nodos x86 para aprender cómo hacer que las aplicaciones solo para x86 sean compatibles con Arm.

Crear el repositorio de Docker de Artifact Registry

  1. Crea un repositorio en Artifact Registry para almacenar imágenes de Docker:

    gcloud artifacts repositories create docker-repo \
          --repository-format=docker \
          --location=us-central1 \
          --description="Docker repository"
    
  2. Configura la herramienta de línea de comandos de Docker para autenticarte en este repositorio de Artifact Registry:

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

Crea la imagen x86 y envíala a Artifact Registry

  1. Compila la versión compatible con x86 de la aplicación:

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1 . 
    
  2. Envía la imagen a Artifact Registry:

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

Desplegar la aplicación x86

  1. Para comprobar que el clúster está listo, ejecuta la siguiente secuencia de comandos:

    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
    

    Cuando el clúster esté listo, la salida debería ser similar a la siguiente:

    GKE Cluster 'my-cluster' is RUNNING
    
  2. Obtén las credenciales del clúster para que kubectl pueda conectarse a la API de Kubernetes del clúster:

    gcloud container clusters get-credentials $CLUSTER_NAME --location $CONTROL_PLANE_LOCATION --project $PROJECT_ID
    
  3. Actualiza la imagen con kustomize y despliega la aplicación 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. Despliega un servicio para exponer la aplicación a Internet:

    kubectl apply -f k8s/hello-service.yaml
    
  5. Comprueba que la dirección IP externa del servicio hello-service se haya aprovisionado:

    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
    

    Una vez aprovisionada la dirección IP externa, la salida debería ser similar a la siguiente:

    External IP: 203.0.113.0
    
  6. Envía una solicitud HTTP para comprobar que la implementación funciona correctamente:

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

    El resultado debería ser similar al siguiente:

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

    El resultado muestra que esta implementación compatible con x86 se está ejecutando en un nodo del grupo de nodos predeterminado en la arquitectura amd64. Los nodos del grupo de nodos predeterminado de tu clúster tienen procesadores x86 (Intel o AMD).

Añadir nodos Arm al clúster

En la siguiente parte de este tutorial, añade nodos Arm al clúster. Estos nodos son donde se implementa la versión compatible con Arm de tu aplicación cuando se vuelve a compilar para ejecutarse en Arm.

Check Point

Hasta ahora, has conseguido los siguientes objetivos:

  • Crea un clúster de GKE con nodos x86.
  • Almacenar una imagen de contenedor compatible con x86 con Docker en Artifact Registry.
  • Desplegar una carga de trabajo compatible con x86 en un clúster de GKE.

Has configurado un entorno de clúster con nodos x86 y una carga de trabajo compatible con x86. Esta configuración es similar a los entornos de clústeres que ya tengas si no usas nodos Arm ni cargas de trabajo compatibles con Arm.

Añadir un grupo de nodos Arm a un clúster

Añade un grupo de nodos Arm al clúster:

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

El c4a-standard-2 tipo de máquina es una VM Arm de la serie de máquinas C4A.

Puedes crear un grupo de nodos con nodos Arm de la misma forma que creas un grupo de nodos con nodos x86. Una vez creado este grupo de nodos, tendrás nodos x86 y nodos Arm ejecutándose en este clúster.

Para obtener más información sobre cómo añadir grupos de nodos Arm a clústeres, consulta Añadir un grupo de nodos Arm a un clúster de GKE.

Escalar verticalmente la aplicación que se ejecuta en nodos basados en x86

Los nodos de varios tipos de arquitectura pueden funcionar conjuntamente sin problemas en un mismo clúster. GKE no programa las cargas de trabajo que se ejecutan en nodos x86 en nodos Arm del clúster porque se coloca automáticamente un taint en los nodos Arm. Para comprobarlo, escala tu aplicación.

  1. Actualiza la carga de trabajo y aumenta el número de réplicas a 6:

    $(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. Espera 30 segundos y, a continuación, ejecuta el siguiente comando para comprobar el estado de la implementación:

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

    La salida debería ser similar a la siguiente:

    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
    

    En este resultado se muestran pods con el estado Pending, ya que no queda espacio en los nodos basados en x86. Como la herramienta de adaptación dinámica de clústeres está inhabilitada y los nodos Arm están contaminados, las cargas de trabajo no se desplegarán en ninguno de los nodos Arm disponibles. Este taint impide que GKE programe cargas de trabajo de x86 en nodos Arm. Para implementar en nodos Arm, debes indicar que la implementación es compatible con nodos Arm.

  3. Comprueba los pods que están en el estado Running:

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

    La salida debería ser similar a la siguiente:

    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>
    

    En este resultado, la columna NODE indica que todos los pods de la implementación se ejecutan solo en el grupo predeterminado, lo que significa que los pods compatibles con x86 solo se programan en los nodos x86. El pod original que ya se había programado antes de crear el grupo de nodos Arm sigue ejecutándose en el mismo nodo.

  4. Ejecuta el siguiente comando para acceder al servicio y ver el resultado:

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

    El resultado debería ser similar al siguiente:

    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
    

    En este resultado se muestra que todos los pods que sirven solicitudes se ejecutan en nodos x86. Algunos pods no pueden responder porque siguen en el estado Pending, ya que no hay espacio en los nodos x86 actuales y no se programarán en los nodos Arm.

Recompila tu aplicación para que se ejecute en Arm

En la sección anterior, has añadido un grupo de nodos Arm a tu clúster. Sin embargo, cuando ampliaste la aplicación x86, no se programó ninguna de las cargas de trabajo en los nodos Arm. En esta sección, volverás a compilar la aplicación para que sea compatible con Arm, de modo que pueda ejecutarse en los nodos Arm del clúster.

En este ejemplo, sigue estos pasos con docker build. Este enfoque de dos pasos incluye lo siguiente:

  • Primera fase: compila el código para Arm.
  • Segunda fase: copia el archivo ejecutable en un contenedor ligero.

Después de seguir estos pasos, tendrás una imagen compatible con Arm además de la imagen compatible con x86.

El segundo paso, que consiste en copiar el archivo ejecutable en otro contenedor, sigue una de las prácticas recomendadas para crear un contenedor, que es crear la imagen más pequeña posible.

En este tutorial se usa una aplicación de ejemplo creada con el lenguaje de programación Go. Con Golang, puedes compilar una aplicación para diferentes sistemas operativos y plataformas de CPU proporcionando variables de entorno, GOOS y GOARCH, respectivamente.

  1. Ejecuta cat Dockerfile_arm para ver el Dockerfile escrito para 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
    

    El fragmento que se muestra aquí solo incluye la primera fase. En el archivo se incluyen ambas fases.

    En este archivo, el ajuste GOARCH=arm64 indica al compilador de Go que compile la aplicación para el conjunto de instrucciones Arm. No es necesario definir GOOS porque la imagen base de la primera fase es una imagen de Linux Alpine.

  2. Compila el código para Arm y envíalo a 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
    

Desplegar la versión Arm de tu aplicación

Ahora que la aplicación se ha compilado para ejecutarse en nodos Arm, puedes desplegarla en los nodos Arm de tu clúster.

  1. Inspecciona el add_arm_support.yaml ejecutando cat k8s/overlays/arm/add_arm_support.yaml:

    El resultado debería ser similar al siguiente:

       nodeSelector:
          kubernetes.io/arch: arm64
    

    Este nodeSelector especifica que la carga de trabajo solo debe ejecutarse en los nodos Arm. Cuando usas nodeSelector, GKE añade una tolerancia que coincide con el taint de los nodos Arm, lo que permite a GKE programar la carga de trabajo en esos nodos. Para obtener más información sobre cómo definir este campo, consulta Prepara una carga de trabajo de Arm para el despliegue.

  2. Despliega una réplica de la versión de la aplicación compatible con 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. Espera 5 segundos y comprueba que la implementación de ARM responda a las solicitudes curl:

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

    El resultado debería ser similar al siguiente:

    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
    

    Este resultado debe incluir las respuestas de las aplicaciones compatibles con x86 y Arm a la solicitud curl.

Crear una imagen multiarquitectura para ejecutar una carga de trabajo en varias arquitecturas

Aunque puedes usar la estrategia descrita en la sección anterior e implementar cargas de trabajo independientes para x86 y Arm, esto requeriría que mantuvieras y organizaras dos procesos de compilación y dos imágenes de contenedor.

Lo ideal es que puedas compilar y ejecutar tu aplicación sin problemas en las plataformas x86 y Arm. Te recomendamos que sigas este procedimiento. Para ejecutar tu aplicación con un manifiesto en varias plataformas de arquitectura, debes usar imágenes de varias arquitecturas. Para obtener más información sobre las imágenes de varias arquitecturas, consulta el artículo Crear imágenes de varias arquitecturas para cargas de trabajo de Arm.

Para usar imágenes de varias arquitecturas, debes asegurarte de que tu aplicación cumpla los siguientes requisitos previos:

  • Tu aplicación no tiene ninguna dependencia específica de la plataforma de arquitectura.
  • Todas las dependencias deben compilarse para varias arquitecturas o, como mínimo, para las plataformas de destino.

La aplicación de ejemplo que se usa en este tutorial cumple ambos requisitos. Sin embargo, te recomendamos que pruebes tus propias aplicaciones al crear sus imágenes de varias arquitecturas antes de implementarlas en producción.

Crear y enviar imágenes multiarquitectura

Puedes crear imágenes de varias arquitecturas con Docker Buildx si tu carga de trabajo cumple los siguientes requisitos:

  • La imagen base admite varias arquitecturas. Para comprobarlo, ejecuta docker manifest inspect en la imagen base y consulta la lista de plataformas de arquitectura. Al final de esta sección se muestra un ejemplo de cómo inspeccionar una imagen.
  • La aplicación no requiere pasos de compilación especiales para cada plataforma de arquitectura. Si se requieren pasos especiales, es posible que Buildx no sea suficiente. Tendrías que tener un Dockerfile independiente para cada plataforma y crear el manifiesto manualmente con docker manifest create.

La imagen base de la aplicación de ejemplo es Alpine, que admite varias arquitecturas. Tampoco hay pasos específicos de la plataforma de arquitectura, por lo que puedes compilar la imagen de varias arquitecturas con Buildx.

  1. Inspecciona el Dockerfile ejecutando 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" ]
    

    Este Dockerfile define dos fases: la de compilación y la de lanzamiento. Usa el mismo Dockerfile que se ha usado para compilar la aplicación x86.

  2. Ejecuta el siguiente comando para crear y usar un nuevo generador de docker buildx:

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

    Ahora que has creado este nuevo compilador, puedes compilar e insertar una imagen que sea compatible con linux/amd64 y linux/arm64 usando la marca --platform. Por cada plataforma proporcionada con la marca, Buildx crea una imagen en la plataforma de destino. Cuando Buildx crea la imagen linux/arm64, descarga arm64 imágenes base. En la primera fase, se compila el archivo binario en la imagen arm64 golang:1.18-alpine para arm64. En la segunda fase, se descarga la imagen de arm64 Alpine Linux y se copia el archivo binario en una capa de esa imagen.

  3. Crea y envía la imagen:

    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 .
    

    El resultado debería ser similar al siguiente:

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

    En este resultado se muestran dos imágenes generadas, una para linux/arm64 y otra para linux/amd64.

  4. Inspecciona el manifiesto de tu nueva imagen de varias arquitecturas:

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

    El resultado debería ser similar al siguiente:

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

    En este resultado, la sección manifests incluye dos manifiestos: uno con la arquitectura de la plataforma amd64 y otro con la arquitectura de la plataforma arm64.

    Cuando despliegues esta imagen de contenedor en tu clúster, GKE descargará automáticamente solo la imagen que coincida con la arquitectura del nodo.

Desplegar la versión multiarquitectura de tu aplicación

  1. Antes de implementar la imagen de varias arquitecturas, elimina las cargas de trabajo originales:

    kubectl delete deploy x86-hello-deployment arm-hello-deployment
    
  2. Inspecciona la superposición de add_multiarch_support.yaml kustomize ejecutando cat k8s/overlays/multiarch/add_multiarch_support.yaml:

    La salida incluye el siguiente conjunto de tolerancias:

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

    Esta tolerancia permite que la carga de trabajo se ejecute en los nodos Arm de tu clúster, ya que coincide con la intolerancia definida en todos los nodos Arm. Como esta carga de trabajo ahora se puede ejecutar en cualquier nodo del clúster, solo se necesita la tolerancia. Con solo la tolerancia, GKE puede programar la carga de trabajo en nodos x86 y Arm. Si quieres especificar dónde puede programar cargas de trabajo GKE, usa selectores de nodos y reglas de afinidad de nodos. Para obtener más información sobre cómo configurar estos campos, consulta Prepara una carga de trabajo de Arm para el despliegue.

  3. Despliega la imagen de contenedor de varias arquitecturas con 6 réplicas:

    $(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. Espera 10 segundos y, a continuación, confirma que todas las réplicas de la aplicación se están ejecutando:

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

    El resultado debería ser similar al siguiente:

    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>
    

    Este resultado incluye una columna NODE que indica que los pods se están ejecutando en ambos nodos del grupo de nodos Arm y en otros del grupo de nodos predeterminado (x86).

  5. Ejecuta el siguiente comando para acceder al servicio y ver el resultado:

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

    El resultado debería ser similar al siguiente:

    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
    

    Deberías ver que los pods que se ejecutan en plataformas de arquitectura responden a las solicitudes.

Has creado y desplegado una imagen de varias arquitecturas para ejecutar una carga de trabajo en varias arquitecturas sin problemas.