Este documento descreve ferramentas e práticas recomendadas para maximizar a utilização de recursos e minimizar o tempo de inatividade de cargas de trabalho heterogêneas de IA/ML no Google Kubernetes Engine (GKE), especialmente quando não há capacidade em reservas ou por recursos sob demanda. Cargas de trabalho heterogêneas se referem a diferentes tipos de cargas de trabalho de IA/ML que são executadas simultaneamente no mesmo cluster do GKE. Por exemplo, é possível executar um serviço de inferência on-line sensível à latência junto com uma série de jobs de treinamento em lote interrompíveis.
Este guia fornece recomendações para administradores e operadores de plataforma e especialistas em dados e IA.
Benefícios da priorização de cargas de trabalho de IA/ML
As cargas de trabalho heterogêneas têm prioridades diferentes e compartilham capacidade e recursos limitados. As práticas recomendadas nesta página descrevem como configurar o GKE e ferramentas de código aberto para ajudar você a ter os seguintes benefícios:
- Minimizar o tempo de inatividade para cargas de trabalho de alta prioridade.
- Execute rapidamente cargas de trabalho de alta prioridade.
- Otimizar o consumo de recursos.
Contexto
O GKE é compatível com as seguintes ferramentas de código aberto para otimizar o uso de recursos.
Kueue:um sistema de enfileiramento de cargas de trabalho nativo do Kubernetes projetado para cargas de trabalho de computação em lote, de IA e de alto desempenho. O Kueue pode ser estendido para gerenciar outros tipos de carga de trabalho, como os definidos por definições de recursos personalizados como
leaderworkerset. O Kueue gerencia cotas e como as cargas de trabalho as consomem em um cluster do Kubernetes. O Kueue decide quando uma carga de trabalho espera, quando uma carga de trabalho é iniciada (por exemplo, criando o pod) e quando um pod pertencente a uma carga de trabalho é interrompido.Para mais informações sobre o Kueue, consulte a documentação de conceitos do Kueue.
Troca a quente:uma técnica que reduz o tempo médio de recuperação (MTTR). O Hotswap permite a remoção com base na prioridade da carga de trabalho quando os recursos do cluster estão totalmente utilizados e não há capacidade adicional disponível, seja de instâncias sob demanda ou reservas atuais.
- Quando um nó que hospeda uma carga de trabalho fica sem integridade, ela é reprogramada em nós sobressalentes qualificados. Se não houver nós extras disponíveis, o Hotswap poderá interromper uma carga de trabalho de baixa prioridade para abrir espaço para a carga de trabalho que está sendo recuperada.
- Se você configurar seus pods com
PriorityClass, a carga de trabalho configurada com maior prioridade vai remover uma carga de trabalho de baixa prioridade em execução para adquirir os recursos dela. Esse processo de remoção é conhecido como remoção por substituição.
Casos de uso
Use a tabela a seguir para entender as práticas recomendadas de cada caso de uso:
| Caso de uso | Prática recomendada | Descrição |
|---|---|---|
| Várias cargas de trabalho com prioridades diferentes | Use o Kueue para definir filas e atribuir prioridades às cargas de trabalho com base na importância delas. O Kueue pode gerenciar a cota para que determinadas equipes ou projetos tenham acesso a uma quantidade definida de recursos. |
Com o Kueue, é possível aplicar as seguintes configurações:
Para testar a configuração de prática recomendada, consulte o exemplo do Kueue neste documento. |
| É preciso reduzir o MTTR atual. | Use o Hotswap para reagendar cargas de trabalho em recursos íntegros quando ocorrer uma interrupção e para remover cargas de trabalho de baixa prioridade em favor de cargas de trabalho de alta prioridade. |
O hot swap permite aplicar as seguintes configurações:
Para testar a configuração de prática recomendada, consulte o exemplo de troca a quente neste documento. |
| Várias cargas de trabalho de IA competindo por recursos limitados | Combine Kueue e Hotswap. Essa combinação oferece um sistema robusto que prioriza cargas de trabalho críticas durante o agendamento inicial e o tempo de execução. |
Com o Kueue e o Hotswap, é possível aplicar as seguintes configurações:
Para testar a configuração de prática recomendada, consulte o exemplo de Kueue e Hotswap neste documento. |
Exemplos de implementações de práticas recomendadas
Os exemplos a seguir demonstram como implementar o Kueue e o Hotswap e como combiná-los para as práticas recomendadas descritas na seção anterior.
Kueue
O exemplo de manifesto a seguir mostra uma configuração do Kueue:
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: tpu-v6e-slice
spec:
nodeLabels:
cloud.google.com/gke-tpu-accelerator: tpu-v6e-slice
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: tpu-training-cq
spec:
resourceGroups:
- flavors:
- name: tpu-v6e-slice
resources:
- name: google.com/tpu
nominalQuota: 32
queueingStrategy: BestEffortFIFO
preemption:
reclaimWithinCohort: Never
reclaimOutOfCohort:
enable: true
reclaimMoreThanNominalQuota: false
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
name: default-queue
namespace: default
spec:
clusterQueue: tpu-training-cq
Esse manifesto faz o seguinte:
- Define um
ResourceFlavorchamadotpu-v6e-sliceque especifica os rótulos de nó para frações de TPU v6e. - Define um
ClusterQueuechamadotpu-training-cqque gerencia a cota para recursos de TPU. - Define um
LocalQueuechamadodefault-queueque permite que cargas de trabalho no namespacedefaultusem a fila do clustertpu-training-cq.
Hotswap
O exemplo a seguir mostra uma configuração de troca a quente que define
duas classes de prioridade, low-priority-job e high-priority-job. Essa configuração do Hotswap cria uma carga de trabalho do JobSet de alta prioridade e usa o MaxText.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority-job
value: 1000000
globalDefault: false
description: "This priority class should be used for low priority pods only."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-job
value: 2000000
globalDefault: false
description: "This priority class should be used for critical pods only."
---
apiVersion: jobset.x-k8s.io/v1alpha2
kind: JobSet
metadata:
name: high-jax-trillium
annotations:
alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
spec:
failurePolicy:
maxRestarts: 10
restartStrategy: BlockingRecreate
replicatedJobs:
- name: slice
replicas: 2
template:
spec:
backoffLimit: 0
completions: 4
parallelism: 4
template:
spec:
nodeSelector:
cloud.google.com/gke-tpu-accelerator: tpu-v6e-slice
cloud.google.com/gke-tpu-topology: 4x4
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
priorityClassName: high-priority-job
containers:
- name: jax-program
image: <IMAGE LOCATION>
command:
- python3
- MaxText/train.py
- MaxText/configs/base.yml
- model_name=llama2-7b
- run_name=<UNIQUE RUN NAME>
- steps=300
- base_output_directory=gs://<OUTPUT BUCKET>
- dataset_path=gs://max-datasets-rogue
- max_target_length=4096
- dataset_type=synthetic
- enable_checkpointing=False
resources:
limits:
google.com/tpu: 4
Com base nessa configuração, o Hotswap executa as seguintes ações:
- Se uma falha de infraestrutura interromper a carga de trabalho de alta prioridade, o JobSet vai reiniciá-la. O Hotswap força a interrupção da carga de trabalho de baixa prioridade para reagendar a de alta prioridade antes que a infraestrutura se recupere. A carga de trabalho de baixa prioridade permanece com status de falha. Esse processo reduz significativamente o tempo ocioso da carga de trabalho.
- Quando a infraestrutura é recuperada, o Hotswap reagenda a carga de trabalho de baixa prioridade no pool de nós recuperado.
Kueue e Hotswap
Combine o Kueue e o Hotswap quando você opera em um ambiente complexo com recursos limitados. Essa combinação oferece um sistema robusto que prioriza cargas de trabalho críticas durante o agendamento inicial e o tempo de execução.
O exemplo a seguir mostra uma configuração combinada do Kueue e do Hotswap. Este exemplo usa o MaxText:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority-job
value: 1000000
globalDefault: false
description: "This priority class should be used for low priority pods only."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-job
value: 2000000
globalDefault: false
description: "This priority class should be used for critical pods only."
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: tpu-v6e-slice
spec:
nodeLabels:
cloud.google.com/gke-tpu-accelerator: tpu-v6e-slice
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: tpu-training-cq
spec:
resourceGroups:
- flavors:
- name: tpu-v6e-slice
resources:
- name: google.com/tpu
nominalQuota: 32
queueingStrategy: BestEffortFIFO
preemption:
reclaimWithinCohort: Never
reclaimOutOfCohort:
enable: true
reclaimMoreThanNominalQuota: false
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
name: default-queue
namespace: default
spec:
clusterQueue: tpu-training-cq
---
apiVersion: jobset.x-k8s.io/v1alpha2
kind: JobSet
metadata:
name: low-jax-trillium
annotations:
kueue.x-k8s.io/queue-name: default-queue
alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
spec:
failurePolicy:
maxRestarts: 10
restartStrategy: BlockingRecreate
replicatedJobs:
- name: slice
replicas: 2
template:
spec:
backoffLimit: 0
completions: 4
parallelism: 4
template:
metadata:
labels:
kueue.x-k8s.io/managed-by: kueue
kueue.x-k8s.io/priority-class: low-priority-job
spec:
nodeSelector:
cloud.google.com/gke-tpu-accelerator: tpu-v6e-slice
cloud.google.com/gke-tpu-topology: 4x4
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
priorityClassName: low-priority-job
containers:
- name: jax-program
image: <IMAGE LOCATION>
command:
- python3
- MaxText/train.py
- MaxText/configs/base.yml
- model_name=llama2-7b
- run_name=low-priority-run
- steps=30000
- base_output_directory=gs://<OUTPUT BUCKET>
- dataset_path=gs://max-datasets-rogue
- max_target_length=4096
- dataset_type=synthetic
- enable_checkpointing=False
resources:
limits:
google.com/tpu: 4
---
apiVersion: jobset.x-k8s.io/v1alpha2
kind: JobSet
metadata:
name: high-jax-trillium
annotations:
kueue.x-k8s.io/queue-name: default-queue
alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
spec:
failurePolicy:
maxRestarts: 10
restartStrategy: BlockingRecreate
replicatedJobs:
- name: slice
replicas: 2
template:
spec:
backoffLimit: 0
completions: 4
parallelism: 4
template:
metadata:
labels:
kueue.x-k8s.io/managed-by: kueue
kueue.x-k8s.io/priority-class: high-priority-job
spec:
nodeSelector:
cloud.google.com/gke-tpu-accelerator: tpu-v6e-slice
cloud.google.com/gke-tpu-topology: 4x4
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
priorityClassName: high-priority-job
containers:
- name: jax-program
image: <IMAGE LOCATION>
command:
- python3
- MaxText/train.py
- MaxText/configs/base.yml
- model_name=llama2-7b
- run_name=high-priority-run
- steps=300
- base_output_directory=gs://<OUTPUT BUCKET>
- dataset_path=gs://max-datasets-rogue
- max_target_length=4096
- dataset_type=synthetic
- enable_checkpointing=False
resources:
limits:
google.com/tpu: 4
Com base nessa configuração, o Kueue é combinado com o Hotswap e realiza as seguintes ações:
- O Kueue gerencia a admissão de
low-jax-trilliumehigh-jax-trilliumJobSets na fila do cluster com base nas prioridades definidas e nos recursos disponíveis. - Se o JobSet
high-jax-trilliumfor interrompido por uma falha de infraestrutura, o Hotswap vai antecipar o JobSetlow-jax-trilliumpara reprogramar o JobSet de alta prioridade. - O hotswap garante que o JobSet de alta prioridade seja reiniciado rapidamente, minimizando o tempo ocioso.
- Quando a infraestrutura é recuperada, o Hotswap reagenda o JobSet de baixa prioridade no pool de nós recuperado.
A seguir
- Saiba como implantar cargas de trabalho de GPU no GKE.
- Saiba como implantar cargas de trabalho de TPU no GKE.