用 Terraform 给 AI Agent 上云(四):计算层选 ECS、ACK 还是函数计算?
Agent 主循环在阿里云上有三个合理落点:长跑 ECS + pm2、ACK 上的 Kubernetes Pod、Function Compute 触发式调用。我用来选择的成本拐点模型,加一段真实的 cloud-init 脚本,从裸 Ubuntu 到 Agent 运行 90 秒搞定。
CK
Chen Kai
· 6 min read · 2909 words
Agent 系统最重要的架构决策就是 Agent 主循环进程到底跑在哪里。阿里云上正好有三个好答案。选错不会致命——后面可以迁——但会让你浪费几周搭无谓的脚手架。
本篇用真实 Terraform、成本拐点和运维坑走完三种方案。
三种模式

各自有甜蜜区:
- ECS 是 Linux 虚拟机。长跑、有状态、debug 时 SSH 进去方便。原型、单租户 Agent、想保留一台带模型缓存或本地 state 的"暖机"——它都是对的。
- ACK(Container Service for Kubernetes)是规模生产答案。多种 Agent、自动伸缩、滚动发布、GPU 调度。值得它的运维重量的前提是你至少有三四个 Agent 服务,且有一个对 K8s 自在的 SRE。
- Function Compute 是按调用计费、scale-to-zero。冷启动 200-800ms。Webhook 触发的 Agent、定时爬虫、所有"突发跑、空闲休眠"的负载用它。
成本拐点
按持续 QPS 看大致月度成本:

持续 ~1 QPS 以下,FC 通杀——空闲几乎不花钱。~1 到 ~30 QPS,单台 ECS 最划算。再往上,ACK 较高的固定成本被足够流量摊薄之后比往 ECS 上塞更便宜。
模型粗——具体数字看实例族、网络、Agent 多嘴程度——但是形状靠谱。我用的决策规则:
突发 + 平均低 → Function Compute
稳态 + 中低 → ECS + pm2
多 Agent + 持续中高 → ACK
模式 1:ECS + pm2
80% 的 Agent 项目你想要的就是这个。一两台 ECS 挂在 ALB 后面,每台用 pm2 当 Python 或 Node Agent 进程的 supervisor。
官方"Create an ECS instance"实践文档给了能跑的基线。我们 Agent 场景下改写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| data "alicloud_images" "ubuntu" {
owners = "system"
name_regex = "^ubuntu_22_04_x64.*"
most_recent = true
}
data "alicloud_instance_types" "agent" {
cpu_core_count = 4
memory_size = 16
availability_zone = "cn-shanghai-l"
instance_type_family = "ecs.c7"
}
resource "alicloud_instance" "agent" {
count = var.agent_count
instance_name = "agent-${terraform.workspace}-${count.index + 1}"
image_id = data.alicloud_images.ubuntu.images[0].id
instance_type = data.alicloud_instance_types.agent.instance_types[0].id
availability_zone = "cn-shanghai-l"
vswitch_id = module.vpc.private_vswitch_ids[count.index % 3]
security_groups = [module.vpc.agent_runtime_sg_id]
system_disk_category = "cloud_essd"
system_disk_size = 80
system_disk_encrypted = true
system_disk_kms_key_id = module.vpc.kms_keys["memory"]
user_data = base64encode(templatefile("${path.module}/cloud-init.sh", {
repo_url = var.agent_repo_url
branch = var.agent_branch
gateway_url = "http://${alicloud_alb_listener.gateway.id}.alb.aliyuncs.com"
sls_project = alicloud_log_project.agents.name
sls_logstore = alicloud_log_store.agent_runs.name
}))
tags = {
Role = "agent-runtime"
App = "research-agent"
}
lifecycle {
create_before_destroy = true
ignore_changes = [user_data] # 别在每次 cloud-init 改动时重建
}
}
|
三个值得强调的点:
data 块挑镜像和实例类型而不是硬写。ubuntu_22_04_x64 解析到最新打补丁的镜像;data.alicloud_instance_types.agent 找一个 ecs.c7 4 vCPU 16 GiB 的。阿里云某天弃用某个 SKU 时,下次 plan 自动拿到新的。system_disk_kms_key_id 把磁盘和第三篇里的 memory CMK 绑起来。 静态加密不额外花钱,去掉一整堆合规头痛。lifecycle { create_before_destroy = true } 意味着计划内的替换会先建新实例、挂上 ALB、排空老的、再销毁——零停机轮换。代价是你短时需要 2 倍容量,两台 fleet 没问题,到 50 台开始重要。
Cloud-init 脚本
cloud-init.sh 是 templatefile,把机器从裸 Ubuntu 启动到 Agent 运行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| #!/bin/bash
set -euxo pipefail
# 更新 apt 装基础依赖
apt-get update -y
apt-get install -y python3.11 python3.11-venv git curl ca-certificates
# Node 20 给 Agent 偶尔 shell 出去用的 JS 工具
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
# pm2 当进程 supervisor
npm install -g pm2 uv
# 拉 Agent runtime
mkdir -p /opt/agent
cd /opt/agent
git clone --depth 1 -b ${branch} ${repo_url} src
cd src
uv venv .venv
uv pip sync requirements.txt
# 写环境变量(来自 Terraform 的 templatefile)
cat > /opt/agent/src/.env <<EOF
LLM_GATEWAY_URL=${gateway_url}
SLS_PROJECT=${sls_project}
SLS_LOGSTORE=${sls_logstore}
EOF
# pm2 拉起来 + 持久化
pm2 start ecosystem.config.js
pm2 save
pm2 startup systemd -u root --hp /root
|
流程:

apply 到 pm2 status 显示 online 大约 90 秒。第一次 apt-get install 是慢的那步(~60s)。等你有了稳定镜像,用 Packer 烤一份,后续 ECS 跳过 apt,25 秒启动。
实操提示: user_data 在实例上写到 /var/log/cloud-init-output.log。Agent 起不来时先看这里。脚本顶部加 set -euxo pipefail,让失败响亮可追。
模式 2:ACK 跑生产 fleet
一旦你有三种以上 Agent 并行跑,每台 VM 的运维成本就压过来了。ACK 给你一个集群、一个调度器、一条升级路径。
最小的 Aliyun 托管 K8s 集群 Terraform:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| resource "alicloud_cs_managed_kubernetes" "agents" {
name_prefix = "agents-${terraform.workspace}"
version = "1.30.1-aliyun.1"
cluster_spec = "ack.pro.small"
vpc_id = module.vpc.vpc_id
worker_vswitch_ids = module.vpc.private_vswitch_ids
pod_vswitch_ids = module.vpc.private_vswitch_ids
service_cidr = "172.21.0.0/20"
proxy_mode = "ipvs"
load_balancer_spec = "slb.s2.small"
enable_ssh = false
delete_protection = true
control_plane_log_components = ["apiserver", "audit"]
addons {
name = "managed-arms-prometheus"
}
addons {
name = "logtail-ds"
}
}
resource "alicloud_cs_kubernetes_node_pool" "agents" {
cluster_id = alicloud_cs_managed_kubernetes.agents.id
node_pool_name = "agent-workers"
vswitch_ids = module.vpc.private_vswitch_ids
instance_types = ["ecs.c7.xlarge"]
desired_size = 3
system_disk_category = "cloud_essd"
system_disk_size = 80
install_cloud_monitor = true
scaling_config {
enable = true
min_size = 2
max_size = 10
}
}
|
几点注解:
ack.pro.small 是托管控制面 SKU。阿里云跑 master,你只付 worker ECS 钱。除非有强理由,别选非托管 SKU。pod_vswitch_ids 给 Terway 用,这是阿里云原生 CNI。每个 pod 拿一个真实 VPC IP——没有 overlay 网络,安全组直接生效。这是合理默认;备选(Flannel)让网络 debug 痛不欲生。delete_protection = true 字面意思——terraform destroy 不会干掉集群。所有 prod 集群都设。addons 块开 ARMS Prometheus(第七篇)和 SLS 日志采集。通过 Terraform 配,新集群天生带观测。
实际 Agent Pod 来自 K8s deployment manifest——通常单独一步 kubectl 应用,或用 kubernetes Terraform provider。我把集群放在这个 terraform 项目里,把 workload 放在另一个 Helm chart 里,因为它们的发布节奏不同。
模式 3:Function Compute 跑事件触发 Agent
有些 Agent 只在被触发时跑——webhook、cron、OSS 对象落地。这种场景 FC 无敌:零空闲成本、自动 scale-out、runtime 完全云端托管。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| resource "alicloud_fc_service" "agent" {
name = "agent-${terraform.workspace}"
description = "事件触发的 Agent 函数"
log_config {
project = alicloud_log_project.agents.name
logstore = alicloud_log_store.agent_runs.name
}
vpc_config {
vswitch_ids = module.vpc.private_vswitch_ids
security_group_id = module.vpc.agent_runtime_sg_id
}
role = alicloud_ram_role.fc_agent.arn
internet_access = false
}
resource "alicloud_fc_function" "scheduled_research" {
service = alicloud_fc_service.agent.name
name = "scheduled-research"
description = "每日 research agent 跑批"
filename = "${path.module}/dist/scheduled-research.zip"
handler = "index.handler"
runtime = "python3.11"
memory_size = 1024
timeout = 600
ca_port = 8080
environment_variables = {
LLM_GATEWAY_URL = "http://${alicloud_alb_listener.gateway.id}.alb.aliyuncs.com"
}
}
resource "alicloud_fc_trigger" "daily" {
service = alicloud_fc_service.agent.name
function = alicloud_fc_function.scheduled_research.name
name = "daily-9am"
type = "timer"
config = jsonencode({
cronExpression = "0 0 9 * * *"
enable = true
payload = "{}"
})
}
|
它给你的:Python 3.11 函数,1 GiB 内存,10 分钟超时,挂在和其它资源同一 VPC 同一安全组上,每天上午 9 点触发。零服务器维护。成本:这个规模约 ¥0.10/次调用,加 ¥0.0001/GB-second 执行。
我反复栽的三个坑:
- 冷启动。 空闲后第一次调用比后续多 200-800ms。亚秒 SLA 的 webhook 在意;cron 不在意。可以买 provisioned concurrency,但那就违背 FC 的初衷了。
- VPC 挂载 给冷启动再加 200-400ms,因为 FC 要给你 VPC 加一个 ENI。函数要访问 RDS/OpenSearch 时值得;只调公网 API 时跳过
vpc_config。 - 24 小时最长运行时间。 长 Agent 循环不适合 FC。要么把循环切成短步骤,要么用 ECS。
一个真实例子:混合
我交付过的多数生产 Agent stack 都是混合的:
- ECS 跑常驻、持有会话状态的对话 Agent
- ACK 跑后台 job worker fleet
- FC 跑 webhook 接收和日/小时级 cron
Terraform 让这件事简单——一个项目里三个 module,共用第三篇里的 VPC 和安全组。技能在于知道哪种模式配哪种负载,不在于学完所有资源语法。
实例规格选型
常见问题:Agent runtime 选哪个 ecs.* 族?我的默认:
| 负载 | 族 | 原因 |
|---|
| 对话 Agent,无 GPU | ecs.c7 | tokenize CPU 受限 + LLM 调用 I/O |
| 大上下文,内存重 | ecs.r7 | 每 vCPU 内存更大 |
| 突发批量 | ecs.c7a(AMD) | 便宜 ~15%,单核略慢 |
| 小模型 GPU 推理 | ecs.gn7i | T4 级,阿里云上最便宜 GPU |
| 预训练 / 大规模微调 | 用 PAI-DLC,不要 ECS | 别重新发明编排 |
Agent runtime 别用突发型 ecs.t6——CPU credit 在持续负载下耗光,延迟跳水。它适合跑 terraform apply 的堡垒机之类。
实操提示: 用 data.alicloud_instance_types 让 API 帮你找"现在这个 zone 里有 4 vCPU 16 GiB 实例"。硬写 ecs.c7.xlarge 在该 SKU 在你 zone 缺货时 Terraform 失败。让 data source 帮你挑提供优雅降级。
下一篇
第五篇填存储层——向量库、关系库、对象存储、备份——刚才建的所有计算都需要它去存取记忆。ECS 实例没有"放记忆的地方"就是空跑。
然后第六篇在所有计算前面建 LLM 网关,第七篇接观测和成本告警,第八篇用一次 terraform apply 串起整个 stack。
Liked this piece?
Follow on GitHub for the next one — usually one a week.
GitHub →