aitayemi/aws-devops-agent
GitHub: aitayemi/aws-devops-agent
基于 AWS DevOps Agent 与 CloudWatch 构建的跨账户自主事件响应流水线,实现多账户基础设施的自动化监控告警与 AI 辅助调查。
Stars: 0 | Forks: 0
# aws-devops-agent
使用 AWS DevOps Agent、CloudWatch Internet Monitor 和跨账户基础设施构建自主事件响应流水线
# 跨账户 CloudFormation 部署
## 账户映射
| 角色 | 账户 ID | 资源 |
|------|-----------|-----------|
| 账户 A (Web 层) | 111111111111 | EC2 httpd, ALB, Elastic IP, CloudWatch Alarms, Internet Monitor, EC2 Auto-Recovery, DevOps Agent Space |
| 账户 B (数据层) | 222222222222 | PostgreSQL RDS 16.13, VPC Peering Accepter, NAT Gateway, DevOps Agent Secondary Role, Resource Explorer |
## 架构
```
┌──────────────────────────────────────────┐ ┌──────────────────────────────────────┐
│ Account A: 111111111111 │ │ Account B: 222222222222 │
│ (Web Tier + DevOps Agent) │ │ (Data Tier) │
│ │ │ │
│ ┌────────────────────────────────────┐ │ │ ┌────────────────────────────────┐ │
│ │ EC2 (httpd) ─── t3.small │──┼────────►│──│ RDS PostgreSQL 16.13 │ │
│ │ Elastic IP (public) │ │ VPC │ │ Table: whoami → "AWS Rocks" │ │
│ │ Ports 80/443/22 open │ │ Peering │ │ Parameter Group: MD5 auth │ │
│ └────────────────────────────────────┘ │ │ └────────────────────────────────┘ │
│ │ │ │
│ ┌────────────────────────────────────┐ │ │ ┌────────────────────────────────┐ │
│ │ ALB (internet-facing) │ │ │ │ Lambda (DB Seed) │ │
│ │ Internet Monitor (VPC) │ │ │ │ Pure Python socket/ssl │ │
│ │ Resource Explorer (AGGREGATOR) │──┼────────►│ │ SSL negotiation + MD5 auth │ │
│ │ DevOps Agent Space │ │ Source │ └────────────────────────────────┘ │
│ └────────────────────────────────────┘ │ Assoc │ │
│ │ │ ┌────────────────────────────────┐ │
│ CloudWatch Alarms (8 total): │ │ │ NAT Gateway (Lambda internet) │ │
│ • Unhealthy Hosts │ │ │ Resource Explorer (LOCAL) │ │
│ • 5xx Errors │ │ │ DevOps Agent Secondary Role │ │
│ • Status Check Failed │ │ └────────────────────────────────┘ │
│ • High CPU │ │ │
│ • Route53 Health Check │ │ │
│ • Internet Availability < 95% │ │ │
│ • Internet Performance < 95% │ │ │
│ • EC2 Auto-Recovery │ │ │
│ │ │ │ │
│ ▼ │ │ │
│ SNS ──► Email + DevOps Agent ──► AI Investigation │ │
│ EC2 Auto-Recovery ──► Automatic instance recovery │ │
└──────────────────────────────────────────┘ └──────────────────────────────────────┘
```
## 标签
所有资源都标记有:
- `auto-delete: no` — 防止自动清理
- `devops-agent-app: httpd-whoami` — 为 DevOps Agent 关联跨账户的资源
- `devops-agent-monitored: true` — 标记资源供 Agent 发现
## 完整部署计划
### 阶段 1:跨账户 IAM 信任(一次性设置)
这些角色使账户 A 能够将 stack 部署到账户 B 中并建立 VPC peering。
**步骤 1.1 — 在账户 A (111111111111) 中创建 StackSet Administration Role**
```
aws iam create-role --role-name AWSCloudFormationStackSetAdministrationRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "cloudformation.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}' --profile account-a
aws iam put-role-policy --role-name AWSCloudFormationStackSetAdministrationRole \
--policy-name AssumeExecutionRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/AWSCloudFormationStackSetExecutionRole"
}]
}' --profile account-a
```
**步骤 1.2 — 在账户 B (222222222222) 中创建 StackSet Execution Role**
```
aws iam create-role --role-name AWSCloudFormationStackSetExecutionRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111111111111:root"},
"Action": "sts:AssumeRole"
}]
}' --profile account-b
aws iam attach-role-policy --role-name AWSCloudFormationStackSetExecutionRole \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--profile account-b
```
**步骤 1.3 — 在账户 B (222222222222) 中创建 VPCPeeringRole**
```
aws iam create-role --role-name VPCPeeringRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111111111111:root"},
"Action": "sts:AssumeRole"
}]
}' --profile account-b
aws iam put-role-policy --role-name VPCPeeringRole \
--policy-name AcceptVPCPeering \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"ec2:AcceptVpcPeeringConnection",
"ec2:CreateVpcPeeringConnection",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeVpcs"
],
"Resource": "*"
}]
}' --profile account-b
```
**步骤 1.4 — 验证跨账户访问**
```
aws sts assume-role \
--role-arn arn:aws:iam::222222222222:role/AWSCloudFormationStackSetExecutionRole \
--role-session-name test-cross-account \
--profile account-a
```
如果返回了临时凭证,则阶段 1 已完成。
### 阶段 2:部署 RDS(账户 B — 222222222222)
**步骤 2.1 — 部署 RDS stack**
```
aws cloudformation deploy \
--template-file rds-stack.yaml \
--stack-name whoami-rds \
--parameter-overrides \
DBMasterPassword=YourSecurePass123 \
PeerAccountId=111111111111 \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-b
```
这会创建:
- 包含私有子网的 VPC (10.1.0.0/16)
- PostgreSQL 16.13 RDS 实例(db.t3.micro,无备份,DeletionPolicy: Delete)
- 带有 `password_encryption=md5` 的 DB Parameter Group(为了兼容 Lambda 所需)
- 将 "AWS Rocks" 种子数据写入 `whoami` 表的 Lambda 函数(纯 Python,无外部 layer)
- 用于 Lambda 访问互联网的 NAT Gateway(cfnresponse callback)
- 允许来自 Web VPC CIDR 和 Lambda SG 的 PostgreSQL 流量的安全组
**步骤 2.2 — 记录输出**
```
aws cloudformation describe-stacks \
--stack-name whoami-rds \
--query 'Stacks[0].Outputs' \
--output table \
--region us-east-1 \
--profile account-b
```
保存这些值以供阶段 3 使用:
- `RDSEndpoint` — 例如 `production-whoami-db.xxxx.us-east-1.rds.amazonaws.com`
- `VpcId` — 例如 `vpc-0abc123`
- `PrivateRouteTableId` — 例如 `rtb-0def456`
### 阶段 3:部署 Web 服务器(账户 A — 111111111111)
**步骤 3.1 — 查找或创建 EC2 密钥对**
```
# 列出现有密钥对
aws ec2 describe-key-pairs --query 'KeyPairs[*].KeyName' --output table \
--region us-east-1 --profile account-a
# 或者创建一个新的
aws ec2 create-key-pair --key-name devops-agent-keypair \
--query 'KeyMaterial' --output text \
--region us-east-1 --profile account-a > ~/devops-agent-keypair.pem
chmod 400 ~/devops-agent-keypair.pem
```
**步骤 3.2 — 部署 Web stack**
```
aws cloudformation deploy \
--template-file web-stack.yaml \
--stack-name whoami-web \
--parameter-overrides \
RDSEndpoint= \
DBPassword=YourSecurePass123 \
KeyPairName=devops-agent-keypair \
PeerVpcId= \
PeerAccountId=222222222222 \
PeerRoleArn=arn:aws:iam::222222222222:role/VPCPeeringRole \
DevOpsAgentEmail=your-email@example.com \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-a
```
这会创建:
- 包含公有子网和 Internet Gateway 的 VPC (10.0.0.0/16)
- 位于公有子网中带有 httpd 的 EC2 实例 (t3.small)
- Elastic IP(稳定的公有地址)
- 安全组:入向开放端口 80, 443, 22,来源为 0.0.0.0/0
- Application Load Balancer (面向互联网)
- 到账户 B 的 VPC Peering 连接(使用 VPCPeeringRole)
- CloudWatch Internet Monitor(监控到 VPC 的互联网路径质量)
- 用于 Internet Monitor 日志的 S3 存储桶(DeletionPolicy: Delete,30天过期)
- 8 个 CloudWatch Alarms → SNS topic(包含 EC2 Auto-Recovery 告警)
- Route 53 Health Check
- Incident Manager IAM 角色(遗留 — 响应计划已被注释掉,见下方注释)
**步骤 3.3 — 记录输出**
```
aws cloudformation describe-stacks \
--stack-name whoami-web \
--query 'Stacks[0].Outputs' \
--output table \
--region us-east-1 \
--profile account-a
```
保存:
- `VPCPeeringConnectionId` — 例如 `pcx-0abc123`
- `WebsiteURL` — 例如 `http://production-web-alb-xxxx.us-east-1.elb.amazonaws.com`
- `WebServerPublicIP` — 例如 `54.x.x.x`
- `WebServerDirectURL` — 例如 `http://54.x.x.x`
### 阶段 4:完成 VPC Peering(账户 B — 222222222222)
**步骤 4.1 — 接受 VPC peering 连接**
```
aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id \
--region us-east-1 \
--profile account-b
```
**步骤 4.2 — 部署 peering accepter stack(添加返回路由)**
```
aws cloudformation deploy \
--template-file vpc-peering-accepter.yaml \
--stack-name whoami-peering \
--parameter-overrides \
VPCPeeringConnectionId= \
RDSRouteTableId= \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-b
```
**步骤 4.3 — 验证连通性**
通过 ALB 测试:
```
curl http:///health
# 预期:OK
curl http:///
# 预期:带有 "AWS Rocks" 的 HTML 页面
```
通过 EC2 公网 IP 直接测试:
```
curl http:///health
# 预期:OK
```
### 阶段 5:部署 DevOps Agent(两个账户)
**步骤 5.1 — 在账户 B (222222222222) 中部署辅助账户角色**
```
aws cloudformation deploy \
--template-file devops-agent-service-account.yaml \
--stack-name DevOpsAgentServiceAccountStack \
--parameter-overrides \
MonitoringAccountId=111111111111 \
AgentSpaceArn='arn:aws:aidevops:us-east-1:111111111111:agentspace/*' \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-b
```
这会创建:
- Resource Explorer LOCAL index(启用账户 B 中的资源发现)
- 具有针对 RDS、VPC、Lambda、CloudWatch、CloudFormation、tags 权限的跨账户 IAM 角色
**步骤 5.2 — 在账户 A (111111111111) 中部署 DevOps Agent Space**
```
aws cloudformation deploy \
--template-file devops-agent-stack.yaml \
--stack-name DevOpsAgentStack \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-a
```
这会创建:
- Resource Explorer AGGREGATOR index(集中资源发现)
- 带有 Operator App 的 DevOps Agent Space
- Monitor 关联(账户 A 资源)
- Source 关联(账户 B 资源)
- 具有对 EC2、ALB、CloudWatch、Route53、SSM、CloudFormation、SNS、Incident Manager、tags、Resource Explorer 完全读取权限的 IAM 角色
**步骤 5.3 — 记录 Agent Space 输出**
```
aws cloudformation describe-stacks \
--stack-name DevOpsAgentStack \
--query 'Stacks[0].Outputs' \
--output table \
--region us-east-1 \
--profile account-a
```
保存:
- `AgentSpaceId`
- `AgentSpaceArn`
**步骤 5.4 — (推荐)使用确切的 ARN 收紧账户 B 角色**
```
aws cloudformation deploy \
--template-file devops-agent-service-account.yaml \
--stack-name DevOpsAgentServiceAccountStack \
--parameter-overrides \
MonitoringAccountId=111111111111 \
AgentSpaceArn= \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-b
```
**步骤 5.5 — 验证 DevOps Agent**
```
# 列出 agent 空间
aws devops-agent list-agent-spaces \
--region us-east-1 \
--profile account-a
# 验证两个关联(monitor + source)
aws devops-agent list-associations \
--agent-space-id \
--region us-east-1 \
--profile account-a
```
您应该会看到两个关联:
- `monitor` — 账户 A (111111111111)
- `source` — 账户 B (222222222222)
**步骤 5.6 — 访问 DevOps Agent Operator App**
在浏览器中打开:
```
https://us-east-1.console.aws.amazon.com/devops-agent/home?region=us-east-1
```
Agent 的资源树应显示来自两个账户的资源:
- 账户 A:EC2, ALB, Elastic IP, CloudWatch Alarms, Route53 Health Checks, SNS, Internet Monitor
- 账户 B:RDS PostgreSQL, VPC, Lambda, NAT Gateway, DB Parameter Group
### 阶段 6:确认端到端连通性
**步骤 6.1 — 确认 SNS 订阅**
检查您的电子邮件以获取 SNS 订阅确认,并点击其中的链接。
**步骤 6.2 — 验证 Internet Monitor 是否在收集数据**
```
aws internetmonitor get-monitor \
--monitor-name production-httpd-internet-monitor \
--region us-east-1 \
--profile account-a
```
状态应为 `ACTIVE`。数据收集将在 15-30 分钟内开始。
**步骤 6.3 — 测试告警(可选)**
停止 EC2 实例以触发告警:
```
INSTANCE_ID=$(aws cloudformation describe-stacks \
--stack-name whoami-web \
--query 'Stacks[0].Outputs[?OutputKey==`InstanceId`].OutputValue' \
--output text --region us-east-1 --profile account-a)
aws ec2 stop-instances --instance-ids $INSTANCE_ID \
--region us-east-1 --profile account-a
```
在 2-3 分钟内:
1. CloudWatch Alarms 转换为 ALARM 状态
2. Composite alarm 触发 → Lambda 调用 → DevOps Agent 调查开始
3. SNS 向您的电子邮件发送通知
4. EC2 Auto-Recovery 告警触发自动实例恢复(在系统状态检查失败时)
重启实例:
```
aws ec2 start-instances --instance-ids $INSTANCE_ID \
--region us-east-1 --profile account-a
```
### 阶段 7(可选):部署 Webhook Lambda 用于自动 DevOps Agent 调查
此阶段部署一个 Lambda 函数和 Composite alarm,只要任何 httpd 告警触发,就会自动触发 DevOps Agent 调查。
**步骤 7.1 — 部署 Webhook Lambda Stack**
```
aws cloudformation deploy \
--template-file devops-agent-webhook-lambda.yaml \
--stack-name devops-agent-webhook \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1 \
--profile account-a
```
这会创建:
- 接收告警事件并将 HMAC 签名的 payload 发送到 DevOps Agent Webhook 的 Lambda 函数
- 具有 CloudWatch 读取权限的 IAM 角色
- 允许 CloudWatch Alarms 调用它的 Lambda 权限
- 监控所有 8 个 httpd 告警并在任何一个进入 ALARM 状态时触发 Lambda 的 Composite alarm
**步骤 7.2 — 验证 Composite alarm 是否存在**
```
aws cloudwatch describe-alarms \
--alarm-names production-devops-agent-investigation-trigger \
--region us-east-1 \
--profile account-a
```
**步骤 7.3 — 测试:触发告警并检查 DevOps Agent App**
当任何告警触发时,Composite alarm 触发 → Lambda 发送 Webhook → 调查任务在 1-2 分钟内出现在 DevOps Agent Operator App 中。
## 文件参考
| 文件 | 部署至 | 阶段 | 用途 |
|------|-----------|-------|---------|
| `setup-cross-account-roles.sh` | 两者 | 1 | 用于 IAM 角色设置的交互式脚本(包含 VPCPeeringRole) |
| `rds-stack.yaml` | 账户 B (222222222222) | 2 | PostgreSQL RDS 16.13 + whoami 表 ("AWS Rocks") + VPC + NAT + Parameter Group (MD5) |
| `web-stack.yaml` | 账户 A (111111111111) | 3 | httpd EC2 + EIP + ALB + 8 个 Alarms + Internet Monitor + EC2 Auto-Recovery + Incident Manager IAM 角色(遗留) |
| `vpc-peering-accepter.yaml` | 账户 B (222222222222) | 4 | 接受 peering + 返回路由 + VPCPeeringRole 定义 |
| `devops-agent-service-account.yaml` | 账户 B (222222222222) | 5 | 跨账户角色 + DevOps Agent 的 Resource Explorer (LOCAL) |
| `devops-agent-stack.yaml` | 账户 A (111111111111) | 5 | Agent Space + 关联 + Resource Explorer (AGGREGATOR) |
| `devops-agent-webhook-lambda.yaml` | 账户 A (111111111111) | 7 | Lambda + Composite alarm,用于在告警时触发 DevOps Agent 调查 |
| `stackset-deployment.yaml` | 管理账户 | 替代方案 | 替代方案:通过 StackSets 从一个账户进行部署 |
## 监控摘要
| # | 告警 | 监控内容 | 触发条件 |
|---|-------|----------------|---------|
| 1 | ALB Unhealthy Hosts | httpd 未响应 ALB health checks | > 0 个不健康,持续 2 分钟 |
| 2 | ALB 5xx Errors | 来自 httpd 的服务器错误 | 5 分钟内 > 10 个错误 |
| 3 | EC2 Status Check | 实例硬件/软件故障 | 任何故障持续 2 分钟 |
| 4 | EC2 CPU | 资源耗尽 | > 80%,持续 10 分钟 |
| 5 | Route53 Health Check | 外部 HTTP 可达性 | 连续 3 次失败 |
| 6 | Internet Monitor Availability | 影响用户的 ISP/路由问题 | 得分 < 95%,持续 10 分钟 |
| 7 | Internet Monitor Performance | 面向用户的延迟下降 | 得分 < 95%,持续 10 分钟 |
| 8 | EC2 Auto-Recovery | 系统状态检查失败(硬件) | > 0,持续 2 × 60s |
所有告警 → SNS → 电子邮件通知
所有告警 → Composite alarm → Lambda → DevOps Agent Webhook → 自动调查
EC2 Auto-Recovery 告警 → 通过 `arn:aws:automate:REGION:ec2:recover` 自动恢复 EC2
## 清理(反向顺序)
```
# 阶段 7 — Webhook Lambda(如果已部署)
aws cloudformation delete-stack --stack-name devops-agent-webhook \
--region us-east-1 --profile account-a
aws cloudformation wait stack-delete-complete --stack-name devops-agent-webhook \
--region us-east-1 --profile account-a
# 阶段 5 — DevOps Agent
aws cloudformation delete-stack --stack-name DevOpsAgentStack \
--region us-east-1 --profile account-a
aws cloudformation wait stack-delete-complete --stack-name DevOpsAgentStack \
--region us-east-1 --profile account-a
aws cloudformation delete-stack --stack-name DevOpsAgentServiceAccountStack \
--region us-east-1 --profile account-b
aws cloudformation wait stack-delete-complete --stack-name DevOpsAgentServiceAccountStack \
--region us-east-1 --profile account-b
# 阶段 4 — VPC Peering
aws cloudformation delete-stack --stack-name whoami-peering \
--region us-east-1 --profile account-b
aws cloudformation wait stack-delete-complete --stack-name whoami-peering \
--region us-east-1 --profile account-b
# 阶段 3 — Web 服务器(删除 Elastic IP、Internet Monitor、S3 日志 bucket)
aws cloudformation delete-stack --stack-name whoami-web \
--region us-east-1 --profile account-a
aws cloudformation wait stack-delete-complete --stack-name whoami-web \
--region us-east-1 --profile account-a
# 阶段 2 — RDS(无最终快照 — BackupRetentionPeriod=0、DeletionPolicy=Delete)
aws cloudformation delete-stack --stack-name whoami-rds \
--region us-east-1 --profile account-b
aws cloudformation wait stack-delete-complete --stack-name whoami-rds \
--region us-east-1 --profile account-b
# 阶段 1 — IAM Roles(可选,手动清理)
aws iam delete-role-policy --role-name VPCPeeringRole --policy-name AcceptVPCPeering --profile account-b
aws iam delete-role --role-name VPCPeeringRole --profile account-b
aws iam delete-role-policy --role-name AWSCloudFormationStackSetAdministrationRole --policy-name AssumeExecutionRole --profile account-a
aws iam delete-role --role-name AWSCloudFormationStackSetAdministrationRole --profile account-a
aws iam detach-role-policy --role-name AWSCloudFormationStackSetExecutionRole --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --profile account-b
aws iam delete-role --role-name AWSCloudFormationStackSetExecutionRole --profile account-b
```
## DevOps Agent 支持的区域
us-east-1, us-west-2, ap-southeast-2, ap-northeast-1, eu-central-1, eu-west-1
## 故障排除
| 问题 | 原因 | 修复 |
|-------|-------|-----|
| Web stack 失败:“VPCPeeringRole does not exist” | 在阶段 3 之前未创建 VPCPeeringRole | 在账户 B 中手动创建该角色(阶段 1,步骤 1.3) |
| RDS Lambda 种子注入失败:“Unsupported auth type: 10” (SASL/SCRAM) | Parameter Group 未使用 MD5 | 已修复 — 模板包含 `password_encryption=md5` Parameter Group |
| RDS Lambda 种子注入失败:“Unsupported auth type: 1397113172” | 在认证前未处理 SSL 协商 | 已修复 — Lambda 在启动消息之前发送 SSLRequest |
| RDS Lambda 种注入超时 | Lambda 无法连接到 CloudWatch endpoint | 已修复 — 添加了 NAT Gateway 以供 Lambda 访问互联网 |
| Lambda layer AccessDenied | 跨账户 layer 访问被拒绝 | 已修复 — 无外部 layer,纯 Python socket/ssl 实现 |
| VPC peering 显示 “pending-acceptance” | 账户 B 中未接受 Peering | 运行阶段 4 步骤 4.1 进行接受 |
| DevOps Agent 无法查看账户 B 资源 | 缺少 Resource Explorer index | 验证阶段 5.1 是否成功部署 |
| 告警未触发 | SNS 订阅未确认 | 确认 SNS 订阅电子邮件(阶段 6.1) |
| httpd 显示 “Error connecting to database” | VPC peering 未完成 | 完成阶段 4(接受 + 返回路由) |
| 无法通过 IP 直接访问 EC2 | 安全组或 EIP 问题 | 检查 EC2 SG 是否允许来自 0.0.0.0/0 的 80/443 流量;验证 EIP 关联 |
| Internet Monitor 显示无数据 | 刚创建 | 创建后等待 15-30 分钟进行初始数据收集 |
| Web stack 重新部署失败:“already exists” | 资源上有显式的 Name/RoleName | 已修复 — ALB/角色不再具有显式的 Name 属性 |
| Incident Manager 响应计划失败 | 没有 replication set | 对于新客户,Incident Manager 已弃用(2025年11月)。请改用 EC2 Auto-Recovery 告警。仅对在弃用前已在使用它的账户可用。 |
| `whoami` 页面显示错误文本 | 种子数据不匹配 | 预期值为 “AWS Rocks” — 如有需要请重新部署 rds-stack |
标签:AWS, DPI, 云基础设施, 响应自动化, 自动化运维