Quando várias equipes compartilham um cluster para cargas de trabalho de IA, machine learning (ML) e processamento em lote, a contenção e a subutilização de recursos tornam-se problemas frequentes. Use ElasticQuotaTree, ack-kube-queue e ack-scheduler em conjunto para atribuir cotas hierárquicas de recursos a unidades organizacionais, enfileirar jobs automaticamente e recuperar recursos quando os mínimos garantidos não puderem ser atendidos.
Pré-requisitos
Antes de começar, verifique se você tem:
O componente ack-koordinator instalado. Consulte Instale ack-koordinator
Como funciona
Três componentes atuam em conjunto para gerenciar a alocação de recursos e o agendamento de jobs:
ElasticQuotaTree: Define cotas hierárquicas de recursos mapeadas para unidades organizacionais (equipes, departamentos). Cada nó folha na árvore corresponde a um ou mais namespaces, e os jobs enviados para esses namespaces ficam vinculados à cota do nó.
ack-kube-queue: Monitora o cluster em busca de novos jobs, cria uma QueueUnit para cada job e o encaminha para a fila correta com base no namespace do job. Os jobs aguardam na fila até que sua solicitação de recursos caiba na cota disponível e, então, são liberados para o agendador.
ack-scheduler: Seleciona os nós para executar os jobs liberados da fila.
Caso o requisito mínimo de recursos de um job não possa ser satisfeito, o sistema de agendamento recupera automaticamente recursos dos nós de cota que estiverem utilizando mais do que sua alocação min.
Configure cotas de recursos com ElasticQuotaTree
O ElasticQuotaTree usa uma estrutura de árvore para atribuir cotas de CPU, memória e GPU às equipes. O exemplo a seguir ilustra uma empresa com três departamentos — devops, algoritmo (com subequipes de texto e vídeo) e infraestrutura (com uma subequipe de testes) — cada um mapeado para namespaces dedicados.
Regras de cota
Antes de criar um ElasticQuotaTree, verifique se sua configuração atende às seguintes restrições:
|
Regra |
Requisito |
|
Posicionamento de namespace |
Monte namespaces apenas em nós folha. Nós pai não podem ter namespaces. |
|
Min/max do nó |
Em qualquer nó, |
|
Regra de min do pai |
O valor |
|
Regra de max do pai |
O valor |
Semântica dos parâmetros:
|
Parâmetro |
Padrão |
Comportamento |
|
|
|
Limite mínimo garantido de recursos. É possível enviar jobs mesmo quando |
|
|
|
Teto de recursos. Os jobs não podem usar mais recursos do que este valor. |
Crie os namespaces e o ElasticQuotaTree
Aplique o manifesto a seguir para criar os namespaces e definir a árvore de cotas. Os comentários no YAML mostram como cada nó se relaciona com o diagrama acima.
---
apiVersion: v1
kind: Namespace
metadata:
name: devops
---
apiVersion: v1
kind: Namespace
metadata:
name: text1
---
apiVersion: v1
kind: Namespace
metadata:
name: text2
---
apiVersion: v1
kind: Namespace
metadata:
name: video
---
apiVersion: v1
kind: Namespace
metadata:
name: test1
---
apiVersion: v1
kind: Namespace
metadata:
name: test2
---
apiVersion: scheduling.sigs.k8s.io/v1beta1
kind: ElasticQuotaTree
metadata:
name: elasticquotatree # Only one ElasticQuotaTree is supported.
namespace: kube-system # Must be created in the kube-system namespace to take effect.
spec:
root:
name: root # Root node: total cluster quota
min:
cpu: 100
memory: 50Gi
nvidia.com/gpu: 16
max:
cpu: 100
memory: 50Gi
nvidia.com/gpu: 16
children:
- name: devops # Child of root
min:
cpu: 20
memory: 10Gi
nvidia.com/gpu: 4
max:
cpu: 40
memory: 20Gi
nvidia.com/gpu: 8
namespaces:
- devops
- name: algorithm # Child of root; parent of text and video
min:
cpu: 50
memory: 25Gi
nvidia.com/gpu: 10
max:
cpu: 80
memory: 50Gi
nvidia.com/gpu: 14
children:
- name: text # Child of algorithm
min:
cpu: 40
memory: 15Gi
nvidia.com/gpu: 8
max:
cpu: 40
memory: 30Gi
nvidia.com/gpu: 10
namespaces:
- text1
- text2
- name: video # Child of algorithm
min:
cpu: 12
memory: 12Gi
nvidia.com/gpu: 2
max:
cpu: 14
memory: 14Gi
nvidia.com/gpu: 4
namespaces:
- video
- name: infrastructure # Child of root; parent of test
min:
cpu: 30
memory: 15Gi
nvidia.com/gpu: 2
max:
cpu: 50
memory: 30Gi
nvidia.com/gpu: 4
children:
- name: test # Child of infrastructure
min:
cpu: 30
memory: 15Gi
nvidia.com/gpu: 2
max:
cpu: 50
memory: 30Gi
nvidia.com/gpu: 4
namespaces:
- test1
- test2
Gerencie filas de jobs com ack-kube-queue
Após aplicar o ElasticQuotaTree, o ack-kube-queue cria automaticamente uma fila para cada nó folha no cluster. A cota de cada nó folha é mapeada para uma fila. Os jobs enviados a um namespace são atribuídos à fila correspondente ao nó de cota desse namespace.
Associação de filas
Um controlador no ack-kube-queue gerencia automaticamente os recursos de fila no cluster. Esse controlador se baseia no ElasticQuotaTree e mapeia a associação entre cotas e namespaces definidos no ElasticQuotaTree para as filas correspondentes.
Por exemplo, o namespace video é um nó folha sob o nó algorithm, filho de root. O ack-kube-queue cria uma fila chamada root-algorithm-video para esse nó. Ao enviar um RayJob no namespace video, o ack-kube-queue cria uma QueueUnit e a encaminha para a fila root-algorithm-video.
Se o total de recursos solicitados pelo RayJob couber na cota disponível de root-algorithm-video, o job sai da fila e passa para o ack-scheduler atribuir os nós.
Operação da fila e transferência de suspensão
O ack-kube-queue controla a execução do job por meio do campo spec.suspend do RayJob:
Envie um RayJob com
spec.suspend: true. Isso impede que o operador KubeRay crie pods imediatamente.O ack-kube-queue detecta o job, cria uma QueueUnit e a coloca na fila correspondente.
Quando a política de enfileiramento permite que o job prossiga, o ack-kube-queue define
spec.suspendcomofalse.O operador KubeRay identifica a alteração e cria os pods. Em seguida, o ack-scheduler atribui os pods aos nós.
Se um job parecer travado na fila, verifique sespec.suspendfoi definido comofalse. Caso contrário, confirme se a solicitação de recursos do job cabe na cota disponível da fila atribuída.