Das Aktualisieren der Amazon Sagemaker AI Real-Time-Endpunktkonfiguration (Ändern des Instanztyps, der Instanzanzahl oder der Umgebungsvariablen) führt dazu, dass Deployments über AWS CloudFormation oder das AWS Cloud Development Kit (AWS CDK) fehlschlagen. SageMaker AI verlangt, dass Sie das skalierbare Ziel abmelden, bevor Sie den Endpunkt aktualisieren; sobald Sie es jedoch abmelden, kann CloudFormation die AWS Application Auto Scaling-Ressourcen nicht mehr nachverfolgen.
In diesem Beitrag zeigen wir Ihnen, wie Sie mit einem wiederverwendbaren CDK-Konstrukt und AWS CloudFormation Custom Resources das Abmelden und Anmelden von Auto Scaling während Endpunktaktualisierungen automatisch orchestrieren. Sie können Ihre Endpunktkonfiguration und Auto-Scaling-Parameter in einem einzigen Deployment ohne manuelles Eingreifen aktualisieren.
Warum dieses Problem auftritt
Wenn Sie einen SageMaker AI-Endpunkt mit nativen CloudFormation-Auto-Scaling-Ressourcen deployen, dann die Endpunktkonfiguration ändern und erneut deployen, treten mehrere Fehlermodi auf. Der konkrete Fehler hängt davon ab, was Sie ändern und wie Sie das Problem umgehen.
Ändern der Endpunktkonfiguration bei angemeldetem Auto Scaling
CloudFormation versucht, den Endpunkt zu aktualisieren, während das skalierbare Ziel noch angemeldet ist. SageMaker AI weist die Aktualisierung mit dem folgenden Fehler zurück:
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.
SageMaker AI blockiert die Endpunktaktualisierung, bevor CloudFormation die Auto-Scaling-Ressourcen erreicht.
Manuelles Abmelden von Auto Scaling und anschließende Änderung ausschließlich der Endpunktkonfiguration
Wenn Sie das skalierbare Ziel über die AWS Command Line Interface (AWS CLI) abmelden und mit einer Änderung nur der Endpunktkonfiguration erneut deployen, ist das Deployment erfolgreich. CloudFormation meldet Auto Scaling jedoch nicht an, obwohl es in der CloudFormation-Vorlage vorhanden ist. Da sich die Auto-Scaling-Parameter in der CloudFormation-Vorlage nicht geändert haben, meldet CloudFormation weder das skalierbare Ziel an noch wendet es die Skalierungsrichtlinie erneut an. Der Endpunkt läuft nun ohne Auto Scaling, und es gibt keinen Fehler, der auf ein Problem hinweist.
Manuelles Abmelden von Auto Scaling und anschließende Änderung der Auto-Scaling-Parameter
Wenn Sie das skalierbare Ziel über die AWS CLI abmelden und mit Änderungen an den Auto-Scaling-Parametern erneut deployen, versucht CloudFormation, die Ressource ScalableTarget zu aktualisieren, die nicht mehr existiert:
Resource of type 'AWS::ApplicationAutoScaling::ScalableTarget' with identifier 'endpoint/<name>/variant/AllTraffic|sagemaker:variant:DesiredInstanceCount|sagemaker' was not found.
Dieser Fehler ist bemerkenswert, weil auch das Rollback fehlschlägt (UPDATE_ROLLBACK_FAILED), wodurch der Stack in einem defekten Zustand verbleibt, der manuelles Eingreifen in der CloudFormation-Konsole erfordert, um ihn wiederherzustellen.
Lösungsübersicht
Sie können dieses CDK-Konstrukt verwenden, um die nativen AWS::ApplicationAutoScaling::ScalableTarget und AWS::ApplicationAutoScaling::ScalingPolicy CloudFormation-Ressourcen durch drei Custom Resources zu ersetzen. Diese Custom Resources melden Auto Scaling um die Endpunktaktualisierung herum ab und wieder an, mit expliziter Abhängigkeitsreihenfolge, erzwungen durch node.add_dependency -Aufrufe in CDK. Die vollständige Sequenz lautet:
- Deregister (Custom Resource): Entfernt das skalierbare Ziel, bevor die Endpunktaktualisierung beginnt. Beim ersten Deployment existiert noch kein skalierbares Ziel, daher behandelt der Handler diesen Fehler graceful und fährt fort.
- Endpoint update (CDK-verwaltet): CDK aktualisiert die Endpunktressource normal und tauscht dabei auf die neue Endpunktkonfiguration um.
- Register Scalable Target (Custom Resource): Wartet, bis der Endpunkt den Status
InServiceerreicht hat, und meldet dann das skalierbare Ziel an. - Attach Scaling Policy (Custom Resource): Wartet, bis das skalierbare Ziel abfragbar ist, und wendet dann die Target-Tracking-Richtlinie an.
Abbildung 1: Orchestrierung der Auto-Scaling-Funktionen eines SageMaker AI-Endpunkts durch Custom Resources um eine CDK-verwaltete Endpunktaktualisierung.
Register Scalable Target und Attach Scaling Policy verwenden das asynchrone Abschlussmuster des CDK-Anbieters. Jede Custom Resource hat einen on_event -Handler, der sofort zurückkehrt, und einen is_complete handler. Der Waiter des Providers ruft den is_complete Handler in einem Intervall (alle 30 Sekunden) erneut auf, bis seine Bereitschaftsprüfung erfolgreich ist. Das Timeout des Providers total_timeout (1 Stunde für Register Scalable Target, 15 Minuten für Attach Scaling Policy) begrenzt die Wartezeit, sodass sie nicht durch das Timeout eines einzelnen Lambda-Aufrufs eingeschränkt ist.
Eine ConfigHash Eigenschaft jeder benutzerdefinierten Ressource zwingt CloudFormation, die Lambda-Funktionen erneut aufzurufen, wann immer sich ein Konfigurationswert ändert. Die Endpunkt-Konfiguration und die Auto-Scaling-Parameter werden zusammen definiert, weil ein einzelner ConfigHash die Auto-Scaling-Orchestrierung antreibt.
Obwohl das Konstrukt drei benutzerdefinierte Ressourcen definiert, enthält der bereitgestellte Stack mehr als drei Lambda-Funktionen. Jede benutzerdefinierte Ressource wird von einem CDK unterstützt cr.Provider, und das Provider-Framework erzeugt seine eigenen Helper-Lambda-Funktionen. Ein synchroner Provider (Deregister) fügt eine Framework-Funktion hinzu. Ein asynchroner Provider (Register Scalable Target und Attach Scaling Policy) fügt drei hinzu („onEvent, isComplete, und onTimeout") plus eine AWS Step Functions State Machine, die den Waiter steuert. Dadurch enthält der bereitgestellte Stack drei Custom Resources, zwei Step Functions State Machines und zwölf Lambda-Funktionen. Fünf der Ressourcen enthalten den eigenen Handler-Code des Konstrukts (einen für Deregister und ein on_event und is_complete Paar für jede asynchrone Ressource), wobei die übrigen sieben vom Provider-Framework generiert werden. Sie schreiben oder warten die frameworkgenerierten Funktionen nicht, aber sie sind im Stack vorhanden und sollten bei der Überprüfung der bereitgestellten Ressourcen berücksichtigt werden.
Komplettlösung
In dieser Anleitung stellen Sie einen SageMaker-AI-Endpunkt mit Auto Scaling unter Verwendung des bereitgestellten Beispiel-Stacks bereit und überprüfen anschließend, ob Konfigurationsaktualisierungen korrekt funktionieren.
Die Anleitung umfasst die folgenden Schritte:
- Klonen Sie das Repository und installieren Sie die Abhängigkeiten.
- Konfigurieren Sie Ihre Endpunkt- und Auto-Scaling-Einstellungen.
- Deploy and verify.
- Testen Sie ein Update.
Der Quellcode ist verfügbar in der verlinktes GitHub-Repository.
Voraussetzungen
Für diese Anleitung benötigen Sie Folgendes:
- Ein AWS-Konto mit Berechtigungen für Amazon SageMaker AI, AWS Lambda, AWS Identity and Access Management (IAM), Application Auto Scaling und Amazon CloudWatch.
- AWS CDK v2 installiert.
- Python 3.12 oder später.
- uv für das Python-Abhängigkeitsmanagement.
- Ein SageMaker-AI-Modellartefakt in Amazon Simple Storage Service (Amazon S3) und ein Container-Image in Amazon Elastic Container Registry (Amazon ECR) oder ein integrierter Algorithmus-Container von SageMaker AI.
Klonen Sie das Repository und installieren Sie die Abhängigkeiten
- Klonen Sie das Repository:
git clone https://github.com/aws-samples/sample-sagemaker-endpoint-autoscaling.git cd sample-sagemaker-endpoint-autoscaling - Installieren Sie die Abhängigkeiten:
uv sync
Konfigurieren Sie Ihre Endpoint- und Auto-Scaling-Einstellungen
Die Endpoint- und Auto-Scaling-Einstellungen werden zusammen in config/ definiert,config.yaml da ein einzelner config_hash die Auto-Scaling-Orchestrierung steuert. Eine Änderung an einem der beiden Abschnitte löst die gesamte Sequenz aus.
Bearbeiten Sie config/config.yaml mit Ihren Werten:
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
Die Endpunkt-Parameter entsprechen den SageMaker AI CreateModel und CreateEndpointConfig APIs. Die Auto-Scaling-Parameter entsprechen den Application Auto Scaling RegisterScalableTarget und PutScalingPolicy APIs.
Bereitstellen und überprüfen
- Richten Sie Ihre AWS-Umgebung mit Bootstrap ein, falls noch nicht geschehen:
uv run cdk bootstrap - Stellen Sie den Stack bereit:
uv run cdk deploy InferenceStack
CloudFormation erstellt das SageMaker AI-Modell, die Endpunkt-Konfiguration und den Endpunkt und führt dann die drei benutzerdefinierten Ressourcen nacheinander aus, um Auto Scaling zu registrieren.
- Überprüfen Sie, ob die Bereitstellung das skalierbare Ziel registriert hat:
aws application-autoscaling describe-scalable-targets --service-namespace sagemaker --resource-ids endpoint/my-model-endpoint/variant/AllTraffic - Überprüfen Sie, ob die Bereitstellung die Skalierungsrichtlinie angewendet hat:
aws application-autoscaling describe-scaling-policies --service-namespace sagemaker --resource-id endpoint/my-model-endpoint/variant/AllTraffic
Ein Update testen
Ändern Sie einen Wert in config/config.yaml, zum Beispiel den Instance-Typ von ml.m5.large auf ml.m5.xlarge, und stellen Sie erneut bereit:
uv run cdk deploy InferenceStack
Nach Abschluss der Bereitstellung überprüfen Sie, ob Auto Scaling weiterhin registriert ist und die aktualisierten Werte enthält:
aws application-autoscaling describe-scalable-targets
--service-namespace sagemaker
--resource-ids endpoint/my-model-endpoint/variant/AllTraffic
Integration in einen bestehenden Stack
Verwenden Sie den Beispiel-Stack, wenn Sie neu starten oder eine Referenzimplementierung wünschen. Verwenden Sie das Construct direkt, wenn Sie bereits einen CDK-Stack mit SageMaker-AI-Ressourcen haben.
Um die Integration in einen bestehenden Stack durchzuführen, kopieren Sie das sagemaker_autoscaling/constructs/ -Verzeichnis in Ihr Projekt und fügen Sie das Construct neben Ihren Endpoint-Ressourcen hinzu:
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,
),
)
Funktionsweise des Constructs
Dieser Abschnitt erläutert die wichtigsten Implementierungsdetails von SagemakerAutoscalingConstruct.
Deregister
Die Deregister-Custom-Resource ruft deregister_scalable_target vor dem Endpoint-Update auf. Sie behandelt ObjectNotFoundException für Erstbereitstellungen, bei denen kein skalierbares Ziel existiert:
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}"}
Die Abhängigkeit wird in CDK wie folgt hergestellt:
props.endpoint.node.add_dependency(deregister)
Register Scalable Target
Obwohl CloudFormation die Endpoint-Ressource als abgeschlossen betrachtet, sobald das Update akzeptiert wurde, kann das skalierbare Ziel erst registriert werden, nachdem der Endpoint InServiceerreicht hat. Anstatt einen einzelnen Lambda-Aufruf auf diese Wartezeit zu blockieren, verwendet Register Scalable Target das asynchrone Abschlussmuster des Providers. Der on_event -Handler kehrt sofort zurück, und der Waiter des Providers ruft den is_complete -Handler bei query_interval erneut auf, bis der Endpoint InServiceist. Die total_timeout (1 Stunde) des Providers begrenzt die Wartezeit, nicht das Timeout eines einzelnen Lambda-Aufrufs:
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}
Beim Löschen des Stacks hebt der on_event -Handler die Registrierung des skalierbaren Ziels auf, um aufzuräumen.
Attach Scaling Policy
Es gibt ein kurzes Zeitfenster nach RegisterScalableTarget , in dem das Ziel noch nicht abfragbar ist. Attach Scaling Policy verwendet dasselbe asynchrone Abschlussmuster: Der on_event -Handler kehrt sofort zurück, und der is_complete -Handler meldet den Abschluss erst, sobald das skalierbare Ziel abfragbar ist, woraufhin er die Richtlinie anwendet. Die total_timeout (15 Minuten) des Providers begrenzt die Wartezeit:
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}
Beim Löschen des Stacks löscht der on_event -Handler die Skalierungsrichtlinie, um aufzuräumen.
Aufräumen
Um künftige Gebühren zu vermeiden, löschen Sie die Ressourcen:
uv run cdk destroy InferenceStack
Dies entfernt den SageMaker-AI-Endpoint, die Endpoint-Konfiguration, das Modell, die Lambda-Funktionen, die IAM-Rollen, die von der Target-Tracking-Skalierungsrichtlinie erstellten Amazon-CloudWatch-Alarme, und hebt die Registrierung des skalierbaren Ziels auf.
Fazit
In diesem Beitrag haben wir gezeigt, wie Sie mit einem wiederverwendbaren CDK-Konstrukt Auto Scaling automatisch abmelden und wieder registrieren können, um SageMaker-AI-Endpoint-Updates zu orchestrieren. Das Konstrukt verwendet drei CloudFormation-Custom-Resources mit expliziter Abhängigkeitsreihenfolge und eine ConfigHash -Eigenschaft, um Auto Scaling über Deployments hinweg intakt zu halten.
Um loszulegen, klonen Sie das sample-sagemaker-endpoint-autoscaling -Repository und folgen Sie den Setup-Anweisungen. Das Repository enthält einen Beispiel-Stack, den Sie direkt deployen können, oder Sie können das Konstrukt in Ihren bestehenden CDK-Stack integrieren.
Weitere Informationen zu Application Auto Scaling für SageMaker AI finden Sie unter Automatically scale Amazon SageMaker AI models. Weitere Informationen zu CloudFormation-Custom-Resources finden Sie unter Custom resources in the AWS CloudFormation User Guide.