把一句「把这个项目部署上云」变成一个可访问的网站,表面上像是执行几条命令,实际却要同时处理环境、凭证、源码识别、实例规格、网络、数据库、费用、制品分发、启动探活和后续清理。任何一个环节靠猜,结果都可能是服务起不来、资源重复创建,或者项目已经下线但云资源还在持续计费。
千问 AI 部署 Skill(以下简称 deploy)解决的不是某一条命令不会写,而是把这段容易遗漏的基础设施工作变成 Agent 可以执行、用户可以确认、系统可以追溯的一条流程。它当前面向阿里云国内站,默认把本地项目或 Git 仓库部署成一套单机服务,并把后续的热更新、可观测和运维诊断接到同一份部署状态上。
文章先给结论:deploy 的核心价值不是「自动创建一台 ECS」,而是建立了三个门:创建前的决策门、创建中的恢复门、创建后的运营门。下面这张图把 14 个步骤压缩成一条主路径,节点内的编号仍然对应仓库中的完整步骤。
先看全流程
图中有意把细节合并了:步骤 1~3 是准备,步骤 4~9 是资源规划和费用门禁,步骤 10~12 是上传、创建和探活,步骤 13~14 是状态交付。真正执行时,Agent 仍需连续展示完整的 1~14 步,并把已跳过的步骤标明原因,例如本地项目跳过 Git clone、没有 MySQL 信号则跳过 RDS 选择。
背景:为什么需要一个部署 Skill
云平台已经标准化,人的上线路径却没有
云产品的 API 很成熟,但一个新项目上线仍然要在多个界面和命令之间往返:先判断项目是什么,再选机器;机器有货不代表数据库所在可用区也有货;模板能通过语法校验,不代表最终报价符合预期;栈创建成功,也不代表应用已经监听端口。
这些工作有三个共同特点:
- 重复:不同项目都会重复做环境检查、规格查询、模板上传和状态记录。
- 有依赖:必须先知道项目类型和端口,才能生成 UserData;必须先得到真实产物 URL,才能创建正式 ROS 栈。
- 有代价:ECS、EIP、RDS 和 OSS 都可能计费,错误通常不是一次失败,而是遗留资源带来的持续成本。
传统脚本可以减少重复,却很难处理自然语言需求和不确定的项目结构;单纯依赖大模型,又容易出现跳步、重复创建、把失败当成功等问题。deploy 的做法是把「模型判断」和「确定性执行」组合起来:Agent 负责识别、询问和编排,脚本负责上传、建栈、轮询、回滚和落盘。
deploy 不是孤立工具,而是三个 Skill 的入口
仓库一次安装会得到三个能力:
| 能力 | 解决的问题 | 对部署状态的依赖 |
|---|---|---|
deploy | 全栈部署、热更新、整栈清理 | 产生 .qianwenai-deploy 和应用档案 |
observe | 只读体检可用性、性能、成本 | 读取状态文件和 app_timeline.jsonl |
operate | 诊断故障并在确认后恢复 | 读取最近部署和观测事件 |
这意味着一次部署不是一个孤立的「成功页面」,而是后续运营的起点。
第一个门:创建前把不确定性说清楚
全栈部署严格按 1~14 步推进。步骤号看起来很多,但它们正好对应一次上线中最容易被省略的判断。
1. 环境检查:先确认能不能安全调用云 API
Agent 首先确认 aliyun CLI 为 3.x,检查国内站凭证、地域和 OSS 服务,并用 STS GetCallerIdentity 验证当前身份。默认地域是 cn-hangzhou。
认证优先推荐 OAuth:浏览器完成授权,凭证不需要复制到聊天窗口。也可以使用 AK/SK,但密钥只能由用户在自己的终端配置。环境检查还会确认 OSS 是否已开通,因为后面的构建产物和模板需要临时存放在 OSS。
这一阶段的业务意义是把「Agent 能否代表我创建资源」变成显式事实,而不是让第一条创建命令充当权限测试。
2. Git URL 处理:让输入形式不再限制部署入口
用户可以给出本地目录,也可以直接给 Git URL。后者只做浅克隆(--depth 1),再进入同一套项目分析流程。私有仓库认证由用户自己的 Git 凭证解决,Agent 不在对话里收集令牌。
3. 项目分析:先识别产物形态,再决定运行方式
分析阶段会读取文件树、构建配置、入口源码和 README,提取应用名、启动命令、监听端口、静态目录和数据库信号,并检查疑似硬编码密钥。
部署类型不是按语言名称机械映射,而是看构建产物:
- 有
Dockerfile或docker-compose.yml,优先走docker。 - Node.js、Python、Java 走
systemd加对应运行时。 - Go、Rust 等默认能产出自包含二进制的语言,可走
systemd且不安装解释器。 - 其他需要解释器或虚拟机的语言,如果没有 Dockerfile,会停下来请求用户确认生成或提供 Dockerfile。
同时,Nginx 模式会区分纯静态、纯应用反代和「静态前端 + 应用」三种情况。这个判断很关键:Flask、Django、Streamlit、Gradio 等应用必须走 proxy,否则 Nginx 可能在应用之前拦截路由。
第二个门:规划资源,并在计费前让用户做决定
4~6. 扫描存量、识别数据库、选择规格
先按 from=qianwenai 标签查询当前地域的存量 ROS 栈。如果同一项目已有部署,Agent 会把任务路由到热更新或删除重建,而不是悄悄再建一套。
如果项目出现 MySQL 依赖,用户可以选择自动创建 RDS MySQL 8.0;PostgreSQL、Redis、MongoDB 等不会被假装成已支持的自动资源。ECS 和 RDS 的规格都来自当前地域的实时可用清单,并过滤 GPU、裸金属和超大规格,避免给轻量项目展示噪声选项。
7. 生成 ROS 模板:把资源关系集中表达
默认的单机拓扑是:
公网请求 → EIP → ECS → Nginx → 应用
└── 可选:RDS MySQL(VPC 内网)
无数据库时,模板创建 VPC、VSwitch、安全组、ECS、EIP 和 EIP 绑定;有数据库时,再加入 RDS 实例、数据库、账号和权限。应用启动脚本通过 UserData 写入 ECS,生产模板则会把真实产物地址注入启动流程。
8. 库存检查:验证资源选择的交集
ECS 有货不代表 RDS 规格在同一个可用区也可用。含 RDS 时,步骤 8 会求 ECS 与 RDS 的可用区交集;交集为空,就回到前面的规格或地域选择,而不是把失败留到创建阶段。
9. 模板验证与费用门禁:真正创建前的最后一道闸
ROS 模板先通过 ValidateTemplate,再调用 GetTemplateEstimateCost 得到各资源的每小时金额,统一用人民币展示。确认卡片必须列出所有可能计费的资源,包括 ECS、EIP、RDS 和临时 OSS,并说明公网流量、快照等动态费用不包含在内。
只有用户确认后,流程才进入会真正创建云资源的阶段。用户拒绝或暂缓时,流程停止,不会因为 Agent 已经准备好模板就偷偷开始计费。
第三个门:创建可恢复,成功可证明
10. 上传构建产物:用 OSS 解耦本地和 ECS
upload_artifacts.py 会创建形如 qianwenai-deploy-tmp-xxxxxx 的临时 OSS 桶,默认设置 7 天生命周期。应用包、静态包和 ROS 模板都通过签名 URL 传递;应用产物尽量使用 VPC 内网端点,让 ECS 下载时不产生不必要的公网流量。
这里有一个容易被忽略的顺序:先上传应用产物,再用真实 app_url、static_url 重新生成模板,最后上传正式模板取得 TemplateURL。ROS 创建阶段只接收 TemplateURL,不使用容易被 WAF 拦截的 TemplateBody。
上传脚本还会排除 node_modules、.git、虚拟环境、缓存和系统缩略图。这样做不仅减少包体,也避免把 macOS 上的原生依赖直接搬到 Linux ECS。
11. 创建 ROS 栈:让云平台处理资源依赖
create_stack.sh 使用一次性生成的栈名,例如 qianwenai-myapp-202609211530,并给栈打上来源、应用名和描述标签。ROS 统一处理 VPC、网段、安全组、ECS、EIP 以及可选的 RDS 之间的依赖关系。
创建前会再次按栈名查询:如果客户端超时但服务端已经创建成功,就复用原来的 StackId;如果栈处于失败状态,则先释放同名栈再重试。创建成功会立即写入一个临时状态文件,避免 Agent 在后续等待中断后留下无法定位的孤儿资源。
12. 等待终态与探活:把「资源成功」和「应用可用」分开
等待脚本轮询 ROS 栈到达终态,提取公网 IP 和实例 ID,然后探测 Nginx 的 /healthz。应用本身不直接用一个固定 HTTP 路径判活,因为不同框架的路由和错误响应可能导致假阴性;应用存活由 Cloud Assistant 检查服务状态、重启次数和应用日志来确认。
因此,最终结论会区分:
- 栈创建失败:列出资源层面的错误和可清理状态。
- Nginx 探活失败:检查 UserData 和引导日志。
- Nginx 已通但应用未启动:检查 systemd 或容器日志,不能把它包装成「部署成功」。
交付不是一句「完成」:状态文件与应用档案
13. .qianwenai-deploy:让后续操作拥有事实依据
状态文件记录地域、栈 ID、拓扑、应用类型、Nginx 模式、产物桶、当前签名 URL 和输出资源 ID;密码单独写入权限为 0600 的 .qianwenai-deploy.local。两个文件都会自动加入 .gitignore。
状态文件的价值在于它是后续动作的唯一入口:热更新依靠它找到 ECS、服务名和产物地址;删除操作依靠它调用整栈销毁;观测和运维依靠它知道要检查哪一组资源。
14. app_timeline.jsonl:把一次性动作变成连续档案
部署成功后会追加一行 event=deploy。后续热更新写入 event=hotfix,observe 和 operate 分别追加观测与运维事件。档案只保存脱敏后的时间、摘要和证据,不记录密码、令牌、连接串或签名 URL。
这条时间线的业务价值很直接:当用户问「网站为什么从今天下午开始变慢」时,系统可以把最近一次发布、体检和恢复动作放在同一个上下文里,而不是只看当前机器的瞬时状态。
部署完成后,真正可持续的两个动作
热更新:IP 不变,代码可回滚
用户在已有部署目录下说「更新应用」时,会走 U1~U4:构建并上传新产物、通过 Cloud Assistant 下发更新、探活并更新状态、追加热更新事件。
systemd 模式采用两阶段原子替换:先下载到 staging 目录并校验压缩包,预装 Python 或 Node 依赖,再停止服务、替换 /opt/qianwenai 并重启。健康检查失败会把旧版本恢复回来,坏产物保留在 .failed 目录供排查。静态文件更新则切换 staging 目录并执行 nginx -t && systemctl reload nginx,不需要重启应用。
Docker 模式会正确区分 docker load 和 docker compose up,不会把容器部署误当成 systemd 二进制部署。无论哪种模式,公网 IP 都保持不变。
删除清理:删除的是整栈,不是几台机器
删除是不可逆操作,含 RDS 时还会销毁数据库数据,必须二次确认。确认后只调用 delete_stack.sh:ROS 负责按依赖顺序释放 ECS、EIP、VPC、安全组和 RDS,脚本再清理临时 OSS 桶。严禁手动逐个删除资源,否则很容易把栈状态和实际资源弄不一致。
这套流程带来的业务价值
| 价值 | 传统手工上线的风险 | deploy 的机制 | 业务结果 |
|---|---|---|---|
| 缩短首次上线时间 | 工程师反复查文档、填参数、切控制台 | 项目分析 + 模板生成 + ROS 编排 | 从「会部署」降到「会描述需求」 |
| 控制云成本 | 忘记报价、误选规格、测试资源忘删 | 实时库存 + 精确询价 + 整栈清理 | 创建前知道小时价,不用时能一次释放 |
| 降低操作风险 | 重试可能重复创建,失败状态不清晰 | 同名栈复用、自动回滚、临时状态 | 失败有路径,恢复有依据 |
| 提升交付稳定性 | 看到公网 IP 就以为上线完成 | Nginx 探活 + 服务状态 + 应用日志 | 区分基础设施就绪与应用可用 |
| 支撑持续迭代 | 更新靠 SSH 手工替换,回滚困难 | Cloud Assistant + staging 原子切换 | IP 不变,更新失败可回退 |
| 形成运营闭环 | 发布、巡检、故障处理各自为战 | 状态文件 + app_timeline.jsonl | 观测和运维能理解最近发生了什么 |
从业务视角看,deploy 把一次上线的交付物从「一个 IP 地址」扩展成四部分:运行中的服务、可复用的状态、可验证的证据、可继续执行的下一步。这才是它比一组云命令更有价值的地方。
适用边界:它解决了什么,还没有解决什么
这套 Skill 适合学习项目、内部工具、原型验证和轻量应用的快速上云。默认拓扑是单 ECS,按量付费,当前访问地址是 HTTP 公网 IP;它没有自动提供域名、HTTPS、负载均衡、跨可用区高可用或生产级备份策略。
正式面向真实用户前,至少还要补上:
- 绑定域名并配置 HTTPS 证书,避免账号、会话和业务数据在 HTTP 上明文传输。
- 评估单机故障、数据备份、RDS 参数和安全组暴露面,决定是否需要多实例或更高等级的托管服务。
- 检查待上传产物中没有
.env、私钥、调试日志和硬编码密钥;公网静态文件尤其不能包含前端可见的服务端密钥。 - 为按量付费资源设置预算和释放习惯;没有访问时 ECS、EIP、RDS 仍可能继续计费。
最后还要记住一条责任边界:deploy 负责把用户提供的代码部署并验证运行,不审查或修改业务逻辑,也不为代码本身的安全性和正确性背书。
结语
千问 AI 部署 Skill 的设计重点不是把所有云产品都封装起来,而是把一次部署中真正需要决策和证明的节点固定下来:先读懂项目,再规划资源;先验证模板和费用,再创建资源;创建后不仅给出地址,还留下状态和时间线。
当 deploy、observe、operate 共用这份事实时,「部署」「看运行状况」「处理故障」就不再是三个互不相干的聊天请求,而是一条可以持续运行的应用生命周期。
项目地址:QianWen-AI/qianwenai-deploy