Ajudar a melhorar esta página
Para contribuir com este guia de usuário, escolha o link Editar esta página no GitHub, disponível no painel direito de cada página.
Configurar o cluster do Amazon EKS para workloads de IA/ML usando o Terraform
dica
Registre-se
Esta seção guia você pelas etapas de criação da infraestrutura necessária para executar workloads de treinamento ou inferência no Amazon EKS usando o Terraform. As etapas incluem a criação de um cluster do EKS, nós habilitados para GPU com o Modo Automatizado do EKS ou o Karpenter, uma pilha de monitoramento com Prometheus e Grafana, e o armazenamento do Amazon S3 para os pesos do modelo.
Consulte a documentação do Modo Automático do EKS e do Karpenter
Arquitetura e fluxo de trabalho de alto nível
O diagrama ilustra a arquitetura de alto nível da AWS para a configuração desta seção.
Pré-requisitos
Importante
Os recursos que você cria neste tutorial, incluindo clusters do EKS, instâncias de GPU, Application Load Balancers e o Amazon Managed Service for Prometheus, incorrem em cobranças. Para evitar cobranças contínuas, exclua os recursos quando terminar.
-
Terraform >= 1.15.0. Para obter instruções de configuração, consulte Installing Terraform
. -
kubectl>= 1.36. Consulte Configurar o kubectl e o eksctl para obter instruções de configuração. -
AWSCLI >= 2.27. Para obter instruções de configuração, consulte Instalar.
-
jq. Para obter instruções de configuração, consulte Baixar jq.
Verifique as versões das suas ferramentas:
terraform --version aws --version kubectl version --client jq --version
Etapa 1: baixar e implantar o código do Terraform
Este passo a passo usa o código do Terraform no repositório de exemplos da AWS no GitHub sample-eks-docs
git clone git@github.com:aws-samples/sample-eks-docs.git cd sample-eks-docs/ai-ml/set-up-cluster
O repositório tem a seguinte estrutura no diretório ai-ml/set-up-cluster/ em que você acabou de entrar:
set-up-cluster/
├── scripts/
│ └── cleanup.sh
└── terraform/
├── auto-mode/
└── karpenter/
O repositório fornece dois caminhos de implantação. Escolha apenas um e use-o em todo o guia.
-
Modo Automático do EKS (
terraform/auto-mode/): além dos principais complementos de rede, armazenamento e balanceamento de carga, o Modo Automático do EKS inclui e gerencia os seguintes recursos para workloads de treinamento e inferência: agente de monitoramento de nós do EKS, reparo automático de nós, snapshotter SOCIpara extração rápida de contêineres e prontidão de GPU para o NodeClass padrão. O plug-in de dispositivo NVIDIA está incluído na AMI acelerada do Bottlerocket que o Modo Auomático do EKS usa para nós habilitados para GPU. -
Karpenter autogerenciado (
terraform/karpenter/): em um cluster do EKS sem o Modo Automático do EKS, o código do Terraform instala e configura os componentes necessários para workloads de treinamento e inferência. Isso inclui os complementos de rede (CNI da VPC, CoreDNS, kube-proxy), o Karpenter, o agente de monitoramento de nós do EKS, o plug-in de dispositivo NVIDIA e o snapshotter SOCI para extração rápida de contêineres.
Importante
Escolha o Modo Automático do EKS ou o Karpenter autogerenciado e use-o em todo o guia. Mudar no meio do processo exige a destruição do cluster e o recomeço do zero.
Opções de cluster do EKS: Modo Automático do EKS e Karpenter autogerenciado
O Grafana é acessível publicamente por HTTP com credenciais padrão
O Ingress do ALB do Grafana padroniza var.my_cidr para 0.0.0.0/0, o que expõe o Grafana à internet pública por meio de HTTP simples com credenciais de administrador padrão. Os verificadores automatizados descobrem balanceadores de carga públicos em minutos. Você deve restringir o acesso substituindo var.my_cidr pelo seu próprio endereço IP:
export MY_CIDR="$(curl -s https://checkip.amazonaws.com)/32" terraform apply -var "my_cidr=${MY_CIDR}"
Trate a lista de permissões de IP de origem como uma proteção mínima, não como uma proteção completa. Altere também a senha padrão do administrador do Grafana após o primeiro login. Para uma postura mais robusta, mude alb.ingress.kubernetes.io/scheme para internal (acessível somente de dentro da sua VPC ou em uma VPN conectada) e adicione um certificado TLS.
Implantar o cluster
Vá para o diretório do caminho escolhido, inicialize o Terraform e aplique:
Ambas as variantes usam como padrão a região us-east-2. Para implantar em outra região, adicione -var "region= ao comando region-code"terraform apply na etapa a seguir, em que region-code é a região da AWS na qual você deseja implantar.
O código do Terraform usa todas as zonas de disponibilidade disponíveis na região de destino, excluindo use1-az3, usw1-az2 e cac1-az3 porque o Amazon EKS não é compatível com a alocação do ambiente de gerenciamento nessas zonas
Analisar os resultados do Terraform
Quando a aplicação é concluída, o Terraform exibe as seguintes saídas (os valores variam de acordo com sua configuração):
Apply complete! Resources: 74 added, 0 changed, 0 destroyed. Outputs: cluster_name = "ai-eks-docs" configure_kubectl = "aws eks update-kubeconfig --region us-east-2 --name ai-eks-docs --alias ai-eks-docs" configure_model_bucket = "export MODEL_BUCKET=ai-eks-docs-models-20250612abc1" model_bucket = "ai-eks-docs-models-20250612abc1" node_iam_role_name = "ai-eks-docs-eks-auto-20250612..." region = "us-east-2"
A saída configure_kubectl é um comando pronto para execução que aponta o kubectl para o cluster. A saída model_bucket contém o nome do bucket do S3 para os pesos do modelo. A saída node_iam_role_name mostra o perfil do IAM que os nós usam.
Configurar o kubectl
Aponte o kubectl para o novo cluster. A saída configure_kubectl é um comando pronto para ser executado:
eval "$(terraform output -raw configure_kubectl)"
Verificar o cluster
Etapa 2: criar o NodePool dinâmico
Os NodePools de GPU são opcionais. Por padrão, o terraform apply cria o cluster e a pilha de monitoramento sem capacidade e sem faturamento de GPU. Para provisionar nós de GPU, passe a variável nodepools com um nome de estratégia.
Habilite a estratégia spot-ondemand, que provisiona instâncias de GPU da família G com uma geração maior que 4, usando a capacidade spot com sob demanda como fallback:
terraform apply -var 'nodepools={"spot-ondemand"={}}'
Esse comando aplica os modelos de NodePool e NodeClass do diretório nodepools/spot-ondemand/. Ambos os caminhos usam a mesma API NodePool, mas diferem no NodeClass ao qual o NodePool faz referência.
Ambos os caminhos mostram nós 0 para gpu-inf até que uma workload de GPU seja agendada. O Modo Automático do EKS e o Karpenter só inicializam nós quando os pods pendentes os exigem.
Etapa 3: testar com um exemplo de pod
Teste a configuração do NodePool da GPU com um pod nvidia-smi:
cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nvidia-smi labels: guide: ai-eks-docs spec: restartPolicy: OnFailure tolerations: - key: "nvidia.com/gpu" operator: "Exists" effect: "NoSchedule" containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["nvidia-smi"] resources: limits: nvidia.com/gpu: 1 EOF
Verifique se o pod foi agendado e concluído com êxito:
kubectl get pods nvidia-smi
Saída esperada:
NAME READY STATUS RESTARTS AGE nvidia-smi 0/1 Completed 0 67s
O STATUS: Completed significa que o comando nvidia-smi foi executado e encerrado. Verifique os logs do pod para ver a GPU detectada pelo nó:
kubectl logs nvidia-smi
Saída esperada:
+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.159.03 Driver Version: 580.159.03 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA L4 On | 00000000:31:00.0 Off | 0 | | N/A 41C P8 13W / 72W | 0MiB / 23034MiB | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+
A saída mostra o modelo da GPU, a versão do driver, a versão do CUDA e a memória disponível. Neste exemplo, o Karpenter provisionou uma instância G6 que tem uma GPU NVIDIA L4 com 24 GB de memória. O modelo e a memória da GPU variam de acordo com o tipo de instância selecionado pelo Karpenter. As instâncias G5 têm GPUs NVIDIA A10G (24 GB), as instâncias G6 têm GPUs NVIDIA L4 (24 GB) e as instâncias G6e têm GPUs NVIDIA L40S (48 GB).
Para entender como o Karpenter e o agendador do Kubernetes se coordenaram para provisionar um nó e posicionar o pod, confira os eventos do ciclo de vida do pod:
kubectl describe pod nvidia-smi
Saída esperada:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 75s default-scheduler 0/2 nodes are available: 2 node(s) had untolerated taint(s). Normal Nominated 74s eks-auto-mode/compute Pod should schedule on: nodeclaim/gpu-inf-z6q75 Normal Scheduled 35s default-scheduler Successfully assigned default/nvidia-smi to i-0eb897a8302551589 Normal Pulling 27s kubelet spec.containers{nvidia-smi}: Pulling image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" Normal Pulled 22s kubelet spec.containers{nvidia-smi}: Successfully pulled image "public.ecr.aws/amazonlinux/amazonlinux:2023-minimal" in 5.625s (5.626s including waiting). Image size: 37440620 bytes. Normal Created 22s kubelet spec.containers{nvidia-smi}: Container created Normal Started 21s kubelet spec.containers{nvidia-smi}: Container started
Esses eventos mostram a sequência de agendamento do pod: o agendamento inicial do pod falha porque não existe nenhum nó de GPU (FailedScheduling), o Karpenter nomeia um novo NodeClaim (Nominated), o agendador atribui o pod quando o nó fica pronto (Scheduled) e, em seguida, a imagem do contêiner é extraída e iniciada. O Modo Automático do EKS tem o pull paralelo SOCI (Seekable OCI) instalado e configurado por padrão nas instâncias G, P e Trn, e o caminho autogerenciado do Karpenter o configura explicitamente por meio do feature gate FastImagePull.
nota
Em um cluster autogerenciado do Karpenter, o evento Nominated exibe karpenter/compute em vez de eks-auto-mode/compute.
Um NodeClaim é uma requisição que o Karpenter cria para provisionar um nó específico. Ele mostra o tipo de instância, o tipo de capacidade, a AZ e se o nó está pronto:
kubectl get nodeclaims
Saída esperada:
NAME TYPE CAPACITY ZONE NODE READY AGE gpu-inf-z6q75 g6.xlarge spot us-east-2a i-0eb897a8302551589 True 5m
O tipo de instância e a AZ variam. Qualquer instância da família G com uma geração maior que 4 é elegível.
dica
Se nenhum nó aparecer, verifique se há erros de capacidade insuficiente:
kubectl get events | grep InsufficientCapacityError
O Karpenter armazena em cache as ofertas indisponíveis por três minutos. Ampliar os tipos de instância e as AZs permitidas no NodePool aumenta as chances de conseguir capacidade.
nota
As instâncias spot inicializadas pelo Karpenter não aparecem no console de requisições spot do EC2. O Karpenter usa a API CreateFleet do EC2 com o type: instant. As instâncias aparecem no console de instâncias do EC2 com um ciclo de vida spot.
Etapa 4: adicionar capacidade reservada ao NodePool (opcional)
Embora o NodePool de GPU da Etapa 2 provisione instâncias spot ou sob demanda dinamicamente, alguns casos de uso exigem capacidade garantida. Você pode criar uma reserva de capacidade sob demanda (ODCR) para garantir que a capacidade da GPU esteja disponível quando necessário.
Com o Terraform, um único comando cria o ODCR, um NodeClass personalizado que faz referência à reserva por tag e atualiza o NodePool para incluir reserved como um tipo de capacidade. O Terraform marca o ODCR com nodepool=reserved-spot-ondemand e o NodeClass o seleciona por essa tag.
Atenção
O comando a seguir cria um ODCR que fatura imediatamente e continua cobrando até que você o destrua com terraform destroy ou com o script de limpeza, independentemente de os nós estarem em execução nele ou não.
Use os padrões (g6e.4xlarge, 1 instância, primeiro cluster da AZ):
terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={}}}'
Escolha o tipo de instância, a contagem e a AZ:
terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={instance_type="g6e.2xlarge",instance_count=1,az="us-east-2a"}}}'
O objeto reservation tem os seguintes campos:
-
instance_type: o tipo de instância de GPU a ser reservada. Padrão:g6e.4xlarge. -
instance_count: o número de instâncias a serem reservadas. Padrão:1. -
az: a zona de disponibilidade para a reserva. Padrão:""(usa o primeiro cluster da AZ).
Importante
As estratégias spot-ondemand e reserved-spot-ondemand são mutuamente exclusivas. Você pode habilitar no máximo um na variável nodepools. Se você usou spot-ondemand anteriormente na Etapa 2, o comando reserved-spot-ondemand o substitui porque ambos gerenciam o mesmo NodePool gpu-inf.
Se você receber um erro InsufficientInstanceCapacity, a reserva não poderá ser atendida na AZ especificada. Cancele a operação do Terraform (Ctrl+C) e execute novamente com outro valor de az:
terraform apply -var 'nodepools={"reserved-spot-ondemand"={reservation={instance_type="g6e.4xlarge",az="us-east-2b"}}}'
Depois de aplicar, o Terraform atualiza o NodePool para incluir reserved, spot e on-demand nos requisitos de tipo de capacidade. O Karpenter trata reserved como a opção mais econômica e a inicia primeiro. Quando a reserva está cheia, ele recorre a spot ou sob demanda.
No caminho do Modo Automático do EKS, o Terraform cria um NodeClass gpu-inf personalizado (porque o NodeClass default incluído é somente leitura) que faz referência ao ODCR por tag por meio de capacityReservationSelectorTerms. No caminho autogerenciado do Karpenter, o Terraform reaplica o EC2NodeClass gpu-inf com os capacityReservationSelectorTerms adicionados e atualiza o NodePool para incluir reserved.
Verifique se o ODCR foi criado:
aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=tag:nodepool,Values=reserved-spot-ondemand" \ --query 'CapacityReservations[0].{Id:CapacityReservationId,State:State,InstanceType:InstanceType,AvailableCount:AvailableInstanceCount}' \ --output table \ --region $(terraform output -raw region)
Verifique se o NodeClass faz referência ao ODCR:
Verifique se o NodePool está pronto:
kubectl get nodepools gpu-inf
Saída esperada:
NAME NODECLASS NODES READY AGE gpu-inf gpu-inf 0 True 30s
Depois de aplicar as alterações, verifique se o Karpenter prioriza a capacidade reservada e depois recorre a spot ou sob demanda. Faça uma implantação com duas réplicas que solicite uma GPU por pod. O ODCR é para uma instância (1 GPU), então, o primeiro pod aciona o Karpenter para iniciar um nó reservado. O segundo pod não cabe no nó reservado e aciona o Karpenter para iniciar outro nó usando capacidade spot ou sob demanda.
cat << 'EOF' | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: gpu-overflow-test labels: guide: ai-eks-docs spec: replicas: 2 selector: matchLabels: app: gpu-overflow-test template: metadata: labels: app: gpu-overflow-test guide: ai-eks-docs spec: tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule containers: - name: nvidia-smi image: public.ecr.aws/amazonlinux/amazonlinux:2023-minimal command: ["sh", "-c", "nvidia-smi && sleep infinity"] resources: limits: nvidia.com/gpu: 1 EOF
Ao contrário do pod de teste nvidia-smi da Etapa 3, que foi executado e encerrado, essa implantação mantém os pods em execução (sleep infinity) para que eles retenham a GPU e impeçam que o nó seja consolidado.
Verifique os pods agendados em nós diferentes:
kubectl get pods -l app=gpu-overflow-test -o wide
Saída esperada:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES gpu-overflow-test-55d55ff5b9-dvg52 1/1 Running 0 4m42s 10.0.75.210 i-08741a36089ff2088 <none> <none> gpu-overflow-test-55d55ff5b9-hw4m9 1/1 Running 0 4m43s 10.0.82.49 i-0f50cdbacb2017202 <none> <none>
Verifique as NodeClaims para ver os tipos de capacidade:
kubectl get nodeclaims
Saída esperada:
NAME TYPE CAPACITY ZONE NODE READY AGE gpu-inf-vw99m g6e.4xlarge reserved us-east-2c i-0f50cdbacb2017202 True 6m gpu-inf-s65s6 g6.xlarge spot us-east-2b i-08741a36089ff2088 True 5m59s
O nó reservado foi iniciado primeiro, seguido por um nó spot ou sob demanda quando a reserva ficou cheia.
Limpar a implantação de teste:
kubectl delete deployment gpu-overflow-test
Monitoramento
O Terraform já provisionou a pilha de monitoramento completa durante o terraform apply na Etapa 1. A pilha inclui um espaço de trabalho do Amazon Managed Service for Prometheus (AMP), políticas do IAM e associações da Identidade de Pods do EKS para gravação remota do Prometheus e acesso a consultas do Grafana, o chart do Helm kube-prometheus-stack (Prometheus, Grafana, kube-state-metrics, node-exporter) e o NVIDIA DCGM Exporter para métricas de GPU.
Esta seção aborda a verificação dos componentes de monitoramento implantados.
Verificar os pods de monitoramento
Aguarde até que todos os pods de monitoramento estejam prontos:
kubectl wait --for=condition=Ready pod --all -n monitoring --timeout=300s kubectl get pods -n monitoring
Saída esperada:
NAME READY STATUS RESTARTS AGE kube-prometheus-stack-grafana-7c58f54f77-rftrj 3/3 Running 0 5m kube-prometheus-stack-kube-state-metrics-d68dcbc84-5smxq 1/1 Running 0 5m kube-prometheus-stack-operator-5895df479f-ttm47 1/1 Running 0 5m kube-prometheus-stack-prometheus-node-exporter-t9q7s 1/1 Running 0 5m kube-prometheus-stack-prometheus-node-exporter-x6vfb 1/1 Running 0 5m prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 5m
Acessar o Grafana
O Grafana é exposto por meio de um AWS Application Load Balancer (ALB) voltado para a internet, restrito ao CIDR que você definiu em var.my_cidr. Exiba o URL do balanceador de carga (aguarde um ou dois minutos para o ALB provisionar):
echo "http://$(kubectl get ingress kube-prometheus-stack-grafana -n monitoring -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')"
Abra o URL em seu navegador. Faça login com o nome de usuário admin e a senha do seguinte comando:
kubectl --namespace monitoring get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo
Verificar o pipeline de métricas
Para verificar se o pipeline de métricas está funcionando de ponta a ponta:
-
Navegue até Conexões > Fontes de dados e confirme se o Amazon-Managed-Prometheus está listado como a fonte de dados padrão.
Valide a fonte de dados do AMP no Grafana
-
Navegue até Drilldown > Metrics e procure a métrica
up. Você deve ver os resultados dos alvos de extração do cluster.Validar a métrica
upno Grafana
Se up mostrar resultados, o pipeline (cluster → Prometheus → AMP → Grafana) estará funcionando.
Validar métricas de GPU do DCGM
O DaemonSet do DCGM Exporter é executado em nós de GPU e reporta métricas de utilização da GPU, memória, temperatura, consumo de energia, largura de banda do NVLink e atividade do tensor.
Verifique o DaemonSet do DCGM Exporter:
kubectl get daemonset dcgm-exporter -n monitoring
Quando um nó da GPU estiver em execução (na Etapa 2 ou na Etapa 4), você verá um ou mais pods prontos. Para validar as métricas do DCGM, navegue até Drilldown > Metrics no Grafana e procure DCGM_.
Validar as métricas do DCGM no Grafana
Para visualizar o painel, navegue até Dashboards > GPU Monitoring > NVIDIA DCGM Exporter Dashboard.
Painel do NVIDIA DCGM Exporter no Grafana
Bucket do S3 de pesos do modelo
O Terraform já criou um bucket do Amazon S3 para armazenar pesos de modelos, um ServiceAccount model-storage-sa no namespace default, uma política do IAM tendo como escopo o bucket e uma associação da Identidade de Pods do EKS que os vincule. Os pods de workloads que definiram serviceAccountName: model-storage-sa poderão ler e gravar no bucket.
Verificar o bucket
Recupere o nome do bucket das saídas do Terraform:
MODEL_BUCKET=$(terraform output -raw model_bucket) echo ${MODEL_BUCKET}
Verifique se o bucket existe:
aws s3api head-bucket --bucket ${MODEL_BUCKET}
Saída esperada:
{
"BucketArn": "arn:aws:s3:::ai-eks-docs-models-20250612abc1",
"BucketRegion": "us-east-2",
"AccessPointAlias": false
}
Execute um pod temporário com a imagem da AWS CLI, usando a ServiceAccount model-storage-sa, para confirmar que o Identidade de Pods do EKS está configurado corretamente e o acesso ao S3 funciona:
cat << EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: s3-test labels: guide: ai-eks-docs spec: serviceAccountName: model-storage-sa containers: - name: aws-cli image: public.ecr.aws/aws-cli/aws-cli:2.27.0 command: - sh - -c - | echo "=== Caller Identity ===" aws sts get-caller-identity echo "" echo "=== S3 Write Test ===" echo "pod identity works" | aws s3 cp - s3://${MODEL_BUCKET}/test.txt echo "" echo "=== S3 List Test ===" aws s3 ls s3://${MODEL_BUCKET}/ echo "" echo "=== S3 Delete Test ===" aws s3 rm s3://${MODEL_BUCKET}/test.txt restartPolicy: Never EOF
Aguarde a conclusão do pod e verifique os logs:
kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/s3-test --timeout=300s kubectl logs s3-test
Saída esperada:
=== Caller Identity ===
{
"UserId": "AROA...:eks-ai-eks-docs-model-s-...",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/ai-eks-docs-models-.../eks-ai-eks-docs-..."
}
=== S3 Write Test ===
upload: - to s3://ai-eks-docs-models-20250612abc1/test.txt
=== S3 List Test ===
2026-07-15 12:00:00 19 test.txt
=== S3 Delete Test ===
delete: s3://ai-eks-docs-models-20250612abc1/test.txtA identidade do chamador confirma que o pod assumiu o perfil de armazenamento do modelo por meio da Identidade de Pods do EKS. Os comandos do S3 confirmam o acesso para leitura e gravação.
Limpe o pod de teste:
kubectl delete pod s3-test
Próximas etapas
Com o cluster pronto, você pode prosseguir para Carregar e servir modelo para implantar um grande modelo de linguagem e interagir com o endpoint de inferência.
Limpeza
dica
Se você planejar continuar nas próximas seções deste guia, pule a limpeza completa. Faça a limpeza completa apenas quando terminar.
Exclua as workloads de teste para que nenhum pod esteja retendo nós de GPU:
kubectl delete pod nvidia-smi --ignore-not-found kubectl delete deployment gpu-overflow-test --ignore-not-found
Se você quiser apenas liberar o ODCR e retornar para a capacidade spot e sob demanda, mude a variável nodepools de volta para a estratégia spot-ondemand:
terraform apply -var 'nodepools={"spot-ondemand"={}}'
Isso remove reserved dos requisitos de tipo de capacidade do NodePool, destrói o ODCR e mantém o cluster, a pilha de monitoramento e o bucket do S3 intactos.
Importante
O cancelamento de uma reserva não encerra as instâncias já em execução nela. Essas instâncias continuam funcionando com taxas padrão sob demanda até serem encerradas. Exclua primeiro as workloads da GPU, conforme mostrado acima, para que o nó reservado seja drenado antes que a reserva seja liberada.
Drene os nós gerenciados pelo Karpenter antes de destruí-los, para que nenhum ciclo de vida de nó em andamento bloqueie a destruição. Exclua quaisquer PodDisruptionBudgets que impeçam a drenagem e, em seguida, exclua os NodeClaims:
kubectl delete pdb -A --all --ignore-not-found kubectl delete nodeclaim --all --wait=true --timeout=900s
Em seguida, destrua tudo o que o Terraform criou, incluindo o cluster do EKS, a VPC, a pilha de monitoramento, os NodePools e NodeClasses, o bucket do S3 do modelo e qualquer ODCR:
terraform destroy
Atenção
O bucket do S3 de pesos do modelo é criado com force_destroy = true, então terraform destroy exclui o bucket junto com todos os pesos do modelo que você enviou para ele. Primeiro, copie tudo o que você quiser manter em outro local.
nota
O repositório também disponibiliza um auxiliar scripts/cleanup.sh que executa as etapas de drenagem e destruição acima e, em seguida, varre quaisquer volumes EBS órfãos marcados com o nome do cluster. Execute-o de dentro do diretório terraform/<mode>/ do qual você aplicou e passe --auto-approve para ignorar o prompt de confirmação do Terraform.
Confirme que nenhuma reserva de capacidade ativa permaneça para o cluster:
aws ec2 describe-capacity-reservations \ --filters "Name=state,Values=active" "Name=tag:nodepool,Values=reserved-spot-ondemand" \ --query 'CapacityReservations[].CapacityReservationId' \ --output text
Um resultado vazio significa que nenhuma reserva está ativa e nenhuma cobrança adicional será aplicada.