Executar uma carga de trabalho em grande escala com início flexível e provisionamento em fila

Nesta página, mostramos como otimizar a capacidade de acesso da GPU para cargas de trabalho em lote e de IA em grande escala com GPUs usando o início flexível com provisionamento em fila com tecnologia do Dynamic Workload Scheduler.

Antes de ler esta página, confira se você conhece os seguintes conceitos:

Este guia é destinado a engenheiros de machine learning (ML), administradores e operadores de plataforma e especialistas em dados e IA interessados em usar os recursos de orquestração de contêineres do Kubernetes para executar cargas de trabalho em lote. Para mais informações sobre papéis comuns e tarefas de exemplo que referenciamos no conteúdo do Google Cloud , consulte Funções e tarefas comuns do usuário do GKE.

Como funciona o início flexível com provisionamento em fila

Com o início flexível com provisionamento em fila, o GKE aloca todos os recursos solicitados ao mesmo tempo. O início flexível com provisionamento em fila usa as seguintes ferramentas:

Para usar o início flexível com provisionamento em fila, adicione as flags --flex-start e --enable-queued-provisioning ao criar o pool de nós.

Prática recomendada:

Use o início flexível com provisionamento em fila para cargas de trabalho em lote e de IA em grande escala quando elas atenderem aos seguintes critérios:

  • Suas cargas de trabalho têm horários de início flexíveis.
  • Suas cargas de trabalho precisam ser executadas em vários nós simultaneamente.

Para cargas de trabalho menores que podem ser executadas em um único nó, use as VMs de início flexível. Para mais informações sobre o provisionamento de GPU no GKE, consulte Receber aceleradores para cargas de trabalho de IA.

Antes de começar

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

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a CLI do Google Cloud para essa tarefa, instale e inicialize a gcloud CLI. 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.

Usar pools de nós com início flexível e provisionamento em fila

Esta seção se aplica apenas aos clusters Standard.

É possível usar qualquer um dos três métodos a seguir para designar que o flex-start com provisionamento em fila pode funcionar com pools de nós específicos no cluster:

Crie um pool de nós.

Crie um pool de nós com flex-start e provisionamento em fila ativados usando a CLI gcloud:

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --enable-queued-provisioning \
    --accelerator type=GPU_TYPE,count=AMOUNT,gpu-driver-version=DRIVER_VERSION \
    --machine-type=MACHINE_TYPE \
    --flex-start \
    --enable-autoscaling  \
    --num-nodes=0   \
    --total-max-nodes TOTAL_MAX_NODES  \
    --location-policy=ANY  \
    --reservation-affinity=none  \
    --no-enable-autorepair

Substitua:

  • NODEPOOL_NAME: o nome escolhido para o pool de nós.
  • CLUSTER_NAME: o nome do cluster.
  • LOCATION: a região do Compute Engine do cluster, como us-central1.
  • GPU_TYPE: o tipo de GPU.
  • AMOUNT: o número de GPUs que serão anexadas aos nós do pool.
  • DRIVER_VERSION: a versão do driver NVIDIA a ser instalado. Será um dos seguintes valores:
    • default: instale a versão padrão do driver para a versão do GKE.
    • latest: instale a versão mais recente disponível do driver para a versão do GKE. Disponível apenas para nós que usam o Container-Optimized OS.
  • TOTAL_MAX_NODES: o número máximo de nós a serem escalonados automaticamente para todo o pool de nós.
  • MACHINE_TYPE: o tipo de máquina do Compute Engine para os nós.

    Prática recomendada:

    Use um tipo de máquina otimizado para aceleradores para melhorar o desempenho e a eficiência das cargas de trabalho de IA/ML.

Opcionalmente, é possível usar as seguintes flags:

  • --node-locations=COMPUTE_ZONES: a lista separada por vírgulas de uma ou mais zonas em que o GKE cria os nós da GPU. As zonas precisam estar na mesma região que o cluster. Escolha zonas que tenham GPUs disponíveis.
  • --enable-gvnic: essa flag ativa a gVNIC nos pools de nós de GPU para aumentar a velocidade do tráfego de rede.

Esse comando cria um pool de nós com a seguinte configuração:

  • A flag --flex-start combinada com a flag --enable-queued-provisioning instrui o GKE a criar um pool de nós com flex-start com provisionamento em fila ativado e a adicionar o taint cloud.google.com/gke-queued ao pool de nós.
  • O GKE ativa o provisionamento de filas e o escalonamento automático de clusters.
  • Inicialmente, o pool de nós não tem nós.
  • A flag --no-enable-autorepair desativa os reparos automáticos, o que pode interromper as cargas de trabalho executadas em nós reparados.

Ative o provisionamento automático de nós para criar pools de nós para início flexível com provisionamento em fila

É possível usar o provisionamento automático de nós para gerenciar pools de nós para flex-start com provisionamento em fila para clusters que executam a versão 1.29.2-gke.1553000 ou posterior. Quando você ativa o provisionamento automático de nós, o GKE cria pools de nós com os recursos necessários para a carga de trabalho associada.

Para ativar o provisionamento automático de nós, considere as seguintes configurações e conclua as etapas em Configurar limites de GPU:

  • Especifique os recursos necessários para o início flexível com provisionamento em fila ao ativar o recurso. Para listar os resourceTypes disponíveis, execute o comando gcloud compute accelerator-types list.
  • Use a flag --no-enable-autoprovisioning-autorepair para desativar o reparo automático de nós.
  • Permita que o GKE instale automaticamente drivers de GPU em nós de GPU com provisionamento automático. Para mais informações, consulte Como instalar drivers usando o provisionamento automático de nós com GPUs.

Executar cargas de trabalho em lote e de IA com início flexível e provisionamento em fila

Para executar cargas de trabalho em lote com início flexível e provisionamento em fila, use uma das seguintes configurações:

  • Início flexível com provisionamento em fila para jobs com o Kueue: use o início flexível com provisionamento em fila com o Kueue para automatizar o ciclo de vida das solicitações de Provisioning Request. O Kueue implementa o enfileiramento de jobs e observa o status do início flexível com provisionamento enfileirado. O Kueue decide quando os jobs devem esperar e quando devem começar, com base em cotas e em uma hierarquia para compartilhar recursos de maneira uniforme entre as equipes.

  • Início flexível com provisionamento em fila para jobs sem Kueue: é possível usar o início flexível com provisionamento em fila sem o Kueue ao usar suas próprias ferramentas ou plataforma interna de programação em lote. Você cria e cancela manualmente a solicitação de provisionamento.

Prática recomendada:

Use o Kueue para executar suas cargas de trabalho em lote e de IA com início flexível e provisionamento em fila.

Início flexível com provisionamento em fila para jobs com Kueue

As seções a seguir mostram como configurar o flex-start com provisionamento em fila para jobs com Kueue:

  • Configuração do pool de nós de início flexível com provisionamento em fila.
  • Configuração do pool de nós de reserva e início flexível com provisionamento em fila.

Esta seção usa os exemplos no diretório dws-examples do repositório ai-on-gke. Publicamos os exemplos no diretório dws-examples sob a licença Apache2.

Você precisa ter permissões de administrador para instalar o Kueue. Para receber essas permissões, confira se você tem o papel do IAM roles/container.admin. Para saber mais sobre os papéis do IAM do GKE, consulte o guia de criação de políticas de permissão do IAM.

Preparar o ambiente

  1. No Cloud Shell, execute este comando:

    git clone https://github.com/GoogleCloudPlatform/ai-on-gke
    cd ai-on-gke/tutorials-and-examples/workflow-orchestration/dws-examples
    
  2. Instale a versão mais recente do Kueue no cluster:

    VERSION=KUEUE_VERSION
    kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    

    Substitua KUEUE_VERSION pela versão mais recente do Kueue.

Se você usa o Kueue em uma versão anterior à 0.7.0, mude a configuração do feature gate do Kueue definindo o feature gate ProvisioningACC como true. Consulte Feature gates do Kueue para uma explicação mais detalhada e valores dos gates padrão. Para mais informações sobre a instalação do Kueue, consulte Instalação.

Criar os recursos do Kueue para a configuração somente do pool de nós do Dynamic Workload Scheduler

Com o manifesto a seguir, crie uma fila no nível do cluster chamada dws-cluster-queue e o namespace LocalQueue chamado dws-local-queue. Os jobs que se referem à fila dws-cluster-queue nesse namespace usam o flex-start com provisionamento em fila para receber os recursos da GPU.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "default-flavor"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: AdmissionCheck
metadata:
  name: dws-prov
spec:
  controllerName: kueue.x-k8s.io/provisioning-request
  parameters:
    apiGroup: kueue.x-k8s.io
    kind: ProvisioningRequestConfig
    name: dws-config
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ProvisioningRequestConfig
metadata:
  name: dws-config
spec:
  provisioningClassName: queued-provisioning.gke.io
  managedResources:
    - nvidia.com/gpu
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "dws-cluster-queue"
spec:
  namespaceSelector: {}
  resourceGroups:
    - coveredResources: ["cpu", "memory", "nvidia.com/gpu", "ephemeral-storage"]
      flavors:
        - name: "default-flavor"
          resources:
            - name: "cpu"
              nominalQuota: 1000000000 # "Infinite" quota
            - name: "memory"
              nominalQuota: 1000000000Gi # "Infinite" quota
            - name: "nvidia.com/gpu"
              nominalQuota: 1000000000 # "Infinite" quota
            - name: "ephemeral-storage"
              nominalQuota: 1000000000Ti # "Infinite" quota
  admissionChecks:
    - dws-prov
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: "default"
  name: "dws-local-queue"
spec:
  clusterQueue: "dws-cluster-queue"
---
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  labels:
    control-plane: controller-manager
  name: controller-manager-metrics-monitor
  namespace: kueue-system
spec:
  endpoints:
    - path: /metrics
      port: 8080
      scheme: http
      interval: 30s
  selector:
    matchLabels:
      control-plane: controller-manager
---

A fila desse cluster tem limites de cota altos, e apenas a integração de início flexível com provisionamento em fila está ativada. Para saber mais sobre as APIs do Kueue e como configurar limites, consulte Conceitos do Kueue.

Implante a LocalQueue:

kubectl create -f ./dws-queues.yaml

O resultado será assim:

resourceflavor.kueue.x-k8s.io/default-flavor created
admissioncheck.kueue.x-k8s.io/dws-prov created
provisioningrequestconfig.kueue.x-k8s.io/dws-config created
clusterqueue.kueue.x-k8s.io/dws-cluster-queue created
localqueue.kueue.x-k8s.io/dws-local-queue created

Se você quiser executar jobs que usam o início flexível com provisionamento em fila em outros namespaces, crie mais LocalQueues usando o modelo anterior.

Executar o job

No manifesto a seguir, o job de exemplo usa o início flexível com provisionamento em fila:

apiVersion: batch/v1
kind: Job
metadata:
  name: sample-job
  namespace: default
  labels:
    kueue.x-k8s.io/queue-name: dws-local-queue
  annotations:
    provreq.kueue.x-k8s.io/maxRunDurationSeconds: "600"
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-nodepool: NODEPOOL_NAME
      tolerations:
        - key: "nvidia.com/gpu"
          operator: "Exists"
          effect: "NoSchedule"
      containers:
        - name: dummy-job
          image: gcr.io/k8s-staging-perf-tests/sleep:v0.0.3
          args: ["120s"]
          resources:
            requests:
              cpu: "100m"
              memory: "100Mi"
              nvidia.com/gpu: 1
            limits:
              cpu: "100m"
              memory: "100Mi"
              nvidia.com/gpu: 1
      restartPolicy: Never

Esse manifesto inclui os seguintes campos relevantes para a configuração de início flexível com provisionamento em fila:

  • O rótulo kueue.x-k8s.io/queue-name: dws-local-queue informa ao GKE que o Kueue é responsável por orquestrar esse job. Esse rótulo também define a fila em que o job está.
  • A flag suspend: true instrui o GKE a criar o recurso do job, mas ainda não a programar os pods. O Kueue muda essa flag para false quando os nós estão prontos para a execução do job.
  • nodeSelector instrui o GKE a programar o job apenas no pool de nós especificado. O valor precisa corresponder a NODEPOOL_NAME, o nome do pool de nós com provisionamento em fila ativado.
  1. Executar o job:

    kubectl create -f ./job.yaml
    

    O resultado será assim:

    job.batch/sample-job created
    
  2. Verifique o status do job:

    kubectl describe job sample-job
    

    O resultado será assim:

    Events:
      Type    Reason            Age    From                        Message
      ----    ------            ----   ----                        -------
      Normal  Suspended         5m17s  job-controller              Job suspended
      Normal  CreatedWorkload   5m17s  batch/job-kueue-controller  Created Workload: default/job-sample-job-7f173
      Normal  Started           3m27s  batch/job-kueue-controller  Admitted by clusterQueue dws-cluster-queue
      Normal  SuccessfulCreate  3m27s  job-controller              Created pod: sample-job-9qsfd
      Normal  Resumed           3m27s  job-controller              Job resumed
      Normal  Completed         12s    job-controller              Job completed
    

O início flexível com provisionamento em fila com integração do Kueue também é compatível com outros tipos de carga de trabalho disponíveis no ecossistema de código aberto, como:

  • RayJob
  • JobSet v0.5.2 ou mais recente
  • Kubeflow MPIJob, TFJob, PyTorchJob.
  • Pods do Kubernetes usados com frequência por orquestradores de fluxo de trabalho
  • Minicluster de fluxo

Para saber mais sobre esse suporte, consulte Usuário em lote do Kueue.

Criar os recursos do Kueue para a configuração do pool de nós do Dynamic Workload Scheduler e da reserva

Com o manifesto abaixo, você cria dois ResourceFlavors vinculados a dois pools de nós diferentes: reservation-nodepool e dws-nodepool. Os nomes desses pools de nós são apenas exemplos. Modifique esses nomes conforme a configuração do pool de nós. Além disso, com a configuração ClusterQueue, os jobs de entrada tentarão usar reservation-nodepool, e, se não houver capacidade, eles usarão o Dynamic Workload Scheduler para acessar os recursos da GPU.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "reservation"
spec:
  nodeLabels:
    cloud.google.com/gke-nodepool: "reservation-nodepool" # placeholder value
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "dws"
spec:
  nodeLabels:
    cloud.google.com/gke-nodepool: "dws-nodepool" # placeholder value
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "cluster-queue"
spec:
  namespaceSelector: {} # match all.
  resourceGroups:
    - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
      flavors:
        - name: "reservation" # first we try reservation
          resources:
            - name: "cpu"
              nominalQuota: 9
            - name: "memory"
              nominalQuota: 36Gi
            - name: "nvidia.com/gpu"
              nominalQuota: 9
        - name: "dws" # if reservation is saturated we try dws
          resources:
            - name: "cpu"
              nominalQuota: 1000000000 # "Infinite" quota
            - name: "memory"
              nominalQuota: 1000000000Gi # "Infinite" quota
            - name: "nvidia.com/gpu"
              nominalQuota: 1000000000 # "Infinite" quota
  admissionChecksStrategy:
    admissionChecks:
      - name: "dws-prov"
        onFlavors: [dws]
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: "default"
  name: "user-queue"
spec:
  clusterQueue: "cluster-queue"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: AdmissionCheck
metadata:
  name: dws-prov
spec:
  controllerName: kueue.x-k8s.io/provisioning-request
  parameters:
    apiGroup: kueue.x-k8s.io
    kind: ProvisioningRequestConfig
    name: dws-config
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ProvisioningRequestConfig
metadata:
  name: dws-config
spec:
  provisioningClassName: queued-provisioning.gke.io
  managedResources:
    - nvidia.com/gpu

A fila desse cluster tem limites de cota altos, e apenas a integração de início flexível com provisionamento em fila está ativada. Para saber mais sobre as APIs do Kueue e como configurar limites, consulte Conceitos do Kueue.

Implante o manifesto usando o seguinte comando:

kubectl create -f ./dws_and_reservation.yaml

O resultado será assim:

resourceflavor.kueue.x-k8s.io/reservation created
resourceflavor.kueue.x-k8s.io/dws created
clusterqueue.kueue.x-k8s.io/cluster-queue created
localqueue.kueue.x-k8s.io/user-queue created
admissioncheck.kueue.x-k8s.io/dws-prov created
provisioningrequestconfig.kueue.x-k8s.io/dws-config created

Executar o job

Ao contrário da configuração anterior, esse manifesto não inclui o campo nodeSelector porque ele é preenchido pelo Kueue, dependendo da capacidade livre no ClusterQueue.

apiVersion: batch/v1
kind: Job
metadata:
  generateName: sample-job-
  namespace: default
  labels:
    kueue.x-k8s.io/queue-name: user-queue
  annotations:
    provreq.kueue.x-k8s.io/maxRunDurationSeconds: "600"
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      tolerations:
        - key: "nvidia.com/gpu"
          operator: "Exists"
          effect: "NoSchedule"
      containers:
        - name: dummy-job
          image: gcr.io/k8s-staging-perf-tests/sleep:v0.0.3
          args: ["120s"]
          resources:
            requests:
              cpu: "100m"
              memory: "100Mi"
              nvidia.com/gpu: 1
            limits:
              cpu: "100m"
              memory: "100Mi"
              nvidia.com/gpu: 1
      restartPolicy: Never
  1. Executar o job:

    kubectl create -f ./job-without-node-selector.yaml
    

    O resultado será assim:

    job.batch/sample-job-v8xwm created
    

Para identificar o pool de nós usado pelo job, você precisa saber qual ResourceFlavor o job usa.

Solução de problemas

Para saber mais sobre a solução de problemas do Kueue, consulte Solução de problemas da solicitação de provisionamento no Kueue.

Início flexível com provisionamento em fila para jobs sem Kueue

Definir um objeto ProvisioningRequest

Crie uma solicitação usando o Provisioning Request para cada job. O início flexível com provisionamento em fila não inicia os pods, apenas provisiona os nós.

  1. Crie o seguinte manifesto provisioning-request.yaml:

    Padrão

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: POD_TEMPLATE_NAME
      namespace: NAMESPACE_NAME
      labels:
        cloud.google.com/apply-warden-policies: "true"
    template:
      spec:
        nodeSelector:
          cloud.google.com/gke-nodepool: NODEPOOL_NAME
          cloud.google.com/gke-flex-start: "true"
        tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
        containers:
          - name: pi
            image: perl
            command: ["/bin/sh"]
            resources:
              limits:
                cpu: "700m"
                nvidia.com/gpu: 1
              requests:
                cpu: "700m"
                nvidia.com/gpu: 1
        restartPolicy: Never
    ---
    apiVersion: autoscaling.x-k8s.io/API_VERSION
    kind: ProvisioningRequest
    metadata:
      name: PROVISIONING_REQUEST_NAME
      namespace: NAMESPACE_NAME
    spec:
      provisioningClassName: queued-provisioning.gke.io
      parameters:
        maxRunDurationSeconds: "MAX_RUN_DURATION_SECONDS"
      podSets:
      - count: COUNT
        podTemplateRef:
          name: POD_TEMPLATE_NAME
    

    Substitua:

    • API_VERSION: a versão da API, v1 ou v1beta1. Recomendamos usar a v1 para ter estabilidade e acesso aos recursos mais recentes.
    • NAMESPACE_NAME: o nome do namespace do Kubernetes. O namespace precisa ser igual ao namespace dos pods.
    • PROVISIONING_REQUEST_NAME: o nome do ProvisioningRequest. Esse nome será usado na anotação do pod.
    • MAX_RUN_DURATION_SECONDS: opcionalmente, o tempo de execução máximo de um nó em segundos, até o padrão de sete dias. Para saber mais, consulte Como funciona o início flexível com provisionamento em fila. Não será possível alterar esse valor após a criação da solicitação. Esse campo está disponível no GKE versão 1.28.5-gke.1355000 ou posterior.
    • COUNT: número de pods solicitados. Os nós são programados atomicamente em uma zona.
    • POD_TEMPLATE_NAME: o nome do PodTemplate.
    • NODEPOOL_NAME: o nome escolhido para o pool de nós. Remova se quiser usar um pool de nós com provisionamento automático.

    O GKE pode aplicar validações e mutações aos pods durante a criação deles. O rótulo cloud.google.com/apply-warden-policies permite que o GKE aplique as mesmas validações e mutações aos objetos PodTemplate. Esse rótulo é necessário para que o GKE calcule os requisitos de recursos de nó para seus pods. A integração de flex-start com provisionamento em fila é compatível com apenas uma especificação PodSet. Se você quiser misturar diferentes modelos de pod, use o modelo que solicita mais recursos. Não é possível misturar tipos de máquina diferentes, como VMs com tipos de GPU distintos.

    Provisionamento automático de nós

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: POD_TEMPLATE_NAME
      namespace: NAMESPACE_NAME
      labels:
        cloud.google.com/apply-warden-policies: "true"
    template:
      spec:
        nodeSelector:
          cloud.google.com/gke-accelerator: GPU_TYPE
          cloud.google.com/gke-flex-start: "true"
        tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
        containers:
          - name: pi
            image: perl
            command: ["/bin/sh"]
            resources:
              limits:
                cpu: "700m"
                nvidia.com/gpu: 1
              requests:
                cpu: "700m"
                nvidia.com/gpu: 1
        restartPolicy: Never
    ---
    apiVersion: autoscaling.x-k8s.io/API_VERSION
    kind: ProvisioningRequest
    metadata:
      name: PROVISIONING_REQUEST_NAME
      namespace: NAMESPACE_NAME
    spec:
      provisioningClassName: queued-provisioning.gke.io
      parameters:
        maxRunDurationSeconds: "MAX_RUN_DURATION_SECONDS"
      podSets:
      - count: COUNT
        podTemplateRef:
          name: POD_TEMPLATE_NAME
    

    Substitua:

    • API_VERSION: a versão da API, v1 ou v1beta1. Recomendamos usar a v1 para ter estabilidade e acesso aos recursos mais recentes.
    • NAMESPACE_NAME: o nome do namespace do Kubernetes. O namespace precisa ser igual ao namespace dos pods.
    • PROVISIONING_REQUEST_NAME: o nome do ProvisioningRequest. Esse nome será usado na anotação do pod.
    • MAX_RUN_DURATION_SECONDS: opcionalmente, o tempo de execução máximo de um nó em segundos, até o padrão de sete dias. Para saber mais, consulte Como funciona o início flexível com provisionamento em fila. Não será possível alterar esse valor após a criação da solicitação. Esse campo está disponível no GKE versão 1.28.5-gke.1355000 ou posterior.
    • COUNT: número de pods solicitados. Os nós são programados atomicamente em uma zona.
    • POD_TEMPLATE_NAME: o nome do PodTemplate.
    • GPU_TYPE: o tipo de hardware da GPU.

    O GKE pode aplicar validações e mutações aos pods durante a criação deles. O rótulo cloud.google.com/apply-warden-policies permite que o GKE aplique as mesmas validações e mutações aos objetos PodTemplate. Esse rótulo é necessário para que o GKE calcule os requisitos de recursos de nó para seus pods.

  2. Aplique o manifesto:

    kubectl apply -f provisioning-request.yaml
    

Configurar os pods

Esta seção usa jobs do Kubernetes para configurar os pods. No entanto, também é possível usar um JobSet do Kubernetes ou qualquer outro framework, como Kubeflow, Ray ou controladores personalizados. Na especificação de Job, vincule os pods ao ProvisioningRequest usando as seguintes anotações:

apiVersion: batch/v1
kind: Job
spec:
  template:
    metadata:
      annotations:
        autoscaling.x-k8s.io/consume-provisioning-request: PROVISIONING_REQUEST_NAME
        autoscaling.x-k8s.io/provisioning-class-name: "queued-provisioning.gke.io"
    spec:
      ...

A chave de anotação do pod consume-provisioning-request define qual ProvisioningRequest consumir. O GKE usa as anotações consume-provisioning-request e provisioning-class-name para fazer o seguinte:

  • Programar os pods apenas nos nós provisionados pelo início flexível com provisionamento em fila.
  • Para evitar a contagem dupla de solicitações de recursos entre pods e flex-start com provisionamento em fila no escalonador automático de cluster.
  • Injetar a anotação safe-to-evict: false, para impedir que o escalonador automático de cluster mova pods entre nós e interrompa os cálculos em lote. É possível alterar esse comportamento especificando safe-to-evict: true nas anotações do pod.

Observar o status de uma solicitação de provisionamento

O status de uma ProvisioningRequest define se um pod pode ser programado ou não. Use relógios do Kubernetes para observar as alterações com eficiência ou outras ferramentas já usadas para rastrear status de objetos do Kubernetes. A tabela a seguir descreve o possível status de uma solicitação de ProvisioningRequest e cada resultado possível:

Status da solicitação de provisionamento Descrição Possível resultado
Pendente A solicitação ainda não foi vista e processada. Após o processamento, a solicitação passa para o estado Accepted ou Failed.
Accepted=true A solicitação foi aceita e está aguardando a disponibilização dos recursos. A solicitação precisa passar para o estado Provisioned, se os recursos tiverem sido encontrados e os nós provisionados, ou para o estado Failed, se isso não tiver sido possível.
Provisioned=true Os nós estão prontos. Você tem 10 minutos para iniciar os pods para consumir recursos provisionados. Depois disso, o escalonador automático de cluster considera os nós como não necessários e os remove.
Failed=true Não é possível provisionar os nós devido a erros. Failed=true é um estado terminal. Solucione a condição com base nas informações nos campos Reason e Message da condição. Crie e tente de novo uma nova solicitação de ProvisioningRequest.
Provisioned=false Os nós ainda não foram provisionados.

Se for Reason=NotProvisioned, este é um estado temporário antes que todos os recursos estejam disponíveis.

Se Reason=QuotaExceeded, solucione o problema da condição com base nesse motivo e nas informações no campo Message da condição. Talvez seja necessário solicitar mais cota. Para mais detalhes, consulte a seção Verificar se a solicitação de provisionamento está limitada pela cota. Este Reason só está disponível com o GKE versão 1.29.2-gke.1181000 ou mais recente.

Se Reason=ResourcePoolExhausted e Message contiver Expected time is indefinite, selecione outra zona ou região ou ajuste os recursos solicitados.

Iniciar os pods

Quando a solicitação de ProvisioningRequest atingir o status Provisioned=true, será possível executar seu job para iniciar os pods. Isso evita a proliferação de pods não programáveis para solicitações pendentes ou com falha, o que pode afetar o desempenho do kube-scheduler e do escalonador automático de cluster.

Como alternativa, se você não se importa em ter pods não programáveis, crie pods em paralelo com a solicitação de ProvisioningRequest.

Cancelar o pedido de ProvisioningRequest

Para cancelar a solicitação antes que ela seja provisionado, exclua a ProvisioningRequest:

kubectl delete provreq PROVISIONING_REQUEST_NAME -n NAMESPACE

Na maioria dos casos, a exclusão de ProvisioningRequest interrompe a criação dos nós. No entanto, dependendo do tempo, por exemplo, se os nós já estiverem sendo provisionados, eles ainda poderão ser criados. Nesses casos, o escalonador automático de cluster removerá os nós após 10 minutos, se nenhum pod for criado.

Resolver problemas de cota

Todas as VMs provisionadas pelas solicitações de provisionamento usam cotas preemptivas.

O número de ProvisioningRequests com o estado Accepted é limitado por uma cota dedicada. Você configura a cota para cada projeto, uma configuração de cota por região.

Verificar a cota no console do Google Cloud

Para verificar o nome do limite de cota e o uso atual no console doGoogle Cloud , siga estas etapas:

  1. Acesse a página Cotas no console do Google Cloud :

    Acessar "Cotas"

  2. Na caixa Filtro, selecione a propriedade Métrica, digite active_resize_requests e pressione Enter.

O valor padrão é 100. Para aumentar a cota, siga as etapas listadas em Solicitar ajuste de cota.

Verificar se a solicitação de ProvisioningRequest está limitada pela cota

Se a solicitação ProvisioningRequest estiver demorando mais do que o esperado para ser atendida, verifique se ela não está limitada pela cota. Talvez seja necessário solicitar mais cota.

Para clusters que executam a versão 1.29.2-gke.1181000 ou posterior, verifique se limitações específicas de cota estão impedindo que a solicitação seja atendida:

kubectl describe provreq PROVISIONING_REQUEST_NAME \
    --namespace NAMESPACE

A saída é semelhante a esta:

…
Last Transition Time:  2024-01-03T13:56:08Z
    Message:               Quota 'NVIDIA_P4_GPUS' exceeded. Limit: 1.0 in region europe-west4.
    Observed Generation:   1
    Reason:                QuotaExceeded
    Status:                False
    Type:                  Provisioned
…

Neste exemplo, o GKE não pode implantar nós porque não há cota suficiente na região de europe-west4.

Migrar pools de nós do provisionamento em fila para o início flexível

A opção de consumo início flexível cria VMs de início flexível. Para migrar pools de nós criados usando a flag --enable-queued-provisioning para usar o flex-start, siga estas etapas:

  1. Verifique se o pool de nós está vazio:

    kubectl get nodes -l cloud.google.com/gke-nodepool=NODEPOOL_NAME
    
  2. Atualize o pool de nós para VMs de início flexível:

    gcloud container node-pools update NODEPOOL_NAME \
      --cluster=CLUSTER_NAME --flex-start
    

Essa operação faz o seguinte:

  • Atualize o pool de nós para um pool de nós de VMs de início flexível.
  • Aplicar os preços dos nós que usam VMs de início flexível.

Todos os nós em clusters que executam a versão 1.32.2-gke.1652000 ou posterior, a versão mínima para nós que usam VMs de início flexível, usam upgrades de curta duração.

A seguir