Series · Terraform Agents · Chapter 5

用 Terraform 给 AI Agent 上云(五):存储层——向量、关系、对象记忆

Agent 有三种记忆,分别落到三个阿里云服务上:会话用 PolarDB/RDS,embedding 用 OpenSearch 向量版或 pgvector,产物用 OSS。每一层的真实 Terraform,加上让账单不暴涨的 lifecycle 和备份规则。

Agent 的"记忆"是多数教程一笔带过的部分。“embedding 丢 Pinecone,会话进 Postgres,截图传 S3。“在阿里云上,三种都有托管服务,而正确地用 Terraform 把它们建出来,就是"记忆好用"和"凌晨四点磁盘满了我们丢了三周对话历史"的差。

本篇覆盖三层、每层的 Terraform,外加无聊但关键的 lifecycle 和备份规则。

三层记忆模型

Agent 三种记忆映射到三个阿里云服务

心智模型:

  • 短期 / 会话——Agent 在当前次和最近几次跑里做过的事。对话轮次、工具调用、中间状态。schema 稳定、低延迟、要事务。放关系型数据库。
  • 长期 / 语义——文档、历史输出、召回库的 embedding。混合 lexical + 向量检索。放向量库。
  • 产物 / blob——生成的图片、PDF、截图、运行快照。有时大、常常写一次很少读。放对象存储。

不要混淆。我见过一个团队把 50 GB 生成的 PDF 塞进 Postgres,因为"它有 bytea 列”。成本是 OSS 的十倍,查询延迟糊成一团,备份要几小时。

第 1 层:关系型,RDS for PostgreSQL

会话状态——对话轮次、工具调用 trace、用户身份——你需要真正的 RDBMS。PostgreSQL 是我的默认;MySQL 也行如果团队偏好。需要横向 scale 时升 PolarDB。

 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
48
49
50
51
52
resource "random_password" "rds_admin" {
  length  = 32
  special = true
}

resource "alicloud_kms_secret" "rds_admin" {
  secret_name              = "agents-${terraform.workspace}-rds-admin"
  secret_data              = random_password.rds_admin.result
  version_id               = "v1"
  description              = "agents-${terraform.workspace} 的 RDS admin 密码"
  encryption_key_id        = module.vpc.kms_keys["secrets"]
  recovery_window_in_days  = 7
  force_delete_without_recovery = false
}

resource "alicloud_db_instance" "memory" {
  engine           = "PostgreSQL"
  engine_version   = "16.0"
  instance_type    = terraform.workspace == "prod" ? "pg.x4.large.2c" : "pg.n2.medium.1c"
  instance_storage = 100
  instance_name    = "agents-memory-${terraform.workspace}"

  vswitch_id          = module.vpc.private_vswitch_ids[0]
  security_ips        = [module.vpc.vpc_cidr_block]
  db_instance_storage_type = "cloud_essd"

  encryption_key = module.vpc.kms_keys["memory"]

  backup_period   = ["Monday", "Wednesday", "Friday"]
  backup_time     = "02:00Z-03:00Z"
  retention_period = terraform.workspace == "prod" ? 30 : 7
  log_backup_retention_period = 30
  preferred_backup_period = ["Monday", "Wednesday", "Friday"]

  deletion_protection = terraform.workspace == "prod"

  zone_id = "cn-shanghai-l"
  zone_id_slave_a = terraform.workspace == "prod" ? "cn-shanghai-m" : null
}

resource "alicloud_db_account" "agent" {
  db_instance_id   = alicloud_db_instance.memory.id
  account_name     = "agent"
  account_password = random_password.rds_admin.result
  account_type     = "Super"
}

resource "alicloud_db_database" "session" {
  instance_id   = alicloud_db_instance.memory.id
  name          = "agent_sessions"
  character_set = "UTF8"
}

要点:

  • 密码出生即在 KMS Secrets Manager 里。 random_password 生成,写进 alicloud_kms_secret,Agent 启动时通过 STS 取。明文密码只在 Terraform 内存里短暂存在,不进 tfstate(用 secret_id 引用)。
  • encryption_key 把磁盘和 memory CMK 绑定。静态加密,零额外成本。
  • backup_period + retention_period 一周三次自动备份,prod 留 30 天、dev 留 7 天。RDS 备份存在 OSS 上,bucket 不用你管。
  • zone_id_slave_a 在 prod 里在第二个 zone 建热备。30 秒内 failover。代价是 2 倍——prod 值得,dev 过头。
  • deletion_protection 在 prod 里挡住 terraform destroy 杀数据库。永远要。

实操提示: 当你的 sessions 表过 ~10M 行或者需要无停机读副本时,PolarDB 是对的选择。RDS → PolarDB 迁移文档完善,Terraform 两边都支持。但别从一开始就用——小规模时 RDS 更简单更便宜。

第 2 层:向量库

阿里云上向量层有两个合理选择:

  1. OpenSearch 向量检索版——托管、Lucene 后端、支持 HNSW + IVF、按 QPS 配额计费
  2. PolarDB 或 RDS PostgreSQL + pgvector——和关系数据共址、新基础设施零成本,过 ~1M 向量后变慢

原型之外我偏好 OpenSearch。成本是真的(最小实例 ~¥800/月),但你拿到开箱即用的 lexical+向量混合检索,正是召回需要的形状。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
resource "alicloud_opensearch_app_group" "vector" {
  app_group_name  = "agent-vec-${terraform.workspace}"
  payment_type    = "PayAsYouGo"
  type            = "vector"
  quota {
    doc_size   = 100
    compute_resource = 20
    spec       = "opensearch.share.junior"
  }
  description = "Agent 的长期语义记忆"
}

app group 是 OpenSearch 持有 index 的概念。从这里通过 OpenSearch 控制台或 SDK 创建 index schema——alicloud_opensearch_app 资源存在但 schema 部分是运维而非 provisioning。

如果你走 pgvector 路线,给 RDS 数据库创建里加上:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
resource "alicloud_db_database" "vectors" {
  instance_id   = alicloud_db_instance.memory.id
  name          = "agent_vectors"
  character_set = "UTF8"
}

# pgvector 扩展通过你的迁移工具创建,不在 Terraform 里:
# CREATE EXTENSION IF NOT EXISTS vector;
# CREATE TABLE embeddings (id bigserial primary key, vec vector(1536), meta jsonb);
# CREATE INDEX embeddings_vec_idx ON embeddings USING hnsw (vec vector_cosine_ops);

Terraform 那一半只管数据库;schema 是应用代码(Alembic、Flyway、sqlx-migrate——挑一个)。别想用 Terraform 管表 schema,这条路通向疯狂。

第 3 层:对象存储

OSS 装产物:生成图片、PDF、截图、运行 trace tarball、微调出来的模型 checkpoint。

官方"Create a bucket with Terraform"实践文档覆盖了基础。Agent stack 用:

 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
resource "alicloud_oss_bucket" "artifacts" {
  bucket = "agents-artifacts-${terraform.workspace}-${random_id.suffix.hex}"
  acl    = "private"

  versioning {
    status = "Enabled"
  }

  server_side_encryption_rule {
    sse_algorithm   = "KMS"
    kms_master_key_id = module.vpc.kms_keys["memory"]
  }

  lifecycle_rule {
    id      = "agent-artifacts-tiering"
    enabled = true

    transitions {
      days          = 30
      storage_class = "IA"
    }
    transitions {
      days          = 90
      storage_class = "Archive"
    }
    transitions {
      days          = 365
      storage_class = "ColdArchive"
    }
    expiration {
      days = 730
    }
  }

  logging {
    target_bucket = alicloud_oss_bucket.access_logs.id
    target_prefix = "artifacts-access/"
  }

  tags = {
    Domain = "agent-artifacts"
  }
}

resource "random_id" "suffix" {
  byte_length = 4
}

三处值得展开:

Bucket 名全局唯一

OSS bucket 名在所有阿里云用户范围内唯一。random_id 后缀避开"名字已被占用"的 plan 失败——每个新手都栽过。一旦建出来,名字就稳定。

Lifecycle 分层

lifecycle_rule 块是 OSS 上最大的成本杠杆:

OSS 产物 lifecycle

  • 标准 (0-30 天,~¥0.12/GB/月)——默认写入
  • 低频访问 (30-90 天,~¥0.08/GB/月)——存便宜,每 GB 取回 ¥0.0125
  • 归档 (90-365 天,~¥0.033/GB/月)——分钟到小时取回
  • 冷归档 (365 天+,~¥0.015/GB/月)——小时取回,最便宜

对 Agent 产物,这条规则说:30 天热、转 IA、3 月转归档、1 年转冷归档、2 年删。1 TB 产物语料下,这是 ¥1500/月(全标准)和 ~¥250/月的差。HCL 里写一次,一年省五位数。

版本化

versioning { status = "Enabled" } 留每个对象版本。Agent 覆写 artifacts/run-123/output.pdf 不会真销毁前一版——它还在,version ID 不同。两个原因重要:

  1. 恢复。 Bug 把 50,000 个对象写成垃圾?脚本恢复前一版。
  2. 防篡改。 配 WORM (Write-Once-Read-Many) 策略,免费拿监管合规。

成本是真的——版本化对象会累积。版本化要配 lifecycle 里的 noncurrent_version_expiration 规则,比如 180 天后剪枝。

备份故事

Terraform 管的备份配置长这样:

备份不是可选项,是有预算的

  • RDS:内置自动备份(上面 HCL 已经有了)
  • OSS:版本化 + 跨区域复制做灾备
  • OpenSearch:通过 alicloud_opensearch_* 快照资源快照到 OSS

OSS 跨区域复制就一个资源:

 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
resource "alicloud_oss_bucket" "artifacts_dr" {
  provider = alicloud.beijing       # 第二 region 的 provider 别名
  bucket   = "${alicloud_oss_bucket.artifacts.bucket}-dr"
  acl      = "private"

  versioning {
    status = "Enabled"
  }

  server_side_encryption_rule {
    sse_algorithm = "AES256"        # KMS key 是 region 范围的,DR 用 AES256 更简单
  }
}

resource "alicloud_oss_bucket_replication" "artifacts" {
  bucket = alicloud_oss_bucket.artifacts.id

  action = "ALL"
  destination {
    bucket   = alicloud_oss_bucket.artifacts_dr.bucket
    location = "oss-cn-beijing"
  }
  enable_historical_object_replication = "enabled"

  encryption_configuration {
    replica_kms_key_id = "alias/agents-prod-memory-dr"
  }
}

带别名的 provider 让一次 Terraform run 触两个 region:

1
2
3
4
provider "alicloud" {
  alias  = "beijing"
  region = "cn-beijing"
}

主要无状态的研究 Agent 你可能决定 DR 不值得双倍存储费。承担对话历史合法持久化的对客 Agent 则强制要求。

实操提示: 季度做一次 restore drill。从未恢复过的备份只是昂贵的希望。我每月跑一个 restore-drill.sh 脚本,把随机 RDS 备份拉到 cn-shanghai-dr 实例上跑 schema/checksum 校验。这是我每月最有用的 30 分钟。

把计算和存储接起来

第四篇的 ECS 实例需要真正能访问到这些存储。三块:

  1. 网络——已经做了。VPC module 输出的 agent_runtime_sg_idmemory_rds_sgvector_store_sg 入站规则的 source。
  2. 凭证——Agent 启动时通过 STS 从 KMS Secrets Manager 读 DB 密码:
    1
    2
    3
    
    from alibabacloud_kms20160120.client import Client as KmsClient
    resp = kms_client.get_secret_value(GetSecretValueRequest(secret_name="agents-prod-rds-admin"))
    db_password = resp.body.secret_data
    
  3. Endpoint——Terraform 输出:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    output "rds_endpoint" {
      value = alicloud_db_instance.memory.connection_string
    }
    output "vector_endpoint" {
      value = alicloud_opensearch_app_group.vector.api_domain
    }
    output "artifacts_bucket" {
      value = alicloud_oss_bucket.artifacts.bucket
    }
    

Agent 从 cloud-init 写入的环境变量读这些。没有硬写的 endpoint,没有手工配置文件。

月成本(dev workspace、低流量)

  • RDS PostgreSQL (pg.n2.medium.1c, 100 GB ESSD):~¥350/月
  • OpenSearch 向量(最小):~¥800/月
  • OSS(10 GB 标准,lifecycle 开):~¥1.5/月 + 流量
  • KMS(第三篇覆盖):~¥10/月

dev 存储层粗略 ¥1200/月。Prod 加 HA RDS、更大 OpenSearch、更多 OSS 会到 ¥3000-5000/月。这就是成本压力开始真实的地方——第七篇讲怎么追踪和告警。

下一篇

第六篇在第四篇的计算和刚刚的存储前面建 LLM 网关。那是 API key 住的地方、配额执行的地方、按 Agent 归因成本的地方。第六篇结束你就拥有一个能跑 Agent 的完整 stack——最后两篇在上面接观测和成本控制。

Liked this piece?

Follow on GitHub for the next one — usually one a week.

GitHub