O problema: por que atualizar endpoints com auto scaling falha
Quem trabalha com endpoints de inferência em tempo real no Amazon SageMaker AI já deve ter se deparado com uma situação frustrante: ao tentar atualizar a configuração do endpoint — seja mudando o tipo de instância, a quantidade de instâncias ou variáveis de ambiente — o deploy via AWS CloudFormation ou Kit de Desenvolvimento em Nuvem da AWS (AWS CDK) simplesmente falha.
O motivo é uma exigência do próprio SageMaker AI: antes de atualizar o endpoint, é necessário desregistrar o scalable target do Auto Scaling de Aplicações da AWS (Application Auto Scaling). O problema é que, ao fazer isso, o CloudFormation perde o rastreamento desse recurso — e aí começa uma série de falhas em cascata.
A AWS documentou em detalhes os três modos de falha mais comuns nesse cenário:
- Atualizar a configuração com o auto scaling ainda registrado: o CloudFormation tenta atualizar o endpoint enquanto o scalable target ainda está ativo. O SageMaker AI rejeita a operação com o erro:
The variant(s) "[AllTraffic]" must be deregistered as scalable targets with Application Auto Scaling before they can be removed or have their instance type updated. - Desregistrar manualmente e atualizar apenas a configuração do endpoint: o deploy funciona, mas o CloudFormation não reregistra o auto scaling — porque os parâmetros de auto scaling no template não mudaram. O endpoint fica rodando sem auto scaling, sem qualquer erro visível. Um problema silencioso e perigoso.
- Desregistrar manualmente e alterar também os parâmetros de auto scaling: o CloudFormation tenta atualizar um recurso
AWS::ApplicationAutoScaling::ScalableTargetque não existe mais, gerando falha. O pior: o rollback também falha (UPDATE_ROLLBACK_FAILED), deixando a stack em estado corrompido que exige intervenção manual no console do CloudFormation.
A solução: um construct CDK com recursos personalizados do CloudFormation
Para resolver esse problema de forma robusta e reutilizável, a AWS propõe substituir os recursos nativos AWS::ApplicationAutoScaling::ScalableTarget e AWS::ApplicationAutoScaling::ScalingPolicy por três recursos personalizados do CloudFormation (CloudFormation custom resources), orquestrados por um construct do CDK.
Esses recursos personalizados gerenciam o ciclo completo de deregistro e reregistro do auto scaling em torno da atualização do endpoint, com ordenação explícita de dependências via chamadas node.add_dependency no CDK. A sequência completa de execução é:
- Deregistro (custom resource): remove o scalable target antes de qualquer atualização do endpoint. No primeiro deploy, como ainda não existe nenhum scalable target, o handler trata o erro graciosamente e continua.
- Atualização do endpoint (gerenciada pelo CDK): o CDK atualiza o recurso de endpoint normalmente, aplicando a nova configuração.
- Registro do Scalable Target (custom resource): aguarda o endpoint atingir o status
InServicee então registra o scalable target. - Aplicação da Scaling Policy (custom resource): aguarda o scalable target estar disponível para consulta e então aplica a política de rastreamento de alvo (target tracking policy).
Os dois últimos recursos utilizam o padrão de conclusão assíncrona do provedor CDK: cada um tem um handler on_event que retorna imediatamente e um handler is_complete que é reinvocado em intervalos de 30 segundos até que a verificação de prontidão seja aprovada. O timeout total é de 1 hora para o registro do scalable target e 15 minutos para a aplicação da política — limites que não dependem do timeout de nenhuma invocação individual do AWS Lambda.
Uma propriedade chamada ConfigHash em cada recurso personalizado força o CloudFormation a reinvocar as funções Lambda sempre que qualquer valor de configuração muda. Por isso, a configuração do endpoint e os parâmetros de auto scaling são definidos juntos: um único ConfigHash dispara toda a orquestração.
O que é implantado na stack
Embora o construct defina três recursos personalizados, a stack implantada contém mais recursos do que isso. Cada recurso personalizado é suportado por um cr.Provider do CDK, e o framework do provedor gera suas próprias funções auxiliares Lambda. No total, a stack implantada contém:
- Três recursos personalizados
- Duas máquinas de estado do AWS Step Functions
- Doze funções Lambda (cinco com código próprio do construct, sete geradas pelo framework do provedor)
As funções geradas pelo framework não precisam ser escritas nem mantidas manualmente, mas é importante contabilizá-las ao revisar os recursos implantados.
Passo a passo: implantando e testando a solução
O código-fonte completo está disponível no repositório GitHub de exemplo. O walkthrough cobre quatro etapas principais.
Pré-requisitos
Para seguir o passo a passo, são necessários:
- Uma conta AWS com permissões para Amazon SageMaker AI, AWS Lambda, Gerenciamento de Identidade e Acesso (IAM), Application Auto Scaling e Amazon CloudWatch
- AWS CDK v2 instalado
- Python 3.12 ou superior
- uv para gerenciamento de dependências Python
- Um artefato de modelo SageMaker AI no Amazon S3 e uma imagem de container no Amazon ECR, ou um container de algoritmo nativo do SageMaker AI
Clonando o repositório e instalando dependências
git clone https://github.com/aws-samples/sample-sagemaker-endpoint-autoscaling.git
cd sample-sagemaker-endpoint-autoscaling
uv sync
Configurando o endpoint e os parâmetros de auto scaling
As configurações do endpoint e do auto scaling são definidas juntas no arquivo config/config.yaml, pois um único config_hash controla toda a orquestração. Qualquer alteração em qualquer uma das seções dispara a sequência completa.
endpoint:
endpoint_name: "my-model-endpoint"
image: "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-model:latest"
model_data_url: "s3://my-bucket/models/model.tar.gz"
instance_type: "ml.m5.large"
initial_instance_count: 1
environment: {}
autoscaling:
min_capacity: 1
max_capacity: 10
target_value: 100
scale_in_cooldown: 600
scale_out_cooldown: 120
Os parâmetros de endpoint mapeiam para as APIs CreateModel e CreateEndpointConfig do SageMaker AI. Os parâmetros de auto scaling mapeiam para as APIs RegisterScalableTarget e PutScalingPolicy do Application Auto Scaling.
Implantando e verificando
uv run cdk bootstrap
uv run cdk deploy InferenceStack
Após o deploy, é possível verificar se o scalable target foi registrado corretamente:
aws application-autoscaling describe-scalable-targets \
--service-namespace sagemaker \
--resource-ids endpoint/my-model-endpoint/variant/AllTraffic
E verificar se a política de escalonamento foi aplicada:
aws application-autoscaling describe-scaling-policies \
--service-namespace sagemaker \
--resource-id endpoint/my-model-endpoint/variant/AllTraffic
Testando uma atualização
Para testar, basta alterar um valor no config.yaml — por exemplo, mudar o tipo de instância de ml.m5.large para ml.m5.xlarge — e reimplantar:
uv run cdk deploy InferenceStack
Após o deploy, a verificação com o comando describe-scalable-targets deve confirmar que o auto scaling continua registrado e com os valores atualizados.
Integrando com uma stack existente
Quem já possui uma stack CDK com recursos SageMaker AI pode integrar o construct diretamente, sem precisar usar o exemplo completo. Basta copiar o diretório sagemaker_autoscaling/constructs/ para o projeto e adicionar o construct junto aos recursos de endpoint existentes:
import json
from sagemaker_autoscaling.constructs.sagemaker_autoscaling_construct import (
AutoscalingConfig,
SagemakerAutoscalingConstruct,
SagemakerAutoscalingProps,
)
# Both endpoint and auto scaling values must be in config_hash so that
# a change to either triggers the auto scaling orchestration.
config_hash = json.dumps({
"endpoint": {
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-model:latest",
"modelDataUrl": "s3://my-bucket/models/model.tar.gz",
"instanceType": "ml.m5.large",
"initialInstanceCount": 1,
},
"autoscaling": {
"minCapacity": 1,
"maxCapacity": 10,
"targetValue": 100,
"scaleInCooldown": 600,
"scaleOutCooldown": 120,
},
})
SagemakerAutoscalingConstruct(
self,
"Autoscaling",
props=SagemakerAutoscalingProps(
endpoint=your_endpoint, # your CfnEndpoint
autoscaling=AutoscalingConfig(
min_capacity=1,
max_capacity=10,
target_value=100,
scale_in_cooldown=600,
scale_out_cooldown=120,
),
config_hash=config_hash,
),
)
Como o construct funciona internamente
Deregistro
O recurso personalizado de deregistro chama deregister_scalable_target antes da atualização do endpoint. Ele trata a exceção ObjectNotFoundException para o caso de primeiro deploy, onde nenhum scalable target existe ainda:
def handler(event, context):
resource_id = event["ResourceProperties"]["ResourceId"]
if event["RequestType"] in ("Create", "Update"):
try:
client.deregister_scalable_target(
ServiceNamespace="sagemaker",
ResourceId=resource_id,
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
)
except client.exceptions.ObjectNotFoundException:
pass # No scalable target on first deploy
return {"PhysicalResourceId": f"deregister-{resource_id}"}
Registro do Scalable Target
Mesmo que o CloudFormation considere o recurso de endpoint como completo assim que a atualização é aceita, o scalable target só pode ser registrado depois que o endpoint atinge o status InService. O handler on_event retorna imediatamente, e o waiter do provedor reinvoca o is_complete em intervalos até que o endpoint esteja pronto:
def handler(event, context):
props = event["ResourceProperties"]
resource_id = props["ResourceId"]
endpoint_name = resource_id.split("/")[1]
if event["RequestType"] == "Delete":
return {"IsComplete": True}
status = sm_client.describe_endpoint(EndpointName=endpoint_name)["EndpointStatus"]
if status == "Failed":
raise Exception("Endpoint in Failed state")
if status != "InService":
return {"IsComplete": False}
as_client.register_scalable_target(
ServiceNamespace="sagemaker",
ResourceId=resource_id,
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
MinCapacity=int(props["MinCapacity"]),
MaxCapacity=int(props["MaxCapacity"]),
)
return {"IsComplete": True}
Na exclusão da stack, o handler on_event desregistra o scalable target para limpeza dos recursos.
Aplicação da Scaling Policy
Existe uma janela breve após o retorno de RegisterScalableTarget em que o target ainda não está disponível para consulta. O mesmo padrão assíncrono é usado: o handler on_event retorna imediatamente, e o is_complete reporta conclusão apenas quando o scalable target está consultável, aplicando então a política:
def handler(event, context):
props = event["ResourceProperties"]
resource_id = props["ResourceId"]
if event["RequestType"] == "Delete":
return {"IsComplete": True}
resp = client.describe_scalable_targets(
ServiceNamespace="sagemaker",
ResourceIds=[resource_id],
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
)
if not resp.get("ScalableTargets"):
return {"IsComplete": False}
client.put_scaling_policy(
PolicyName=props["PolicyName"],
ServiceNamespace="sagemaker",
ResourceId=resource_id,
ScalableDimension="sagemaker:variant:DesiredInstanceCount",
PolicyType="TargetTrackingScaling",
TargetTrackingScalingPolicyConfiguration=json.loads(props["ScalingPolicyConfig"]),
)
return {"IsComplete": True}
Limpeza dos recursos
Para evitar cobranças desnecessárias após os testes, basta destruir a stack:
uv run cdk destroy InferenceStack
Esse comando remove o endpoint do SageMaker AI, a configuração de endpoint, o modelo, as funções Lambda, as roles do IAM, os alarmes do Amazon CloudWatch criados pela política de rastreamento de alvo e desregistra o scalable target.
Conclusão
A solução apresentada pela AWS resolve de forma elegante um problema real e recorrente: manter o auto scaling funcionando corretamente em endpoints SageMaker AI durante atualizações de configuração, sem exigir intervenção manual. O construct CDK reutilizável encapsula toda a orquestração com três recursos personalizados, ordenação explícita de dependências e um mecanismo de ConfigHash que garante que qualquer mudança — seja no endpoint ou nos parâmetros de escalonamento — dispare o fluxo completo.
Para mais informações sobre o Application Auto Scaling para SageMaker AI, consulte a documentação Escalonamento automático de modelos Amazon SageMaker AI. Para mais detalhes sobre recursos personalizados do CloudFormation, consulte o Guia do Usuário do AWS CloudFormation.
Fonte
Orchestrating SageMaker AI endpoint auto scaling with AWS CDK (https://aws.amazon.com/blogs/machine-learning/orchestrating-sagemaker-ai-endpoint-auto-scaling-with-aws-cdk/)
Leave a Reply