mcpField
H
hf-cloud-sagemaker-production-defaults

hf-cloud-sagemaker-production-defaults

github.com/huggingface云与 DevOps11.2k555 次安装5 天前更新
代码仓库

关于 hf-cloud-sagemaker-production-defaults

hf-cloud-sagemaker-production-defaults 用于在 Amazon SageMaker 部署实时推理端点,并采用面向生产的默认配置。它创建端点资源、自动扩缩和 CloudWatch 警报,并通过实际调用和日志检查验证部署。

主要功能

  1. 01创建 SageMaker 模型和端点
  2. 02配置自动扩缩
  3. 03添加 CloudWatch 警报
  4. 04支持推理组件部署
  5. 05提供端点调用与诊断脚本
  6. 06以 JSON 输出部署信息

适用场景

  1. 01在 SageMaker 部署 LLM 或嵌入模型
  2. 02根据调用量扩缩端点
  3. 03执行端点冒烟测试并排查故障
  4. 04使用推理组件实现缩至零实例

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/huggingface/skills --skill hf-cloud-sagemaker-production-defaults

安装后在 Claude Code 中输入/hf-cloud-sagemaker-production-defaults确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
deployment-template.md
scripts/
_common.py
deploy_async.py
deploy_ic.py
deploy.py
invoke_endpoint.py
teardown.py

详细介绍

SageMaker 生产默认配置

演示端点与可长期运行的端点之间的区别在于:它能随流量扩缩,在发生故障时发出通知,并且之后可以调试。本技能将这三项设为默认配置,而非可选项。

运行本技能时,规划器已选择实时端点,IAM 已有可用角色,镜像选择也已确定容器 URI 和 AMI 版本。本技能会将这些内容转化为实际部署。

创建的内容

对于每个端点,本技能都会创建以下资源:

  1. SageMaker Model — 镜像、环境变量、执行角色和 S3 构件
  2. 端点配置 — 实例类型、初始数量、可选的数据捕获
  3. 端点 — 用于提供推理服务的实时端点
  4. 自动扩缩目标和策略 — 根据每个实例的调用次数进行目标跟踪
  5. CloudWatch 警报 — 延迟、错误和平台开销

推理组件部署(deploy_ic.py)会创建相同的一组资源,但有两处不同:端点配置包含执行角色和 ManagedInstanceScaling,并且由推理组件承载模型。其自动扩缩目标是组件,而不是变体。

默认情况下,数据捕获(将请求/响应记录到 S3)处于关闭状态——它有助于调试,但会产生用户未必需要的持续 S3 费用。使用 --enable-data-capture 启用。

所有资源都会获得一组统一标签,其中包括 CreatedBy=agentic-deploy-skills,以便之后清理。

默认配置及其理由见 references/deployment-template.md。

运行部署

对于文本生成大模型(vLLM),请先将固定版本的模型快照打包成 SageMaker model.tar.gz 构件,并上传到由账户控制的 S3 存储桶。SageMaker 会将其解压到 /opt/ml/model,因此部署不会在运行时获取或执行代码仓库中的代码:

python scripts/deploy.py \
    --model-name qwen3-medical \
    --image-uri "$IMAGE_URI" \
    --inference-ami-version "$AMI" \
    --role-arn "$ROLE_ARN" \
    --model-s3-uri "s3://<your-model-bucket>/qwen3-medical/model.tar.gz" \
    --instance-type ml.g5.xlarge \
    --region "$REGION" \
    --env SM_VLLM_MODEL=/opt/ml/model \
    --env SM_VLLM_HOST=0.0.0.0 \
    --env SM_VLLM_TRUST_REMOTE_CODE=false \
    --env SM_VLLM_MAX_MODEL_LEN=4096

对于嵌入模型(TEI,通常在 CPU 上运行):

python scripts/deploy.py \
    --model-name bge-large-embeddings \
    --image-uri "$IMAGE_URI" \
    --role-arn "$ROLE_ARN" \
    --instance-type ml.c6i.2xlarge \
    --region "$REGION" \
    --env HF_MODEL_ID=BAAI/bge-large-en-v1.5

注意:TEI 部署不需要 --inference-ami-version。该标志仅适用于 vLLM。TEI 环境变量也更简单(使用 HF_MODEL_ID 而非 SM_VLLM_*,且无需配置主机或 trust-remote-code)。

各参数的来源:

参数来源
--image-urihf-cloud-serving-image-selection — Agent 从 AWS DLC 目录页面读取
--inference-ami-versionhf-cloud-serving-image-selection — 对包含 cu130+ 的 vLLM 标签,此项为必需
--role-arnhf-cloud-sagemaker-iam-preflight(check_role.py)
--regionhf-cloud-aws-context-discovery
--instance-type用户输入或规划器建议
--env因模型而异;所需的 SM_VLLM_* 变量见 hf-cloud-serving-image-selection
--model-s3-uri生产环境首选 — 固定版本模型构件的 S3 URI;该构件会解压到 /opt/ml/model;仅在 Hub 运行时加载这一例外情况下省略

脚本会按顺序创建资源并处理错误,等待端点达到 InService 状态(最长 30 分钟),显示失败原因,注册自动扩缩和警报,并打印包含拆除命令的摘要。脚本会在 stdout 输出一个 JSON 数据块,其中包含供下游脚本使用的端点、配置和模型名称。

这些脚本随本技能一同提供。如果已安装的副本缺少 scripts/ 目录(某些运行环境安装时只会复制 SKILL.md),请从源代码仓库获取脚本,而不要根据本说明重新实现。

模型加载默认方式:将固定版本的权重预先暂存到 S3,并传入 --model-s3-uri;容器会从 /opt/ml/model 加载权重,不依赖运行时访问 Hub。通过 Hub 加载属于明确的例外情况:预计端点启动后还需下载 5–15 分钟或更久;对于受限模型,请提供令牌;除非特定架构需要经过审核的自定义代码,否则应保持 SM_VLLM_TRUST_REMOTE_CODE=false。deploy.py 会等待 30 分钟。

InService 并不代表成功 — 宣布完成前先进行烟雾测试

InService 只表示容器对 /ping 作出了响应。对于基于 MMS 的容器(HF Inference Toolkit),即使 Python 工作进程不断崩溃重启,Java 前端仍会响应 ping — 端点可能处于 InService 状态,却无法提供任何服务。始终进行以下两项检查:

  1. 进行一次真实调用。

    • 实时:使用 invoke_endpoint.py(见下文)发送最小载荷;要求返回 HTTP 200,且响应正文合理。
    • 异步:将一个输入上传到 S3,调用 invoke-endpoint-async,并轮询输出 URI 几分钟(参见“调用异步端点”)。出现结果对象 = 成功;失败 URI 上出现对象,或始终没有对象 = 故障。
  2. 扫描端点日志,查找工作进程崩溃标记 — 即使烟雾测试请求只是超时,也能发现崩溃重启的情况:

    aws logs filter-log-events \
        --log-group-name /aws/sagemaker/Endpoints/<endpoint-name> \
        --filter-pattern '?"Worker died" ?"Load model failed" ?"ImportError"' \
        --region <region> --max-items 5
    

推理组件部署的日志则记录在 /aws/sagemaker/InferenceComponents/<component-name> 中。deploy_ic.py 会在等待时自动扫描该日志组。

诊断权限被拒时的一般规则:如果工作流用于诊断的只读调用遭到拒绝(例如受限角色缺少 logs:FilterLogEvents、servicequotas:ListServiceQuotas 等权限),请用一行说明,然后继续执行可行的检查。绝不要因为缺少仅用于诊断的权限而阻止部署,也绝不要将调用遭拒视为没有问题的证据。

只有两项检查都通过后,才能报告部署完成。如果日志扫描发现问题,应从 CloudWatch 中提供实际的回溯信息 — 而不是 InService 状态。

测试实时端点

端点进入 InService 状态后,使用随附的辅助工具进行测试。该工具跨平台且兼容 BOM — 请使用它,而不要手动编写载荷文件并直接调用 invoke-endpoint:

# macOS / Linux
python3 scripts/invoke_endpoint.py \
    --endpoint-name <endpoint-name> \
    --payload '{"inputs": "Hello"}' \
    --region "$REGION"
# Windows (PowerShell)
python scripts\invoke_endpoint.py `
    --endpoint-name <endpoint-name> `
    --payload-file payload.json `
    --region $REGION

它支持 --payload '<json>'(内联)或 --payload-file <path>,会验证 JSON、以纯 UTF-8 格式写入请求正文、调用端点,并将响应正文打印到标准输出。

UTF-8 BOM 注意事项(Windows)

如果你在 Windows 上自行编写请求载荷,不要使用 Set-Content -Encoding UTF8 — 根据 PowerShell 版本不同,它可能会在文件开头添加 UTF-8 字节顺序标记(BOM)。SageMaker 的 JSON 解析器会因 BOM 而拒绝请求,并返回 400 ModelError:

Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1 (char 0)

这不是模型、端点健康状况或镜像的问题 — 只有请求正文的文件编码有问题。invoke_endpoint.py 完全避免了这个问题(即使 --payload-file 指向的文件已有 BOM,它也会将其剥除)。如果必须直接调用 CLI,请将正文写成不含 BOM 的 UTF-8:

# BOM-free UTF-8 — use this
[System.IO.File]::WriteAllText((Resolve-Path "payload.json"), $json, [System.Text.UTF8Encoding]::new($false))

aws sagemaker-runtime invoke-endpoint `
    --endpoint-name <endpoint-name> `
    --content-type application/json `
    --body fileb://payload.json `
    --region $REGION `
    response.json

**备用方案:**如果任何调用因 Unexpected UTF-8 BOM 失败,请将载荷重新写成不含 BOM 的 UTF-8(或通过 invoke_endpoint.py 重新运行),并重试一次,然后再判定端点或模型发生故障。

调用生成式重排器(vLLM)

生成式重排器(如 Qwen3-Reranker — 由 hf-cloud-serving-image-selection 路由至 HuggingFace vLLM DLC)是通过生成的第一个 token 进行评分的因果语言模型,而不是聊天模型。请使用带原始 prompt 的 completions API,而不要使用 messages/chat API:聊天模板无法可靠遵循 {"enable_thinking": false} 等 chat_template_kwargs 设置,错误的模板会静默地为每个查询–文档对返回几乎相同的分数,而不是报错。

载荷格式(Qwen3-Reranker 的预期格式 — 将 {query} / {document} 替换为实际内容):

{
  "prompt": "<|im_start|>system\nJudge whether the Document meets the requirements based on the Query and the Instruct provided. Note that the answer can only be \"yes\" or \"no\".<|im_end|>\n<|im_start|>user\n<Instruct>: Given a web search query, retrieve relevant passages that answer the query\n<Query>: {query}\n<Document>: {document}<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n",
  "max_tokens": 1,
  "temperature": 0,
  "logprobs": 20
}

末尾的 <|im_start|>assistant\n\n\n 后缀至关重要:它会预先填入一个空的思考块,确保生成的第一个 token 是是/否判断。根据返回的 logprobs 计算分数:P("yes") / (P("yes") + P("no"))。使用一个相关配对(预期 >0.9)和一个不相关配对(预期 <0.05)对端点进行合理性检查 — 如果不同配对的分数几乎相同,说明提示词模板有误,而不是模型发生故障。

同样的规则也适用于其他情况:对于任何要求提示词逐字节精确的思考模式模型,优先使用原始 completions API,而不要使用 chat。

选择镜像 URI

Agent 从 AWS 的 Deep Learning Containers 目录读取镜像 URI——选择与模型系列匹配的行(LLM 使用 HuggingFace vLLM,嵌入使用 TEI 等),将 <region> 替换为部署区域,然后传递给 deploy.py --image-uri。

对于 vLLM 镜像(包括 huggingface-vllm 和 AWS 的 vllm 回退镜像),还要检查标签中的 CUDA 版本:

# Example: HuggingFace vLLM 0.21.0 from the catalog
IMAGE_URI="763104351884.dkr.ecr.eu-west-1.amazonaws.com/huggingface-vllm:0.21.0-transformers5.8.1-gpu-py312-cu130-ubuntu22.04"

# cu130 tag → must pass --inference-ami-version
python deploy.py --image-uri "$IMAGE_URI" \
    --inference-ami-version al2-ami-sagemaker-inference-gpu-3-1 \
    ...

对于标签为 cu129 或更低版本的镜像,请省略 --inference-ami-version。有关完整的 vLLM AMI 查找表以及各镜像系列的环境变量要求,请参阅 hf-cloud-serving-image-selection。

实时端点缩容至零

实时端点只有在托管推理组件时才能将实例缩减至零。deploy.py 注册的变体级目标实例数不能低于一个。deploy_ic.py 则会构建基于组件的配置。

当流量稀疏或按计划出现,且客户端能够容忍首次请求耗时数分钟时,请使用此方案。对于有 SLA 的交互式流量,请勿使用此方案:唤醒需要数分钟,唤醒期间的每个请求都会失败。

python scripts/deploy_ic.py \
    --model-name qwen3-scale-to-zero \
    --image-uri "$IMAGE_URI" \
    --inference-ami-version "$AMI" \
    --role-arn "$ROLE_ARN" \
    --model-s3-uri "s3://<your-model-bucket>/qwen3-scale-to-zero/model.tar.gz" \
    --instance-type ml.g5.xlarge \
    --region "$REGION" \
    --env SM_VLLM_MODEL=/opt/ml/model \
    --env SM_VLLM_HOST=0.0.0.0 \
    --env SM_VLLM_TRUST_REMOTE_CODE=false \
    --env SM_VLLM_MAX_MODEL_LEN=4096
与 deploy.py 的区别
部分基于模型(deploy.py)基于组件(deploy_ic.py)
执行角色位于 Model 上位于端点配置上(ExecutionRoleArn)
模型引用ProductionVariants[].ModelNameInferenceComponent.Specification.ModelName;变体没有 ModelName
实例下限InitialInstanceCount,最小值为 1ManagedInstanceScaling {Status: ENABLED, MinInstanceCount: 0}
扩缩目标endpoint/<ep>/variant/AllTraffic,sagemaker:variant:DesiredInstanceCountinference-component/<ic>,sagemaker:inference-component:DesiredCopyCount
扩缩指标SageMakerVariantInvocationsPerInstance(20 次/分钟)SageMakerInferenceComponentConcurrentRequestsPerCopyHighResolution(每个副本 5 个并发请求)
从零唤醒不适用步进策略 + NoCapacityInvocationFailures 警报
调用端点名称端点名称加上 InferenceComponentName

InferenceAmiVersion 仍应设置在变体上,并且可以与 ManagedInstanceScaling 共存(已在 cu130 + ml.g5.xlarge 上验证)。

要实现缩容至零,需要四个部分,缺一不可。目标跟踪无法从零扩容,因为它无法除以零个副本。移除步进策略或其警报后,端点会缩容至零,然后再也无法响应。deploy_ic.py 会配置这四个部分。

实测行为

从 Hub 获取的 Qwen/Qwen3-0.6B,ml.g5.xlarge,us-east-1,2026 年 7 月:

步骤时间
端点 InService(初始为空,不加载模型)4 分钟
组件 InService(Hub 下载 + vLLM 启动 + CUDA 图)+6 分钟
空闲至 0 个副本最后一次请求后 11 分钟
0 个副本至 0 个实例+12 分钟
副本数为 0 时的首次请求 → HTTP 400 has no capacity立即
NoCapacityInvocationFailures 警报 → ALARM+67 秒
步进策略将期望副本数和实例数提高至 1+1 分 42 秒
HTTP 200+9 分 24 秒

此技能无法调整缩容行为:Application Auto Scaling 会自行创建 AlarmLow,周期为 10 秒,评估周期为 90 次,因此需要累积 15 分钟的空闲数据点才能触发。

请预先准备生产权重,并传递 --model-s3-uri。这样除了避免运行时访问 Hub,还能缩短每次唤醒时间:模型制品在每次唤醒时都会重新加载,因此其获取时间会成为每次空闲后首次请求关键路径的一部分。

组件规格

ComputeResourceRequirements 是调度预留,而不是上限。请求 1024 MB 的组件运行 vLLM 时,即使主机内存占用达到数 GB,也不会有问题。

可调度资源池远小于实例内存。在 ml.g5.xlarge(16 GiB)上,调度器接受 1024 MB,拒绝 4096 MB。请求过多会立即导致令人困惑的失败:

There is not enough hardware resources on the instances for this endpoint to
create a copy of the inference component.

即使端点有正常运行的实例,也会出现这条消息。应将其理解为“请求过大”,而不是“添加实例”。从默认的 1024 MB 开始,仅在多个组件共享一个实例时才调高。

对于多 GPU 模型,--accelerator-devices 必须与 SM_VLLM_TENSOR_PARALLEL_SIZE 相匹配。

调用与测试

传入组件名称,并留出唤醒时间:

python3 scripts/invoke_endpoint.py \
    --endpoint-name <endpoint-name> \
    --inference-component-name <component-name> \
    --payload '{"prompt": "hello", "max_tokens": 16}' \
    --wait-for-capacity 900 --region "$REGION"

400 has no capacity 错误是唤醒信号,而不是故障:它会发布触发步进策略的指标。使用 --wait-for-capacity 时,助手会每隔 30 s 重试,直到有副本处理请求。不使用时,冷启动端点看起来总像是坏了。

拆除顺序

teardown.py 可处理这两种形式,但顺序至关重要:

  1. 告警(<endpoint>-* 和 <component>-*)
  2. 扩缩策略和可扩缩目标,针对组件资源 ID
  3. 推理组件
  4. 端点、端点配置、模型

以下两种情况使这一顺序不可或缺:

  • delete-endpoint 不会删除组件。 这些组件会继续存在,持续报告 InService,并阻止创建同名的新组件。务必先删除组件。
  • 处于临时状态时无法删除组件——容器启动期间的 CREATE_IN_PROGRESS,以及扩缩操作更改副本数量期间的 UPDATE_RC_IN_PROGRESS。脚本每隔 15 s 重试一次,最长 15 min;扩缩事件刚发生后立即拆除,确实可能需要几分钟。

TargetTracking-inference-component/<ic>-AlarmHigh|Low 告警属于 Application Auto Scaling。删除策略会移除这些告警,因此脚本不会处理它们(已验证:拆除后不会残留告警)。

异步推理部署

对于运行时间较长(>60s)的推理、大型负载,或足够突发/稀疏、适合缩容至零的工作负载,请使用 deploy_async.py,而不是 deploy.py。异步部署支持在变体本身设置 MinCapacity=0。实时端点也能缩容至零,但只能通过推理组件实现——请参阅下文的“实时端点缩容至零”。当单次推理超过 InvokeEndpoint 的 60s 响应限制时,异步仍然是正确的选择。

python scripts/deploy_async.py \
    --model-name flux-text-to-image \
    --image-uri "$IMAGE_URI" \
    --role-arn "$ROLE_ARN" \
    --instance-type ml.g5.2xlarge \
    --region "$REGION" \
    --output-s3-uri s3://amzn-s3-demo-async-output/async-output/ \
    --env HF_MODEL_ID=black-forest-labs/FLUX.1-dev

相比 deploy.py 所需的额外参数:

  • --output-s3-uri — 异步结果的存放位置(结果不会同步返回)

异步专用的可选标志:

  • --failure-s3-uri — 失败调用的单独路径
  • --success-sns-topic、--error-sns-topic — 异步结果就绪或失败时接收通知
  • --min-capacity 0(默认值)— 在批次之间缩容至零
  • --backlog-per-instance-target N — 每个实例的目标队列深度(默认值为 5)
  • --max-concurrent-invocations-per-instance N — 默认值为 4
缩容至零的工作原理

异步脚本会在变体上注册两个自动扩缩策略:

  1. 对 ApproximateBacklogSizePerInstance 使用目标跟踪——负责在最小值和最大值之间持续扩缩
  2. 由 HasBacklogWithoutCapacity CloudWatch 告警触发的步进扩缩——负责在 0→1 时从零唤醒

两者缺一不可。仅靠目标跟踪无法从零转换(因为零个实例时无法进行除法运算),因此没有步进策略的话,端点启动后会在第一个批次处理完毕时缩容至零,此后再也不会唤醒。脚本会自动完成配置。

异步告警

该脚本会创建 3 个 CloudWatch 告警:

  • ApproximateBacklogSize > 50 — 队列积压速度超过处理能力
  • InvocationsFailed > 5 — 处理反复失败
  • HasBacklogWithoutCapacity — 用于触发从零唤醒策略(这不是通知告警;其操作是阶梯扩缩策略,而不是 SNS 主题)

如果传入 --sns-alarm-topic <arn>,前两个告警会向该主题发送通知。唤醒告警始终指向阶梯策略。

调用异步端点

异步端点不能同步调用。你需要先将输入上传到 S3,然后使用 S3 输入位置调用 invoke-endpoint-async;完成后,SageMaker 会将结果写入 --output-s3-uri:

# Upload your input first
aws s3 cp input.json s3://amzn-s3-demo-input/job1/input.json

# Invoke
aws sagemaker-runtime invoke-endpoint-async \
    --endpoint-name <endpoint-name> \
    --input-location s3://amzn-s3-demo-input/job1/input.json \
    --content-type application/json \
    --region <region>

# Poll for the result at your output URI
aws s3 cp s3://amzn-s3-demo-async-output/async-output/<inference-id>.out result.json

同样需要注意上传的 input.json 中的 UTF-8 BOM(请参阅上文“UTF-8 BOM 陷阱”)——如果在 Windows 上构建该文件,请将其写成不带 BOM 的 UTF-8,否则容器的 JSON 解析器会拒绝该文件。

拆除方式与实时端点相同:python3 scripts/teardown.py <endpoint-name>(拆除脚本会按名称前缀查找策略和告警,因此两种部署模式都适用)。

默认值一览

设置默认值覆盖方式
初始实例数1--initial-instance-count
自动扩缩最小值 / 最大值1 / 4--min-capacity、--max-capacity
自动扩缩目标20 次调用/分钟/实例--target-invocations-per-instance
数据捕获已禁用(选择启用)--enable-data-capture
CloudWatch 告警3 个告警--no-alarms
SNS 通知无(会创建告警,但不会发送通知)--sns-alarm-topic <arn>
环境标签dev--environment
InferenceAmiVersion无(SageMaker 默认值)--inference-ami-version(vLLM CUDA 13+ 必需)

未提供默认值(需要用户提供特定输入):VPC 配置、KMS 密钥、多变体、异步推理。

自动扩缩目标——按模型类型调整

默认的 --target-invocations-per-instance 20 较为保守,针对每个请求耗时 1–5 秒的大模型工作负载进行了调优。对于嵌入部署(TEI),每个请求快得多(CPU 上通常 <100ms,GPU 上通常 <20ms),因此单个实例可以处理高得多的吞吐量。对于嵌入部署,请根据实例和模型大小将目标提高到 100–500。 默认值 20 会导致嵌入部署过于频繁地触发自动扩缩,造成资金浪费。

经验法则:目标值 ≈ 60 /(典型请求延迟,单位为秒)。延迟为 3s 的大模型 → 目标值为 20。延迟为 100ms 的嵌入模型 → 目标值为 600。生成式重排器介于两者之间——每个请求只生成一个令牌,因此目标值设为约 40–100 较为合适。

数据捕获 + IAM 陷阱

如果用户启用了数据捕获,执行角色需要对捕获前缀拥有 S3 写入权限。默认 URI(s3://sagemaker-<region>-<account>/<endpoint>/data-capture/)通常与模型构件所在的存储桶不同。如果 hf-cloud-sagemaker-iam-preflight 将内联策略的范围限制为仅模型存储桶,捕获写入会静默失败——端点仍会继续提供服务,但不会出现任何数据。

如果用户反馈“没有看到数据捕获内容”,请检查角色的 S3 访问权限。可以扩大内联策略的范围,或传入 --data-capture-s3-uri,指向角色有写入权限的存储桶。

拆除

python3 scripts/teardown.py <endpoint-name> <region>   # macOS / Linux
python  scripts\teardown.py <endpoint-name> <region>   # Windows

按安全顺序删除:告警 → 自动扩缩 → 端点(停止计费)→ 端点配置 → 模型。可幂等执行。

不会删除:IAM 执行角色(可能会共享)、数据捕获 S3 对象(用户可能希望保留)、SNS 主题、原始模型构件。

部署摘要之后,务必告知用户拆除命令。用户容易忘记;端点会持续产生费用。

部署失败时

CannotStartContainerError + 从未创建 CloudWatch 日志 — 这是 InferenceAmiVersion 问题。如果镜像标签包含 cu130 或更高版本,且你没有传入 --inference-ami-version al2-ami-sagemaker-inference-gpu-3-1,原因就在这里。请参阅 hf-cloud-serving-image-selection。不要排查镜像、IAM 角色、环境变量或实例类型——许多其他问题的故障特征都相同,但这里的原因是 AMI。

“Failed to pass ping health check” — 容器确实已启动并生成了日志,但 /ping 没有响应。请检查 /aws/sagemaker/Endpoints/<endpoint-name> 中的 CloudWatch 日志。通常是镜像与模型架构不匹配、缺少 HF 令牌或内存溢出。

“Container failed to start”(存在日志) — 入口点已运行,随后退出。请检查 CloudWatch。常见原因:缺少必需的环境变量(SM_VLLM_MODEL、SM_VLLM_HOST、SM_VLLM_TRUST_REMOTE_CODE)、ModelDataUrl 格式错误或模型构件不可读。

ResourceLimitExceeded — 此区域没有该实例类型的配额。申请提高配额或选择其他类型(规划器本应提前检查配额——请参阅 hf-cloud-sagemaker-deployment-planner)。

CloudWatch 日志中出现 ImportError: libtorch_cuda.so: undefined symbol: ncclCommResume — 这是 huggingface-pytorch-inference GPU 镜像中已知的打包缺陷(请参阅 hf-cloud-serving-image-selection 中的“已知有问题的镜像”)。问题发生在容器内部,因此更改环境变量、AMI、实例类型或同系列标签都无法修复。请切换到 DJL Inference。

状态为 InService,但调用超时 / 从未出现异步输出 — 存活的 MMS 前端后有一个失效的 Python 工作进程。运行上方“InService 不代表成功”中的日志扫描;CloudWatch 中的回溯才是真正的错误。

启动期间从 HF Hub 下载权重时出现 403 Forbidden — 容器中捆绑的 huggingface_hub 版本早于 HF 的 XET CDN 身份验证支持。请添加 --env HF_HUB_ENABLE_HF_TRANSFER=0,或将权重预先暂存到 S3。注意:这可能会掩盖更深层的问题(下载成功后,工作进程仍可能崩溃)——修复后请重新检查日志。

诊断规则:当多个配置(不同镜像、角色、实例类型)出现相同故障,且从未生成任何日志时,原因几乎总是在容器之外——主机 AMI、网络或账户级别问题,而非部署配置。请停止反复调整配置;检查 AMI 版本和账户状态。

组件卡在 Creating,没有 FailureReason — 容器陷入崩溃循环,supervisord 会重启它,因此状态始终不会改变。组件会保持 Creating,直到 ContainerStartupHealthCheckTimeoutInSeconds 超时,最长可达一小时。请查看 /aws/sagemaker/InferenceComponents/<component-name>,查找 exited: app、not expected 或 api_server.py: error:。deploy_ic.py 会在每次轮询时执行此扫描,并在约一分钟内中止。

There is not enough hardware resources on the instances for this endpoint — 组件的 ComputeResourceRequirements 超出了可调度资源池,而该资源池远小于实例内存。请降低 --min-memory-mb(ml.g5.xlarge 上 1024 可用;4096 会被拒绝)。不要增加实例:即使实例运行正常,也会出现此消息。

Cannot delete inference component ... while it is in state CREATE_IN_PROGRESS / UPDATE_RC_IN_PROGRESS — 这是正常情况,不是错误。请重试;teardown.py 会重试 15 分钟。UPDATE_RC_IN_PROGRESS 表示扩缩容操作正在更改副本数量。

组件的生命周期长于其端点 — delete-endpoint 会留下组件,它们仍会报告 InService,从而阻止重用名称。请先删除组件;teardown.py 就是这样处理的。

不要盲目重试。脚本会打印 describe-endpoint 返回的具体 FailureReason——请先修复根本原因,再重试。

评论

支持 Markdown