用 Terraform 给 AI Agent 上云(八):端到端——一次 apply 起整个 research-agent-stack
把七个 module 拼到一个仓库,跑一次 terraform apply,看一个完整的 Agent runtime——VPC、ECS、RDS、OpenSearch、OSS、LLM 网关、SLS 观测、成本告警——七分钟内起来。真实 apply 输出、module DAG、可 fork 的起手仓库。
这是第二到第七篇所有东西落到一处的文章。读完之后你会跑过一次 terraform apply,在阿里云上产出一个完整、可观测、有预算的 Agent runtime stack。约 31 个资源,~7 分钟实际时间。
我们要建的 stack:

五层——edge、compute、memory、platform、ops——由本系列做出的 module 组合。
项目结构
research-agent-stack/
├── README.md
├── versions.tf # Terraform + provider 版本
├── backend.tf # OSS + Tablestore 远程 state
├── providers.tf # alicloud + alicloud.beijing 别名
├── variables.tf # ��层输入
├── locals.tf # 看 workspace 计算的 local
├── main.tf # module 组合
├── outputs.tf # endpoint + 连接串
├── env/
│ ├── dev.tfvars
│ ├── staging.tfvars
│ └── prod.tfvars
├── secrets/
│ └── secrets.auto.tfvars # gitignore——provider key
├── modules/
│ ├── vpc-baseline/ # 第三篇
│ ├── storage/ # 第五篇
│ ├── compute/ # 第四篇
│ ├── llm-gateway/ # 第六篇
│ └── observability/ # 第七篇
└── scripts/
├── cloud-init/
│ ├── agent.sh
│ └── gateway.sh
└── restore-drill.sh
顶层八个 *.tf,modules/ 下五个 module,env/*.tfvars 装环境特定值,secrets/secrets.auto.tfvars 装 git 之外的密钥。这是我每个项目都用的布局——无聊就是好。
main.tf——组合
| |
五个 module 调用。注意每个 module 把前一个 module 的输出当输入——module.compute 读 module.vpc、module.storage、module.gateway、module.observability。这种依赖接线就是 Terraform 用来构建 apply DAG 的:

network 和 KMS 在最上——它们没有依赖。storage、compute、gateway 依赖 network + KMS 但相互独立,所以 Terraform 并行建。compute 还依赖 storage 和 gateway 因为 cloud-init 模板需要它们的 endpoint。observability 和 alarm 依赖 compute 因为它们引用 SG ID。
variables.tf
| |
sensitive = true 让 Terraform 不在 plan/apply 输出里打值。值还是会进 tfstate(这就是为什么第二篇我们给 OSS bucket 开了加密)。
env/dev.tfvars
| |
secrets/secrets.auto.tfvars(gitignore)
| |
*.auto.tfvars 文件不加 -var-file 自动加载。从第一次 commit 起 secrets/ 就要在 .gitignore 里。
Apply
| |
新建 apply 的真实耗时:

时钟分解:
- 0-60s: VPC、vSwitch、NAT、EIP、KMS 密钥——快资源
- 60-380s: RDS(5 分钟)、OpenSearch(5.5 分钟)、ECS(~2 分钟)、网关(~1.5 分钟)——全部并行,被最慢的卡住
- 380-460s: Agent 应用部署、observability 资源、告警
总共约 7 分钟,被 RDS 和 OpenSearch 主导。无变更的重复 apply 30 秒内结束因为 Terraform 只 diff。
精简后的 apply 文字记录:
Terraform will perform the following actions:
# module.vpc.alicloud_vpc.this will be created
+ resource "alicloud_vpc" "this" {
+ cidr_block = "10.20.0.0/16"
+ vpc_name = "agents-dev"
...
}
...(再 29 个资源)...
Plan: 31 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ agent_endpoints = (known after apply)
+ gateway_url = (known after apply)
+ sls_dashboard_url = (known after apply)
+ total_estimated_cost = "~¥1450/月(dev 规格)"
Do you want to perform these actions in workspace "dev"?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
module.vpc.alicloud_vpc.this: Creating...
module.vpc.alicloud_kms_key.this["memory"]: Creating...
module.vpc.alicloud_kms_key.this["secrets"]: Creating...
module.vpc.alicloud_kms_key.this["logs"]: Creating...
module.vpc.alicloud_vpc.this: Creation complete after 4s [id=vpc-uf6abc123]
module.vpc.alicloud_vswitch.private["0"]: Creating...
module.vpc.alicloud_vswitch.private["1"]: Creating...
module.vpc.alicloud_vswitch.private["2"]: Creating...
module.vpc.alicloud_vswitch.public["0"]: Creating...
...
module.storage.alicloud_db_instance.memory: Still creating... [4m 30s elapsed]
module.storage.alicloud_opensearch_app_group.vector: Still creating... [5m 10s elapsed]
module.storage.alicloud_db_instance.memory: Creation complete after 4m 38s [id=pgm-uf6def456]
module.storage.alicloud_opensearch_app_group.vector: Creation complete after 5m 24s [id=os-uf6ghi789]
...
module.compute.alicloud_instance.agent[0]: Creation complete after 1m 52s [id=i-uf6jkl012]
module.gateway.alicloud_alb_listener.gateway: Creation complete after 12s
module.observability.alicloud_log_alert.cost_ceiling: Creation complete after 3s
...
Apply complete! Resources: 31 added, 0 changed, 0 destroyed.
Outputs:
agent_endpoints = [
"http://alb-uf6.cn-shanghai.alb.aliyuncs.com",
]
gateway_url = "http://alb-uf7.cn-shanghai.alb.aliyuncs.com/v1"
sls_dashboard_url = "https://sls.console.aliyun.com/lognext/project/agents-dev/dashboard/agent-cost-overview"
total_estimated_cost = "~¥1450/月(dev 规格)"
这就是一个完整的 Agent stack。ALB endpoint、网关 URL、SLS 看板 URL——任何一个粘进浏览器都能用。
Day-2 运维
stack 起来了。然后呢?
加新 Agent
- 给
dev.tfvars里的var.agent_quotas加一项 terraform apply -var-file=env/dev.tfvarsnull_resource给 LiteLLM 配新 key- 用新
LITELLM_API_KEY环境变量部署你的新 Agent 代码
端到端约 30 秒。
扩容
改 module 调用里的 ecs_count(或者通过 tfvars 设)。terraform apply 起新实例、挂上 ALB,老实例全程健康(create_before_destroy)。零停机。
Dev → prod 提升
| |
同样 module,不同规格(HA RDS、更大 OpenSearch 配额、更多 ECS、真钉钉 webhook、真 LLM key、成本上限 ¥800 而不是 ¥100)。第一次 prod apply 7-10 分钟;后续 apply 几秒。
销毁 dev
实验做完了:
| |
会因为 prod-like 资源上的 deletion_protection = true 和 bootstrap state bucket 上的 prevent_destroy = true 失败。这是有意的。dev 里设 deletion_protection = local.is_prod,所以只在 prod 开——terraform destroy 在 dev 能跑。
实操提示:
terraform destroy之前永远先terraform plan -destroy。读 plan 输出。要销毁的资源数应当跟你想的一样。我见过一个工程师因为忘记切 workspace 把staging销了。
接你真实的 Agent 代码
stack 是平台。Agent 本身来自你仓库(var.agent_repo_url),ECS 启动时 cloud-init 部署。Agent 代码需要遵守的最小契约:
| |
所有这些从 Terraform 输出取值。Agent 代码形状上保持云无关——只读环境变量——但运行时完全接到阿里云 stack 上。
成本汇总
dev workspace 真实账单,低流量:
| 组件 | 月费 |
|---|---|
| VPC + NAT + EIP | ~¥150 |
| ECS x1 (c7.large) | ~¥250 |
| RDS Postgres (小) | ~¥350 |
| OpenSearch 向量 | ~¥800 |
| OSS (10 GB 标准) | ~¥2 |
| LLM 网关 ECS x1 | ~¥150 |
| ALB(小) | ~¥50 |
| SLS + ARMS | ~¥300 |
| KMS | ~¥10 |
| dev 合计 | ~¥2060/月 |
Prod 配 HA、更大规格、跨区 DR:LLM API 成本之外大约 ¥6000-9000/月。LLM 账单通常是最大头——这就是为什么有第六篇的网关和第七篇的成本告警。
我跳过的
- CDN 公网服务产物 URL——alicloud_cdn_domain 可用,但多数 Agent 通过自己网关服产物
- WAF 在 ALB 前——对外 prod 必需,dev 用 Intranet ALB
- PrivateLink 到 DashScope——规模上省 NAT 出网,alicloud_privatelink_* 可配
- 自定义域名 + SSL——alicloud_alb_listener 支持 SSL 证书但你得自带(或用 ACM)
四个都值得在基础跑通后加。第一天别加。
接下来
你现在拥有一个生产形状的 Agent runtime 在阿里云上,全部用 Terraform 表达,自带可观测、密钥管理、成本守门。下一步看你的项目:
- 更多 Agent: 加进
var.agent_quotas,terraform apply - 不同 LLM provider: 加进网关 module 的
local.litellm_config - 多 region: 加 provider 别名,复制 stack
- GitOps: 把
terraform apply包进有 PR review 守门的 CI 流水 - Pulumi 或 Crossplane 迁移: 资源图直接对应
最重要的一件事是你的基础设施现在在 git 里。每次变更可评审。每个环境可重现。每笔成本可归因。这就是 IaC 给你的,也就是让在阿里云上交付 Agent 成为可持续实践而不是永久救火的原因。
谢谢读完本系列。如果你基于本系列交付了一个 stack,我很想听你改了什么、为什么——这就是模式演进的方式。