作者用Terraform而非控制台完成了AWS Organizations下的DevOps Agent落地部署,详细记录了IAM配置、多账户访问和官方文档与实际不符的四处坑点。
我在我们的 AWS Organizations 环境中搭建了 AWS DevOps Agent——一个运行 Agent Space 的中心账户,开发和生产账户都连接到这里——IAM 部分用的是 Terraform,而不是在控制台点点点。
这正是我起步时想要看到的教程:各个移动部件是什么、正确的操作顺序,以及文档上的happy path与实际发生情况不匹配的四五个地方。
如果你只想要官方步骤,AWS 用户指南写得不错,我会在讲解过程中附上相关页面链接。下面分享的是官方路径加上那些摩擦点。
2026 年 3 月底正式发布。分为两个部分:发布管理(仍在预览——代码审查、发布就绪性、自主测试)和生产运营,后者是我实际使用的部分。
生产运营做四件事:收到告警时调查事件、生成缓解方案、从事件历史模式中提出预防性建议,以及通过对话方式回答 SRE 问题。
有用的心智模型不是"AWS 控制台里的 AI"。它是建立在你已经接入的基础设施之上的只读关联层。事件发生时,我通常会打开 CloudWatch、RDS 指标、EC2、EKS 控制台、负载均衡器健康状态、Logs Insights 和部署历史——然后才开始思考。Agent 把收集这个环节去掉了。它不会生成遥测数据,如果你的可观测性薄弱,它只是让你更快地得到一幅不完整的图。
在开始任何设置之前,你需要理解三个概念:
Agent Space — 容器和访问边界。它定义了 Agent 可以访问哪些 AWS 账户、哪些集成以及哪些用户。调查历史和聊天历史按 Agent Space 隔离。Agent Space 是区域级的。
Topology — 你连接账户后 Agent 构建的内容。它是资源及其关系的图谱,这让 Agent 能够推理爆炸半径,而不仅仅是读取指标。
IAM roles — 它如何访问任何内容。Agent 永远不会使用你的凭证。它假设你创建的角色,使用服务主体 aidevops.amazonaws.com。
有件事困扰了我十分钟:这里有两个控制台。管理员在 AWS Management Console 中配置 Agent Spaces。操作员在另一个独立的 Web 应用中运行调查,该应用有自己的 IAM 角色和自己的认证流程。所以在你连接第二个账户之前,你已经在创建两个角色了。
在开始点击之前:
一个支持的区域。共六个:弗吉尼亚北部、俄勒冈、法兰克福、爱尔兰、悉尼、东京。Agent Space 将其数据存储在创建它的区域中,所以要考虑数据驻留来选择——这个以后不容易改。
在你要连接的每个账户中创建角色的 IAM 权限。控制台的自动创建选项在主账户中需要这个权限;辅助账户需要在创建跨账户角色的地方拥有这个权限。
主账户中的 iam:PassRole ——只有在连接辅助账户时才需要,但提前准备好。关于为什么需要这个,以及为什么它会产生一个真正令人困惑的错误,下面会详述。
选择控制台还是基础设施即代码。控制台的自动创建路径是让 Agent Space 运行起来的最快方式,也是我用来评估服务的首选。但长期维护指向生产环境的跨账户信任关系,我不愿意用这种方式。你可以从自动创建开始,之后再迁移到 IaC;但你没法轻易回溯为什么手动的信任策略是那个样子的。
意识到这是要花钱的。按秒计费,无需承诺,计费从 2026 年 4 月 10 日开始。AWS Support 客户根据支持级别获得月度积分。在让它在大规模环境中运行之前,值得检查一下你的级别包含什么。
在 AWS DevOps Agent 控制台中,选择 Create Agent Space。你给它一个名称、一个可选的描述,以及一个可选的响应语言(默认为匹配你输入的语言)。
然后是两个都创建 IAM 角色的部分,这是整个设置中真正的决策点。
"Give this Agent Space AWS resource access"(授予此 Agent Space AWS 资源访问权限)—— Agent 用来在主账户中调查资源的角色。三个选项:自动创建角色、分配现有角色,或从策略模板构建。自动创建是推荐的默认选项。
"Enable web app"(启用 Web 应用)—— 操作员角色,用于实际发生调查的独立 Web 应用。同样三个选项。然后点击 Create。
空间一旦存在,它就开始扫描账户中的资源和关系。这需要几分钟。一旦完成,Operator 访问权限就会出现在 Agent Space 详情页上,并在新标签页中打开 Web 应用。
如果让我重新来一次我会怎么做:Web 应用角色用自动创建,资源访问用一个预先创建的角色。Web 应用角色很无聊且仅限于账户本地。资源访问角色才是重要的那个,那个你以后想要去推理的角色,也是你在连接任何后续东西时需要再次用到其 ARN 的角色。
自动创建很方便,对于初次体验我仍然推荐,但你应该知道它在构建什么,因为你以后连接的每个账户都会出现相同的三个组件。
该角色直接信任 AWS DevOps Agent 服务主体:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "aidevops.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "<PRIMARY_ACCOUNT_ID>"
},
"ArnLike": {
"aws:SourceArn": "arn:aws:aidevops:<REGION>:<PRIMARY_ACCOUNT_ID>:agentspace/*"
}
}
}
]
}
这两个条件就是整个安全机制。aws:SourceAccount 和 aws:SourceArn 是防止混乱代理人的机制——没有它们,服务主体就是一扇敞开的门,因为 aidevops.amazonaws.com 在地球上每个 AWS 账户中都是相同的主体。这些条件在说"只有我账户中的 Agent Space 才可以使用这个角色"。
操作员角色的信任策略几乎相同,但需要在 sts:AssumeRole 之外加上 sts:TagSession,因为 Web 应用使用会话标签(aws:PrincipalTag/AgentSpaceId)来划分访问权限。如果你手动构建那个角色却失败了,缺少 TagSession 就是原因。
附加 AWS 托管的 AIDevOpsAgentAccessPolicy 用于资源访问——只读权限,用于发现、配置和指标读取以及日志分析。操作员角色则获得 AIDevOpsOperatorAppAccessPolicy。
一个小内联策略,允许 iam:CreateServiceLinkedRole,范围限定到 Resource Explorer 服务链接角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCreateServiceLinkedRoles",
"Effect": "Allow",
"Action": ["iam:CreateServiceLinkedRole"],
"Resource": [
"arn:aws:iam::<ACCOUNT_ID>:role/aws-service-role/resource-explorer-2.amazonaws.com/AWSServiceRoleForResourceExplorer"
]
}
]
}
这让 Agent 能够在该账户中引导 Resource Explorer。如果跳过它,设置仍然会成功——你只是得到一个薄得多的 Topology,而且没有明显的错误告诉你原因。它附加在每个账户、每个主账户和辅助账户的每个角色上。
为什么重要:Agent 通过两种方式发现资源——通过遍历 CloudFormation 堆栈,以及通过 Resource Explorer 获取其他一切。如果你是一个 Terraform 团队,第二条路径几乎做了所有的工作,因为你的基础设施都不在 CloudFormation 中。一旦这个策略就位,Resource Explorer 基本上会自行设置,然后根据标签建立索引,所以标签不一致会导致 Topology 不一致。在恐慌之前给它一点时间:带标签的资源会在几分钟内出现,没有标签的最多可能需要两个小时。
如果你使用了控制台流程,这已经发生了——用资源访问角色创建 Agent Space 就会自动关联主账户。
如果你通过 CLI 或 IaC 来做,这是一个显式关联,需要注意的是 accountType:
aws devops-agent associate-service \
--agent-space-id <AGENT_SPACE_ID> \
--service-id aws \
--configuration '{
"aws": {
"assumableRoleArn": "arn:aws:iam::<PRIMARY_ACCOUNT_ID>:role/<AGENT_SPACE_ROLE>",
"accountId": "<PRIMARY_ACCOUNT_ID>",
"accountType": "monitor"
}
}' \
--region <REGION>
monitor 是托管 Agent Space 的主账户。source 是每个额外的账户。你会在步骤 5 中使用 source。
三个检查,可信度递增。
一 — 关联存在:
aws devops-agent list-associations \
--agent-space-id <AGENT_SPACE_ID> \
--region <REGION>
第二步——拓扑里有料。进入 Operator 访问网页应用,找到 Topology 页面,切换到 System 视图,它会显示账户和 Region 的边界。然后点击 All Resources,看是否真正发现了你的资产。这里为空意味着 Resource Explorer、标签或耐心——按这个优先级排查。
第三步——问一个只有正常连接才能回答的问题。不是"你能做什么",而是针对真实资源的具体问题:"列出这个账户里的 RDS 实例及其实例类。"如果它能返回你实际的库存,说明角色生效了。这是唯一我完全信任的检查方式,因为前两个可能通过,但智能体仍然读不到任何有用的东西。
第五步——连接额外的 AWS 账户
这是大多数真实部署最终的状态,因为应用很少只生活在一个账户里。
需要理解一个关键点——控制台流程并不明显——智能体不是在主账户里担任角色然后链到第二个账户。AWS DevOps Agent 服务主体直接在新账户里担任角色:
AWS DevOps Agent (aidevops.amazonaws.com)
│
│ sts:AssumeRole
├──────────────► DevOpsAgentRole (Secondary Account A)
│ ├── AIDevOpsAgentAccessPolicy
│ └── inline: Resource Explorer SLR
│
└──────────────► DevOpsAgentRole (Secondary Account B)
├── AIDevOpsAgentAccessPolicy
└── inline: Resource Explorer SLR
中间没有角色。限制它的是信任策略条件——同样是 aws:SourceAccount 和 aws:SourceArn 这对条件,指向主账户及其 Agent Space。
Agent Space → Capabilities 标签 → Cloud 部分 → Secondary sources → Add。给角色起个名字,控制台会给你一个信任策略和一个内联策略。把这两个带到目标账户的 IAM 控制台,创建一个自定义信任策略角色,粘贴信任策略,附加 AIDevOpsAgentAccessPolicy,角色名必须和你告诉控制台的一模一样,创建它,然后添加内联策略。回到主账户,选择 Next,确认状态显示为 Active。
能用。但对于一个授予生产环境跨账户读取权限的东西来说,剪贴板操作有点多了。
一个会浪费你二十分钟的坑
添加辅助账户的主体需要在主账户里有 iam:PassRole。
这会失败,报 HTTP 403 AccessDeniedException,指出是 iam:PassRole——即使该主体已经有了完整的 aidevops:* 权限。修复方法本身还有个陷阱:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<PRIMARY_ACCOUNT_ID>:role/*",
"Condition": {
"StringEquals": { "iam:PassedToService": "aidevops.amazonaws.com" }
}
}
]
}
Resource 必须是角色通配符。范围限定到具体角色 ARN 的策略不会通过检查——检查本身是针对通配符进行的。这和那种习惯给所有东西都限定范围的做法是反直觉的,而且你会花一段时间以为是自己 ARN 写错了。
另外:每次更新辅助账户时检查都会重新执行,不只是添加时。已连接的账户会继续工作直到下一次更新,所以这个问题可能在几周后才浮出水面。
我的 setup:一个 Agent Space,Dev 和 Prod
这是我的环境里的样子:
Organization / Management Account
│
AWS DevOps Agent Agent Space
│
┌────────┴────────┐
│ │
Development Production
Account Account
一个中心账户里放一个 Agent Space,dev 和 prod 作为辅助源连接。每个目标账户有自己的角色——不是共享的——这样权限以后可以分化,两个角色在 CloudTrail 里显示为不同主体,撤销一个环境意味着删除一个角色。
为什么用一个 Agent Space 而不是每个环境一个
我本来可以建两个。AWS 的文档实际上在往那个方向推——它把"环境隔离:将生产环境与非生产环境分开"列为创建多个 Agent Space 的理由之一。
我选一个是因为很多真实的调查不会遵守账户边界。"昨晚部署后开始的"从 dev 开始,落到 prod。"为什么 prod 在相同查询模式下表现不同?"本质上是对比。两个 Agent Space 会让我回到在两个互相看不见的工具之间做集成层的状态——这正是我想减少的问题。
附带好处:一个地方查看、一个拓扑、集成只配一次而不是每个环境配一次、添加下一个账户只需要三个 Terraform 资源而不是一个新的搭建项目。账户分离完全不受影响——dev 和 prod 仍然是独立的 AWS 账户和独立角色。
直白地说你做的权衡:operator 访问和调查数据都是按 Agent Space 作用域的,不是按连接账户的。任何能打开网页应用的人都可以询问该空间里所有账户的情况。空间内没有"dev-only operator"层级。并发也是共享的——默认值是每个 space 3 个并发调查和 10 个并发聊天调用,都可调整。
对我来说这没问题,因为网页应用访问限制在 DevOps 团队,而这个团队本来就持有生产权限。开发者没有 operator 登录。当允许调查 dev 的人和允许调查 prod 的人是同一批人时,按环境隔离保护的是组织架构中不存在的边界。
所以决策规则不是"总是分离 prod"。而是"同样的人会调查两者吗?"如果开发者在 dev 里自助调查而另一组人负责 prod,那就分开 space——隔离在那里是真正有意义的。
为什么我用 Terraform 做 IAM
通过手工剪贴板创建通向生产的跨账户信任,没有 diff 没有 review,是那种第一天正确、第九十天莫名其妙的东西。
结构是每个目标账户一个别名 provider,每个里三个资源:
provider "aws" {
alias = "dev"
region = "eu-central-1"
assume_role { role_arn = "arn:aws:iam::<DEV_ACCOUNT_ID>:role/<DEPLOY_ROLE>" }
}
provider "aws" {
alias = "prod"
region = "eu-central-1"
assume_role { role_arn = "arn:aws:iam::<PROD_ACCOUNT_ID>:role/<DEPLOY_ROLE>" }
}
locals {
agent_space_account = "<MANAGEMENT_ACCOUNT_ID>"
agent_space_arn = "arn:aws:aidevops:eu-central-1:<MANAGEMENT_ACCOUNT_ID>:agentspace/<AGENT_SPACE_ID>"
}
每个 provider 都要加别名,不要留 default。在这个配置里碰生产 IAM 时,如果有一个未加别名的 default provider,意味着任何忘记加 provider 参数的资源会悄悄落到 default 指向的地方。
data "aws_caller_identity" "dev" { provider = aws.dev }
data "aws_iam_policy" "devops_agent_access_dev" {
provider = aws.dev
name = "AIDevOpsAgentAccessPolicy"
}
resource "aws_iam_role" "devops_agent_dev" {
provider = aws.dev
name = "DevOpsAgentRole-AgentSpace-dev"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "aidevops.amazonaws.com" }
Action = "sts:AssumeRole"
Condition = {
StringEquals = {
"aws:SourceAccount" = local.agent_space_account
"aws:SourceArn" = local.agent_space_arn
}
}
}]
})
}
resource "aws_iam_role_policy_attachment" "devops_agent_access_dev" {
provider = aws.dev
role = aws_iam_role.devops_agent_dev.name
policy_arn = data.aws_iam_policy.devops_agent_access_dev.arn
}
resource "aws_iam_role_policy" "devops_agent_dev_slr" {
provider = aws.dev
name = "AllowCreateResourceExplorerServiceLinkedRole"
role = aws_iam_role.devops_agent_dev.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "AllowCreateServiceLinkedRoles"
Effect = "Allow"
Action = ["iam:CreateServiceLinkedRole"]
Resource = [
"arn:aws:iam::${data.aws_caller_identity.dev.account_id}:role/aws-service-role/resource-explorer-2.amazonaws.com/AWSServiceRoleForResourceExplorer"
]
}]
})
}
有两个细节值得照搬:
StringEquals 搭配 aws:SourceArn 而非 ArnLike 用于 agentspace/*。文档中使用通配符是因为在主角色上存在先有鸡还是先有蛋的问题——空间尚不存在。对于从账户来说它已经存在,所以应精确锁定 ARN。零成本,而且意味着明天在同一账户中由他人创建的第二个 Agent Space 无法访问生产环境。
使用 data.aws_caller_identity 而非硬编码账户 ID 来构建服务链接角色 ARN。它必须解析为角色所在账户。手写数字,未来 provider 变更会导致策略指向错误账户,引发 SLR 失败并给出毫无帮助的错误。
生产块是对 aws.prod 的三个相同资源。目前这是字面重复;当第三个账户到来时才会进行模块重构。两份复制尚不足以证明间接层的必要性。
这样做的收益:信任关系可以在 pull request 中审查,漂移可见,且有 git 历史解释生产环境为何信任一个特定的 Agent Space ARN。关联也可以用代码管理——awscc provider 有用于 agent space 及其关联的资源。
运行第一次真正的调查
两个账户连接完成后,我使用的测试是一个在事件期间真正会问的问题:"为什么昨天 14:30 左右数据库连接断开了?"
手动版本的调查:
CloudWatch 告警历史
↓
该时间窗口内的 RDS 连接 + CPU 指标
↓
CloudWatch Logs Insights 中的应用日志
↓
部署历史——有上线过吗?
↓
安全组 / 子网 / NAT——网络有变动吗?
↓
CloudTrail——有人改过配置吗?
六个地方,每个都需要我在导航到下一个之前在脑中记住上一个答案。大约二十分钟后才能得到一个假设。
智能体辅助版本是相同的调查,但数据获取被压缩了。我描述症状和时间窗口;它拉取指标,检查连接到该数据库的拓扑,如果流水线已连接则查看部署数据,并返回带有推理过程的关联图景。
你得到的是一个起始假设及其背后的证据——不是定论。有时它会命中原因。有时它会浮出一个最终被证明是巧合的相关性,而我之所以能发现只是因为我了解这个系统。它从未消除我理解连接池是什么的需要。
每一步推理都会落入不可变的智能体日志,API 调用会落入 CloudTrail。这在实践中很重要,不仅仅是为了合规:无法审计的答案就是一个在凌晨三点无法据此采取行动的答案。
在日常工作中它最有价值的地方:
RDS——CPU 峰值、连接波动、内存压力、利用率是否与实例类型匹配。优势不在于它知道我不知道的东西;而是"拉取这个时间窗口内的五个指标并告诉我有什么异常"变成了一句话而非五次控制台导航。
EKS——因为 Kubernetes 事件往往根本不是 Kubernetes 事件。一个无法访问数据库的 Pod 的问题存在于 RDS、安全组、路由表或 IAM 策略中。在一次对话中同时询问 Pod 和 AWS 端依赖关系消除了一次真实的上下文切换。如果你跟着操作有一个额外注意事项:EKS 需要在上述 IAM 角色之外再走一步——在集群上为智能体角色添加访问条目——这将在另一篇文章中介绍。
资源大小调整,谨慎使用。AWS 记录了涵盖可观测性、基础设施优化、流水线和弹性的预防性建议。当询问某东西是否看起来过大时,我将智能体作为一个输入——它快速汇总利用率情况。它不是一款自动优化工具,我仍然会交叉检查 Compute Optimizer、Cost Explorer 以及对工作负载流量形态的实际了解。
我学到的和需要关注的
我的技术栈中没有任何东西被关掉。Prometheus 和 Grafana 仍然持有我的仪表板。CloudWatch 仍然持有 AWS 原生信号。告警仍然触发,日志和追踪仍在原处,Terraform 仍然拥有基础设施,kubectl 仍然在终端中打开。智能体读取已有的东西——它是现有可观测性之上的关联层,而非替代品。把这个顺序搞反是失望的最可靠方式。
先让开发环境上线,先用起来。就像你不会在故障期间第一次测试恢复一样。
在连接生产环境之前决定谁可以打开 Web 应用,而不是之后。在共享 Agent Space 中这是控制点,因为操作员访问是按空间划分的。我通过外部 IdP 流程将操作员应用连接到我们的企业身份提供商——Microsoft Entra ID——这样访问就遵循与其他所有内容相同的目录组和 MFA 策略,而离职人员的邮箱移除也同时移除其智能体访问权限。IAM Identity Center 是另一个一等选项;带 10 分钟会话的原始 IAM 认证链接是备选方案。该设置有足够的活动部件,值得单独写一篇文章,我会在之后撰写。
日志中的 PII 是你的问题。AWS 声明 PII 不会被自动过滤,建议进行脱敏处理。如果你的应用日志包含客户数据,智能体可以在日志分析期间读取它。对于任何受监管行业的从业者,这是上线前要进行的对话,而非上线后。
考虑 Agent Space 放在哪里。我的在中央组织账户中,这很方便,但我会重新审视。AWS 自身的指导倾向于以专用账户为主账户、以应用账户作为从账户的方式,而通用的 Organizations 实践将工作负载排除在管理账户之外。从头设计,我会把它放在一个专用的工具账户中。
移除从账户不会删除 IAM 角色。清理工作由你负责——或者由 Terraform 负责,这是将其作为代码管理的又一个理由。
根据你的实际情况检查配额。默认每个 Agent Space 3 个并发调查和 10 个并发聊天调用,均可调整。每个账户每个区域 100 个 Agent Space。对大多数团队来说够用,如果有大规模规划则值得一看。
设置单个账户真正大约需要一小时,多账户设置用 Terraform 妥善完成并经过 IAM 审查可能需要两小时左右。