Kamaji e HAMi: como testar Kubernetes multi-tenant para workloads de GPU
Uma plataforma de processamento acelerado precisa responder a duas perguntas diferentes: quem controla cada ambiente Kubernetes e como os workloads utilizam as GPUs disponíveis. Misturar essas decisões costuma produzir testes enganosos: dois Pods executando simultaneamente não demonstram isolamento entre clientes, e duas APIs Kubernetes independentes não demonstram compartilhamento seguro de uma GPU.
Kamaji organiza os control planes; HAMi gerencia o compartilhamento de aceleradores dentro do cluster em que está instalado. A combinação é útil, mas não cria automaticamente um pool de GPUs compartilhado entre clusters independentes. A documentação do Kamaji estabelece que cada worker pertence a um único tenant cluster. (kamaji.clastix.io)
Este artigo propõe um laboratório verificável, seguido de critérios para evolução à produção. Os valores são didáticos; os comandos não representam um ambiente executado nem resultados de benchmark.
1. Conceitos e fronteiras de responsabilidade
Kamaji: Kubernetes com control planes hospedados
Kamaji é um operador que reconcilia recursos TenantControlPlane, definidos por uma Custom Resource Definition, ou CRD. Cada recurso representa um control plane Kubernetes hospedado como Pods no management cluster, com API server, scheduler e controller manager próprios. Os workers conectam-se ao endpoint desse tenant. (kamaji.clastix.io)
O DataStore representa o armazenamento do estado dos control planes. Compartilhar sua infraestrutura não significa compartilhar uma única API Kubernetes. Entretanto, cria uma dependência operacional que deve entrar no planejamento de falhas e recuperação. (clastix.io)
HAMi: alocação e controle de recursos de GPU
HAMi significa Heterogeneous AI Computing Virtualization Middleware. No caminho NVIDIA com HAMi-core, os principais componentes são:
- Webhook: participa da admissão e prepara workloads para o fluxo de scheduling.
- Scheduler e extender: selecionam nós e dispositivos considerando os recursos solicitados.
- Device plugin: integra a alocação dos dispositivos ao kubelet.
- HAMi-core: intercepta chamadas CUDA dentro do contêiner para controlar memória e utilização computacional. (project-hami.io)
Isso não deve ser tratado como uma fronteira de segurança equivalente a uma máquina virtual ou ao particionamento por hardware. Para este projeto, considere o compartilhamento por software apropriado somente depois de avaliar confiança, privilégios e compatibilidade das aplicações. O próprio mecanismo depende da interceptação de chamadas da aplicação. (github.com)
Três dimensões que precisam de testes separados
- Isolamento administrativo: identidades, APIs, Secrets e permissões.
- Isolamento de execução: workers, rede, armazenamento e runtime.
- Isolamento de recursos: memória de GPU, concorrência e interferência de desempenho.
Essa separação é importante porque multi-tenancy envolve tanto o control plane quanto o data plane; namespaces, isoladamente, não resolvem todas essas dimensões. (kubernetes.io)
2. Arquitetura do laboratório
Adote a seguinte topologia proposta:
Management cluster
├── Kamaji + datastore
├── TenantControlPlane tenant-a
└── TenantControlPlane tenant-b
Tenant A: API A → HAMi A → worker GPU A → Pods A1 e A2
Tenant B: API B → HAMi B → worker GPU B → Pods B1 e B2Neste desenho, A1 e A2 podem compartilhar a GPU do worker A. B1 e B2 podem compartilhar a GPU do worker B. A e B não disputam a mesma GPU física por ação automática do Kamaji ou do HAMi. Essa é uma consequência da associação exclusiva dos workers aos tenant clusters. (kamaji.clastix.io)
Se houver somente uma GPU disponível, teste um tenant cluster e dois namespaces para avaliar compartilhamento interno. Para testar duas APIs, o segundo tenant pode começar sem GPU, mas isso não valida isolamento entre dois pools acelerados.
3. Pré-requisitos e controle de versões
Prepare previamente:
- Management cluster com Kamaji, suas CRDs, cert-manager e datastore funcionando.
- StorageClass adequada ao datastore e mecanismo de exposição dos endpoints dos tenants.
- Workers Linux separados para A e B.
kubectl, Helm,kubeadmeenvsubstna estação de administração.- Plugin Container Network Interface, ou CNI, homologado para cada tenant.
O guia oficial do Kamaji documenta esse bootstrap. Aqui, o ponto de partida é um management cluster já preparado, não uma instalação completa de infraestrutura. (kamaji.clastix.io)
Nos workers GPU, prepare driver NVIDIA compatível com o hardware e a imagem CUDA, NVIDIA Container Toolkit e runtime. Este laboratório assume driver instalado no host e runtime NVIDIA configurado como padrão. Não mantenha dois device plugins registrando nvidia.com/gpu nos mesmos nós; se utilizar GPU Operator, desabilite seu device plugin para esse pool. (project-hami.io)
Antes de executar, registre em Git uma matriz de versões: management cluster, tenant Kubernetes, Kamaji, CNI, HAMi, driver, Toolkit e imagem de teste. Fixe artefatos e digests homologados; não interprete exemplos antigos das documentações como uma recomendação de patch para produção.
4. Criar e verificar os tenant control planes
Salve como tenant.yaml.tpl:
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: ${TENANT_NAME}
namespace: tenants
spec:
dataStore: default
controlPlane:
deployment:
replicas: 1
service:
serviceType: LoadBalancer
kubernetes:
version: "${TENANT_K8S_VERSION}"
kubelet:
cgroupfs: systemd
admissionControllers:
- ResourceQuota
- LimitRanger
networkProfile:
port: 6443
serviceCidr: "${TENANT_SERVICE_CIDR}"
podCidr: "${TENANT_POD_CIDR}"
dnsServiceIPs:
- "${TENANT_DNS_IP}"
addons:
coreDNS: {}
kubeProxy: {}
konnectivity:
server:
port: 8132Esse template usa campos da API do Kamaji. dataStore precisa apontar para um datastore existente; replicas: 1 é uma escolha de laboratório. Ajuste CIDRs, versão e exposição do Service. Um LoadBalancer não é necessariamente privado: configure a implementação da infraestrutura antes de aplicar. (kamaji.clastix.io)
Defina MGMT_CONTEXT com o contexto administrativo e TENANT_K8S_VERSION com uma versão exata homologada, incluindo o prefixo v:
: "${MGMT_CONTEXT:?Defina o contexto do management cluster}"
: "${TENANT_K8S_VERSION:?Defina a versao Kubernetes homologada}"
export TENANT_K8S_VERSION
kubectl --context "$MGMT_CONTEXT" create namespace tenants \
--dry-run=client -o yaml | kubectl --context "$MGMT_CONTEXT" apply -f -
export TENANT_NAME=tenant-a
export TENANT_SERVICE_CIDR=10.96.0.0/16
export TENANT_POD_CIDR=10.244.0.0/16
export TENANT_DNS_IP=10.96.0.10
envsubst '${TENANT_NAME} ${TENANT_K8S_VERSION} ${TENANT_SERVICE_CIDR} ${TENANT_POD_CIDR} ${TENANT_DNS_IP}' \
< tenant.yaml.tpl > tenant-a.yaml
kubectl --context "$MGMT_CONTEXT" apply --dry-run=server -f tenant-a.yaml
kubectl --context "$MGMT_CONTEXT" apply -f tenant-a.yaml
kubectl --context "$MGMT_CONTEXT" -n tenants get tenantcontrolplanes,pods,svcRepita para tenant-b, usando, por exemplo, 10.97.0.0/16, 10.245.0.0/16 e 10.97.0.10. Esses endereços são ilustrativos: verifique conflitos com management, redes corporativas e rotas futuras.
Quando o control plane estiver pronto, extraia seu kubeconfig administrativo:
umask 077
kubectl --context "$MGMT_CONTEXT" -n tenants \
get secret tenant-a-admin-kubeconfig \
-o jsonpath='{.data.admin\.conf}' | base64 --decode > tenant-a.kubeconfig
kubectl --kubeconfig tenant-a.kubeconfig cluster-info
kubeadm --kubeconfig tenant-a.kubeconfig token create --print-join-commandExecute o comando de join gerado somente nos workers de A. Repita a extração e o join para B. Instale o CNI em cada tenant, com os CIDRs correspondentes, e valide os nós. O kubeconfig administrativo é um Secret operacional, não um arquivo para commit. (kamaji.clastix.io)
kubectl --kubeconfig tenant-a.kubeconfig get nodes -o wide
kubectl --kubeconfig tenant-b.kubeconfig get nodes -o wide5. Instalar HAMi dentro de cada tenant
Salve hami-values.yaml para o cenário com driver e Toolkit administrados no host:
devicePlugin:
deviceListStrategy: envvar
nvidiaDriverRoot: /
gpuOperatorToolkitReady:
enabled: falseO arquivo seleciona a estratégia por variável de ambiente, o diretório do driver no host e desabilita a espera pelo marcador do GPU Operator. Ele pressupõe runtime NVIDIA padrão. Não reutilize esses valores em uma instalação com driver containerizado sem adaptar os caminhos e o runtime. (project-hami.io)
Escolha uma versão do chart cuja documentação contenha esses parâmetros:
: "${HAMI_CHART_VERSION:?Defina a versao homologada do chart}"
: "${GPU_NODE_A:?Defina o nome do worker GPU de A}"
helm repo add hami-charts https://project-hami.github.io/HAMi/
helm repo update
helm show values hami-charts/hami --version "$HAMI_CHART_VERSION" > hami-defaults.yaml
kubectl --kubeconfig tenant-a.kubeconfig label node "$GPU_NODE_A" gpu=on --overwrite
helm upgrade --install hami hami-charts/hami \
--kubeconfig tenant-a.kubeconfig \
--namespace kube-system \
--version "$HAMI_CHART_VERSION" \
--values hami-values.yaml \
--wait --timeout 10m
kubectl --kubeconfig tenant-a.kubeconfig -n kube-system get pods,daemonsets,deployments
kubectl --kubeconfig tenant-a.kubeconfig describe node "$GPU_NODE_A"O chart, a seleção de nós por gpu=on e os componentes de verificação seguem o fluxo oficial. Repita a instalação usando o kubeconfig e o worker de B. HAMi instalado apenas no management cluster não gerencia automaticamente os workers dos tenants. (project-hami.io)
Para a primeira rodada, mantenha overcommit de memória desabilitado e configure pelo menos dois slots compartilháveis por GPU. Arquive os valores efetivos do Helm para reproduzir o ensaio.
6. Executar um workload CUDA de verdade
Namespace e quota
Salve como gpu-namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: gpu-lab
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-budget
namespace: gpu-lab
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
requests.nvidia.com/gpu: "2"A quota limita o orçamento agregado do namespace. Aqui, requests.nvidia.com/gpu contabiliza unidades solicitadas, não duas placas necessariamente exclusivas. Não confunda quota com reserva física. O Kubernetes permite quotas de extended resources usando o prefixo requests.. (kubernetes.io)
HAMi também documenta uma extensão de quota com chaves limits.nvidia.com/..., incluindo tratamento de solicitações multi-GPU. Isso é comportamento do HAMi, não uma equivalência com a quota nativa acima; valide sua versão antes de adotar a extensão. (project-hami.io)
Job com duas execuções concorrentes
Salve como gpu-job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: gpu-smoke
namespace: gpu-lab
spec:
completions: 2
parallelism: 2
backoffLimit: 0
activeDeadlineSeconds: 600
ttlSecondsAfterFinished: 3600
template:
metadata:
labels:
app: gpu-smoke
annotations:
hami.io/node-scheduler-policy: binpack
hami.io/gpu-scheduler-policy: binpack
spec:
restartPolicy: Never
automountServiceAccountToken: false
nodeSelector:
gpu: "on"
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: cuda-test
image: pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime
command: [python, -u, -c]
args:
- |
import json
import time
import torch
assert torch.cuda.is_available(), 'CUDA unavailable'
torch.manual_seed(42)
a = torch.randn((2048, 2048), device='cuda')
b = torch.randn((2048, 2048), device='cuda')
for _ in range(10):
c = a @ b
torch.cuda.synchronize()
start = time.monotonic()
iterations = 0
while time.monotonic() - start < 120:
c = a @ b
torch.cuda.synchronize()
iterations += 1
elapsed = time.monotonic() - start
print(json.dumps({
'device': torch.cuda.get_device_name(0),
'iterations': iterations,
'seconds': elapsed,
'iterations_per_second': iterations / elapsed,
'allocated_bytes': torch.cuda.memory_allocated(),
'reserved_bytes': torch.cuda.memory_reserved()
}))
env:
- name: HOME
value: /tmp
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
resources:
requests:
cpu: "1"
memory: 2Gi
limits:
cpu: "2"
memory: 4Gi
nvidia.com/gpu: "1"
nvidia.com/gpumem: "4096"
nvidia.com/gpucores: "25"A imagem existe no repositório PyTorch; a tag é uma referência didática fixa, não uma recomendação de atualização ou segurança para outubro de 2026. Homologue uma imagem suportada e fixe seu digest antes da produção. (hub.docker.com)
Com memoryFactor: 1, gpumem: 4096 corresponde a 4096 MiB por GPU solicitada; use inteiro sem sufixo Mi. gpucores: 25 expressa um percentual de controle computacional, não 25 núcleos físicos dedicados. O controle do HAMi-core utiliza time slicing e pode apresentar flutuações. (project-hami.io)
Os recursos estendidos foram definidos em limits; o Kubernetes utiliza esses valores como requests quando estes não são explicitados. CPU e memória do host continuam sendo dimensões separadas. (kubernetes.io)
O Job limita duração e tentativas para preservar falhas como evidência. Ele não serve tráfego, portanto não precisa de readiness HTTP. A sincronização CUDA evita medir somente o enfileiramento assíncrono das operações. (kubernetes.io)
kubectl --kubeconfig tenant-a.kubeconfig apply -f gpu-namespace.yaml
kubectl --kubeconfig tenant-a.kubeconfig apply -f gpu-job.yaml
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab get pods -o wide
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab \
wait --for=condition=complete job/gpu-smoke --timeout=650s
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab \
logs -l app=gpu-smoke --prefix=trueRepita no tenant B. Em cada cluster, confirme sobreposição temporal e o UUID físico alocado aos Pods. binpack favorece consolidação, mas a anotação sozinha não prova compartilhamento da mesma placa. (project-hami.io)
7. Plano de testes e critérios de aceite
Use esta matriz como proposta de homologação, não como resultado já observado:
| Teste | Procedimento | Evidência exigida |
|---|---|---|
| Baseline | Uma execução, sem concorrentes, mantendo os mesmos limites | Tempo, throughput e memória registrados |
| Compartilhamento | Duas execuções simultâneas na mesma GPU | Mesmo UUID e intervalo de execução sobreposto |
| Pressão de memória | Em pool descartável, tentar alocar mais que o limite concedido | Falha controlada da alocação e comportamento do vizinho registrado |
| Quota | Manter dois Pods ativos e tentar admitir um terceiro | Rejeição por quota, não simples falta de capacidade |
| Isolamento administrativo | Usar uma identidade de A contra a API B | Ausência de acesso indevido |
| Falha de worker | Interromper um worker de teste | Tempo de detecção e recuperação mensurados |
| Falha do control plane | Remover um Pod do control plane em configuração redundante | Disponibilidade da API e reconciliação registradas |
Para gerar pressão de memória, crie uma cópia do Job, com outro nome, substituindo o código por uma alocação CUDA maior que 4096 MiB. Faça isso apenas no pool descartável. Diferencie erro CUDA de falta de memória de OOMKilled por memória do host. Não deduza isolamento de memória apenas do valor mostrado por nvidia-smi.
Faça uma rodada de aquecimento e várias repetições. Compare workloads iguais, imagens iguais e políticas iguais. Para inferência, meça latências p50, p95 e p99, taxa de erros, throughput e fila. Defina o Service Level Objective, ou SLO, antes de decidir quanto compartilhamento aceitar.
8. Segurança e isolamento de rede
Como configuração inicial do namespace de teste, salve deny-all.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: gpu-lab
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressEssa política bloqueia ingress e egress dos Pods selecionados quando o CNI implementa NetworkPolicy. O teste numérico não precisa de rede. Aplicações reais precisarão de permissões explícitas para DNS, armazenamento, filas e serviços. A política não substitui controles no host nem isola memória de GPU. (kubernetes.io)
Como critérios de produção, exija Role-Based Access Control, ou RBAC, mínimo; identidades distintas por tenant; APIs privadas quando possível; TLS; Secrets fora do Git; criptografia e rotação de credenciais. Restrinja Pods privilegiados, hostPath e alteração de políticas pelos consumidores.
Um usuário com cluster-admin dentro do tenant não deve ser considerado sujeito a quotas e políticas que ele próprio pode modificar. Para orçamento corporativo, imponha também limites no provisionamento dos workers e na camada de infraestrutura. Essa distinção entre confiança e isolamento é central ao desenho multi-tenant. (kubernetes.io)
9. Do cenário corporativo à produção
Problema: equipes de visão computacional precisam de APIs Kubernetes independentes, enquanto seus serviços menores não justificam uma GPU exclusiva por processo.
Solução proposta: um tenant por domínio administrativo, workers separados por tenant e compartilhamento HAMi dentro de cada pool autorizado.
Implementação: disponibilizar templates via GitOps, quotas, perfis de GPU e testes automatizados de compatibilidade.
Resultado esperado: maior autonomia com evidências de utilização e interferência. A economia deve ser medida; não é consequência garantida da instalação.
Para um desenho próximo de produção, proponho:
- Control planes redundantes distribuídos entre nós e zonas, quando disponíveis.
- Datastore com quorum, armazenamento confiável e capacidade reservada.
- Workers GPU sobressalentes compatíveis com a carga crítica.
- Para serviços de inferência: múltiplas réplicas,
startupProbe,readinessProbe,livenessProbe, PodDisruptionBudget e distribuição topológica. - Autoscaling baseado em fila e demanda, validando também a criação e a preparação de novos workers GPU.
- Checkpoints e retomada para processamento interrompível.
Esses são critérios de projeto: duas réplicas na mesma GPU não devem ser aceitas como prova de tolerância à falha dessa GPU.
Desenvolvimento versus produção
| Dimensão | Laboratório | Produção proposta |
|---|---|---|
| Control plane | Uma réplica | Redundância e distribuição verificadas |
| GPU | Um worker por tenant | Capacidade de recuperação e pools por criticidade |
| Imagens | Tag fixa didática | Digest homologado e análise de vulnerabilidades |
| Observabilidade | Eventos e logs | Métricas, alertas, rastreamento e retenção |
| Recuperação | Recriação manual | Backups e restauração ensaiada |
10. Observabilidade, custos e manutenção
Estruture dashboards por tenant, namespace, workload, worker e UUID físico. Recomendo acompanhar:
- Control plane: disponibilidade da API, latência, erros, reinícios e saúde do datastore.
- Scheduling: tempo em Pending, recusas, quota e capacidade disponível.
- GPU: memória alocada e usada, utilização, temperatura e falhas do dispositivo.
- Aplicação: throughput, latência, fila, erros CUDA e tempo de carregamento.
Use Prometheus e Grafana como componentes possíveis; centralize logs e conecte traces da API à fila e ao processamento. Antes de fazer chargeback por Pod, valide a atribuição das métricas: compartilhamento pode limitar a associação entre métricas físicas e contêineres, como documentado no time slicing do device plugin NVIDIA. (docs.nvidia.com)
Para FinOps, compare custo por tarefa concluída dentro do SLO, não apenas quantidade de GPUs provisionadas. Inclua workers ociosos, storage, tráfego entre zonas, load balancers, datastore e observabilidade. Considere Spot somente para cargas com retomada testada; reserve capacidade mais previsível para serviços críticos.
Na manutenção, promova alterações primeiro em um tenant canário. Faça backup do datastore, recursos do management cluster e material necessário à recuperação. Um snapshot isolado não substitui o procedimento completo de restauração do Kamaji. (kamaji.clastix.io)
Upgrades de tenant exigem tratar control plane e workers separadamente. Reserve capacidade temporária para o rollout. Não trate a alteração inversa de spec.kubernetes.version como rollback seguro; prefira procedimentos suportados, restauração ensaiada ou migração para outro cluster. (kamaji.clastix.io)
11. Troubleshooting orientado por sintomas
| Sintoma | Possível causa | Investigação | Correção |
|---|---|---|---|
| Tenant sem endpoint | Load balancer ou rede indisponível | Status do TenantControlPlane e Service | Corrigir exposição e conectividade |
| Worker NotReady | CNI ausente ou configuração incompatível | Condições do nó e Pods do CNI | Ajustar CNI, CIDR e runtime |
| Job sem Pods | Quota recusou criação | Eventos do Job e ResourceQuota | Ajustar orçamento ou liberar consumo |
| Pod Pending | Capacidade, taints ou scheduling | Eventos, nó e logs do HAMi | Corrigir restrição identificada |
| CUDA indisponível | Driver, runtime ou injeção | Logs, configuração do runtime e device plugin | Homologar a combinação |
| Latência elevada | Contenção, CPU ou entrada de dados | Baseline, GPU, fila e CPU | Reduzir compartilhamento ou separar pools |
Comandos de investigação:
kubectl --kubeconfig tenant-a.kubeconfig get pods -A
kubectl --kubeconfig tenant-a.kubeconfig get deployments -A
kubectl --kubeconfig tenant-a.kubeconfig get nodes
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab describe job gpu-smoke
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab describe resourcequota gpu-budget
kubectl --kubeconfig tenant-a.kubeconfig get events -A --sort-by=.metadata.creationTimestamp
# Substitua POD pelo nome observado.
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab describe pod POD
kubectl --kubeconfig tenant-a.kubeconfig -n gpu-lab logs PODUse logs --previous somente quando houver uma instância anterior do contêiner. O Job apresentado usa restartPolicy: Never; não espere encontrar automaticamente logs anteriores no mesmo Pod. (kubernetes.io)
Evite ausência de requests, privilégios excessivos, credenciais hardcoded, descarte precoce dos logs e cópia direta de configurações de laboratório. Antes de desmontar, exporte as evidências e confirme o kubeconfig de cada operação destrutiva.
12. Quando utilizar e alternativas
Considere Kamaji com HAMi quando houver necessidade real de APIs independentes, automação de vários clusters e workloads compatíveis com compartilhamento interno. Evite essa combinação se uma equipe pequena consegue operar adequadamente um único cluster com namespaces e políticas.
| Alternativa | Principal trade-off |
|---|---|
| Um cluster com namespaces | Menor operação, mas API e governança compartilhadas |
| Clusters independentes com GPU exclusiva | Menor densidade, fronteiras mais simples de avaliar |
| NVIDIA time slicing | Compartilhamento sem isolamento de memória e falhas entre réplicas |
| NVIDIA Multi-Instance GPU, ou MIG | Particionamento por hardware, limitado aos modelos e perfis suportados |
As diferenças de isolamento entre time slicing e MIG são documentadas pela NVIDIA. MIG pode integrar um desenho com HAMi, mas isso exige outro perfil de homologação; não é o backend testado neste artigo. (docs.nvidia.com)
Resumo prático
- Separe o teste de APIs do teste de GPUs.
- Instale HAMi no tenant que possui os workers acelerados.
- Confirme compartilhamento pelo dispositivo físico e pela execução simultânea.
- Teste quotas, pressão de memória, interferência e recuperação.
- Preserve versões, manifests, métricas e logs como evidências.
- Só avance para produção após demonstrar isolamento adequado e atendimento ao SLO.
Conclusão
O valor dessa arquitetura não está em instalar dois projetos, mas em transformar autonomia, utilização e confiabilidade em contratos verificáveis. Platform Engineering fornece os caminhos padronizados; DevOps automatiza sua entrega; SRE estabelece os objetivos e os ensaios de falha.
A decisão madura pode ser compartilhar algumas GPUs, dedicar outras e manter certos tenants em infraestrutura separada. O laboratório deve produzir evidências para essa decisão, não apenas uma captura de tela com Pods em Running.
Artigos relacionados
Quer aplicar isso no seu ambiente?
Agende uma conversa de 30 minutos sem compromisso. Eu olho o seu cenário e digo por onde começar.
Agendar uma conversaReceba os novos artigos por e-mail
Um e-mail quando sair artigo novo sobre infraestrutura, backend e IA. Sem spam, cancele quando quiser.