Migre a aplicação x86 no GKE para multi-arquitetura com Arm

Este tutorial descreve como migrar uma aplicação criada para nós que usam um processador x86 (Intel ou AMD) num cluster do Google Kubernetes Engine (GKE) para uma aplicação de várias arquiteturas (multi-arch) que é executada em nós x86 ou Arm. O público-alvo deste tutorial são os administradores da plataforma, os operadores de apps e os programadores de apps que querem executar as respetivas cargas de trabalho compatíveis com x86 existentes no Arm.

Com os clusters do GKE, pode executar cargas de trabalho em nós Arm através da série de máquinas C4A ou da série de máquinas Tau T2A. Este tutorial usa nós C4A que, tal como os nós T2A, podem ser executados no seu cluster do GKE, tal como qualquer outro nó que use processadores x86 (Intel ou AMD). Os nós C4a oferecem um desempenho consistentemente elevado baseado em Arm para as suas cargas de trabalho.

Para saber mais, consulte o artigo Prepare cargas de trabalho no GKE.

Este tutorial pressupõe que tem conhecimentos de Kubernetes e Docker. O tutorial usa o Google Kubernetes Engine e o Artifact Registry.

Objetivos

Neste tutorial, vai concluir as seguintes tarefas:

  • Armazene imagens de contentores com o Docker no Artifact Registry.
  • Implemente uma carga de trabalho compatível com x86 num cluster do GKE.
  • Recompile uma carga de trabalho compatível com x86 para ser executada no Arm.
  • Adicione um pool de nós Arm a um cluster existente.
  • Implemente uma carga de trabalho compatível com Arm para ser executada num nó Arm.
  • Crie uma imagem de várias arquiteturas para executar uma carga de trabalho em várias arquiteturas.
  • Execute cargas de trabalho em várias arquiteturas num cluster do GKE.

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

Siga estes passos para ativar a API Kubernetes Engine:
  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.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

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

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

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

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  8. Quando terminar este tutorial, pode evitar a faturação contínua eliminando os recursos que criou. Consulte a secção Limpar para ver mais detalhes.

Inicie o Cloud Shell

Neste tutorial, vai usar o Cloud Shell, que é um ambiente de shell para gerir recursos alojados no Google Cloud.

O Cloud Shell vem pré-instalado com a CLI Google Cloud e a ferramenta de linha de comandos kubectl. A CLI gcloud fornece a interface de linhas de comando principal para o Google Cloude o kubectl fornece a interface de linhas de comando principal para executar comandos em clusters do Kubernetes.

Inicie o Cloud Shell:

  1. Aceda à Google Cloud consola.

    Google Cloud consola

  2. No canto superior direito da consola, clique no botão Ativar Cloud Shell:

É apresentada uma sessão do Cloud Shell na consola. Use esta shell para executar os comandos gcloud e kubectl.

Prepare o seu ambiente

Nesta secção, prepara o seu ambiente para seguir o tutorial.

Defina as predefinições para a CLI gcloud

Defina variáveis de ambiente para o ID do projeto, a localização do Compute Engine para o cluster e o nome do novo cluster.

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

Substitua PROJECT_ID pelo ID do projeto que escolheu para este tutorial na secção Antes de começar.

Neste tutorial, cria recursos em us-central1-a. Para ver uma lista completa das localizações onde a série de máquinas C4A está disponível, consulte o artigo Regiões e zonas disponíveis.

Clone o repositório Git

  1. Clone o repositório:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  2. Altere o diretório de trabalho atual para o repositório clonado no passo anterior:

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

    Este repositório contém os ficheiros de que precisa para concluir este tutorial. Este tutorial usa implementações do Kubernetes. Uma implementação é um objeto da API Kubernetes que lhe permite executar várias réplicas de pods distribuídas entre os nós num cluster.

Crie um cluster do GKE e implemente a aplicação x86

Na primeira parte deste tutorial, cria um cluster com nós x86 e implementa uma aplicação x86. A aplicação de exemplo é um serviço que responde a pedidos HTTP. É criada com a linguagem de programação Golang.

Esta configuração representa o aspeto de um ambiente de cluster típico, com aplicações compatíveis com x86 e nós x86.

Crie um cluster do GKE

Primeiro, crie um GKE com nós com processadores x86. Com esta configuração, cria um ambiente de cluster típico para executar aplicações x86.

Crie o cluster:

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

Este cluster tem o dimensionamento automático desativado para demonstrar uma funcionalidade específica nos passos posteriores.

A criação do cluster pode demorar alguns minutos. A flag --async permite que esta operação seja executada em segundo plano enquanto conclui os passos seguintes.

Pode criar clusters apenas com nós Arm. No entanto, neste tutorial, vai criar primeiro um cluster apenas com nós x86 para saber mais sobre o processo de tornar as aplicações apenas x86 compatíveis com Arm.

Crie o repositório Docker do Artifact Registry

  1. Crie um repositório no Artifact Registry para armazenar imagens Docker:

    gcloud artifacts repositories create docker-repo \
          --repository-format=docker \
          --location=us-central1 \
          --description="Docker repository"
    
  2. Configure a ferramenta de linha de comandos do Docker para autenticar neste repositório no Artifact Registry:

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

Crie a imagem x86 e envie-a para o Artifact Registry

  1. Crie a versão da aplicação compatível com x86:

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1 . 
    
  2. Envie a imagem para o Artifact Registry:

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

Implemente a aplicação x86

  1. Verifique se o cluster está pronto executando o seguinte script:

    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
    

    Quando o cluster estiver pronto, o resultado deve ser semelhante ao seguinte:

    GKE Cluster 'my-cluster' is RUNNING
    
  2. Recupere as credenciais do cluster para que kubectl possa estabelecer ligação à API Kubernetes do cluster:

    gcloud container clusters get-credentials $CLUSTER_NAME --location $CONTROL_PLANE_LOCATION --project $PROJECT_ID
    
  3. Atualize a imagem com kustomize e implemente a aplicação 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. Implemente um serviço para expor a aplicação à Internet:

    kubectl apply -f k8s/hello-service.yaml
    
  5. Verifique se o endereço IP externo do serviço, hello-service, está totalmente 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
    

    Depois de o endereço IP externo ser aprovisionado, o resultado deve ser semelhante ao seguinte:

    External IP: 203.0.113.0
    
  6. Faça um pedido HTTP para testar se a implementação funciona conforme esperado:

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

    O resultado é semelhante ao seguinte:

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

    O resultado mostra que esta implementação compatível com x86 está a ser executada num nó no conjunto de nós predefinido na arquitetura amd64. Os nós no conjunto de nós predefinido do cluster têm processadores x86 (Intel ou AMD).

Adicione nós ARM ao cluster

Na parte seguinte deste tutorial, adicione nós Arm ao cluster existente. Estes nós são onde a versão compatível com Arm da sua aplicação é implementada quando é recompilada para ser executada no Arm.

Posto de controlo

Até agora, alcançou os seguintes objetivos:

  • criar um cluster do GKE com nós x86.
  • armazenar uma imagem de contentor compatível com x86 com o Docker no Artifact Registry.
  • Implementar uma carga de trabalho compatível com x86 num cluster do GKE.

Configurou um ambiente de cluster com nós x86 e uma carga de trabalho compatível com x86. Esta configuração é semelhante aos seus ambientes de cluster existentes se não usar atualmente nós Arm e cargas de trabalho compatíveis com Arm.

Adicione um conjunto de nós Arm ao seu cluster

Adicione um node pool Arm ao cluster existente:

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

O tipo de máquina c4a-standard-2 é uma VM Arm da série de máquinas C4A.

Crie um node pool com nós Arm da mesma forma que cria um node pool com nós x86. Depois de criar este conjunto de nós, terá nós x86 e nós Arm em execução neste cluster.

Para saber como adicionar pools de nós Arm a clusters existentes, consulte o artigo Adicione um pool de nós Arm a um cluster do GKE.

Aumentar a escala da aplicação existente em execução em nós baseados em x86

Os nós de vários tipos de arquitetura podem funcionar perfeitamente em conjunto num cluster. O GKE não agenda cargas de trabalho existentes em execução em nós x86 para nós Arm no cluster porque é colocado automaticamente um taint em nós Arm. Pode ver isto ao expandir a sua aplicação existente.

  1. Atualize a carga de trabalho, aumentando-a para 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. Aguarde 30 segundos e, de seguida, execute o seguinte comando para verificar o estado da implementação:

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

    O resultado deve ser semelhante ao seguinte:

    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
    

    Este resultado mostra os pods com o estado Pendente, uma vez que não existe espaço nos nós baseados em x86. Uma vez que o redimensionador automático de clusters está desativado e os nós Arm estão danificados, as cargas de trabalho não são implementadas em nenhum dos nós Arm disponíveis. Esta restrição impede o GKE de agendar cargas de trabalho x86 em nós Arm. Para implementar em nós Arm, tem de indicar que a implementação é compatível com nós Arm.

  3. Verifique os pods que estão no estado Running:

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

    O resultado deve ser semelhante ao seguinte:

    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>
    

    Nesta saída, a coluna NODE indica que todos os pods da implementação estão a ser executados apenas no conjunto predefinido, o que significa que os pods compatíveis com x86 só são agendados para os nós x86. O pod original que já estava agendado antes da criação do conjunto de nós ARM continua a ser executado no mesmo nó.

  4. Execute o seguinte comando para aceder ao serviço e ver o resultado:

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

    O resultado é semelhante ao seguinte:

    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
    

    Este resultado mostra que todos os pedidos de publicação de pods estão a ser executados em nós x86. Alguns Pods não conseguem responder porque ainda se encontram no estado pendente, uma vez que não existe espaço nos nós x86 existentes e não vão ser agendados para nós Arm.

Recompile a sua aplicação para ser executada em Arm

Na secção anterior, adicionou um conjunto de nós Arm ao cluster existente. No entanto, quando aumentou a escala da aplicação x86 existente, não agendou nenhuma das cargas de trabalho para os nós Arm. Nesta secção, recompila a sua aplicação para que seja compatível com a arquitetura Arm, de modo que esta aplicação possa ser executada nos nós Arm no cluster.

Para este exemplo, execute estes passos através do docker build. Esta abordagem de dois passos inclui:

  • Primeira fase: crie o código para o ARM.
  • Segunda fase: copie o ficheiro executável para um contentor simples.

Depois de seguir estes passos, terá uma imagem compatível com Arm, além da imagem compatível com x86.

O segundo passo de copiar o ficheiro executável para outro contentor segue uma das práticas recomendadas para criar um contentor, que consiste em criar a imagem mais pequena possível.

Este tutorial usa uma aplicação de exemplo criada com a linguagem de programação Golang. Com o Golang, pode compilar uma aplicação para diferentes sistemas operativos e plataformas de CPU fornecendo variáveis de ambiente, GOOS e GOARCH, respetivamente.

  1. Execute cat Dockerfile_arm para ver o ficheiro Docker 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
    

    O fragmento apresentado aqui mostra apenas a primeira fase. No ficheiro, ambas as fases estão incluídas.

    Neste ficheiro, a definição GOARCH=arm64 indica ao compilador Go que crie a aplicação para o conjunto de instruções Arm. Não precisa de definir GOOS porque a imagem base na primeira fase é uma imagem Linux Alpine.

  2. Crie o código para o Arm e envie-o para o 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
    

Implemente a versão Arm da sua aplicação

Agora que a aplicação está criada para ser executada em nós Arm, pode implementá-la nos nós Arm no seu cluster.

  1. Inspecione o add_arm_support.yaml executando o comando cat k8s/overlays/arm/add_arm_support.yaml:

    O resultado é semelhante ao seguinte:

       nodeSelector:
          kubernetes.io/arch: arm64
    

    Este nodeSelector especifica que a carga de trabalho deve ser executada apenas nos nós Arm. Quando usa o nodeSelector, o GKE adiciona uma tolerância que corresponde à mancha nos nós Arm, permitindo que o GKE agende a carga de trabalho nesses nós. Para saber como definir este campo, consulte o artigo Prepare uma carga de trabalho Arm para implementação.

  2. Implemente uma réplica da versão da aplicação compatível com 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. Aguarde 5 segundos e, em seguida, verifique se a implementação do ARM está a responder a pedidos curl:

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

    O resultado é semelhante ao seguinte:

    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 deve incluir respostas das aplicações compatíveis com x86 e Arm que respondem ao pedido curl.

Crie uma imagem de várias arquiteturas para executar uma carga de trabalho em várias arquiteturas

Embora possa usar a estratégia descrita na secção anterior e implementar cargas de trabalho separadas para x86 e Arm, isto exigiria que mantivesse e organizasse dois processos de compilação e duas imagens de contentores.

Idealmente, quer criar e executar a sua aplicação de forma integrada nas plataformas x86 e Arm. Recomendamos esta abordagem. Para executar a sua aplicação com um manifesto em várias plataformas de arquitetura, tem de usar imagens de várias arquiteturas. Para saber mais sobre imagens de várias arquiteturas, consulte o artigo Crie imagens de várias arquiteturas para cargas de trabalho Arm.

Para usar imagens de várias arquiteturas, tem de garantir que a sua aplicação cumpre os seguintes pré-requisitos:

  • A sua aplicação não tem dependências específicas da plataforma de arquitetura.
  • Todas as dependências têm de ser criadas para várias arquiteturas ou, no mínimo, para as plataformas segmentadas.

A aplicação de exemplo usada neste tutorial cumpre ambos os pré-requisitos. No entanto, recomendamos que teste as suas próprias aplicações quando criar as respetivas imagens de várias arquiteturas antes de as implementar para produção.

Crie e envie imagens de várias arquiteturas

Pode criar imagens multi-arquitetura com o Docker Buildx se a sua carga de trabalho cumprir os seguintes pré-requisitos:

  • A imagem base suporta várias arquiteturas. Para verificar isto, execute o comando docker manifest inspect na imagem base e verifique a lista de plataformas de arquitetura. Veja um exemplo de como inspecionar uma imagem no final desta secção.
  • A aplicação não requer passos de compilação especiais para cada plataforma de arquitetura. Se foram necessários passos especiais, o Buildx pode não ser suficiente. Tem de ter um Dockerfile separado para cada plataforma e criar o manifesto manualmente com docker manifest create.

A imagem base da aplicação de exemplo é o Alpine, que suporta várias arquiteturas. Também não existem passos específicos da plataforma de arquitetura, pelo que pode criar a imagem multi-arquitetura com o Buildx.

  1. Inspecione o ficheiro Docker executando o comando 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 duas fases: a fase de compilação e a fase de lançamento. Usar o mesmo Dockerfile usado para criar a aplicação x86.

  2. Execute o seguinte comando para criar e usar um novo criador de docker buildx:

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

    Agora que criou este novo criador, pode criar e enviar uma imagem compatível com linux/amd64 e linux/arm64 usando a flag --platform. Para cada plataforma fornecida com a flag, o Buildx cria uma imagem na plataforma de destino. Quando o Buildx cria a imagem linux/arm64, transfere arm64 imagens base. Na primeira fase, cria o ficheiro binário na imagem arm64 golang:1.18-alpine para arm64. Na segunda fase, a imagem do arm64 Alpine Linux é transferida e o ficheiro binário é copiado para uma camada dessa imagem.

  3. Crie e envie a imagem:

    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 .
    

    O resultado é semelhante ao seguinte:

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

    Este resultado mostra que são geradas duas imagens, uma para linux/arm64 e outra para linux/amd64.

  4. Inspeccione o manifesto da sua nova imagem de várias arquiteturas:

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

    O resultado é semelhante ao seguinte:

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

    Nesta saída, a secção manifests inclui dois manifestos, um com a arquitetura da plataforma amd64 e o outro com a arquitetura da plataforma arm64.

    Quando implementa esta imagem do contentor no seu cluster, o GKE transfere automaticamente apenas a imagem que corresponde à arquitetura do nó.

Implemente a versão multi-arquitetura da sua aplicação

  1. Antes de implementar a imagem de várias arquiteturas, elimine as cargas de trabalho originais:

    kubectl delete deploy x86-hello-deployment arm-hello-deployment
    
  2. Inspecione a sobreposição do add_multiarch_support.yaml kustomize executando o seguinte comando: cat k8s/overlays/multiarch/add_multiarch_support.yaml:

    A saída inclui o seguinte conjunto de tolerâncias:

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

    Esta tolerância permite que a carga de trabalho seja executada nos nós Arm no seu cluster, uma vez que a tolerância corresponde à restrição definida em todos os nós Arm. Como esta carga de trabalho pode agora ser executada em qualquer nó no cluster, apenas é necessária a tolerância. Com apenas a tolerância, o GKE pode agendar a carga de trabalho para nós x86 e Arm. Se quiser especificar onde o GKE pode agendar cargas de trabalho, use seletores de nós e regras de afinidade de nós. Para saber como definir estes campos, consulte o artigo Prepare uma carga de trabalho Arm para implementação.

  3. Implemente a imagem de contentor de várias arquiteturas com 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. Aguarde 10 segundos e, em seguida, confirme que todas as réplicas da aplicação estão em execução:

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

    O resultado é semelhante ao seguinte:

    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 inclui uma coluna NODE que indica que os pods estão a ser executados em ambos os nós no conjunto de nós Arm e outros no conjunto de nós predefinido (x86).

  5. Execute o seguinte comando para aceder ao serviço e ver o resultado:

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

    O resultado é semelhante ao seguinte:

    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
    

    Deve ver que os pods em execução em plataformas de arquitetura estão a responder aos pedidos.

Criou e implementou uma imagem de várias arquiteturas para executar perfeitamente uma carga de trabalho em várias arquiteturas.

Limpar

Para evitar incorrer em custos na sua conta do Google Cloud pelos recursos usados neste tutorial, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

Depois de concluir o tutorial, pode limpar os recursos que criou para reduzir a utilização da quota e parar as cobranças de faturação. As secções seguintes descrevem como eliminar ou desativar estes recursos.

Elimine o projeto

A forma mais fácil de eliminar a faturação é eliminar o projeto que criou para o tutorial.

Para eliminar o projeto:

  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.

Elimine o serviço, o cluster e o repositório

Se não quiser eliminar todo o projeto, elimine o cluster e o repositório que criou para o tutorial:

  1. Elimine o serviço da aplicação executando kubectl delete:

    kubectl delete service hello-service
    

    Este comando elimina o equilibrador de carga do Compute Engine que criou quando expôs a implementação.

  2. Elimine o cluster executando gcloud container clusters delete:

    gcloud container clusters delete $CLUSTER_NAME --location $CONTROL_PLANE_LOCATION
    
  3. Elimine o repositório:

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

O que se segue?