Colocar pods do GKE em zonas específicas

Nesta página, mostramos como instruir o Google Kubernetes Engine (GKE) a executar pods em nós em zonas Google Cloud específicas usando a topologia zonal. Esse tipo de posicionamento é útil em situações como as seguintes:

  • Os pods precisam acessar dados armazenados em um disco permanente zonal do Compute Engine.
  • Os pods precisam ser executados com outros recursos zonais, como instâncias do Cloud SQL.

Também é possível usar a colocação zonal com roteamento de tráfego com reconhecimento de topologia para reduzir a latência entre clientes e cargas de trabalho. Para detalhes sobre o roteamento de tráfego com reconhecimento de topologia, consulte Roteamento ciente de topologia.

O uso de topologia zonal para controlar a colocação de pods é um mecanismo avançado do Kubernetes que só deve ser usado se a situação exigir que os pods sejam executados em zonas específicas. Na maioria dos ambientes de produção, recomendamos o uso de recursos regionais, que é o padrão do GKE, quando possível.

Métodos de posicionamento por zona

A topologia zonal é integrada ao Kubernetes com o rótulo de nó topology.kubernetes.io/zone: ZONE. Para instruir o GKE a colocar um pod em uma zona específica, use um dos seguintes métodos:

  • nodeAffinity: especifique uma regra de nodeAffinity na especificação do pod para uma ou mais zonas Google Cloud . Esse método é mais flexível que um nodeSelector porque permite colocar pods em várias zonas.
  • nodeSelector: especifique um nodeSelector na especificação do pod para uma única zona Google Cloud .

  • Classes de computação: configure o pod para usar uma classe de computação do GKE. Com essa abordagem, é possível definir uma lista priorizada de conjuntos de Google Cloud zonas. Ele permite que a carga de trabalho seja movida dinamicamente para o conjunto de zonas preferido quando os nós estão disponíveis nessas zonas. Para mais informações, consulte Sobre as classes de computação personalizadas.

Considerações

O posicionamento do pod zonal usando a topologia zonal tem as seguintes considerações:

  • O cluster precisa estar na mesma região Google Cloud que as zonas solicitadas.
  • Em clusters padrão, é preciso usar o provisionamento automático de nós ou criar pools de nós com zonas nas zonas solicitadas. Os clusters do Autopilot gerenciam esse processo automaticamente para você.
  • Os clusters padrão precisam ser regionais.

Preços

A topologia zonal é um recurso de programação do Kubernetes e é oferecida sem nenhum custo extra no GKE.

Para detalhes sobre preços, consulte Preços do GKE.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ative a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a Google Cloud CLI para essa tarefa, instale e, em seguida, inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da CLI gcloud não sejam compatíveis com a execução dos comandos neste documento.
  • Verifique se você tem um cluster do GKE na mesma regiãoGoogle Cloud que as zonas em que quer colocar os pods. Para criar um novo cluster, consulte Criar um cluster do Autopilot.

Colocar pods em várias zonas usando nodeAffinity

O nodeAffinity do Kubernetes fornece um mecanismo de controle de programação flexível compatível com vários seletores de rótulos e operadores lógicos. Use nodeAffinity se quiser permitir que os pods sejam executados em uma de um conjunto de zonas (por exemplo, em us-central1-a ou us-central1-f).

  1. Salve o seguinte manifesto como multi-zone-affinity.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-multi-zone
      template:
        metadata:
          labels:
            app: nginx-multi-zone
        spec:
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - us-central1-a
                    - us-central1-f
    

    Esse manifesto cria uma implantação com três réplicas e coloca os pods em us-central1-a ou us-central1-f com base na disponibilidade do nó.

    Verifique se o cluster está na região us-central1. Se o cluster estiver em uma região diferente, altere as zonas no campo de valores do manifesto para zonas válidas na região do cluster.

    Opcional: se você estiver provisionando VMs de TPU, use uma zona de IA, como us-central1-ai1a. As zonas de IA são locais especializados otimizados para cargas de trabalho de IA/ML em Google Cloud regiões.

  2. Crie a implantação:

    kubectl create -f multi-zone-affinity.yaml
    

    O GKE cria os pods em nós em uma das zonas especificadas. Vários pods podem ser executados no mesmo nó. Opcionalmente, é possível usar a antiafinidade de pods para instruir o GKE a colocar cada pod em um nó separado.

Colocar pods em uma única zona usando um nodeSelector

Para colocar pods em uma única zona, use um nodeSelector na especificação do pod. Um nodeSelector é equivalente a uma regra de nodeAffinity requiredDuringSchedulingIgnoredDuringExecution que tem uma única zona especificada.

  1. Salve o seguinte manifesto como single-zone-selector.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-singlezone
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-singlezone
      template:
        metadata:
          labels:
            app: nginx-singlezone
        spec:
          nodeSelector:
            topology.kubernetes.io/zone: "us-central1-a"
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    

    Esse manifesto informa ao GKE para colocar todas as réplicas na implantação na zona us-central1-a.

  2. Crie a implantação:

    kubectl create -f single-zone-selector.yaml
    

Priorizar a colocação de pods em zonas selecionadas usando uma classe de computação

As classes de computação do GKE oferecem um mecanismo de controle que permite definir uma lista de prioridades de configuração de nós. Com as preferências zonais, você define as zonas em que quer que o GKE coloque os pods.

Como usar a prioridade das zonas de local

Para definir preferências zonais em classes de computação usando a prioridade de zonas de localidade, é necessário o GKE versão 1.33.1-gke.1545000 ou mais recente.

O exemplo a seguir cria uma classe de computação que especifica uma lista de zonas preferenciais para pods.

Nestas etapas, presumimos que o cluster está na região us-central1. Se o cluster estiver em uma região diferente, altere os valores das zonas no manifesto para zonas válidas na região do cluster.

  1. Salve o seguinte manifesto como zones-custom-compute-class.yaml:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: zones-custom-compute-class
    spec:
      priorities:
      - location:
        zones: [us-central1-a, us-central1-b]
      - location:
        zones: [us-central1-c]
      activeMigration:
        optimizeRulePriority: true
      nodePoolAutoCreation:
        enabled: true
      whenUnsatisfiable: ScaleUpAnyway
    

    O manifesto dessa classe de computação muda o comportamento de escalonamento da seguinte maneira:

    1. O GKE tenta colocar os pods em us-central1-a ou em us-central1-b.
    2. Se us-central1-a e us-central1-b não tiverem capacidade disponível, o GKE tentará colocar pods em us-central1-c.
    3. Se us-central1-c não tiver capacidade disponível, o campo whenUnsatisfiable: ScaleUpAnyway fará com que o GKE coloque os pods em qualquer zona disponível na região.
    4. Se uma zona com maior prioridade na classe de computação ficar disponível depois, o campo activeMigration.optimizeRulePriority: true fará com que o GKE mova os pods para essa zona de qualquer zona de prioridade mais baixa. Essa migração usa o orçamento de interrupção do pod para ajudar a garantir a disponibilidade do serviço.
  2. Crie a classe de computação personalizada:

    kubectl create -f zones-custom-compute-class.yaml
    

    O GKE cria uma classe de computação personalizada que pode ser referenciada pelas cargas de trabalho.

  3. Salve o seguinte manifesto como custom-compute-class-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-zonal-preferences
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-zonal-preferences
      template:
        metadata:
          labels:
            app: nginx-zonal-preferences
        spec:
          nodeSelector:
            cloud.google.com/compute-class: "zones-custom-compute-class"
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    
  4. Crie a implantação:

    kubectl create -f custom-compute-class-deployment.yaml
    

Usar a prioridade de locationZoneTypes

Para definir preferências zonais em classes de computação usando a prioridade de tipos de zona de local, é necessário o GKE versão 1.35.2-gke.1842000 ou mais recente. Dependendo das suas configurações, selecionar um tipo de zona para seus pods vai usar ou criar um novo pool de nós que abrange todas as zonas de um determinado tipo.

É possível especificar os seguintes tipos de zona na sua classe de computação:

  • STANDARD: zonas de uso geral, Google Cloud em uma região. Recomendado para cargas de trabalho que não são de ML.
  • AI: zonas especializadas otimizadas para capacidade de IA/acelerador. Recomendado para cargas de trabalho de IA/ML.
  • CLUSTER_DEFAULT: zonas especificadas no autoprovisioning-locations do cluster (ou os locais do cluster, se estiver vazio).

Para mais informações sobre zonas padrão e de IA, consulte Sobre as zonas de IA.

Restrições para combinar campos

Não é possível combinar o campo zoneTypes com o campo location.zones ou reservations.specific na mesma entrada de prioridade. Você pode usar os campos zoneTypes e location.zones na mesma classe de computação, desde que os coloque em entradas de prioridade separadas.

Além disso, o campo priorityDefaults se aplica a todas as prioridades na classe de computação. Uma consequência dessa regra é que definir o campo zoneTypes no campo priorityDefaults impede que você use o campo location.zones ou reservations.specific em qualquer prioridade.

Exemplo válido: prioridades separadas

O exemplo a seguir é válido porque zones e zoneTypes são especificados em entradas de prioridade separadas:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: valid-zonal-preferences
spec:
  priorities:
  - location:
      zones: [us-central1-a]
  - location:
      zoneTypes: [AI]

Exemplo inválido: mesma prioridade

O exemplo a seguir é inválido porque zones e zoneTypes são especificados na mesma entrada de prioridade:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: invalid-same-priority
spec:
  priorities:
  - location:
      zones: [us-central1-a]
      zoneTypes: [AI] # Error: mutually exclusive

Exemplo inválido: conflito com padrões

O exemplo a seguir é inválido porque a definição do campo zoneTypes na seção priorityDefaults entra em conflito com o campo zones na entrada de prioridade:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: invalid-defaults-conflict
spec:
  priorityDefaults:
    location:
      zoneTypes: [AI]
  priorities:
  - location:
      zones: [us-central1-a] # Error: merges with defaults

Exemplo de uso

O exemplo a seguir cria uma classe de computação que especifica uma lista de tipos de zona preferenciais para pods.

  1. Salve o seguinte manifesto como zone-types-custom-compute-class.yaml:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: zone-types-custom-compute-class
    spec:
      priorities:
      - location:
        zones: [us-central1-c]
      - location:
        zoneTypes:
        - AI
      - location:
        zoneTypes:
        - CLUSTER_DEFAULT
      activeMigration:
        optimizeRulePriority: true
      nodePoolAutoCreation:
        enabled: true
      whenUnsatisfiable: ScaleUpAnyway
    

    O manifesto dessa classe de computação muda o comportamento de escalonamento da seguinte maneira:

    1. O GKE tenta colocar os pods na zona us-central1-c.
    2. Se us-central1-c não tiver capacidade disponível, o GKE tentará colocar pods em qualquer zona AI na região.
    3. Se nenhuma das zonas AI tiver capacidade disponível, o GKE tentará colocar pods em qualquer uma das zonas CLUSTER_DEFAULT.
    4. Se nenhuma das zonas CLUSTER_DEFAULT tiver capacidade disponível, o campo whenUnsatisfiable: ScaleUpAnyway fará com que o GKE coloque os pods em qualquer zona disponível na região.
    5. Se uma zona com maior prioridade na classe de computação ficar disponível depois, o campo activeMigration.optimizeRulePriority: true fará com que o GKE mova os pods para essa zona de qualquer zona de prioridade mais baixa. Essa migração usa o orçamento de interrupção do pod para ajudar a garantir a disponibilidade do serviço.
  2. Crie a classe de computação personalizada:

    kubectl create -f zone-types-custom-compute-class.yaml
    

    O GKE cria uma classe de computação personalizada que pode ser referenciada pelas cargas de trabalho.

  3. Salve o seguinte manifesto como custom-compute-class-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-zonal-preferences
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx-zonal-preferences
      template:
        metadata:
          labels:
            app: nginx-zonal-preferences
        spec:
          nodeSelector: cloud.google.com/compute-class: "zone-types-custom-compute-class"
          containers:
          - name: nginx
            image: nginx:latest
            ports:
            - containerPort: 80
    
  4. Crie a implantação:

    kubectl create -f custom-compute-class-deployment.yaml
    

Como o NAP avalia zoneTypes

Ao determinar se é necessário reutilizar um pool de nós ou criar um novo, o provisionamento automático de nós (NAP) geralmente exige uma correspondência exata entre as zonas atuais do pool de nós e o zoneTypes solicitado. Se você atualizar uma prioridade para incluir tipos de zona mais amplos (por exemplo, de [AI] para [AI, STANDARD]), o NAP vai provisionar um novo pool de nós para corresponder ao novo formato exato.

Remoção com reconhecimento do tipo de máquina

Se um tipo de máquina (como h3-standard-88) estiver disponível apenas em um subconjunto das zonas definidas por um tipo (por exemplo, apenas em us-central1-a), o GKE vai cortar automaticamente a lista de locais do pool de nós para incluir apenas as zonas em que esse hardware está fisicamente presente.

Segmentar zonas de IA

As zonas de IA são especializadas e usadas para treinamento de IA/ML e cargas de trabalho de inferência. Essas zonas oferecem uma capacidade significativa de acelerador de ML. Para mais informações, consulte a documentação sobre zonas de IA.

Neste documento e na documentação do GKE, "zonas padrão" ou "zonas" se referem a zonas não relacionadas à IA em uma região Google Cloud .

Antes de usar uma zona de IA no GKE, considere as seguintes características:

  • As zonas de IA são fisicamente separadas das zonas padrão para oferecer mais espaço de armazenamento e energia. Essa separação pode resultar em maior latência, o que geralmente é tolerável para cargas de trabalho de IA/ML.
  • As zonas de IA têm um sufixo com a notação ai. Por exemplo, uma zona de IA na região us-central1 é chamada de us-central1-ai1a.
  • No momento, apenas as VMs de TPU são aceitas.
  • O plano de controle do cluster é executado em uma ou mais zonas padrão na mesma região da zona de IA.
  • É possível executar VMs sem TPUs anexadas em uma zona de IA somente se você atender aos seguintes requisitos:

    • Você já está executando outras cargas de trabalho que usam VMs da TPU na mesma zona.
    • As VMs que não são de TPU são VMs spot, vinculadas a uma reserva ou parte de um pool de nós com uma proporção específica de VM aceleradora para uso geral.
  • As zonas de IA compartilham componentes, como conexões de rede e implantações de software, com zonas padrão que têm o mesmo sufixo na mesma região. Para cargas de trabalho de alta disponibilidade, recomendamos usar zonas diferentes. Por exemplo, evite usar us-central1-ai1a e us-central1-a para alta disponibilidade.

Por padrão, o GKE não implanta cargas de trabalho em zonas de IA. Para usar uma zona de IA, configure uma das seguintes opções:

  • (Recomendado) ComputeClasses: defina a prioridade mais alta para solicitar TPUs sob demanda em uma zona de IA. As ComputeClasses ajudam a definir uma lista priorizada de configurações de hardware para suas cargas de trabalho. Para um exemplo, consulte Sobre ComputeClasses.
  • Provisionamento automático de nós: use um nodeSelector ou nodeAffinity na especificação do pod para instruir o provisionamento automático de nós a criar um pool de nós na zona de IA. Se a carga de trabalho não segmentar explicitamente uma zona de IA, o provisionamento automático de nós considerará apenas zonas padrão ou zonas de --autoprovisioning-locations ao criar novos pools de nós. Essa configuração ajuda a garantir que as cargas de trabalho que não executam modelos de IA/ML permaneçam em zonas padrão, a menos que você configure explicitamente o contrário. Para um exemplo de manifesto que usa um nodeSelector, consulte Definir as zonas padrão para nós criados automaticamente.
  • GKE Standard: se você gerenciar diretamente seus pools de nós, use uma zona de IA na flag --node-locations ao criar um pool de nós. Confira um exemplo em Implantar cargas de trabalho de TPU no GKE Standard.

Verificar o posicionamento do pod

Para verificar o posicionamento do pod, liste os pods e verifique os rótulos dos nós. Vários pods podem ser executados em um único nó. Portanto, talvez você não veja pods espalhados por várias zonas se tiver usado nodeAffinity.

  1. Liste os pods:

    kubectl get pods -o wide
    

    A saída é uma lista de pods em execução e o nó do GKE correspondente.

  2. Descreva os nós:

    kubectl describe node NODE_NAME | grep "topology.kubernetes.io/zone"
    

    Substitua NODE_NAME pelo nome do nó.

    O resultado será assim:

    topology.kubernetes.io/zone: us-central1-a
    

Se você quiser que o GKE distribua os pods uniformemente entre várias zonas para melhorar o failover em vários domínios de falha, use topologySpreadConstraints.

A seguir