O Dynamic Resource Allocation, ou DRA, do Kubernetes não elimina o projeto HAMi para compartilhamento de unidades de processamento gráfico, mas altera a distribuição de funções entre ambos. Depois que o DRA alcançou disponibilidade geral no Kubernetes v1.34 e foi ativado por padrão desde a v1.35, o Kubernetes passou a ser capaz de compreender e agendar nativamente solicitações de cotas parciais de recursos do dispositivo. Já a imposição dessas cotas dentro do contêiner durante as chamadas CUDA não faz parte das funções do DRA; é nesse ponto que o HAMi-core continua essencial.
O artigo da CNCF, escrito por Mesut Oezdil, apresenta uma análise da diferença entre as duas etapas e explica como o HAMi reconstrói parte de seu ecossistema sobre o DRA, em vez de abandonar o projeto. O autor observa que a questão não é se um dos projetos substituirá o outro, mas qual função do HAMi passou a ser coberta pelas capacidades nativas do Kubernetes.
Por que o compartilhamento de GPU precisou de soluções específicas?
A interface Device Plugin do Kubernetes era essencialmente capaz de contar dispositivos. A solicitação tradicional, como nvidia.com/gpu: 1, significava reservar uma placa inteira, sem uma linguagem nativa para solicitar 8.000 megabytes da memória de uma placa ou 10% de sua capacidade computacional.
Para lidar com isso, o HAMi utiliza recursos estendidos como nvidia.com/gpumem e nvidia.com/gpucores. Porém, o agendador padrão do Kubernetes trata esses valores como números opacos; ele não sabe que a memória e a capacidade computacional devem vir da mesma placa física, nem consegue determinar sozinho se várias cotas ultrapassarão a capacidade de uma determinada placa.
Por isso, o fluxo tradicional depende de um webhook para modificar a solicitação, de uma extensão específica do agendador que filtra os nós e escolhe o identificador do dispositivo e, depois, registra a decisão em uma annotation. O Device Plugin lê essa decisão posteriormente para injetar limites como CUDA_DEVICE_MEMORY_LIMIT_0=8000m e CUDA_DEVICE_SM_LIMIT=10, além de carregar previamente a biblioteca libvgpu.so para impor os limites.
Segundo o artigo, a DaoCloud executou mais de 10.000 unidades de GPU em mais de 10 centros de dados usando essa abordagem. No entanto, sua arquitetura continua vinculada a um formato específico de annotations e a componentes compreendidos pelo HAMi — lacuna que o DRA foi projetado para resolver.
O que o DRA acrescenta?
O DRA substitui o modelo de contagem de dispositivos por um modelo baseado em reivindicações, com quatro objetos principais na API resource.k8s.io/v1:
- ResourceSlice: publicado pelo driver do dispositivo, descreve o hardware real de cada nó, incluindo modelo, memória e arquitetura.
- DeviceClass: define classes de dispositivos e seus filtros usando expressões CEL.
- ResourceClaim: criado pelo proprietário da carga de trabalho para solicitar um dispositivo de acordo com a classe, os seletores e as restrições.
- ResourceClaimTemplate: cria uma reivindicação independente para cada réplica da carga de trabalho.
O agendador atribui um dispositivo específico à reivindicação antes de vincular o contêiner, e o resultado aparece no status do ResourceClaim como um objeto de API estruturado. Isso dá à decisão um local nativo que o kubectl pode ler, que o RBAC pode proteger e sobre o qual outros controladores podem construir, em vez de armazená-la como uma cadeia de texto em uma annotation.
Mas o DRA básico, por si só, não é suficiente para compartilhar memória no estilo do HAMi. A extensão importante aqui é a Consumable Capacity, que surgiu experimentalmente na v1.34 por trás do gate DRAConsumableCapacity e passou a ser experimental e ativada por padrão desde a v1.36. Essa extensão permite que o driver anuncie que o dispositivo aceita várias alocações e também permite que a reivindicação solicite uma quantidade específica de um recurso nomeado no dispositivo, como memória ou capacidade computacional.
Assim, o mapeamento dos recursos do HAMi se torna praticamente direto: gpumem transforma-se em uma solicitação de capacidade de memória, gpucores transforma-se em uma solicitação de capacidade computacional, enquanto o cálculo para determinar se a placa ainda possui a capacidade solicitada passa da extensão de agendamento do HAMi para o próprio agendador do Kubernetes.
Agendamento não significa imposição de limites
A análise enfatiza que o DRA acompanha as promessas feitas pelo agendador, mas não impede que o contêiner as ultrapasse durante a execução. As chamadas CUDA não sabem o que o ResourceClaim declara, e uma carga de trabalho voraz pode tentar consumir memória adicional às custas de outro contêiner.
O HAMi-core assume essa função por meio de uma biblioteca C, libvgpu.so, que intercepta chamadas da CUDA e da NVIDIA Management Library e aplica os limites no espaço do usuário. De acordo com o exemplo apresentado no artigo, se dois contêineres recebem 8.000 megabytes cada um, o contêiner que exceder sua cota recebe um erro CUDA de falta de memória ao atingir seu limite, enquanto o outro continua funcionando.
Essa proteção por software não substitui a particionamento de hardware em ambientes hostis de múltiplos locatários. Uma carga de trabalho que contorne o carregamento prévio da biblioteca, use vinculação estática ao driver CUDA ou aproveite configurações como CUDA_DISABLE_CONTROL pode escapar da interceptação. O autor observa que a NVIDIA Multi-Instance GPU, ou MIG, é mais adequada para isolamento de hardware, enquanto a interceptação por software oferece granularidade de até 1 megabyte para memória e 1% para computação, em comparação com os perfis MIG fixos.
Como o HAMi reconstrói seu ecossistema sobre o DRA?
A nova arquitetura está distribuída em três repositórios com funções diferentes:
- k8s-dra-driver: publica a memória e a capacidade computacional de cada GPU como capacidade consumível nos ResourceSlices, executa o plugin do kubelet e conecta os contêineres por meio do CDI, anexando a imposição do HAMi-core.
- HAMi-DRA: é um webhook de mutação de admissão que remove os recursos estendidos tradicionais das solicitações e cria ResourceClaims equivalentes, mantendo as annotations específicas para direcionamento por UUID e tipo de dispositivo. Segundo o artigo, o HAMi-DRA v0.2.0 ficou pronto para produção com o HAMi v2.9; posteriormente, a série de versões avançou para a v0.2.1.
- HAMi: documenta o modo DRA como uma opção de instalação desde a versão v2.8, além de ativar o componente de monitoramento por padrão e expor métricas dos dispositivos por contêiner via Prometheus na porta 31995.
Um dos benefícios do HAMi-DRA é deixar o agendamento a cargo do agendador que gerencia o cluster, permitindo usar o Volcano, o KAI Scheduler ou qualquer outro agendador que compreenda DRA sem adicionar uma integração específica com o HAMi. Porém, essa decisão tem um custo: o HAMi-DRA não possui um agendador próprio e, portanto, não garante decisões conscientes da topologia, como escolher um par de unidades de GPU conectadas por NVLink.
Requisitos e escolha prática
O modo DRA requer Kubernetes v1.34 ou posterior com DRAConsumableCapacity ativado. Nas versões v1.34 e v1.35, o gate é experimental e desativado por padrão, o que pode impedir seu uso em serviços gerenciados que não permitem alterar as configurações do servidor da API. Na v1.36, ele passou a ser experimental e ativado por padrão. Também é necessário um runtime compatível com CDI, como containerd ou CRI-O com CDI ativado, um driver NVIDIA na versão 440 ou posterior e um driver DRA adequado ao tipo de acelerador.
O artigo descreve o caminho da NVIDIA como o mais maduro, com suporte ao Ascend e ao Enflame disponível e a documentação do Hygon DCU por meio do k8s-dcu-dra-driver. Em contrapartida, o modo tradicional do HAMi cobre mais de 12 famílias de dispositivos desde a v2.9, incluindo Cambricon MLUs, Iluvatar, MetaX, Moore Threads, Kunlunxin, AWS Neuron e Vastai. Por isso, os clusters com múltiplos fornecedores continuam sendo candidatos a permanecer no caminho tradicional até que a cobertura dos drivers DRA se amplie.
Não se deve executar o modo DRA e o modo tradicional Device Plugin no mesmo cluster, pois os dois sistemas de agendamento parecerão gerenciar a mesma capacidade sem ter visibilidade dos compromissos assumidos pelo outro sistema. De acordo com a avaliação do autor, o modo tradicional é adequado para clusters gerenciados que não disponibilizam feature gates, para versões mais antigas e para frotas de vários fornecedores. Já os clusters NVIDIA que controlam o plano de controle do Kubernetes, especialmente no v1.36, podem experimentar o modo DRA em um ambiente de teste, começando pelo HAMi-DRA para evitar alterações nos arquivos de implantação atuais.
O Consumable Capacity continua definitivamente instável no Kubernetes, e o chart Helm do k8s-dra-driver ainda está classificado como em desenvolvimento; além disso, a cobertura de fornecedores no lado do DRA continua inferior à do modo tradicional. A conclusão do artigo é que o DRA assume a linguagem de solicitação e o agendamento, enquanto o HAMi-core mantém a capacidade de execução dentro do contêiner; em outras palavras, a relação entre eles tende à integração, não à substituição.