Migra la aplicación de x86 en GKE a multiarquitectura con Arm


En este instructivo, se describe cómo migrar una aplicación compilada para nodos mediante un procesador x86 (Intel o AMD) en un clúster de Google Kubernetes Engine (GKE) a una aplicación de varias arquitecturas (varios arcos) que se ejecuta en Nodos x86 o Arm. El público previsto para este instructivo son administradores de plataformas, operadores de apps y desarrolladores de apps que deseen ejecutar sus cargas de trabajo existentes compatibles con x86 en Arm.

Con los clústeres de GKE, puedes ejecutar cargas de trabajo en nodos Arm mediante la serie de máquina Tau T2A Arm. Los nodos T2A se pueden ejecutar en el clúster de GKE como cualquier otro nodo con procesadores x86 (Intel o AMD). Son una buena opción para cargas de trabajo de escalamiento horizontal y de procesamiento intensivo.

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

En este instructivo, suponemos que estás familiarizado con Kubernetes y Docker. Además, aquí usamos Google Kubernetes Engine y Artifact Registry.

Objetivos

En este instructivo, realizará las siguientes tareas:

  • Almacenar imágenes de contenedor con Docker en Artifact Registry
  • Implementar una carga de trabajo compatible con x86 en un clúster de GKE
  • Volver a compilar una carga de trabajo compatible con x86 para que se ejecute en Arm
  • Agrega un grupo de nodos Arm a un clúster existente.
  • Implementar una carga de trabajo compatible con Arm para que se ejecute en un nodo Arm
  • Compila una imagen multiarquitectura para ejecutar una carga de trabajo en varias arquitecturas.
  • Ejecutar cargas de trabajo en varias arquitecturas en un clúster de GKE

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

Sigue los pasos que se indican a continuación para habilitar la API de Kubernetes Engine:
  1. Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. Habilita las API de Artifact Registry and Google Kubernetes Engine.

    Habilita las API

  5. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  6. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  7. Habilita las API de Artifact Registry and Google Kubernetes Engine.

    Habilita las API

Cuando finalices este instructivo, puedes borrar los recursos creados para evitar que se te siga facturando. Consulta la sección Limpieza para obtener más detalles.

Inicia Cloud Shell

En este instructivo usarás Cloud Shell, que es un entorno de shell para administrar recursos alojados en Google Cloud.

Cloud Shell ya viene instalado en Google Cloud CLI y la herramienta de línea de comandos de kubectl. La CLI de gcloud proporciona la interfaz de línea de comandos principal para Google Cloud, y kubectl proporciona la interfaz de línea de comandos principal a fin de ejecutar comandos en clústeres de Kubernetes.

Iniciar Cloud Shell:

  1. Ve a la consola de Google Cloud.

    Consola de Google Cloud

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

Aparecerá una sesión de Cloud Shell dentro de la consola. Usa esta shell para ejecutar los comandos de gcloud y kubectl.

Prepare el entorno

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

Configura los ajustes predeterminados para la CLI de gcloud

Configura las variables de entorno del ID del proyecto, la zona y el nombre del clúster nuevo.

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

Reemplaza PROJECT_ID por el ID del proyecto que elegiste para este instructivo en la sección Antes de comenzar.

En este instructivo, crearás recursos en us-central1-a. Para ver una lista completa de los lugares donde está disponible la serie de máquinas Tau T2A, consulta Regiones y zonas disponibles.

Clona el repositorio git

En este instructivo, se usan recursos del repositorio de GitHub de Arm on GKE.

  1. Clone el repositorio:

    git clone https://github.com/GoogleCloudPlatform/gke-arm
    
  2. Cambia tu directorio de trabajo actual al gke-arm/migrate-x86-app-to-multi-arch/ desde el repositorio clonado en el paso anterior:

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

Crea un clúster de GKE e implementa la aplicación x86

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

Esta configuración representa cómo podría ser un entorno de clúster típico, mediante aplicaciones compatibles con x86 y nodos x86.

Cree un clúster de GKE

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

Crea el clúster:

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

Este clúster tiene inhabilitado el ajuste de escala automático a fin de demostrar una funcionalidad específica en los pasos posteriores.

La creación del clúster podría demorar varios minutos. La marca --async permite que esta operación se ejecute en segundo plano mientras completas los siguientes pasos.

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

Crea el repositorio de Artifact Registry Docker

  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 autenticar en este repositorio en Artifact Registry:

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

Compila la imagen x86 y envíala a Artifact Registry

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

    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
    

Implementa la aplicación de x86

  1. Ejecuta la siguiente secuencia de comandos para verificar que el clúster esté listo:

    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, el resultado debe ser similar al siguiente:

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

    gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID
    
  3. Actualiza la imagen mediante kustomize y, luego, implementa 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. Implementa un servicio para exponer la aplicación en Internet:

    kubectl apply -f k8s/hello-service.yaml
    
  5. Verifica que la dirección IP externa del servicio, hello-service, haya finalizado el aprovisionamiento:

    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
    

    Después de aprovisionar la dirección IP externa, el resultado debe ser similar al siguiente:

    External IP: 203.0.113.0
    
  6. Realiza una solicitud HTTP para probar que la implementación funcione como se espera:

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

    El resultado es similar a este:

    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 ejecuta 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 (ya sea Intel o AMD).

Agrega nodos Arm al clúster

En la siguiente parte de este instructivo, agrega nodos Arm a tu clúster existente. En estos nodos, se implementa la versión compatible con Arm de tu aplicación cuando se vuelve a compilar para ejecutarse en Arm.

Punto de control

Hasta ahora, alcanzaste los siguientes objetivos:

  • crear un clúster de GKE con nodos x86.
  • almacenar una imagen de contenedor compatible con x86 con Docker en Artifact Registry.
  • implementar una carga de trabajo compatible con x86 en un clúster de GKE.

Configuraste un entorno de clúster con nodos x86 y una carga de trabajo compatible con x86. Esta configuración es similar a tus entornos de clúster existentes si, por el momento, no usas nodos ni cargas de trabajo compatibles con Arm.

Agrega un grupo de nodos Arm a tu clúster

Agrega un grupo de nodos Arm a tu clúster existente:

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

El tipo de máquina t2a-standard-2 es una VM de Arm de la serie de máquinas Tau T2A (vista previa).

Puedes crear un grupo de nodos con nodos Arm de la misma manera que cuando creas un grupo de nodos con nodos x86. Después de crear este grupo de nodos, tendrás nodos x86 y Arm en ejecución en este clúster.

Para obtener más información sobre cómo agregar grupos de nodos Arm a clústeres existentes, consulta Agrega un grupo de nodos ARM a un clúster de GKE.

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

Los nodos de varios tipos de arquitectura pueden funcionar sin problemas en un clúster. GKE no programa cargas de trabajo existentes que se ejecutan en nodos x86 para nodos Arm en el clúster porque se coloca un taint de forma automática en los nodos Arm. Puedes ver esto mediante el escalamiento vertical de tu aplicación existente.

  1. Actualiza la carga de trabajo y escala hasta 6 réplicas:

    $(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, luego, ejecuta el siguiente comando para verificar el estado de la implementación:

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

    El resultado debería ser similar al 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 esta salida, se muestran los pods con un estado pendiente, ya que no queda espacio en los nodos basados en x86. Dado que el escalador automático del clúster está inhabilitado y los nodos Arm tienen taints, las cargas de trabajo no se implementarán en ninguno de los nodos Arm disponibles. Este taint evita que GKE programe las cargas de trabajo x86 en nodos Arm. Para implementar en nodos Arm, debes indicar que la implementación es compatible con nodos Arm.

  3. Verifica los Pods que estén en el estado En ejecución:

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

    El resultado debería ser similar al 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 están programados en los nodos x86. El Pod original que ya se programó antes de la creación del grupo de nodos Arm aún se ejecuta 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 es similar a este:

    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 entregan solicitudes se ejecutan en nodos x86. Algunos Pods no pueden responder porque aún están en estado Pendiente, ya que no hay espacio en los nodos x86 existentes y no se programarán en nodos Arm.

Vuelve a compilar la aplicación para que se ejecute en Arm

En la sección anterior, agregaste un grupo de nodos Arm a tu clúster existente. Sin embargo, cuando escalaste verticalmente la aplicación x86 existente, no programaron 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 a fin de que esta aplicación se pueda ejecutar en los nodos Arm del clúster.

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

  • Primera etapa: Compila el código para Arm.
  • Segunda etapa: Copia el archivo ejecutable en un contenedor optimizado.

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

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

En este instructivo, se usa una aplicación de ejemplo compilada con el lenguaje de programación Golang. Con Golang, puedes compilar de forma cruzada una aplicación en diferentes sistemas operativos y plataformas de CPU si proporcionas variables de entorno, GOOS y GOARCH respectivamente.

  1. Ejecuta cat Dockerfile_arm a fin de 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 muestra la primera etapa. En el archivo, se incluyen ambas etapas.

    En este archivo, la configuración de GOARCH=arm64 le indica al compilador de Go que compile la aplicación para el conjunto de instrucciones de Arm. No es necesario que configures GOOS porque la imagen base en la primera etapa 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
    

Implementa la versión de Arm de tu aplicación

Ahora que la aplicación está compilada para ejecutarse en nodos Arm, puedes implementarla en los nodos de Arm en tu clúster.

  1. Ejecuta cat k8s/overlays/arm/add_arm_support.yaml para inspeccionar add_arm_support.yaml:

    El resultado es similar a este:

       nodeSelector:
          kubernetes.io/arch: arm64
    

    Este nodeSelector especifica que la carga de trabajo se debe ejecutar solo en los nodos Arm. Cuando usas nodeSelector, GKE agrega una tolerancia que coincide con el taint en los nodos Arm, lo que permite que GKE programe la carga de trabajo en esos nodos. A fin de obtener más información sobre cómo configurar este campo, consulta Prepara una carga de trabajo de Arm para la implementación.

  2. Implementa una réplica de la versión compatible con Arm de la aplicación:

    $(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 verifica 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 es similar a este:

    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 respuestas de las aplicaciones compatibles con x86 y Arm que responden a la solicitud curl.

Compila una imagen de varias arquitecturas para ejecutar una carga de trabajo entre arquitecturas

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

Lo ideal es que compiles y ejecutes tu aplicación sin problemas en las plataformas x86 y Arm. Recomendamos usar este método. Para ejecutar tu aplicación con un manifiesto en varias plataformas de arquitectura, debes usar imágenes de varias arquitecturas (varios arcos). A fin de obtener más información sobre las imágenes de varias arquitecturas, consulta Compila imágenes de varios arcos para las cargas de trabajo de Arm.

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

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

La aplicación de ejemplo que se usa en este instructivo cumple con estos dos requisitos. Sin embargo, te recomendamos probar tus propias aplicaciones cuando compiles sus imágenes de varios arcos antes de implementarlas en la producción.

Compila y envía imágenes de varias arquitecturas

Puedes compilar imágenes multiarquitectura con Docker Buildx si la carga de trabajo cumple con los siguientes requisitos previos:

  • La imagen base admite varias arquitecturas. Para ello, ejecuta docker manifest inspect en la imagen base y verifica la lista de plataformas de arquitectura. Consulta un ejemplo de cómo inspeccionar una imagen al final de esta sección.
  • 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. Deberás tener un Dockerfile independiente para cada plataforma y crear el manifiesto de forma manual 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 varios arcos con Buildx.

  1. Ejecuta cat Dockerfile para inspeccionar el 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 etapas: la etapa de compilación y la etapa de lanzamiento. Usa el mismo Dockerfile que se usa para compilar la aplicación x86. Si sigues las prácticas recomendadas para compilar contenedores, es posible que puedas volver a compilar tus propias imágenes de contenedor sin realizar cambios.

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

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

    Ahora que creaste este compilador nuevo, puedes compilar y enviar una imagen compatible con linux/amd64 y linux/arm64 mediante la marca --platform. Para cada plataforma proporcionada con la marca, Buildx compila una imagen en la plataforma de destino. Cuando Buildx compila la imagen linux/arm64, descarga arm64 imágenes base. En la primera, compila el objeto binario en la imagen arm64 golang:1.18-alpine para arm64. En la segunda, se descarga la imagen arm64 de Alpine Linux y se copia el objeto binario en una capa de esa imagen.

  3. Compila 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 es similar a este:

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

    En este resultado, se muestra que se generan dos imágenes, una para linux/arm64 y otra para linux/amd64.

  4. Inspecciona el manifiesto de tu nueva imagen multiarquitectura:

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

    El resultado es similar a este:

    {
       "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 el otro con la arquitectura de la plataforma arm64.

    Cuando implementas esta imagen de contenedor en tu clúster, GKE descarga de forma automática solo la imagen que coincide con la arquitectura del nodo.

Implementa la versión multiarquitectura de tu aplicación

  1. Antes de implementar la imagen multiarquitectura, borra las cargas de trabajo originales:

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

    El resultado 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 la tolerancia coincide con el taint configurado 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. Solo con la tolerancia, GKE puede programar la carga de trabajo en los nodos x86 y Arm. Si deseas especificar dónde GKE puede programar las cargas de trabajo, usa selectores de nodo y reglas de afinidad de nodos. A fin de obtener más información sobre cómo configurar estos campos, consulta Prepara una carga de trabajo de Arm para la implementación.

  3. Implementa la imagen de contenedor multiarquitectura 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, luego, confirma que todas las réplicas de la aplicación estén en ejecución:

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

    El resultado es similar a este:

    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, en la que se indica que los pods se ejecutan en ambos nodos, unos en el grupo de nodos Arm y otros en el 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 es similar a este:

    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 las plataformas de arquitectura responden las solicitudes.

Compilaste e implementaste una imagen multiarquitectura para ejecutar sin problemas una carga de trabajo en varias arquitecturas.

Realiza una limpieza

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Una vez que completes el instructivo, podrás limpiar los recursos que creaste para reducir el uso de la cuota y detener los cargos de facturación. En las siguientes secciones, se describe cómo borrar o desactivar estos recursos.

Borra el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

Para borrar el proyecto, haga lo siguiente:

  1. En la consola de Google Cloud, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Borra el servicio, el clúster y el repositorio

Si no deseas borrar todo el proyecto, borra el clúster y el repositorio que creaste para el instructivo:

  1. Borra el Service de la aplicación mediante la ejecución de kubectl delete:

    kubectl delete service hello-service
    

    Este comando borra el balanceador de cargas de Compute Engine que creaste al momento de exponer la implementación.

  2. Si deseas borrar tu clúster, ejecuta gcloud container clusters delete:

    gcloud container clusters delete $CLUSTER_NAME --zone $ZONE
    
  3. Borra el repositorio:

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

¿Qué sigue?