Este tutorial mostra como otimizar os recursos disponíveis agendando tarefas no Google Kubernetes Engine (GKE) com o Kueue. Neste tutorial, vai aprender a usar o Kueue para gerir e agendar eficazmente trabalhos em lote, melhorar a utilização de recursos e simplificar a gestão da carga de trabalho. Configura um cluster partilhado para duas equipas de inquilinos em que cada equipa tem o seu próprio espaço de nomes e cada equipa cria tarefas que partilham recursos globais. Também configura o Kueue para agendar as tarefas com base nas quotas de recursos que definir.
Este tutorial destina-se a arquitetos da nuvem e engenheiros de plataformas que tenham interesse em implementar um sistema de processamento em lote com o GKE. Para saber mais sobre as funções comuns e as tarefas de exemplo referenciadas no Google Cloud conteúdo, consulte Funções e tarefas comuns de utilizadores do GKE.
Antes de ler esta página, certifique-se de que conhece o seguinte:
Contexto
As tarefas são aplicações executadas até à conclusão, como aprendizagem automática, renderização, simulação, análise, CI/CD e cargas de trabalho semelhantes.
O Kueue é um programador de tarefas nativo da nuvem que funciona com o programador do Kubernetes predefinido, o controlador de tarefas e o dimensionamento automático de clusters para fornecer um sistema de processamento em lote completo. O Kueue implementa o enfileiramento de tarefas, decidindo quando as tarefas devem esperar e quando devem começar, com base em quotas e numa hierarquia para partilhar recursos de forma justa entre as equipas.
O Kueue tem as seguintes características:
- Está otimizado para arquiteturas na nuvem, onde os recursos são heterogéneos, intercambiáveis e escaláveis.
- Oferece um conjunto de APIs para gerir quotas elásticas e gerir o enfileiramento de tarefas.
- Não reimplementa capacidades existentes, como o dimensionamento automático, o agendamento de pods ou a gestão do ciclo de vida de tarefas.
- O Kueue tem suporte incorporado para a API Kubernetes
batch/v1.Job
. - Pode integrar-se com outras APIs de emprego.
O Kueue refere-se a tarefas definidas com qualquer API como cargas de trabalho, para evitar a confusão com a API Kubernetes Job específica.
Crie o ResourceFlavor
Um ResourceFlavor é um objeto que representa as variações nos nós disponíveis no seu cluster, associando-os a etiquetas e taints de nós. Por exemplo, pode usar ResourceFlavors para representar VMs com diferentes garantias de aprovisionamento (por exemplo, spot versus a pedido), arquiteturas (por exemplo, CPUs x86 versus ARM), marcas e modelos (por exemplo, GPUs Nvidia A100 versus T4).
Neste tutorial, o cluster kueue-autopilot
tem recursos homogéneos.
Como resultado, crie um único ResourceFlavor para CPU, memória, armazenamento temporário e GPUs, sem etiquetas nem restrições.
kubectl apply -f flavors.yaml
Crie a ClusterQueue
Uma ClusterQueue é um objeto com âmbito de cluster que gere um conjunto de recursos, como CPU, memória e GPU. Faz a gestão dos ResourceFlavors, limita a utilização e determina a ordem em que as cargas de trabalho são admitidas.
Implemente a ClusterQueue:
kubectl apply -f cluster-queue.yaml
A ordem de consumo é determinada por .spec.queueingStrategy
, em que existem duas configurações:
BestEffortFIFO
- A configuração da estratégia de colocação em fila predefinida.
- A admissão da carga de trabalho segue a regra de primeiro a entrar, primeiro a sair (FIFO), mas se não houver quota suficiente para admitir a carga de trabalho no início da fila, é tentada a seguinte na fila.
StrictFIFO
- Garante a semântica FIFO.
- A carga de trabalho no início da fila pode bloquear a colocação em fila até que a carga de trabalho possa ser admitida.
Em cluster-queue.yaml
, cria uma nova ClusterQueue denominada cluster-queue
. Esta
ClusterQueue gere quatro recursos: cpu
, memory
, nvidia.com/gpu
e
ephemeral-storage
com o tipo criado em flavors.yaml
.
A quota é consumida pelos pedidos nas especificações do pod da carga de trabalho.
Cada opção inclui limites de utilização representados como .spec.resourceGroups[].flavors[].resources[].nominalQuota
. Neste caso, o ClusterQueue admite cargas de trabalho se e só se:
- A soma dos pedidos de CPU é inferior ou igual a 10
- A soma dos pedidos de memória é inferior ou igual a 10 Gi
- A soma dos pedidos de GPU é inferior ou igual a 10
- A soma do armazenamento usado é inferior ou igual a 10 Gi
Crie o LocalQueue
Uma LocalQueue é um objeto com espaço de nomes que aceita cargas de trabalho de utilizadores no espaço de nomes.
As LocalQueues de diferentes espaços de nomes podem apontar para a mesma ClusterQueue, onde podem partilhar a quota de recursos. Neste caso,
LocalQueue do espaço de nomes team-a
e team-b
aponta para a mesma ClusterQueue
cluster-queue
em .spec.clusterQueue
.
Cada equipa envia as respetivas cargas de trabalho para a LocalQueue no seu próprio espaço de nomes. Em seguida, o ClusterQueue atribui recursos.
Implemente as LocalQueues:
kubectl apply -f local-queue.yaml
Crie tarefas e observe as cargas de trabalho admitidas
Nesta secção, cria tarefas do Kubernetes no espaço de nomes team-a
. Um controlador de tarefas no Kubernetes cria um ou mais pods e garante que executam com êxito uma tarefa específica.
O trabalho no espaço de nomes team-a
tem os seguintes atributos:
- Aponta para o
lq-team-a
LocalQueue. - Pede recursos de GPU definindo o campo
nodeSelector
comonvidia-tesla-t4
. - É composto por três pods que ficam em suspensão durante 10 segundos em paralelo. As tarefas são limpas após 60 segundos, de acordo com o valor definido no campo
ttlSecondsAfterFinished
. - Requer 1500 milliCPU, 1536 Mi de memória, 1536 Mi de armazenamento efémero e três GPUs, uma vez que existem três pods.
As tarefas também são criadas no ficheiro
job-team-b.yaml
onde o respetivo espaço de nomes pertence a team-b
, com pedidos para
representar diferentes equipas com diferentes necessidades.
Para saber mais, consulte o artigo sobre a implementação de cargas de trabalho de GPU no Autopilot.
Num novo terminal, observe o estado da ClusterQueue que é atualizado a cada dois segundos:
watch -n 2 kubectl get clusterqueue cluster-queue -o wide
Num novo terminal, observe o estado dos nós:
watch -n 2 kubectl get nodes -o wide
Num novo terminal, crie trabalhos para LocalQueue a partir do espaço de nomes
team-a
eteam-b
a cada 10 segundos:./create_jobs.sh job-team-a.yaml job-team-b.yaml 10
Observe as tarefas a serem colocadas em fila, admitidas na ClusterQueue e os nós a serem iniciados com o GKE Autopilot.
Obter uma tarefa do espaço de nomes
team-a
:kubectl -n team-a get jobs
O resultado é semelhante ao seguinte:
NAME COMPLETIONS DURATION AGE sample-job-team-b-t6jnr 3/3 21s 3m27s sample-job-team-a-tm7kc 0/3 2m27s sample-job-team-a-vjtnw 3/3 30s 3m50s sample-job-team-b-vn6rp 0/3 40s sample-job-team-a-z86h2 0/3 2m15s sample-job-team-b-zfwj8 0/3 28s sample-job-team-a-zjkbj 0/3 4s sample-job-team-a-zzvjg 3/3 83s 4m50s
Copie um nome de trabalho do passo anterior e observe o estado de admissão e os eventos de um trabalho através da API Workloads:
kubectl -n team-a describe workload JOB_NAME
Quando os trabalhos pendentes começarem a aumentar a partir da ClusterQueue, termine o script premindo
CTRL + C
no script em execução.Quando todas as tarefas estiverem concluídas, repare que os nós estão a ser reduzidos.