PAI-EAS 服务部署
⚠️ 顶部规则(先读)
1. 🔴 不允许重复服务名 🔴
如果目标名称的服务已存在:停止并告知用户。不要删除后重建。也不要复用。
2. 强制 API 调用 —— 按顺序执行以下所有:
| # | API | CLI | 用途 |
|---|---|---|---|
| 1 | ListImages | aliyun aiworkspace list-images | 验证镜像 |
| 2 | describe-machine-spec | aliyun eas describe-machine-spec | 验证 GPU 类型 |
| 3 | create-service | aliyun eas create-service | 创建服务 |
| 4 | describe-service | aliyun eas describe-service | 检查状态(一次) |
| 5 | describe-service-endpoints | aliyun eas describe-service-endpoints | 获取 endpoint |
始终执行 #1 和 #2,即使用户已提供信息。
describe-machine-spec ≠ list-resources。describe-service ≠ ListServices。
3. 禁止 —— ❌ 复用现有服务
❌ 编写 bash 脚本(直接运行 CLI)
❌ CPU + vLLM/SGLang ❌ 在 create-service 中使用 file://
❌ 跳过强制 API ❌ 更改用户指定的服务名
❌ 循环轮询 describe-service(只调用一次)
❌ 写完/验证 service.json 后停止——写 JSON 不是完成任务。你必须运行 create-service(Step 6)然后 describe-service(Step 7)。如果找到了资源,就部署它们。
4. 自主执行 —— 不要向用户询问可通过 API 发现的信息。不要问“我可以继续吗?”直接执行。
超时?用 --read-timeout 60 重试。错误?告知用户并继续。
缺少参数?选择合理默认值。
如果任何预检查或资源发现步骤失败,记录失败并继续下一步。仅在自验证检查点中列出的特定条件下停止(重复服务名、缺少 NLB/GW/专用资源组)。
5. 自验证检查点:
Step 2 之前:Step 1.5 是否确认无重复服务名?
如果重复 → 停止,告知用户,不要继续。
Step 5 之前:我是否已运行 list-images 和 describe-machine-spec?
如果否 → 停止并立即运行它们。
Step 6 之前:Step 1.5 是否确认无重复服务名?
如果存在重复 → 停止,告知用户,不要继续。
Step 4 资源:如果 NLB/GW/资源组未找到 → 告知用户并停止。
不要阻塞或尝试变通。
Step 7 之后:我是否调用了一次 describe-service 并报告了状态?
6. 直接运行 CLI 命令 —— 使用 execute_shell_command 一次一个地运行每条 aliyun CLI 命令。不要编写 bash 脚本、部署脚本或 shell 文件。不要使用 retry_command() 或任何包装函数。每条命令 = 一次直接执行。
预检查
安装或升级 Aliyun CLI 到 >= 3.3.3(所需基线),然后验证。
curl -fsSL https://aliyuncli.alicdn.com/install.sh | bash
aliyun version # 必须报告 >= 3.3.3;如果更低,重新运行 install.sh 升级
每会话生成一次追踪 ID(见可观测性章节)并构建
统一 user-agent。在每条 CLI 命令上通过 --user-agent 传入。
SESSION_ID=$(openssl rand -hex 16)
UA="AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy/${SESSION_ID}"
aliyun plugin update
aliyun configure set --auto-plugin-install true
**⚠️ 强制:在继续之前安装并更新所需插件:**
aliyun plugin update
aliyun plugin install aiworkspace --force
aliyun plugin install eas --force
**验证插件已安装:**
aliyun plugin list 2>/dev/null | grep -E "aiworkspace|eas"
如果安装后任一插件缺失,用以下命令重试:
aliyun plugin install <plugin-name> --force
见 [CLI 指南](references/cli-installation-guide.md)。
绝不读取/回显 AK/SK。超时?用 `--read-timeout 60` 重试。
**⚠️ 强制检查点:预检查后,无论插件安装期间有任何警告,
你都必须继续 Step 1。插件安装失败是非阻塞的——插件可能
已经安装。绝不在预检查阶段停止执行。**
---
可观测性
所有 CLI、SDK 和 Terraform 调用都必须携带统一 user-agent(UA),使
请求可追溯到此 Skill 和单一会话。
UA 模板声明(占位符形式):
--user-agent AlibabaCloud-Agent-Skills/{SKILL_NAME}/{session-id}
{SKILL_NAME}—— 固定标识符:alibabacloud-pai-eas-service-deploy{session-id}—— 32 位小写十六进制(128 位),每会话生成一次
session-id 规则: 在任何调用之前通过
SESSION_ID=$(openssl rand -hex 16) 生成一次;为每次
CLI(--user-agent)、SDK(client UA)和 Terraform(ALIBABACLOUDSTACK_UA /
provider ua)调用复用同一个值,使所有请求共享一个追踪 ID。不要在步骤之间重新生成或硬编码。
SESSION_ID=$(openssl rand -hex 16)
UA="AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy/${SESSION_ID}"
在每条命令上传入,例如:
aliyun eas describe-service --cluster-id <region> --service-name <service> --user-agent "$UA"
---
Step 1:收集参数
| 参数 | 必填 | 默认 |
|---|---|---|
| RegionId | 是 | - |
| Service Name | 是 | - |
| Workspace ID | 否 | 自动选择 |
| Image URI | 是 | - |
| Instance Type | 是 | - |
| Replicas | 否 | 1 |
| Port | 否 | 8000 |
| OSS Path | 否 | - |
服务名:仅小写字母/数字/下划线。不允许连字符。3-63 字符。
重要:使用用户指定的确切服务名。不要重命名。
如果用户指定前缀(例如“以 skill_qwen_ 开头”),生成 6 位随机后缀(例如 skill_qwen_482917)。
设置 profile 地域 —— 将 CLI profile 地域设置为匹配
部署地域。这避免了当 --cluster-id 与 profile 默认地域不同时的
“Region mismatch”错误:
aliyun configure set --region <region>
Workspace ID:在 metadata.workspace_id 中必填。如果用户未
指定 workspace,查询可用 workspace 并选一个:
aliyun aiworkspace list-workspaces --region <region> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '.Workspaces[] | select(.Status == "ENABLED") | {WorkspaceId, WorkspaceName}'
如果存在多个 workspace,列出它们让用户选择。
如果只有一个,直接使用。
Step 1.5:检查重复服务名
aliyun eas list-services --region <region> --cluster-id <region> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '.ServiceList[] | select(.ServiceName == "<name>") | {ServiceName, Status}'
**如果同名服务已存在 → 停止并告知
用户:“名为 <name> 的服务已存在(Status: <status>)。
请选择不同的名称。”不要删除或复用它。**
如果无重复 → 进入 Step 2。
Step 2:ListImages(🚧 阻塞门禁——绝不跳过)
即使用户提供了镜像 URI 也执行。目的 = 验证。
**⚠️ 如果看到“parse error”或“Exit Code 4”,说明插件
安装失败。你必须用显式安装重试:**
aliyun plugin install aiworkspace --force
然后重试 list-images 命令。不要跳过此步骤。
aliyun aiworkspace list-images --region <region> --verbose true \
--labels 'system.official=true,system.supported.eas=true' \
--page-size 50 --user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '.Images[] | {ImageId, ImageUri, ImageCategory}' > /tmp/eas_images.json
echo "Saved $(jq length /tmp/eas_images.json) images"
如果插件重装后仍失败,用超时重试:
aliyun aiworkspace list-images --region <region> --verbose true \
--labels 'system.official=true,system.supported.eas=true' \
--page-size 50 --read-timeout 60 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '.Images[] | {ImageId, ImageUri, ImageCategory}' > /tmp/eas_images.json
echo "Saved $(jq length /tmp/eas_images.json) images"
见 Model-Image。
此输出是 Step 5 所必需的。不要跳过。
❌ 绝不要说“用户已提供镜像”而跳过此步骤。
Step 3:describe-machine-spec(🚧 阻塞门禁——绝不跳过)
即使用户指定了实例类型也执行。不是 list-resources。
**⚠️ 如果此命令失败,用 --read-timeout 60 重试。
绝不在 /tmp/eas_specs.json 不存在时进入 Step 5。**
aliyun eas describe-machine-spec --region <region> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '.InstanceTypes[] | select(.GPU > 0) | {InstanceType, CPU, GPU, Memory}' \
> /tmp/eas_specs.json
echo "Available GPU specs:"; cat /tmp/eas_specs.json
CPU→GPU 自动切换:如果 vLLM/SGLang + CPU,静默选择 GPU。不要询问。
此输出是 Step 5 所必需的。不要跳过。
Step 4:网络与资源配置
| 类型 | VPC | 配置 |
|---|---|---|
| 共享 | 否 | (默认,无网络字段) |
| 专用 GW | 是 | networking.gateway + cloud.networking |
| NLB | 是 | networking.nlb + cloud.networking |
**⚠️ 如果所需资源不存在 → 停止并告知用户。
不要阻塞或尝试变通。这是一个有效结果。**
专用网关 —— 调用 list-gateway。如果无网关存在 →
告知用户并停止。否则调用 describe-gateway 获取
VPC/VSwitch,然后查询该 VPC 下的安全组。
如果未找到安全组 → 告知用户并停止。
aliyun eas list-gateway --region <region> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy
如果找到网关,获取详情:
aliyun eas describe-gateway --region <region> --cluster-id <region> \
--gateway-id <gateway_id> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy
提取 VPC 和逗号分隔的 VSwitch ID:
aliyun eas describe-gateway --region <region> --cluster-id <region> \
--gateway-id <gateway_id> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '{vpc_id: .LoadBalancerList[0].VpcId, vswitch_id: (.LoadBalancerList[0].VSwitchIds | join(","))}'
NLB —— 需要 VPC/VSwitch/SecurityGroup。如果用户未提供
它们,通过 API 查询。如果任何所需资源未找到 → 告知
用户并停止。
⚠️ NLB 需要跨不同可用区的 ≥2 个 VSwitch。
使用逗号分隔格式:"vswitch_id": "vsw-zone-a,vsw-zone-b"。
⚠️ NLB 插件 Bug(aliyun-cli-eas v0.2.0): 如果带
NLB 配置的 create-service 返回 400 且报 'vswitch can not be null' 或
'vpcId, vswId and securityGroupId are required',这是已知
CLI 插件 bug(非资源问题)。回退策略:
- 再重试一次带 NLB 配置的 create-service(最多 2 次尝试)。
- 如果都失败 → 从 service.json 移除
networking.nlb和cloud.networking,
用共享网关重新部署。
- 告知用户:“由于 CLI 插件限制,NLB 配置失败。
已改用共享网关部署。”
EAS 专用资源组 —— 调用 list-resources。
筛选 ResourceType == "Dedicated" 且 Status == "ResourceReady"。
aliyun eas list-resources --region <region> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '.Resources[] | select(.ResourceType == "Dedicated" and .Status == "ResourceReady") | {ResourceId, ResourceType, Status}'
- 如果存在 → 设置
"metadata": {"resource": "<ResourceId>"}。
不要设置 cloud.computing。
- 如果不存在 → 告知用户并停止。
不要回退到公共资源组。
Step 5:构建 Service JSON
⚠️ 构建 JSON 之前,你必须阅读这些参考文件:
references/config-patterns.md—— 所有 8 种模式的完整 JSON 模板references/config-schema.md—— 字段描述和验证规则references/storage-mount.md—— OSS/NAS 挂载配置详情references/network-config.md—— NLB/网关网络配置详情
**⚠️ 硬门禁:写 service.json 之前,验证这些文件
存在且有内容。如果任一缺失 → 停止并立即运行
该步骤。**
test -s /tmp/eas_images.json || echo "MISSING: Run Step 2 NOW"
test -s /tmp/eas_specs.json || echo "MISSING: Run Step 3 NOW"
⚠️ JSON 格式规则:
- 允许的顶层键:
metadata、containers、storage、cloud、autoscaler、networking - ❌ 绝不使用作为顶层键:
spec、ServiceName、Image、Cpu、Memory、Gpu、processor_path、resourceGroupId、instance、port、command、access - ❌ 禁止字段:
processor_path、resourceGroupId、spec、access metadata.name= 服务名,metadata.workspace_id= workspace(必填)containers[].image= 镜像 URI,containers[].command= 启动命令,containers[].port= 端口cloud.computing.instance_type= 实例类型(共享网关必需)
快速参考 —— JSON 骨架
以下是最小骨架。**阅读 references/config-patterns.md 获取
包含所有字段和示例的完整模板。**
基础(共享网关):
{"metadata":{"name":"<name>","instance":1,"workspace_id":"<ws>"},
"containers":[{"image":"<img>","port":<p>,"command":"<cmd>"}],
"cloud":{"computing":{"instance_type":"<type>"}}}
+ OSS → 添加 "storage":[{"mount_path":"/dir","oss":{"path":"oss://<b>/<p>/","readOnly":true}}]
+ 自动扩缩容 → 添加 "autoscaler":{"min":1,"max":4,"scaleStrategies":[{"metricName":"qps","threshold":20}]}
+ 健康检查 → 向 containers[] 添加 startup_check(见 config-patterns.md Pattern 4)
NLB —— 完整模板(阅读 references/network-config.md 获取详情):
{"metadata":{"name":"<name>","instance":1,"workspace_id":"<ws>"},
"containers":[{"image":"<img>","port":<p>,"command":"<cmd>"}],
"cloud":{"computing":{"instance_type":"<type>"},
"networking":{"vpc_id":"<vpc>","vswitch_id":"<vsw1>,<vsw2>","security_group_id":"<sg>"}},
"networking":{"nlb":[{"id":"default","listener_port":<p>,"netType":"intranet"}]}}
⚠️ vswitch_id 必须跨不同可用区 ≥2 个 VSwitch 逗号分隔
专用资源组 —— "metadata.resource" 而非 cloud.computing:
{"metadata":{"name":"<name>","instance":1,"resource":"<res_id>","workspace_id":"<ws>"},
"containers":[{"image":"<img>","port":<p>,"command":"<cmd>"}]}
专用网关 —— networking.gateway + cloud.networking:
{"metadata":{"name":"<name>","instance":1,"workspace_id":"<ws>"},
"containers":[{"image":"<img>","port":<p>,"command":"<cmd>"}],
"networking":{"gateway":"<gw_id>"},
"cloud":{"computing":{"instance_type":"<type>"},
"networking":{"vpc_id":"<vpc>","vswitch_id":"<vsw1>,<vsw2>","security_group_id":"<sg>"}}}
⚠️ 如果网关返回多个 VSwitch,vswitch_id 逗号分隔
写前验证
jq -r '.[] | select(.ImageUri | contains("vllm")) | .ImageUri' /tmp/eas_images.json
jq -r '.[] | select(.InstanceType == "<type>") | .InstanceType' /tmp/eas_specs.json
➡️ service.json 验证通过后,立即进入 Step 6——验证通过的 JSON 不是部署。
Step 6:创建服务(强制)
**🔴 确认:Step 1.5 是否确认无重复服务名?
如果此名称的服务已存在 → 停止。告知用户
且不要继续 create-service。**
使用 $(cat service.json) 而非 file://service.json。
通过 execute_shell_command 直接运行,不要写 bash 脚本。
aliyun eas create-service --region <region> \
--body "$(cat service.json)" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy
409 Conflict → 服务已存在。告知用户并停止。
400 BadRequest 且报 'vswitch can not be null' 或
'vpcId, vswId and securityGroupId are required' → NLB CLI 插件
bug(见 Step 4 回退)。从 service.json 移除 networking.nlb 和
cloud.networking 并重试。
Step 7:验证部署
**调用 describe-service 一次检查当前状态。不要轮询。
不要循环。不要等待 Running。**
aliyun eas describe-service --region <region> --cluster-id <region> \
--service-name <name> \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '{Status, ServiceName, ServiceId}'
**报告你得到的任何状态(Running、Waiting、Creating 等)
并立即进入 Step 8。create-service 返回 200 = 成功。**
Step 8:报告结果(强制)
通过 DescribeServiceEndpoint 获取 endpoint 信息:
aliyun eas describe-service-endpoints --region <region> --cluster-id <region> \
--service-name <name> --user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-eas-service-deploy | \
jq '{AccessToken, Endpoints: [.Endpoints[] | {
Type: .EndpointType, Port: .Port,
InternetEndpoints: .InternetEndpoints,
IntranetEndpoints: .IntranetEndpoints
}]}'
使用 Step 7 的状态和上述 endpoint 报告。
将完整输出复制到你的最终响应中。格式:
部署摘要
==================
服务名:<name>
状态:<from Step 7>
Endpoints:
- <EndpointType>:
InternetEndpoint: <url or null>
IntranetEndpoint: <url or null>
Port: <port or 0>
服务调用示例:
curl <internet-endpoint>/api/predict/<name> \
-H "Authorization: <AccessToken>"
curl <intranet-endpoint>/api/predict/<name> \
-H "Authorization: <AccessToken>"
curl <nlb-domain>:<listener_port>/api/predict/<name> \
-H "Authorization: <AccessToken>"
**InternetEndpoint 和 IntranetEndpoint 必须出现在你的
响应中,即使为 null。** 如果为 null:(此网络类型不可用)
**始终包含使用 AccessToken
和 endpoint URL 的服务调用示例。**
**成功标准:create-service 返回 200 且带 ServiceId =
成功。任何状态(Running、Waiting、Creating)都可接受。**
参考(按需阅读)
| 文档 | 何时阅读 |
|---|---|
| Config Patterns | Step 5 —— 所有 8 种模式的完整 JSON 模板 |
| Config Schema | Step 5 —— 字段描述和验证规则 |
| Storage Mount | Step 5 —— OSS/NAS 挂载详情 |
| Network Config | Step 4/5 —— NLB/网关配置详情 |
| Model-Image | Step 2 —— 镜像选择指南 |
| Related APIs | 任何步骤 —— CLI 命令参考 |
| Workflow | 概览 —— 完整部署流程 |
| CLI Guide | 预检查 —— 插件安装 |
| RAM Policies | 预检查 —— 所需权限 |
| Service Features | Step 5 —— 高级功能 |
阿里云skills
◯ 评论 0