O problema: IDEs fora do cluster
Quem trabalha com fluxos de Inteligência Artificial no Amazon Elastic Kubernetes Service (EKS) conhece bem o atrito: os cientistas de dados precisam de ambientes interativos como JupyterLab e Code Editor, mas rodar esses ambientes geralmente significa sair do cluster onde os pipelines vivem. Isso implica migrar para um JupyterHub dedicado ou trabalhar em um laptop local — e, com isso, perder acesso aos nós de GPU, ao armazenamento compartilhado e às roles do Gerenciamento de Identidade e Acesso da AWS (IAM) que os pipelines dependem.
Para fechar essa lacuna, a Amazon SageMaker AI lançou o SageMaker AI Spaces add-on para Amazon EKS. Ele permite rodar ambientes gerenciados de JupyterLab e Code Editor diretamente no cluster que a equipe já opera. Configurar um JupyterHub standalone com acesso a GPU, armazenamento e autenticação costuma levar de 3 a 5 dias para um time de plataforma. Com o add-on, um cientista de dados consegue subir um Space completamente configurado em cerca de 5 minutos.
Visão geral da solução
A solução opera em um único cluster EKS, organizada em três camadas:
- Rede e acesso: O Amazon Route 53 resolve um domínio wildcard para um Application Load Balancer (ALB) voltado para a internet, com TLS provido pelo AWS Certificate Manager (ACM). Para acesso via VS Code, o AWS Systems Manager cria um túnel direto até o pod do Space.
- Roteamento no cluster: O AWS Load Balancer Controller provisiona o ALB. O Traefik faz o roteamento por hostname. Um middleware de autenticação valida tokens usando o AWS Key Management Service (AWS KMS) para criptografia de Token Web JSON (JWT).
- Computação e armazenamento: Os pods dos Spaces rodam em workers em sub-redes privadas. O driver CSI do Amazon Elastic Block Store (Amazon EBS) fornece volumes persistentes, enquanto o Amazon Elastic File System (Amazon EFS) ou o Amazon FSx cuidam do armazenamento compartilhado ou de alto throughput. O EKS Pod Identity concede roles IAM com escopo definido para cada pod.
Consolidar cargas de trabalho interativas e de treinamento em um único cluster mantém os nós de GPU ocupados entre jobs. Segundo a AWS, isso pode elevar a utilização de GPU em até 30% em comparação com uma frota dedicada de notebooks, além de evitar o custo de um ambiente GPU sempre ligado — que pode chegar a milhares de dólares por mês.
Pré-requisitos
Para seguir o passo a passo, são necessários: uma conta AWS com a Interface de Linha de Comando da AWS (AWS CLI) 2.x ou superior configurada para a região alvo, kubectl 1.30 ou superior e Helm v3. Também é preciso ter uma zona hospedada pública no Route 53 para um domínio próprio (referenciado como <YOUR_DOMAIN> ao longo do guia) e permissões IAM para criar roles, políticas, add-ons EKS, entradas de acesso, associações de Pod Identity, certificados ACM e chaves KMS. O add-on Spaces deve ser a versão 0.1.4 ou superior, pois versões anteriores suportavam apenas o Amazon SageMaker HyperPod.
Atenção aos custos: este guia cria recursos que geram cobranças na AWS: um ALB voltado para a internet, volumes EBS e um cluster EKS. O nível avançado do SSM (Systems Manager) adiciona aproximadamente US$ 0,00695/hora por pod de Space. Siga a seção de limpeza ao finalizar.
Criando o cluster EKS
A criação do cluster segue o guia de introdução ao EKS padrão, mas com quatro requisitos específicos para o Spaces. O EKS Auto Mode deve estar desabilitado, pois o add-on exige nós EC2 clássicos no Kubernetes 1.30 ou superior. É preciso usar uma Nuvem Privada Virtual (VPC) com sub-redes públicas e privadas em pelo menos duas Zonas de Disponibilidade, com um gateway NAT servindo as sub-redes privadas, e o acesso ao endpoint do cluster deve ser configurado como público e privado.
Durante a criação, os seguintes add-ons devem ser adicionados: EKS Pod Identity Agent, Amazon EBS CSI Driver, Cert Manager e External DNS. O Amazon SageMaker Spaces e o AWS Load Balancer Controller são instalados em etapas posteriores. O grupo de nós gerenciado deve usar Amazon Linux 2023, instâncias m5.xlarge ou maiores, com 2 nós nas sub-redes privadas.
Um passo frequentemente esquecido é a marcação (tagging) das sub-redes da VPC, necessária para que o AWS Load Balancer Controller possa descobri-las. Isso deve ser feito antes de instalar o add-on Spaces, caso contrário o controlador pode posicionar o ALB em sub-redes privadas, tornando os Spaces inacessíveis.
export VPC_ID=$(aws eks describe-cluster \
--name $CLUSTER_NAME --region $REGION \
--query 'cluster.resourcesVpcConfig.vpcId' --output text)
ALL_SUBNETS=$(aws ec2 describe-subnets --region $REGION \
--filters "Name=vpc-id,Values=${VPC_ID}" \
--query 'Subnets[*].SubnetId' --output text)
aws ec2 create-tags --region $REGION --resources ${ALL_SUBNETS} \
--tags Key=kubernetes.io/cluster/$CLUSTER_NAME,Value=shared
PUBLIC_SUBNETS=$(aws ec2 describe-subnets --region $REGION \
--filters "Name=vpc-id,Values=${VPC_ID}" "Name=map-public-ip-on-launch,Values=true" \
--query 'Subnets[*].SubnetId' --output text)
aws ec2 create-tags --region $REGION --resources ${PUBLIC_SUBNETS} \
--tags Key=kubernetes.io/role/elb,Value=1
PRIVATE_SUBNETS=$(aws ec2 describe-subnets --region $REGION \
--filters "Name=vpc-id,Values=${VPC_ID}" "Name=map-public-ip-on-launch,Values=false" \
--query 'Subnets[*].SubnetId' --output text)
aws ec2 create-tags --region $REGION --resources ${PRIVATE_SUBNETS} \
--tags Key=kubernetes.io/role/internal-elb,Value=1
Configurando a base do ambiente
Com o cluster em execução, o kubectl é apontado para ele e confirmado que os pods dos add-ons estão saudáveis. O External DNS precisa de permissões no Route 53 para gerenciar registros DNS. A role é criada com uma política de privilégio mínimo e vinculada via Pod Identity:
aws iam create-role --role-name ExternalDNSRole \
--assume-role-policy-document file://pod-identity-trust.json
aws iam put-role-policy --role-name ExternalDNSRole \
--policy-name ExternalDNSRoute53Policy \
--policy-document '{
"Version":"2012-10-17",
"Statement":[
{"Effect":"Allow","Action":["route53:ChangeResourceRecordSets"],
"Resource":"arn:aws:route53:::hostedzone/*"},
{"Effect":"Allow","Action":["route53:ListHostedZones","route53:ListResourceRecordSets","route53:ListTagsForResource"],
"Resource":"*"}
]}'
aws eks create-pod-identity-association \
--cluster-name $CLUSTER_NAME --region $REGION \
--namespace external-dns --service-account external-dns \
--role-arn arn:aws:iam::${ACCOUNT_ID}:role/ExternalDNSRole
kubectl rollout restart deployment -n external-dns external-dns
Nota de segurança: o escopo de cada role de Pod Identity deve ser limitado às ações e recursos mínimos necessários. Prefira ARNs explícitos em vez de wildcards, e confirme que apenas a service account pretendida pode assumir a role.
Instalando o AWS Load Balancer Controller
O AWS Load Balancer Controller é responsável por provisionar o ALB que expõe a interface dos Spaces. A instalação é feita via Helm, após criar a política IAM, a role e a associação de Pod Identity:
curl -sS -o /tmp/lbc-iam-policy.json \
https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file:///tmp/lbc-iam-policy.json
aws iam create-role --role-name AWSLoadBalancerControllerRole \
--assume-role-policy-document file://pod-identity-trust.json
aws iam attach-role-policy --role-name AWSLoadBalancerControllerRole \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy
aws eks create-pod-identity-association \
--cluster-name $CLUSTER_NAME --region $REGION \
--namespace kube-system --service-account aws-load-balancer-controller \
--role-arn arn:aws:iam::${ACCOUNT_ID}:role/AWSLoadBalancerControllerRole
helm repo add eks https://aws.github.io/eks-charts
helm repo update eks
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=$CLUSTER_NAME \
--set serviceAccount.create=true \
--set serviceAccount.name=aws-load-balancer-controller \
--set region=$REGION \
--set vpcId=$VPC_ID
kubectl rollout status deployment -n kube-system aws-load-balancer-controller --timeout=180s
Atenção: no chart v3.2 ou superior, o controlador falha se tentar detectar a VPC automaticamente via metadados EC2, que o EKS bloqueia para pods. Por isso, os parâmetros vpcId e region devem ser passados explicitamente.
Criando o certificado, a chave KMS e configurando o SSM
O add-on Spaces exige um certificado TLS, uma chave KMS para criptografia de JWT e configurações do SSM para acesso remoto. O certificado ACM deve cobrir o domínio raiz e um wildcard, usando validação DNS:
CERT_ARN=$(aws acm request-certificate \
--domain-name "<YOUR_DOMAIN>" \
--subject-alternative-names "*<YOUR_DOMAIN>" \
--validation-method DNS \
--region $REGION \
--query CertificateArn --output text)
aws acm describe-certificate --certificate-arn "$CERT_ARN" \
--region $REGION \
--query 'Certificate.DomainValidationOptions[].ResourceRecord'
Nota de segurança: a validação DNS verifica a propriedade do domínio e aciona a renovação automática do ACM. Os CNAMEs de validação devem permanecer no Route 53 — removê-los interrompe a renovação.
Em seguida, cria-se a chave KMS para criptografia de JWT (o padrão da CLI já é simétrica ENCRYPT_DECRYPT):
KMS_KEY_ARN=$(aws kms create-key --region $REGION \
--description "SageMaker Spaces JWT encryption" \
--query 'KeyMetadata.Arn' --output text)
aws kms create-alias --region $REGION \
--alias-name alias/sagemaker-spaces-jwt \
--target-key-id "$KMS_KEY_ARN"
Por fim, ativa-se o nível avançado de instâncias gerenciadas do SSM, necessário para que o túnel SSH-over-SSM do VS Code funcione (custo aproximado de US$ 0,00695/hora por pod de Space):
aws ssm update-service-setting --region $REGION \
--setting-id arn:aws:ssm:$REGION:${ACCOUNT_ID}:servicesetting/ssm/managed-instance/activation-tier \
--setting-value advanced
Instalando o add-on Spaces
Antes de instalar o add-on, são criadas as roles IAM para o controlador do Spaces e para o middleware de autenticação. A role SSM managed-instance é usada por cada pod de Space na frota do SSM:
aws iam create-role --role-name SageMakerSpacesSSMManagedNodeRole \
--assume-role-policy-document '{
"Version":"2012-10-17",
"Statement":[{"Effect":"Allow","Principal":{"Service":"ssm.amazonaws.com"},"Action":"sts:AssumeRole"}]
}'
aws iam attach-role-policy --role-name SageMakerSpacesSSMManagedNodeRole \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
A role do controlador Spaces precisa de permissões SSM, PassRole e KMS. Após criar o arquivo de política spaces-controller-policy.json com os valores corretos de <REGION>, <ACCOUNT_ID> e <KMS_KEY_ARN>, a role é criada e as service accounts são vinculadas via Pod Identity:
aws iam create-role --role-name SageMakerSpacesControllerRole \
--assume-role-policy-document file://pod-identity-trust.json
aws iam put-role-policy --role-name SageMakerSpacesControllerRole \
--policy-name SageMakerSpacesControllerPolicy \
--policy-document file://spaces-controller-policy.json
for SA in jupyter-k8s-controller-manager jupyter-k8s-authmiddleware; do
aws eks create-pod-identity-association \
--cluster-name $CLUSTER_NAME --region $REGION \
--namespace jupyter-k8s-system --service-account $SA \
--role-arn arn:aws:iam::${ACCOUNT_ID}:role/SageMakerSpacesControllerRole
done
Com as roles prontas, define-se o arquivo addon-config.yaml com o domínio, ARN do certificado, ARN da chave KMS e nome da role de nó gerenciado, e então instala-se o add-on:
aws eks create-addon \
--cluster-name $CLUSTER_NAME --region $REGION \
--addon-name amazon-sagemaker-spaces \
--configuration-values file://addon-config.yaml \
--resolve-conflicts OVERWRITE
O add-on leva cerca de três minutos para atingir o status ACTIVE. Quando pronto, o controlador, duas réplicas do middleware de autenticação e dois roteadores Traefik devem estar em execução no namespace jupyter-k8s-system.
Concedendo acesso e criando o primeiro Space
Com o add-on saudável, o acesso de usuário é concedido via entrada de acesso EKS com escopo para um único namespace. No console do EKS, navega-se até a aba Access do cluster e cria-se uma entrada de acesso vinculando o usuário ou role IAM à política AmazonSagemakerHyperpodSpacePolicy para o namespace padrão.
Nota de segurança: prefira acesso com escopo de namespace em vez de políticas globais no cluster, para que os usuários não possam modificar recursos fora do seu namespace.
Para criar o primeiro Space JupyterLab, define-se um arquivo workspace.yaml:
apiVersion: workspace.jupyter.org/v1alpha1
kind: Workspace
metadata:
name: my-space
namespace: default
spec:
templateRef:
name: sagemaker-jupyter-template
namespace: jupyter-k8s-system
appType: jupyterlab
accessType: OwnerOnly
accessStrategy:
name: hyperpod-access-strategy
namespace: jupyter-k8s-system
image: public.ecr.aws/sagemaker/sagemaker-distribution:latest-cpu
kubectl apply -f workspace.yaml
kubectl get workspace -n default -w
A inicialização pela primeira vez leva cerca de cinco minutos, pois o cluster faz o pull da imagem SageMaker Distribution (aproximadamente 4 GB) e registra o pod no SSM.
Acessando via browser e via VS Code
Acesso pelo navegador
O controlador de Spaces emite uma URL pré-assinada de curta duração com o token criptografado do usuário. Para gerar uma:
kubectl create -f - -o yaml <<EOF
apiVersion: connection.workspace.jupyter.org/v1alpha1
kind: WorkspaceConnection
metadata:
namespace: default
generateName: my-space-conn-
spec:
workspaceName: my-space
workspaceConnectionType: web-ui
EOF
O campo status.workspaceConnectionUrl na resposta contém a URL para acessar o JupyterLab no browser.
Nota de segurança: as URLs pré-assinadas carregam o JWT criptografado pelo KMS com expiração de 5 minutos, aplicada pelo campo exp. Esse valor não é configurável na versão atual do add-on. Não registre nem compartilhe essas URLs por canais não criptografados. Para acesso duradouro, use o VS Code remoto.
Acesso via VS Code
Para uma experiência de IDE local, o VS Code se conecta ao pod do Space por meio de um túnel SSM, sem necessidade de browser, domínio ou ALB. É preciso instalar o VS Code, a extensão AWS Toolkit e o plugin do Session Manager localmente.
Para gerar a URL de conexão do VS Code, cria-se o mesmo recurso WorkspaceConnection, mas com workspaceConnectionType: vscode-remote. A resposta retorna um deep link vscode:// em vez de uma URL HTTPS. Ao colar esse link no browser, ele solicita a abertura no VS Code, e o AWS Toolkit estabelece um túnel SSH-over-SSM até o Space, com o VS Code se conectando ao sistema de arquivos remoto.
Para configurações em sub-redes privadas e alternativas via SDK, a AWS disponibiliza a documentação sobre acesso remoto aos SageMaker AI Spaces.
Autenticação corporativa com OIDC
O acesso descrito até aqui usa usuários e roles IAM. Para permitir que a equipe faça login com credenciais corporativas, é possível registrar um provedor OpenID Connect (OIDC) no cluster e vincular o Controle de Acesso Baseado em Funções (RBAC) do Kubernetes aos grupos do provedor de identidade. O Kubernetes então autoriza as pessoas por associação a grupos, sem necessidade de um principal IAM por usuário.
O projeto open source jupyter-deploy disponibiliza um template aws-eks-oidc que configura isso automaticamente. O Dex roda no cluster como provedor OIDC, o Amazon EKS confia nele como provedor de identidade, e um console web oferece gerenciamento self-service de workspaces para a equipe.
O Amazon Cognito funciona por meio do conector genérico OIDC no Dex e requer dois mapeamentos de claims que o GitHub não exige. O EKS lê o nome de usuário do claim preferred_username, que o Cognito não emite — por isso é necessário mapeá-lo a partir do email. O Cognito também publica a associação a grupos como cognito:groups em vez de groups. Se o mapeamento de nome de usuário for omitido, as requisições chegam ao servidor de API sem usuário resolvível, e o console reporta uma sessão expirada em vez de um erro de autorização.
O template vincula sua role RBAC a um grupo chamado <org>:<team>, portanto é necessário criar um grupo no Cognito com exatamente esse nome e adicionar os usuários a ele. A equipe então faz login pela página gerenciada do Cognito.
Limpeza dos recursos
Para evitar cobranças contínuas, os recursos devem ser removidos na ordem inversa:
kubectl delete workspace my-space -n default
aws eks delete-addon --cluster-name $CLUSTER_NAME --region $REGION \
--addon-name amazon-sagemaker-spaces
helm uninstall aws-load-balancer-controller -n kube-system
for a in aws-ebs-csi-driver external-dns cert-manager eks-pod-identity-agent kube-proxy; do
aws eks delete-addon --cluster-name $CLUSTER_NAME --region $REGION --addon-name $a
done
Também devem ser removidos: as roles IAM, políticas e associações de Pod Identity criadas (ExternalDNSRole, AWSLoadBalancerControllerRole, AWSLoadBalancerControllerIAMPolicy, SageMakerSpacesControllerRole, SageMakerSpacesSSMManagedNodeRole), o certificado ACM, a chave KMS (com agendamento mínimo de 7 dias para exclusão) e os registros no Route 53. O nível avançado do SSM deve ser revertido para evitar cobranças por instância em toda a conta:
aws ssm update-service-setting --region $REGION \
--setting-id arn:aws:ssm:$REGION:${ACCOUNT_ID}:servicesetting/ssm/managed-instance/activation-tier \
--setting-value standard
Por fim, o grupo de nós e o cluster EKS devem ser deletados, assim como a VPC, caso tenha sido criada especificamente para este guia.
Conclusão
O add-on SageMaker AI Spaces para Amazon EKS representa uma mudança significativa na forma como equipes de dados gerenciam seus ambientes de desenvolvimento. Ao consolidar IDEs interativos no mesmo cluster que já roda os pipelines, a AWS elimina a necessidade de gerenciar dois ambientes separados e reduz o tempo de configuração de dias para minutos. Para evoluir ainda mais a solução, a AWS sugere adicionar o AWS WAF, federar provedores de identidade adicionais, separar as roles IAM do controlador e do middleware de autenticação, ou definir cotas de recursos por namespace.
Para abordagens relacionadas, vale conferir os artigos sobre IDEs interativos no SageMaker HyperPod e sobre aceleração de treinamento e inferência com SageMaker HyperPod e SageMaker Studio.
Fonte
Run interactive IDEs on Amazon EKS with SageMaker AI to power up your AI workflows (https://aws.amazon.com/blogs/machine-learning/run-interactive-ides-on-amazon-eks-with-sagemaker-ai-to-power-up-your-ai-workflows/)
Leave a Reply