Migrar um aplicativo x86 no GKE para várias arquiteturas com Arm


Neste tutorial, descrevemos como migrar um aplicativo criado para nós usando um processador x86 (Intel ou AMD) em um cluster do Google Kubernetes Engine (GKE) para um aplicativo de várias arquiteturas (multiarquiteturas) executado em nós x86 ou Arm. O público-alvo deste tutorial são administradores de plataforma, operadores de apps e desenvolvedores de apps que querem executar cargas de trabalho atuais compatíveis com x86 em Arm.

Com os clusters do GKE, é possível executar cargas de trabalho em nós Arm usando a série de máquinas Arm Tau T2A. Os nós T2A podem ser executados no cluster do GKE como qualquer outro nó usando processadores x86 (Intel ou AMD). Eles são uma boa opção para cargas de trabalho de escalonamento horizontal e computação intensiva.

Para saber mais, consulte Cargas de trabalho em Arm no GKE.

Neste tutorial, presumimos que você tenha familiaridade com o Kubernetes e o Docker. O tutorial usa o Google Kubernetes Engine e o Artifact Registry.

Objetivos

Neste tutorial, você realizará as seguintes tarefas:

  • Armazenar imagens de contêiner com o Docker no Artifact Registry.
  • Implantar uma carga de trabalho compatível com x86 em um cluster do GKE.
  • Recriar uma carga de trabalho compatível com x86 para ser executada em Arm.
  • Adicionar um pool de nós Arm a um cluster atual.
  • Implantar uma carga de trabalho compatível com Arm em execução em um nó Arm.
  • Criar uma imagem de várias arquiteturas para executar uma carga de trabalho entre várias arquiteturas.
  • Executar cargas de trabalho entre várias arquiteturas em um só cluster do GKE.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Antes de começar

Siga estas etapas para ativar a API do Kubernetes Engine:
  1. Faça login na sua conta do Google Cloud. Se você começou a usar o Google Cloud agora, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  4. Ative as APIs Artifact Registry and Google Kubernetes Engine.

    Ative as APIs

  5. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  6. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  7. Ative as APIs Artifact Registry and Google Kubernetes Engine.

    Ative as APIs

Ao concluir este tutorial, exclua os recursos criados para evitar o faturamento contínuo. Veja mais detalhes em Limpar.

Iniciar o Cloud Shell

Neste tutorial, você usará o Cloud Shell, um ambiente de shell para gerenciar recursos hospedados no Google Cloud.

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

Inicie o Cloud Shell:

  1. Acesse o console do Google Cloud.

    Console do Google Cloud

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

Uma sessão do Cloud Shell aparece dentro do console. Use esse shell para executar os comandos gcloud e kubectl.

prepare o ambiente

Nesta seção, você prepara o ambiente para seguir o tutorial.

Definir as configurações padrão para a CLI gcloud

Defina variáveis de ambiente para o ID do projeto, a zona e o nome do novo cluster.

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

Substitua PROJECT_ID pelo ID do projeto escolhido para este tutorial na seção Antes de começar.

Neste tutorial, você cria recursos em us-central1-a. Para ver uma lista completa de locais onde a série de máquinas Tau T2A está disponível, consulte Regiões e zonas disponíveis.

Clonar o repositório git

Neste tutorial, usamos recursos do repositório do GitHub para Arm no GKE.

  1. Clone o repositório:

    git clone https://github.com/GoogleCloudPlatform/gke-arm
    
  2. Altere o diretório de trabalho atual para gke-arm/migrate-x86-app-to-multi-arch/ do repositório clonado na etapa anterior:

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

Criar um cluster do GKE e implantar o aplicativo x86

Na primeira parte deste tutorial, você cria um cluster com nós x86 e implanta um aplicativo x86. O aplicativo de exemplo é um serviço que responde a solicitações HTTP. Ele foi criado com a linguagem de programação Golang.

Essa configuração é a representação de um ambiente de cluster típico, que usa aplicativos compatíveis com x86 e nós x86.

Criar um cluster do GKE

Primeiro, crie um GKE usando nós com processadores x86. Com essa configuração, você cria um ambiente de cluster típico para executar aplicativos x86.

Crie o cluster:

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

O escalonamento automático está desativado nesse cluster para demonstrar uma funcionalidade específica em etapas posteriores.

A criação do cluster talvez demore alguns minutos. A flag --async permite que essa operação seja executada em segundo plano enquanto você conclui as próximas etapas.

É possível criar clusters apenas com nós Arm, entretanto, neste tutorial, você criará primeiro um cluster apenas com nós x86 para conhecer o processo de tornar aplicativos exclusivamente x86 compatíveis com Arm.

Criar o repositório do Docker no Artifact Registry

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

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

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

Criar a imagem x86 e enviá-la para o Artifact Registry

  1. Crie a versão compatível com x86 do aplicativo:

    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
    

Implantar o aplicativo 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, a saída será semelhante a esta:

    GKE Cluster 'my-cluster' is RUNNING
    
  2. Recupere as credenciais do cluster para que kubectl possa se conectar à API Kubernetes do cluster:

    gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID
    
  3. Atualize a imagem usando o kustomize e implante o aplicativo 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. Implante um Serviço para expor o aplicativo à Internet:

    kubectl apply -f k8s/hello-service.yaml
    
  5. Verifique se o endereço IP externo do Serviço, hello-service, está concluído provisionando:

    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 que o endereço IP externo for provisionado, a saída será semelhante a esta:

    External IP: 203.0.113.0
    
  6. Faça uma solicitação HTTP para testar se a implantação funciona conforme o esperado:

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

    O resultado será assim:

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

    A saída mostra que essa implantação compatível com x86 está em execução em um nó no pool de nós padrão na arquitetura amd64. Os nós no pool de nós padrão do cluster têm processadores x86 (Intel ou AMD).

Adicionar nós Arm ao cluster

Na próxima parte deste tutorial, adicione nós Arm ao cluster. Esses nós são onde a versão compatível com ARM do aplicativo é implantada ao ser recriada para execução em Arm.

Check Point

Até aqui, você realizou os seguintes objetivos:

  • Criar um cluster do GKE usando nós x86.
  • Armazenar uma imagem de contêiner compatível com x86 com o Docker no Artifact Registry.
  • Implantar uma carga de trabalho compatível com x86 em um cluster do GKE.

Você configurou um ambiente de cluster com nós x86 e uma carga de trabalho compatível com x86. Se você não usa nós Arm e cargas de trabalho compatíveis com Arm, essa configuração é semelhante aos ambientes de cluster atuais.

Adicionar um pool de nós Arm ao cluster

Adicione um pool de nós Arm a um cluster atual:

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

O tipo de máquina t2a-standard-2 é uma VM Arm da série de máquinas Tau T2A (pré-lançamento).

Crie um pool de nós Arm da mesma forma que você cria um pool de nós x86. Após a criação do pool de nós, os nós x86 e Arm estarão em execução nesse cluster.

Para saber mais sobre como adicionar pools de nós Arm a clusters atuais, consulte Adicionar um pool de nós Arm a um cluster do GKE.

Escalonar verticalmente o aplicativo atual em execução em nós baseados em x86

Os nós de vários tipos de arquitetura podem funcionar perfeitamente juntos em um cluster. O GKE não programa cargas de trabalho atuais em execução em nós x86 para nós Arm no cluster porque um taint é colocado automaticamente em nós Arm. É possível ver isso ao escalonar verticalmente o aplicativo atual.

  1. Atualize a carga de trabalho, escalonando-a verticalmente para seis 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 execute o comando a seguir para verificar o status da implantação:

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

    A resposta será parecida com esta:

    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
    

    Essa saída mostra pods com status pendente, já que não há espaço nos nós baseados em x86. Como o escalonador automático de cluster está desativado e há taints nos nós Arm, as cargas de trabalho não serão implantadas em nenhum dos nós Arm disponíveis. Esse taint impede que o GKE programe cargas de trabalho x86 nos nós Arm. Para implantação nos nós Arm, você precisa indicar que a implantação é compatível com os nós Arm.

  3. Verifique os pods que estão no estado "Em execução":

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

    A resposta será parecida com esta:

    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>
    

    Nessa saída, a coluna NODE indica que todos os pods da implantação estão em execução apenas no pool padrão, o que significa que os pods compatíveis com x86 são programados apenas para os nós x86. O pod original que já estava programado antes da criação do pool de nós Arm ainda está em execução no mesmo nó.

  4. Execute o seguinte comando para acessar o serviço e ver a saída:

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

    O resultado será assim:

    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
    

    Essa saída mostra que todas as solicitações de disponibilização dos pods estão em execução nos nós x86. Alguns pods não podem responder porque ainda estão no estado pendente uma vez que não há espaço nos nós x86 atuais e eles não serão programados para os nós Arm.

Recriar o aplicativo para ser executado em Arm

Na seção anterior, você adicionou um pool de nós Arm ao cluster atual. No entanto, quando você escalonou verticalmente o aplicativo x86 atual, isso não programou nenhuma das cargas de trabalho para os nós Arm. Nesta seção, você recria o aplicativo para que seja compatível com Arm a fim de executá-lo nos nós Arm no cluster.

Para este exemplo, execute as etapas usando docker build. Essa abordagem em duas etapas inclui:

  • Primeiro estágio: crie o código para Arm.
  • Segundo estágio: copie o executável para um contêiner enxuto.

Depois de seguir essas etapas, você terá uma imagem compatível com Arm, além da imagem compatível com x86.

A segunda etapa de copiar o executável para outro contêiner segue uma das práticas recomendadas para criação de um contêiner, que é criar a menor imagem possível.

Neste tutorial, usamos um aplicativo de exemplo criado com a linguagem de programação Golang. Com Golang, é possível fazer compilação cruzada de um aplicativo em diferentes sistemas operacionais e plataformas de CPU fornecendo variáveis de ambiente, GOOS e GOARCH, respectivamente.

  1. Execute cat Dockerfile_arm para ver o Dockerfile gravado 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 snippet mostrado aqui mostra apenas o primeiro estágio. No arquivo, os dois estágios estão incluídos.

    Nesse arquivo, definir GOARCH=arm64 instrui o compilador Go a criar o aplicativo para o conjunto de instruções Arm. Não é necessário definir GOOS porque a imagem de base na primeira etapa é uma imagem do Alpine Linux.

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

Implantar a versão Arm do aplicativo

Agora que o aplicativo foi criado para execução nos nós Arm, é possível implantá-lo nesses nós no cluster.

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

    O resultado será assim:

       nodeSelector:
          kubernetes.io/arch: arm64
    

    Esse nodeSelector especifica que a carga de trabalho precisa ser executada apenas nos nós Arm. Quando você usa nodeSelector, o GKE adiciona uma tolerância que corresponde ao taint em nós Arm. Assim, o GKE programa a carga de trabalho nesses nós. Para saber mais sobre como definir esse campo, consulte Preparar uma carga de trabalho do Arm para implantação.

  2. Implante uma réplica da versão compatível com ARM do aplicativo:

    $(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 verifique se a implantação Arm está respondendo às solicitações curl:

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

    O resultado será assim:

    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
    

    Essa saída precisa incluir respostas dos aplicativos compatíveis com x86 e Arm respondendo à solicitação curl.

Criar uma imagem de várias arquiteturas para executar uma carga de trabalho entre arquiteturas

É possível usar a estratégia descrita na seção anterior e implantar cargas de trabalho separadas para x86 e Arm, mas seria necessário manter organizados dois processos de compilação e duas imagens de contêiner.

O ideal é criar e executar o aplicativo perfeitamente entre plataformas x86 e Arm. Recomendamos essa abordagem. Para executar o aplicativo com um só manifesto entre plataformas de várias arquiteturas, você precisa usar imagens de várias arquiteturas (multiarquiteturas). Para saber mais sobre imagens de várias arquiteturas, consulte Criar imagens de várias arquiteturas para cargas de trabalho em Arm.

Para usar imagens de várias arquiteturas, verifique se o aplicativo atende aos pré-requisitos a seguir:

  • O aplicativo não tem dependências específicas da plataforma de arquitetura.
  • Todas as dependências precisam ser criadas para várias arquiteturas ou, no mínimo, para as plataformas desejadas.

O aplicativo de exemplo usado neste tutorial atende a esses dois pré-requisitos. No entanto, recomendamos testar os próprios aplicativos ao criar as imagens de várias arquiteturas antes de implantá-las na produção.

Criar e enviar imagens de várias arquiteturas

É possível criar imagens de várias arquiteturas com o Docker Buildx se a carga de trabalho atende a estes pré-requisitos:

  • A imagem de base é compatível com várias arquiteturas. Para verificar isso, execute docker manifest inspect na imagem de base e verifique a lista de plataformas de arquitetura. Veja um exemplo de como inspecionar uma imagem no final desta seção.
  • O aplicativo não requer etapas de compilação especiais para cada plataforma de arquitetura. Se as etapas especiais forem necessárias, o Buildx talvez não seja suficiente. Você precisaria ter um Dockerfile separado para cada plataforma e criar o manifesto manualmente com docker manifest create.

A imagem de base do aplicativo de exemplo é o Alpine, que é compatível com várias arquiteturas. Também não há etapas específicas da plataforma de arquitetura, então é possível criar a imagem de várias arquiteturas com o Buildx.

  1. Execute cat Dockerfile para inspecionar o 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" ]
    

    Esse Dockerfile define dois estágios: o de compilação e o de lançamento. Use o mesmo Dockerfile para criar o aplicativo x86. Se você seguir as práticas recomendadas para a criação de contêineres, poderá recriar as próprias imagens de contêiner sem mudar nada.

  2. Execute este comando para criar e usar um novo builder docker buildx:

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

    Agora que você criou esse novo builder, poderá 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, ele faz o download das imagens de base arm64. Na primeira etapa, ele cria o binário na imagem arm64 golang:1.18-alpine para arm64. No segundo estágio, é feito o download da imagem do Alpine Linux arm64, e o 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 será assim:

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

    Essa saída mostra que duas imagens são geradas, uma para linux/arm64 e outra para linux/amd64.

  4. Inspecione o manifesto da 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 será assim:

    {
       "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 seção manifests inclui dois manifestos, um com a arquitetura de plataforma amd64 e outro com a arquitetura de plataforma arm64.

    Quando você implanta essa imagem de contêiner no cluster, o GKE faz o download automático apenas da imagem que corresponde à arquitetura do nó.

Implantar a versão de várias arquiteturas do aplicativo

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

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

    A saída inclui a seguinte tolerância definida:

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

    Essa tolerância permite que a carga de trabalho seja executada nos nós Arm no cluster, uma vez que a tolerância corresponde ao taint definido em todos os nós Arm. Como essa carga de trabalho agora pode ser executada em qualquer nó do cluster, apenas a tolerância é necessária. Com apenas a tolerância, o GKE pode programar a carga de trabalho para os nós x86 e Arm. Se você quiser especificar onde o GKE pode programar cargas de trabalho, use seletores de nós e regras de afinidade de nós. Para saber mais sobre como definir esses campos, consulte Preparar uma carga de trabalho em Arm para implantação.

  3. Implante a imagem de contêiner de várias arquiteturas com seis 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 confirme se todas as réplicas do aplicativo estão em execução:

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

    O resultado será assim:

    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>
    

    Essa saída inclui uma coluna NODE que indica que os pods estão em execução nos dois nós no pool de nós Arm e outros no pool de nós padrão (x86).

  5. Execute o seguinte comando para acessar o serviço e ver a saída:

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

    O resultado será assim:

    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
    

    Você verá que os pods em execução entre várias plataformas de arquitetura estão respondendo às solicitações.

Você criou e implantou uma imagem de várias arquiteturas para executar perfeitamente uma carga de trabalho entre várias arquiteturas.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Depois de concluir o tutorial, limpe os recursos criados para reduzir o uso da cota e interromper as cobranças do faturamento. Nas seções a seguir, descrevemos como excluir ou desativar esses recursos.

Excluir o projeto

O jeito mais fácil de evitar cobranças é excluir o projeto que você criou para o tutorial.

Para excluir o projeto:

  1. No Console do Google Cloud, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

Excluir o serviço, cluster e repositório

Se você não quiser excluir todo o projeto, exclua o cluster e o repositório criados para o tutorial:

  1. Execute kubectl delete para excluir o Serviço do aplicativo:

    kubectl delete service hello-service
    

    Esse comando exclui o balanceador de carga do Compute Engine que você criou quando expôs a implantação.

  2. Execute gcloud container clusters delete para excluir o cluster:

    gcloud container clusters delete $CLUSTER_NAME --zone $ZONE
    
  3. Exclua o repositório:

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

A seguir