duyluann/aws-devops-agent-demo
GitHub: duyluann/aws-devops-agent-demo
一套生产就绪的 AWS 基础设施测试平台,用于模拟真实故障场景并验证 DevOps AI Agent 的事件检测与响应能力。
Stars: 0 | Forks: 0
# AWS DevOps Agent 演示




一个生产就绪的 AWS 基础设施平台,旨在**测试和验证 DevOps AI Agent 的事件响应能力**。该演示环境通过快速的 CloudWatch 警报、自动恢复机制和全面的监控来模拟真实世界的基础设施事件——非常适合训练和验证 AI 驱动的自动化 Agent。
## 功能特性
- **交互式仪表板**:基于 Python 的 Web 应用程序,支持一键式事件模拟
- **6 种事件类型**:不健康主机、崩溃、响应缓慢、5xx 泛洪和关机
- **快速警报**:10 秒 CloudWatch 评估周期,用于快速事件检测(2-4 分钟)
- **自动恢复**:内置 5 分钟恢复计时器,自动恢复健康状态
- **成本优化**:Auto-shutdown Lambda 在 2 小时后停止实例,每月节省 $50-100
- **GitHub Actions 集成**:通过 CI/CD 工作流自动触发事件
## 目录
1. [快速入门](#quick-start)
2. [架构](#architecture)
3. [Web 应用程序](#the-web-application)
4. [事件模拟](#incident-simulation)
5. [监控与警报](#monitoring--alarms)
6. [DevOps Agent 集成](#devops-agent-integration)
7. [基础设施详情](#infrastructure-details)
8. [开发](#development)
9. [进阶主题](#advanced-topics)
10. [文档索引](#documentation-index)
11. [技术参考](#technical-reference)
## 快速入门
在 5 分钟内启动演示基础设施。
### 前置条件
- 已配置凭证的 AWS 账户
- Terraform >= 1.0([安装指南](https://learn.hashicorp.com/tutorials/terraform/install-cli))
### 部署
```
# 1. 克隆仓库
git clone
cd aws-devops-agent-demo
# 2. 初始化 Terraform
terraform init
# 3. 部署到 dev 环境
terraform apply -var-file=environments/dev/dev.tfvars
# 4. 获取应用 URL
terraform output -raw alb_url
```
### 首次事件测试
```
# 获取您的 ALB URL
ALB_URL=$(terraform output -raw alb_url)
# 通过仪表板触发不健康主机事件
open ${ALB_URL} # Opens interactive dashboard in browser
# 或通过 curl 触发
curl "${ALB_URL}/simulate/unhealthy"
# 检查 CloudWatch 警报 (应在 2-3 分钟内触发)
# 系统将在 5 分钟内自动恢复
```
## 架构
该基础设施创建了一个完整的测试环境,包含 Application Load Balancer、EC2 实例、CloudWatch 监控和自动恢复机制。
```
graph TB
Internet[Internet Users]
ALB[Application Load Balancer
Port 80] EC2_1[EC2 Instance #1
Python Web App
Port 80] EC2_2[EC2 Instance #2
Python Web App
Port 80] CW[CloudWatch Alarms
10-second periods] Lambda[Auto-Shutdown Lambda
2-hour timer] Internet -->|HTTP Requests| ALB ALB -->|Health Checks| EC2_1 ALB -->|Health Checks| EC2_2 EC2_1 -->|Custom Metrics
HealthStatus, Incidents| CW EC2_2 -->|Custom Metrics
HealthStatus, Incidents| CW Lambda -.->|Stop Instances
Cost Savings| EC2_1 Lambda -.->|Stop Instances
Cost Savings| EC2_2 subgraph VPC["VPC (10.0.0.0/16)"] ALB subgraph PublicSubnets["Public Subnets (Multi-AZ)"] EC2_1 EC2_2 end end style CW fill:#FF9900,color:#fff style Lambda fill:#FF9900,color:#fff style ALB fill:#0066CC,color:#fff style EC2_1 fill:#0066CC,color:#fff style EC2_2 fill:#0066CC,color:#fff ``` ### 组件 | 组件 | 描述 | 用途 | |-----------|-------------|---------| | **VPC** | 10.0.0.0/16 网络 | 隔离的网络环境 | | **Application Load Balancer** | 面向互联网的 ALB | 路由流量,健康检查 | | **EC2 实例** | t3.micro(默认 2 个) | 运行 Python Web 应用程序 | | **Python Web App** | 端口 80 上的 HTTP 服务器 | 模拟端点,指标 | | **CloudWatch 警报** | 10 秒评估周期 | 快速事件检测 | | **Auto-Shutdown Lambda** | 每 2 小时运行一次 | 节省空闲演示的成本 | | **IAM 角色** | EC2 实例配置文件 | CloudWatch 指标,SSM 访问 | ### 网络架构 - **公有子网**:多可用区部署以实现高可用性 - **互联网网关**:ALB 的直接互联网访问 - **安全组**:ALB(端口 80 入站) → EC2(仅允许来自 ALB 的端口 80 流量) - **路由表**:指向互联网网关的公有路由 ### 关键文件 - **main.tf**:VPC、ALB、EC2 实例、网络 - **monitoring.tf**:CloudWatch 警报(第 5-77 行) - **auto_shutdown.tf**:用于成本优化的 Lambda 函数(第 20-96 行) - **templates/userdata.sh.tpl**:Python 应用程序安装 ## Web 应用程序 一个在端口 80 上作为 systemd 服务运行的 Python 3.12 HTTP 服务器,提供交互式仪表板和用于事件测试的模拟端点。 ### 概述 - **技术**:Python 3 内置 `http.server` 模块 - **部署**:具有自动重启功能的 Systemd 服务 - **指标**:通过 boto3 发布 CloudWatch 自定义指标 - **自动恢复**:用于自动健康恢复的 5 分钟计时器 ### 交互式仪表板 访问您的 ALB URL 处的仪表板以: - 查看实时健康状态 - 监控实例信息(ID,环境) - 使用一键按钮触发事件 - 查看所有可用的 API 端点 - 每 5 秒自动刷新 ### 模拟端点 | 端点 | 方法 | 描述 | 自动恢复 | |----------|--------|-------------|---------------| | `/simulate/unhealthy` | GET | 健康检查失败(返回 503) | 5 分钟 | | `/simulate/healthy` | GET | 恢复健康状态(返回 200) | 不适用 | | `/simulate/crash` | GET | 10 秒后崩溃应用程序 | systemd 重启 | | `/simulate/slow-health` | GET | 触发响应缓慢/超时 | 5 分钟 | ### 健康检查端点 **`GET /health`** - ALB 健康检查端点 **响应**: - **200 OK**:`{"status": "healthy"}` - 实例健康 - **503 Service Unavailable**:`{"status": "unhealthy", "reason": "..."}` - 健康检查失败 ALB 健康检查配置: - **间隔**:30 秒 - **超时**:5 秒 - **健康阈值**:连续 2 次成功 - **不健康阈值**:连续 2 次失败 ### CloudWatch 指标 应用程序每 60 秒发布一次自定义指标: | 指标 | 值 | 用途 | |--------|--------|---------| | **HealthStatus** | 1.0(健康)/ 0.0(不健康) | 跟踪随时间变化的健康状态 | | **IncidentSimulations** | 计数 | 跟踪事件触发频率 | **命名空间**:`CustomApp/HealthDemo` **维度**:InstanceId, Environment, IncidentType ### 自动恢复功能 当触发 unhealthy 或 slow-health 事件时,应用程序会自动安排恢复: - **延迟**:300 秒(5 分钟) - **操作**:恢复 `healthy = true` 状态 - **取消**:调用 `/simulate/healthy` 可取消待处理的恢复 - **指标**:将更新的健康状态发布到 CloudWatch - **日志**:所有恢复事件记录到 `/var/log/user-data.log` 这允许在没有手动干预的情况下测试 Agent 检测和响应。 ### 实现细节 **源码**:`templates/userdata.sh.tpl`(第 33-650 行) **关键特性**: - Python 3.12 配合 boto3 作为 AWS SDK - 多线程:主 HTTP 服务器 + 后台指标发布器 - CloudWatch API 失败的优雅错误处理 - IMDSv2 用于安全的实例元数据检索 - Systemd 服务在崩溃时自动重启 **Systemd 服务**: ``` # 检查服务状态 sudo systemctl status webapp # 查看日志 sudo journalctl -u webapp -f # 重启服务 sudo systemctl restart webapp ``` ## 事件模拟 通过 6 种真实的故障场景测试 DevOps Agent 的事件响应能力。 ### 概述 可以通过以下方式触发事件: 1. **交互式仪表板**:Web UI 中的一键按钮 2. **直接 API**:对 ALB URL 执行 curl 命令 3. **GitHub Actions**:自动化工作流(`.github/workflows/trigger-incidents.yml`) 4. **AWS SSM**:直接向实例发送命令 所有事件都会在 2-4 分钟内生成 CloudWatch 警报,用于快速的 Agent 测试。 ### 事件类型 #### 1. 不健康主机 (`unhealthy_host`) **行为**:单个实例健康检查失败 **触发**:`unhealthy-hosts` 警报(UnHealthyHostCount ≥ 1) **预期警报时间**:2-3 分钟 **自动恢复**:5 分钟 **用例**:测试单主机故障检测和恢复 ``` # 通过 API curl "${ALB_URL}/simulate/unhealthy" # 通过 GitHub Actions gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=unhealthy_host ``` #### 2. 所有主机不健康 (`unhealthy_all`) **行为**:所有实例同时健康检查失败 **触发**:`unhealthy-hosts` 警报(UnHealthyHostCount ≥ instance_count) **预期警报时间**:2-3 分钟 **自动恢复**:5 分钟 **用例**:测试完全服务中断检测 ``` # 通过 GitHub Actions (需要 SSM) gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=unhealthy_all ``` #### 3. 应用程序崩溃 (`crash_instance`) **行为**:应用程序在 10 秒后以代码 1 退出 **触发**:`unhealthy-hosts` 警报(systemd 在约 5 秒后重启应用) **预期警报时间**:2-4 分钟 **自动恢复**:systemd 自动重启 **用例**:测试应用程序崩溃检测和 systemd 恢复 ``` # 通过 API curl "${ALB_URL}/simulate/crash" # 注意:应用响应 "will crash in 10 seconds" 然后退出 ``` #### 4. 健康检查缓慢 (`slow_health`) **行为**:健康端点变得无响应/缓慢 **触发**:`high-response-time` 警报(TargetResponseTime > 2s) **预期警报时间**:2-3 分钟 **自动恢复**:5 分钟 **用例**:测试性能下降检测 ``` # 通过 API curl "${ALB_URL}/simulate/slow-health" ``` #### 5. 关闭实例 (`shutdown_instances`) **行为**:Lambda 函数停止所有 EC2 实例 **触发**:所有警报(不健康主机、响应时间、5xx) **预期警报时间**:3-5 分钟 **自动恢复**:手动(需要 `aws ec2 start-instances`) **用例**:测试基础设施关闭检测 **要求**:`enable_auto_shutdown = true` ``` # 通过 GitHub Actions gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=shutdown_instances ``` #### 6. HTTP 5xx 错误泛洪 (`http_5xx_flood`) **行为**:生成 15 个并发的 HTTP 503 错误 **触发**:`5xx-errors` 警报(HTTPCode_Target_5XX_Count > 10) **预期警报时间**:2-3 分钟 **自动恢复**:无(错误是瞬态的) **用例**:测试错误率激增检测 ``` # 通过 API (生成多个请求) for i in {1..15}; do curl -s "${ALB_URL}/simulate/unhealthy" & done wait ``` ### GitHub Actions 工作流 用于自动化、可重复的事件测试,具有警报监控和自动恢复功能。 **文件**:`.github/workflows/trigger-incidents.yml` **功能**: - 通过 Terraform 输出自动发现基础设施 - 预检健康检查 - CloudWatch 警报状态监控 - 可选的自动恢复,具有可配置的延迟 - 详细的执行摘要及时间线 **示例用法**: ``` # 通过 GitHub CLI 触发工作流 gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=unhealthy_host \ -f target_instance_index=0 \ -f restore_after_incident=true \ -f restore_delay_seconds=300 \ -f wait_for_alarm=true ``` 有关全面的工作流文档,请参阅 [.github/workflows/README-incidents.md](.github/workflows/README-incidents.md)。 ### 通过 SSM 运行事件 用于在没有 SSH 的情况下直接访问实例: ``` # 获取实例 ID INSTANCE_ID=$(terraform output -json instance_ids | jq -r '.[0]') # 通过 SSM 触发不健康状态 aws ssm send-command \ --instance-ids ${INSTANCE_ID} \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["curl http://localhost/simulate/unhealthy"]' # 恢复健康状态 aws ssm send-command \ --instance-ids ${INSTANCE_ID} \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["curl http://localhost/simulate/healthy"]' ``` ## 监控与警报 为快速事件检测设计的快速 CloudWatch 警报(10 秒评估周期)。 ### CloudWatch 警报 **配置**:`monitoring.tf`(当 `enable_monitoring = true` 时启用) | 警报名称 | 指标 | 阈值 | 周期 | 评估 | 预期触发时间 | |------------|--------|-----------|--------|------------|----------------------| | **unhealthy-hosts** | UnHealthyHostCount | ≥ 1 | 10 秒 | 1 个周期 | 2-3 分钟 | | **high-response-time** | TargetResponseTime | > 2 秒 | 10 秒 | 1 个周期 | 2-3 分钟 | | **5xx-errors** | HTTPCode_Target_5XX_Count | > 10 | 10 秒 | 1 个周期 | 2-3 分钟 | **命名空间**:`AWS/ApplicationELB` **维度**:TargetGroup, LoadBalancer ### 为什么使用 10 秒周期? 传统的 CloudWatch 警报使用 60-300 秒的周期。此演示使用 **10 秒周期** 以实现: - **更快的检测**:警报在 2-3 分钟内触发,而不是 5-10 分钟 - **更好的 Agent 测试**:AI Agent 验证的快速反馈循环 - **逼真的演示**:保持测试会话简短且互动 **权衡**:较高的 CloudWatch API 成本(约 $0.10/警报/月)。对于生产环境,请使用 60-300 秒的周期。 ### 自定义指标 由 Python 应用程序每 60 秒发布一次: **命名空间**:`CustomApp/HealthDemo` | 指标 | 值 | 用例 | |--------|--------|----------| | **HealthStatus** | 1.0 / 0.0 | 随时间跟踪应用程序健康状况 | | **IncidentSimulations** | 按类型计数 |监控事件测试频率 | **查询示例**: ``` aws cloudwatch get-metric-statistics \ --namespace CustomApp/HealthDemo \ --metric-name HealthStatus \ --dimensions Name=Environment,Value=dev \ --start-time 2026-01-24T00:00:00Z \ --end-time 2026-01-24T23:59:59Z \ --period 300 \ --statistics Average ``` ### Agent 测试的监控最佳实践 1. **首先建立基线**:部署基础设施并观察正常指标 10 分钟 2. **记录时间线**:记录事件触发 → 警报转换时间 3. **一次测试一种类型**:隔离变量以进行准确的 Agent 验证 4. **使用自动恢复**:用于可重复的自动化测试 5. **禁用自动恢复**:在验证 Agent 修复操作时 6. **监控 CloudWatch 成本**:10 秒周期会增加 API 使用量 ### 查看警报 ``` # 列出所有警报 aws cloudwatch describe-alarms \ --query 'MetricAlarms[*].[AlarmName,StateValue]' \ --output table # 获取特定警报状态 ALARM_NAME=$(terraform output -json cloudwatch_alarm_names | jq -r '.unhealthy_hosts') aws cloudwatch describe-alarms --alarm-names ${ALARM_NAME} # 查看警报历史 aws cloudwatch describe-alarm-history \ --alarm-name ${ALARM_NAME} \ --max-records 10 ``` ## DevOps Agent 集成 使用此演示基础设施配置和测试 AI 驱动的 DevOps Agent。 ### 设置 Agent 环境 #### 1. AWS 凭证(建议只读) 授予您的 Agent IAM 权限: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudwatch:DescribeAlarms", "cloudwatch:GetMetricStatistics", "ec2:DescribeInstances", "elasticloadbalancing:DescribeTargetHealth", "elasticloadbalancing:DescribeLoadBalancers", "logs:GetLogEvents" ], "Resource": "*" } ] } ``` 对于 Agent 修复测试,添加: ``` { "Effect": "Allow", "Action": [ "ssm:SendCommand", "ec2:StartInstances", "ec2:RebootInstances" ], "Resource": "*", "Condition": { "StringEquals": { "aws:RequestedRegion": "us-east-1" } } } ``` #### 2. 资源发现 配置 Agent 通过标签发现基础设施: ``` # 获取环境标签进行过滤 ENVIRONMENT=$(terraform output -raw environment_tag) # 发现 EC2 实例 aws ec2 describe-instances \ --filters "Name=tag:Environment,Values=${ENVIRONMENT}" \ --query 'Reservations[*].Instances[*].[InstanceId,State.Name,Tags[?Key==`Name`].Value|[0]]' # 获取警报名称 terraform output -json cloudwatch_alarm_names ``` **资源标签**: - `Environment`:dev/qa/prod(用于过滤) - `ManagedBy`:Terraform(自动化配置) - `Name`:描述性资源名称 #### 3. 警报配置 向 Agent 提供用于监控的警报名称: ``` terraform output cloudwatch_alarm_names # 示例输出: # { # "unhealthy_hosts": "dev-devops-demo-unhealthy-hosts", # "high_response_time": "dev-devops-demo-high-response-time", # "http_5xx_errors": "dev-devops-demo-5xx-errors" # } ``` ### 测试事件检测工作流 **目标**:验证 Agent 可以检测和诊断事件 #### 步骤 1:触发事件 ``` # 触发不健康主机事件 curl "${ALB_URL}/simulate/unhealthy" echo "Incident triggered at $(date)" ``` #### 步骤 2:等待警报(2-4 分钟) ``` # 监控警报状态 ALARM_NAME=$(terraform output -json cloudwatch_alarm_names | jq -r '.unhealthy_hosts') while true; do STATE=$(aws cloudwatch describe-alarms \ --alarm-names ${ALARM_NAME} \ --query 'MetricAlarms[0].StateValue' \ --output text) echo "[$(date +%H:%M:%S)] Alarm state: ${STATE}" [ "$STATE" == "ALARM" ] && break sleep 10 done ``` #### 步骤 3:观察 Agent 检测 您的 Agent 应该: 1. **检测**:识别警报状态变化(轮询或 EventBridge) 2. **识别**:确定受影响的资源(EC2 实例、ALB 目标组) 3. **诊断**:将警报与健康检查失败相关联 4. **提议**:建议修复操作 #### 步骤 4:验证建议的修复 **预期的 Agent 输出**: ``` Incident Detected: Unhealthy Host Alarm - Alarm: dev-devops-demo-unhealthy-hosts - Metric: UnHealthyHostCount = 1 - Affected Instance: i-0123456789abcdef0 - Root Cause: Health check endpoint returning 503 Proposed Remediation: 1. Restart application: systemctl restart webapp 2. Or restore via API: curl http://localhost/simulate/healthy 3. Or wait for auto-recovery (5 minutes) ``` ### 预期的 Agent 能力 | 能力 | 描述 | 验证方法 | |------------|-------------|-------------------| | **警报检测** | 检测 CloudWatch 警报状态变化 | 触发事件,验证 Agent 日志 | | **资源关联** | 识别受影响的 EC2/ALB 资源 | 检查 Agent 是否识别正确的实例 | | **根因分析** | 诊断健康检查失败 | 验证 Agent 确定 503 响应 | | **修复提议** | 建议修复操作 | 审查提议的命令 | | **操作执行** | 执行 SSM 命令或 API 调用 | 使用读写 IAM 权限进行测试 | | **恢复验证** | 验证警报返回 OK 状态 | 确认 Agent 监控修复后状态 | ### 测试自动修复操作 对于具有修复能力的 Agent(需要 IAM 权限): #### 通过 SSM 重启应用程序 ``` # Agent 执行 INSTANCE_ID=""
aws ssm send-command \
--instance-ids ${INSTANCE_ID} \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["sudo systemctl restart webapp"]'
```
#### 通过 API 恢复健康
```
# Agent 执行
INSTANCE_ID=""
aws ssm send-command \
--instance-ids ${INSTANCE_ID} \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["curl http://localhost/simulate/healthy"]'
```
#### 启动已停止的实例
```
# 对于 shutdown_instances 事件
INSTANCE_IDS=$(terraform output -json instance_ids | jq -r '.[]')
aws ec2 start-instances --instance-ids ${INSTANCE_IDS}
```
### 验证恢复检查清单
Agent 修复后,验证:
- [ ] 警报状态恢复为 OK(在 2-3 分钟内)
- [ ] 目标健康状况在 ALB 中显示为 "healthy"
- [ ] 应用程序在 `/health` 上响应 200
- [ ] CloudWatch 指标显示 HealthStatus = 1.0
- [ ] 未触发新警报
### Agent 提示词示例
用于测试具有自然语言界面的 AI Agent:
```
You are a DevOps agent monitoring AWS infrastructure in us-east-1.
Environment: dev
Available Alarms:
- dev-devops-demo-unhealthy-hosts
- dev-devops-demo-high-response-time
- dev-devops-demo-5xx-errors
Task: Monitor CloudWatch alarms and respond to incidents.
When an alarm triggers:
1. Identify affected resources
2. Diagnose root cause
3. Propose remediation
4. Execute fix (if approved)
5. Validate recovery
Start monitoring now.
```
### 集成模式
#### 基于轮询
```
# 每 30 秒轮询 CloudWatch
while True:
alarms = cloudwatch.describe_alarms(AlarmNames=alarm_list)
for alarm in alarms['MetricAlarms']:
if alarm['StateValue'] == 'ALARM':
handle_incident(alarm)
time.sleep(30)
```
#### 事件驱动 (EventBridge)
```
{
"source": ["aws.cloudwatch"],
"detail-type": ["CloudWatch Alarm State Change"],
"detail": {
"state": {
"value": ["ALARM"]
}
}
}
```
#### 基于 API (GitHub Actions Webhook)
配置 webhook 以在工作流触发事件时通知 Agent。
## 基础设施详情
### 环境配置
三种具有不同资源配置文件的预配置环境:
| 设置 | dev | qa | prod |
|---------|-----|-----|------|
| **实例类型** | t3.micro | t3.small | t3.medium |
| **实例数量** | 2 | 2 | 3 |
| **自动关闭** | 启用(2 小时) | 启用(2 小时) | 禁用 |
| **监控** | 启用 | 启用 | 启用 |
| **SSH 访问** | 可选 | 可选 | 禁用 |
| **区域** | us-east-1 | us-east-1 | us-east-1 |
**成本估算**(启用自动关闭):
- **dev**:约 $15-20/月(每天活动 8 小时)
- **qa**:约 $25-30/月(每天活动 8 小时)
- **prod**:约 $80-100/月(始终开启,更大的实例)
### 自定义
编辑特定于环境的 tfvars 文件:
```
# environments/dev/dev.tfvars
env = "dev"
region = "us-east-1"
instance_type = "t3.micro"
instance_count = 2
enable_auto_shutdown = true
enable_monitoring = true
enable_ssh_access = false
```
**常见自定义**:
```
# 增加实例数量以进行多主机测试
instance_count = 4
# 使用更大的实例进行性能测试
instance_type = "t3.small"
# 禁用自动关闭以进行长时间运行测试
enable_auto_shutdown = false
# 启用 SSH 以直接访问实例
enable_ssh_access = true
ssh_allowed_cidrs = ["1.2.3.4/32"] # Your IP
key_pair_name = "my-key" # Existing EC2 key pair
```
应用更改:
```
terraform apply -var-file=environments/dev/dev.tfvars
```
### 成本优化
#### 自动关闭 Lambda
**文件**:`auto_shutdown.tf`
**默认启用**:dev、qa(在 prod 中禁用)
**工作原理**:
1. EventBridge 规则每 2 小时触发一次 Lambda
2. Lambda 停止环境中的所有 EC2 实例
3. 为空闲演示节省约 60% 的 EC2 成本
**手动控制**:
```
# 手动停止实例
INSTANCE_IDS=$(terraform output -json instance_ids | jq -r '.[]')
aws ec2 stop-instances --instance-ids ${INSTANCE_IDS}
# 启动实例
aws ec2 start-instances --instance-ids ${INSTANCE_IDS}
```
**禁用自动关闭**:
```
# environments/dev/dev.tfvars
enable_auto_shutdown = false
```
**成本节省示例**:
- **不使用自动关闭**:2x t3.micro × 730 小时 = $15/月
- **使用自动关闭(8 小时/天)**:2x t3.micro × 240 小时 = $5/月
- **节省**:$10/月(67%)
#### 不需要时销毁
```
# 完全移除基础设施
terraform destroy -var-file=environments/dev/dev.tfvars
```
### SSH 访问(可选)
**默认**:SSH 禁用以确保安全
**启用步骤**:
1. 在 AWS 控制台中创建 EC2 密钥对
2. 更新 tfvars:
```
enable_ssh_access = true
ssh_allowed_cidrs = ["YOUR_IP/32"]
key_pair_name = "your-key-name"
```
3. 应用更改:
```
terraform apply -var-file=environments/dev/dev.tfvars
```
4. SSH 连接到实例:
```
INSTANCE_IP=$(aws ec2 describe-instances \
--instance-ids $(terraform output -json instance_ids | jq -r '.[0]') \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text)
ssh -i ~/.ssh/your-key.pem ec2-user@${INSTANCE_IP}
```
### Terraform 状态后端
**默认**:本地状态(`.terraform/terraform.tfstate`)
**团队协作**:使用 S3 后端
更新 `versions.tf`:
```
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "aws-devops-demo/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-locks"
encrypt = true
}
}
```
创建后端资源:
```
# 创建 S3 存储桶
aws s3 mb s3://my-terraform-state-bucket --region us-east-1
# 创建 DynamoDB 表用于锁定
aws dynamodb create-table \
--table-name terraform-state-locks \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--region us-east-1
```
## 开发
### 本地设置
```
# 安装 pre-commit 钩子 (首次提交前必须执行)
pre-commit install
# 初始化 Terraform
terraform init
# 手动运行 pre-commit 检查
pre-commit run --all-files
# 验证 Terraform
terraform fmt -recursive
terraform validate
# 运行 TFLint (首次会下载 AWS 插件)
tflint --init
tflint --config=.tflint.hcl
# 运行 Checkov 安全扫描
checkov --config-file .checkov.yml
# 生成文档
terraform-docs markdown table --output-file README.md .
```
### Pre-Commit 检查
在每次提交前自动运行:
| 检查 | 目的 |
|-------|---------|
| **terraform_fmt** | 格式化 .tf 文件 |
| **terraform_validate** | 验证语法 |
| **terraform_docs** | 生成 README 文档 |
| **terraform_tflint** | 使用 AWS 规则进行 Lint |
| **terraform_checkov** | 安全扫描 |
| **gitleaks** | 机密检测 |
| **trailing-whitespace** | 修复空白字符 |
| **check-yaml** | 验证 YAML 文件 |
**配置**:`.pre-commit-config.yaml`
### CI/CD 工作流
**位置**:`.github/workflows/`
| 工作流 | 触发器 | 目的 |
|----------|---------|---------|
| **pre-commit-ci.yaml** | 拉取请求 | 运行所有质量检查 |
| **terraform-aws.yml** | 手动(workflow_dispatch) | 部署基础设施 |
| **trigger-incidents.yml** | 手动(workflow_dispatch) | 触发事件以进行测试 |
| **release.yaml** | 推送到 main | 语义版本控制和变更日志 |
### 语义提交
遵循 Conventional Commits 进行自动化版本控制:
```
# 补丁版本升级 (1.0.0 → 1.0.1)
git commit -m "fix(monitoring): correct alarm threshold"
# 次版本升级 (1.0.0 → 1.1.0)
git commit -m "feat(incidents): add new slow-response incident type"
# 主版本升级 (1.0.0 → 2.0.0)
git commit -m "feat(api): change health endpoint path
BREAKING CHANGE: health endpoint moved from /health to /api/v2/health"
# 无版本升级
git commit -m "docs: update README with new examples"
git commit -m "chore: update pre-commit hooks"
```
**类型**:
- `feat`:新功能(次版本升级)
- `fix`:Bug 修复(修订版本升级)
- `perf`:性能改进(修订版本升级)
- `refactor`:代码重构(修订版本升级)
- `docs`:仅文档(无版本升级)
- `chore`:维护任务(无版本升级)
- `test`:测试添加(无版本升级)
### 分支策略
**关键规则**:永远不要直接提交到 `main`
**工作流**:
1. 创建功能分支:`git checkout -b feat/your-feature`
2. 使用语义提交进行更改
3. 推送并创建拉取请求
4. 等待 CI/CD 检查通过
5. 通过拉取请求合并
**分支命名**:
- `feat/description` - 新功能
- `fix/description` - Bug 修复
- `chore/description` - 维护任务
### DevContainer
可用的预配置开发环境:
```
# 在 VSCode 中打开
code .
# 提示:"Reopen in Container" → 接受
# 或手动
docker-compose -f .devcontainer/docker-compose.yml up
```
**包含**:Terraform、TFLint、Checkov、AWS CLI、pre-commit
有关完整的开发指南,请参阅 [CLAUDE.md](CLAUDE.md)。
## 进阶主题
### 故障排除
#### Web App 无响应
**症状**:ALB 返回 502/503 错误,健康检查失败
**诊断**:
```
# 检查实例状态
INSTANCE_ID=$(terraform output -json instance_ids | jq -r '.[0]')
aws ec2 describe-instances --instance-ids ${INSTANCE_ID} \
--query 'Reservations[0].Instances[0].State.Name'
# 通过 SSM 检查服务状态
aws ssm send-command \
--instance-ids ${INSTANCE_ID} \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["systemctl status webapp"]'
# 查看应用日志
aws ssm send-command \
--instance-ids ${INSTANCE_ID} \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["journalctl -u webapp -n 50"]'
```
**解决方案**:
1. 重启 webapp:`systemctl restart webapp`
2. 检查 UserData 日志:`/var/log/user-data.log`
3. 验证 boto3 已安装:`python3 -c "import boto3"`
4. 如有需要重启实例
#### 警报未触发
**症状**:事件已触发但警报保持 OK
**诊断**:
```
# 检查警报配置
ALARM_NAME=$(terraform output -json cloudwatch_alarm_names | jq -r '.unhealthy_hosts')
aws cloudwatch describe-alarms --alarm-names ${ALARM_NAME}
# 检查实际指标值
aws cloudwatch get-metric-statistics \
--namespace AWS/ApplicationELB \
--metric-name UnHealthyHostCount \
--dimensions Name=TargetGroup,Value=$(terraform output -raw alb_arn | cut -d: -f6) \
--start-time $(date -u -d '10 minutes ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 \
--statistics Maximum
# 验证目标健康状态
aws elbv2 describe-target-health \
--target-group-arn $(aws elbv2 describe-target-groups \
--load-balancer-arn $(terraform output -raw alb_arn) \
--query 'TargetGroups[0].TargetGroupArn' --output text)
```
**解决方案**:
1. 等待完整的评估周期(10-60 秒)
2. 验证实例在 ALB 中确实处于不健康状态
3. 检查警报维度是否匹配资源
4. 确认 `enable_monitoring = true`
#### 自动关闭问题
**症状**:实例在 2 小时后未停止
**诊断**:
```
# 检查 Lambda 函数
LAMBDA_ARN=$(terraform output -raw auto_shutdown_lambda_arn)
aws lambda get-function --function-name ${LAMBDA_ARN}
# 检查 EventBridge 规则
aws events list-rules --name-prefix "dev-devops-demo-auto-shutdown"
# 查看 Lambda 日志
aws logs tail /aws/lambda/dev-devops-demo-auto-shutdown --follow
```
**解决方案**:
1. 手动调用 Lambda 进行测试
2. 检查 Lambda 是否具有 ec2:StopInstances 的 IAM 权限
3. 验证 EventBridge 规则已启用
4. 检查 Lambda 环境变量中的实例 ID
### 多区域部署
使用 Terraform 工作区部署到多个区域:
```
# 为 us-west-2 创建工作区
terraform workspace new us-west-2
# 更新 provider 区域
export TF_VAR_region=us-west-2
# 部署
terraform apply -var-file=environments/dev/dev.tfvars
# 切换回 us-east-1
terraform workspace select default
```
或为每个区域使用单独的状态文件:
```
# 部署到 us-east-1
terraform apply -var-file=environments/dev/dev.tfvars -var="region=us-east-1"
# 使用不同状态部署到 us-west-2
terraform apply -var-file=environments/dev/dev.tfvars -var="region=us-west-2" \
-state=terraform-us-west-2.tfstate
```
### 自定义事件类型
使用自定义事件扩展 Web 应用程序:
**文件**:`templates/userdata.sh.tpl`(第 545+ 行)
**示例**:添加数据库连接失败模拟
```
elif self.path == '/simulate/db-timeout':
health_status["healthy"] = False
health_status["reason"] = "Database connection timeout"
health_status["last_updated"] = datetime.now().isoformat()
schedule_auto_recovery(300)
publish_health_metric()
publish_incident_metric('db-timeout')
self.send_json_response(200, {
"message": "Simulating database timeout (auto-recovery in 5 minutes)"
})
```
重新部署:
```
terraform taint aws_instance.web[0] # Force UserData re-run
terraform apply -var-file=environments/dev/dev.tfvars
```
### 与外部监控集成
将 CloudWatch 警报发送到外部系统:
**SNS 主题**(添加到 `monitoring.tf`):
```
resource "aws_sns_topic" "alarms" {
name = "${local.name_prefix}-alarm-notifications"
}
resource "aws_sns_topic_subscription" "email" {
topic_arn = aws_sns_topic.alarms.arn
protocol = "email"
endpoint = "your-email@example.com"
}
# 添加到警报
resource "aws_cloudwatch_metric_alarm" "unhealthy_hosts" {
# ... existing config ...
alarm_actions = [aws_sns_topic.alarms.arn]
}
```
**Webhook 集成**:
```
resource "aws_sns_topic_subscription" "webhook" {
topic_arn = aws_sns_topic.alarms.arn
protocol = "https"
endpoint = "https://your-agent-endpoint.com/alarms"
}
```
## 文档索引
| 文档 | 目的 |
|----------|---------|
| **README.md**(本文件) | 主要文档、快速入门、架构 |
| **[CLAUDE.md](CLAUDE.md)** | 开发指南、分支策略、CI/CD |
| **[BEST-PRACTICES.md](BEST-PRACTICES.md)** | Terraform 最佳实践、安全性、性能 |
| **[.github/workflows/README-incidents.md](.github/workflows/README-incidents.md)** | 全面的事件工作流文档 |
| **[CHANGELOG.md](CHANGELOG.md)** | 版本历史和发行说明 |
| **[LICENSE](LICENSE)** | MIT 许可证条款 |
### 外部资源
- **Terraform AWS Provider**: https://registry.terraform.io/providers/hashicorp/aws/latest/docs
- **CloudWatch Alarms**: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html
- **ALB Health Checks**: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html
- **AWS SSM Session Manager**: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html
- **Semantic Commits**: https://www.conventionalcommits.org/
## 技术参考
自动生成的 Terraform 文档(由 `terraform-docs` pre-commit 钩子更新)。
## 需求
| 名称 | 版本 |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.0 |
| [archive](#requirement\_archive) | ~> 2.7 |
| [aws](#requirement\_aws) | ~> 6.28 |
## 提供商
| 名称 | 版本 |
|------|---------|
| [archive](#provider\_archive) | 2.7.1 |
| [aws](#provider\_aws) | 6..0 |
## 模块
无模块。
## 资源
| 名称 | 类型 |
|------|------|
| [aws_cloudwatch_event_rule.auto_shutdown](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | 资源 |
| [aws_cloudwatch_event_target.auto_shutdown](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | 资源 |
| [aws_cloudwatch_log_group.auto_shutdown](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | 资源 |
| [aws_cloudwatch_metric_alarm.high_response_time](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | 资源 |
| [aws_cloudwatch_metric_alarm.http_5xx_errors](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | 资源 |
| [aws_cloudwatch_metric_alarm.unhealthy_hosts](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | 资源 |
| [aws_iam_instance_profile.ec2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | 资源 |
| [aws_iam_role.ec2_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | 资源 |
| [aws_iam_role.lambda_auto_shutdown](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | 资源 |
| [aws_iam_role_policy.lambda_ec2_stop](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | 资源 |
| [aws_iam_role_policy_attachment.ec2_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | 资源 |
| [aws_iam_role_policy_attachment.ec2_ssm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | 资源 |
| [aws_iam_role_policy_attachment.lambda_basic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | 资源 |
| [aws_instance.web](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | 资源 |
| [aws_internet_gateway.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway) | 资源 |
| [aws_lambda_function.auto_shutdown](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | 资源 |
| [aws_lambda_permission.auto_shutdown](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | 资源 |
| [aws_lb.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb) | 资源 |
| [aws_lb_listener.http](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | 资源 |
| [aws_lb_target_group.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group) | 资源 |
| [aws_lb_target_group_attachment.web](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group_attachment) | 资源 |
| [aws_route.public_internet](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | 资源 |
| [aws_route_table.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | 资源 |
| [aws_route_table_association.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | 资源 |
| [aws_security_group.alb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | 资源 |
| [aws_security_group.ec2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | 资源 |
| [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | 资源 |
| [aws_vpc.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) | 资源 |
| [aws_vpc_security_group_egress_rule.alb_to_ec2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | 资源 |
| [aws_vpc_security_group_egress_rule.ec2_all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | 资源 |
| [aws_vpc_security_group_ingress_rule.alb_http](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | 资源 |
| [aws_vpc_security_group_ingress_rule.ec2_http_from_alb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | 资源 |
| [aws_vpc_security_group_ingress_rule.ec2_ssh](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | 资源 |
| [archive_file.auto_shutdown](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | 数据源 |
| [aws_ami.amazon_linux_2023](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | 数据源 |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | 数据源 |
## 输入
| 名称 | 描述 | 类型 | 默认值 | 必需 |
|------|-------------|------|---------|:--------:|
| [enable\_auto\_shutdown](#input\_enable\_auto\_shutdown) | 在 2 小时后启用实例自动关闭(演示成本节省) | `bool` | `true` | 否 |
| [enable\_monitoring](#input\_enable\_monitoring) | 为 ALB 和目标启用 CloudWatch 警报 | `bool` | `true` | 否 |
| [enable\_ssh\_access](#input\_enable\_ssh\_access) | 启用到 EC2 实例的 SSH 访问(需要 ssh\_allowed\_cidrs) | `bool` | `false` | 否 |
| [env](#input\_env) | 部署资源的环境 | `string` | `"dev"` | 否 |
| [instance\_count](#input\_instance\_count) | 要创建的 EC2 实例数量 | `number` | `2` | 否 |
| [instance\_type](#input\_instance\_type) | 演示 Web 服务器的 EC2 实例类型 | `string` | `"t3.micro"` | 否 |
| [key\_pair\_name](#input\_key\_pair\_name) | 用于 SSH 访问的 EC2 密钥对名称(可选,留空以禁用 SSH 密钥) | `string` | `""` | 否 |
| [prefix](#input\_prefix) | 所有资源名称的前缀 | `string` | `"dev"` | 否 |
| [region](#input\_region) | 部署资源的区域 | `string` | `"us-east-1"` | 否 |
| [ssh\_allowed\_cidrs](#input\_ssh\_allowed\_cidrs) | 允许 SSH 到 EC2 实例的 CIDR 块列表 | `list(string)` | `[]` | 否 |
| [vpc\_cidr](#input\_vpc\_cidr) | VPC 的 CIDR 块 | `string` | `"10.0.0.0/16"` | 否 |
## 输出
| 名称 | 描述 |
|------|-------------|
| [alb\_arn](#output\_alb\_arn) | Application Load Balancer 的 ARN |
| [alb\_dns\_name](#output\_alb\_dns\_name) | Application Load Balancer 的 DNS 名称 |
| [alb\_url](#output\_alb\_url) | 访问应用程序的 URL |
| [auto\_shutdown\_enabled](#output\_auto\_shutdown\_enabled) | 是否启用自动关闭 |
| [auto\_shutdown\_lambda\_arn](#output\_auto\_shutdown\_lambda\_arn) | 自动关闭 Lambda 函数的 ARN(如果启用) |
| [cloudwatch\_alarm\_names](#output\_cloudwatch\_alarm\_names) | 用于事件测试的警报类型到警报名称的映射 |
| [cloudwatch\_alarms](#output\_cloudwatch\_alarms) | CloudWatch 警报的名称(如果启用监控) |
| [environment](#output\_environment) | 环境名称 |
| [environment\_tag](#output\_environment\_tag) | 在 DevOps Agent Space 中用于资源发现的标签值 |
| [health\_check\_url](#output\_health\_check\_url) | 检查健康端点的 URL |
| [instance\_ids](#output\_instance\_ids) | EC2 实例的 ID |
| [instance\_private\_ips](#output\_instance\_private\_ips) | EC2 实例的私有 IP 地址 |
| [public\_subnet\_ids](#output\_public\_subnet\_ids) | 公有子网的 ID |
| [region](#output\_region) | 部署资源的 AWS 区域 |
| [resource\_prefix](#output\_resource\_prefix) | 用于资源命名的前缀 |
| [restore\_health\_command](#output\_restore\_health\_command) | 恢复健康状态的命令 |
| [trigger\_failure\_command](#output\_trigger\_failure\_command) | 触发健康检查失败的命令(通过 SSM 或 SSH 运行) |
| [vpc\_id](#output\_vpc\_id) | VPC 的 ID |
Port 80] EC2_1[EC2 Instance #1
Python Web App
Port 80] EC2_2[EC2 Instance #2
Python Web App
Port 80] CW[CloudWatch Alarms
10-second periods] Lambda[Auto-Shutdown Lambda
2-hour timer] Internet -->|HTTP Requests| ALB ALB -->|Health Checks| EC2_1 ALB -->|Health Checks| EC2_2 EC2_1 -->|Custom Metrics
HealthStatus, Incidents| CW EC2_2 -->|Custom Metrics
HealthStatus, Incidents| CW Lambda -.->|Stop Instances
Cost Savings| EC2_1 Lambda -.->|Stop Instances
Cost Savings| EC2_2 subgraph VPC["VPC (10.0.0.0/16)"] ALB subgraph PublicSubnets["Public Subnets (Multi-AZ)"] EC2_1 EC2_2 end end style CW fill:#FF9900,color:#fff style Lambda fill:#FF9900,color:#fff style ALB fill:#0066CC,color:#fff style EC2_1 fill:#0066CC,color:#fff style EC2_2 fill:#0066CC,color:#fff ``` ### 组件 | 组件 | 描述 | 用途 | |-----------|-------------|---------| | **VPC** | 10.0.0.0/16 网络 | 隔离的网络环境 | | **Application Load Balancer** | 面向互联网的 ALB | 路由流量,健康检查 | | **EC2 实例** | t3.micro(默认 2 个) | 运行 Python Web 应用程序 | | **Python Web App** | 端口 80 上的 HTTP 服务器 | 模拟端点,指标 | | **CloudWatch 警报** | 10 秒评估周期 | 快速事件检测 | | **Auto-Shutdown Lambda** | 每 2 小时运行一次 | 节省空闲演示的成本 | | **IAM 角色** | EC2 实例配置文件 | CloudWatch 指标,SSM 访问 | ### 网络架构 - **公有子网**:多可用区部署以实现高可用性 - **互联网网关**:ALB 的直接互联网访问 - **安全组**:ALB(端口 80 入站) → EC2(仅允许来自 ALB 的端口 80 流量) - **路由表**:指向互联网网关的公有路由 ### 关键文件 - **main.tf**:VPC、ALB、EC2 实例、网络 - **monitoring.tf**:CloudWatch 警报(第 5-77 行) - **auto_shutdown.tf**:用于成本优化的 Lambda 函数(第 20-96 行) - **templates/userdata.sh.tpl**:Python 应用程序安装 ## Web 应用程序 一个在端口 80 上作为 systemd 服务运行的 Python 3.12 HTTP 服务器,提供交互式仪表板和用于事件测试的模拟端点。 ### 概述 - **技术**:Python 3 内置 `http.server` 模块 - **部署**:具有自动重启功能的 Systemd 服务 - **指标**:通过 boto3 发布 CloudWatch 自定义指标 - **自动恢复**:用于自动健康恢复的 5 分钟计时器 ### 交互式仪表板 访问您的 ALB URL 处的仪表板以: - 查看实时健康状态 - 监控实例信息(ID,环境) - 使用一键按钮触发事件 - 查看所有可用的 API 端点 - 每 5 秒自动刷新 ### 模拟端点 | 端点 | 方法 | 描述 | 自动恢复 | |----------|--------|-------------|---------------| | `/simulate/unhealthy` | GET | 健康检查失败(返回 503) | 5 分钟 | | `/simulate/healthy` | GET | 恢复健康状态(返回 200) | 不适用 | | `/simulate/crash` | GET | 10 秒后崩溃应用程序 | systemd 重启 | | `/simulate/slow-health` | GET | 触发响应缓慢/超时 | 5 分钟 | ### 健康检查端点 **`GET /health`** - ALB 健康检查端点 **响应**: - **200 OK**:`{"status": "healthy"}` - 实例健康 - **503 Service Unavailable**:`{"status": "unhealthy", "reason": "..."}` - 健康检查失败 ALB 健康检查配置: - **间隔**:30 秒 - **超时**:5 秒 - **健康阈值**:连续 2 次成功 - **不健康阈值**:连续 2 次失败 ### CloudWatch 指标 应用程序每 60 秒发布一次自定义指标: | 指标 | 值 | 用途 | |--------|--------|---------| | **HealthStatus** | 1.0(健康)/ 0.0(不健康) | 跟踪随时间变化的健康状态 | | **IncidentSimulations** | 计数 | 跟踪事件触发频率 | **命名空间**:`CustomApp/HealthDemo` **维度**:InstanceId, Environment, IncidentType ### 自动恢复功能 当触发 unhealthy 或 slow-health 事件时,应用程序会自动安排恢复: - **延迟**:300 秒(5 分钟) - **操作**:恢复 `healthy = true` 状态 - **取消**:调用 `/simulate/healthy` 可取消待处理的恢复 - **指标**:将更新的健康状态发布到 CloudWatch - **日志**:所有恢复事件记录到 `/var/log/user-data.log` 这允许在没有手动干预的情况下测试 Agent 检测和响应。 ### 实现细节 **源码**:`templates/userdata.sh.tpl`(第 33-650 行) **关键特性**: - Python 3.12 配合 boto3 作为 AWS SDK - 多线程:主 HTTP 服务器 + 后台指标发布器 - CloudWatch API 失败的优雅错误处理 - IMDSv2 用于安全的实例元数据检索 - Systemd 服务在崩溃时自动重启 **Systemd 服务**: ``` # 检查服务状态 sudo systemctl status webapp # 查看日志 sudo journalctl -u webapp -f # 重启服务 sudo systemctl restart webapp ``` ## 事件模拟 通过 6 种真实的故障场景测试 DevOps Agent 的事件响应能力。 ### 概述 可以通过以下方式触发事件: 1. **交互式仪表板**:Web UI 中的一键按钮 2. **直接 API**:对 ALB URL 执行 curl 命令 3. **GitHub Actions**:自动化工作流(`.github/workflows/trigger-incidents.yml`) 4. **AWS SSM**:直接向实例发送命令 所有事件都会在 2-4 分钟内生成 CloudWatch 警报,用于快速的 Agent 测试。 ### 事件类型 #### 1. 不健康主机 (`unhealthy_host`) **行为**:单个实例健康检查失败 **触发**:`unhealthy-hosts` 警报(UnHealthyHostCount ≥ 1) **预期警报时间**:2-3 分钟 **自动恢复**:5 分钟 **用例**:测试单主机故障检测和恢复 ``` # 通过 API curl "${ALB_URL}/simulate/unhealthy" # 通过 GitHub Actions gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=unhealthy_host ``` #### 2. 所有主机不健康 (`unhealthy_all`) **行为**:所有实例同时健康检查失败 **触发**:`unhealthy-hosts` 警报(UnHealthyHostCount ≥ instance_count) **预期警报时间**:2-3 分钟 **自动恢复**:5 分钟 **用例**:测试完全服务中断检测 ``` # 通过 GitHub Actions (需要 SSM) gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=unhealthy_all ``` #### 3. 应用程序崩溃 (`crash_instance`) **行为**:应用程序在 10 秒后以代码 1 退出 **触发**:`unhealthy-hosts` 警报(systemd 在约 5 秒后重启应用) **预期警报时间**:2-4 分钟 **自动恢复**:systemd 自动重启 **用例**:测试应用程序崩溃检测和 systemd 恢复 ``` # 通过 API curl "${ALB_URL}/simulate/crash" # 注意:应用响应 "will crash in 10 seconds" 然后退出 ``` #### 4. 健康检查缓慢 (`slow_health`) **行为**:健康端点变得无响应/缓慢 **触发**:`high-response-time` 警报(TargetResponseTime > 2s) **预期警报时间**:2-3 分钟 **自动恢复**:5 分钟 **用例**:测试性能下降检测 ``` # 通过 API curl "${ALB_URL}/simulate/slow-health" ``` #### 5. 关闭实例 (`shutdown_instances`) **行为**:Lambda 函数停止所有 EC2 实例 **触发**:所有警报(不健康主机、响应时间、5xx) **预期警报时间**:3-5 分钟 **自动恢复**:手动(需要 `aws ec2 start-instances`) **用例**:测试基础设施关闭检测 **要求**:`enable_auto_shutdown = true` ``` # 通过 GitHub Actions gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=shutdown_instances ``` #### 6. HTTP 5xx 错误泛洪 (`http_5xx_flood`) **行为**:生成 15 个并发的 HTTP 503 错误 **触发**:`5xx-errors` 警报(HTTPCode_Target_5XX_Count > 10) **预期警报时间**:2-3 分钟 **自动恢复**:无(错误是瞬态的) **用例**:测试错误率激增检测 ``` # 通过 API (生成多个请求) for i in {1..15}; do curl -s "${ALB_URL}/simulate/unhealthy" & done wait ``` ### GitHub Actions 工作流 用于自动化、可重复的事件测试,具有警报监控和自动恢复功能。 **文件**:`.github/workflows/trigger-incidents.yml` **功能**: - 通过 Terraform 输出自动发现基础设施 - 预检健康检查 - CloudWatch 警报状态监控 - 可选的自动恢复,具有可配置的延迟 - 详细的执行摘要及时间线 **示例用法**: ``` # 通过 GitHub CLI 触发工作流 gh workflow run trigger-incidents.yml \ -f environment=dev \ -f incident_type=unhealthy_host \ -f target_instance_index=0 \ -f restore_after_incident=true \ -f restore_delay_seconds=300 \ -f wait_for_alarm=true ``` 有关全面的工作流文档,请参阅 [.github/workflows/README-incidents.md](.github/workflows/README-incidents.md)。 ### 通过 SSM 运行事件 用于在没有 SSH 的情况下直接访问实例: ``` # 获取实例 ID INSTANCE_ID=$(terraform output -json instance_ids | jq -r '.[0]') # 通过 SSM 触发不健康状态 aws ssm send-command \ --instance-ids ${INSTANCE_ID} \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["curl http://localhost/simulate/unhealthy"]' # 恢复健康状态 aws ssm send-command \ --instance-ids ${INSTANCE_ID} \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["curl http://localhost/simulate/healthy"]' ``` ## 监控与警报 为快速事件检测设计的快速 CloudWatch 警报(10 秒评估周期)。 ### CloudWatch 警报 **配置**:`monitoring.tf`(当 `enable_monitoring = true` 时启用) | 警报名称 | 指标 | 阈值 | 周期 | 评估 | 预期触发时间 | |------------|--------|-----------|--------|------------|----------------------| | **unhealthy-hosts** | UnHealthyHostCount | ≥ 1 | 10 秒 | 1 个周期 | 2-3 分钟 | | **high-response-time** | TargetResponseTime | > 2 秒 | 10 秒 | 1 个周期 | 2-3 分钟 | | **5xx-errors** | HTTPCode_Target_5XX_Count | > 10 | 10 秒 | 1 个周期 | 2-3 分钟 | **命名空间**:`AWS/ApplicationELB` **维度**:TargetGroup, LoadBalancer ### 为什么使用 10 秒周期? 传统的 CloudWatch 警报使用 60-300 秒的周期。此演示使用 **10 秒周期** 以实现: - **更快的检测**:警报在 2-3 分钟内触发,而不是 5-10 分钟 - **更好的 Agent 测试**:AI Agent 验证的快速反馈循环 - **逼真的演示**:保持测试会话简短且互动 **权衡**:较高的 CloudWatch API 成本(约 $0.10/警报/月)。对于生产环境,请使用 60-300 秒的周期。 ### 自定义指标 由 Python 应用程序每 60 秒发布一次: **命名空间**:`CustomApp/HealthDemo` | 指标 | 值 | 用例 | |--------|--------|----------| | **HealthStatus** | 1.0 / 0.0 | 随时间跟踪应用程序健康状况 | | **IncidentSimulations** | 按类型计数 |监控事件测试频率 | **查询示例**: ``` aws cloudwatch get-metric-statistics \ --namespace CustomApp/HealthDemo \ --metric-name HealthStatus \ --dimensions Name=Environment,Value=dev \ --start-time 2026-01-24T00:00:00Z \ --end-time 2026-01-24T23:59:59Z \ --period 300 \ --statistics Average ``` ### Agent 测试的监控最佳实践 1. **首先建立基线**:部署基础设施并观察正常指标 10 分钟 2. **记录时间线**:记录事件触发 → 警报转换时间 3. **一次测试一种类型**:隔离变量以进行准确的 Agent 验证 4. **使用自动恢复**:用于可重复的自动化测试 5. **禁用自动恢复**:在验证 Agent 修复操作时 6. **监控 CloudWatch 成本**:10 秒周期会增加 API 使用量 ### 查看警报 ``` # 列出所有警报 aws cloudwatch describe-alarms \ --query 'MetricAlarms[*].[AlarmName,StateValue]' \ --output table # 获取特定警报状态 ALARM_NAME=$(terraform output -json cloudwatch_alarm_names | jq -r '.unhealthy_hosts') aws cloudwatch describe-alarms --alarm-names ${ALARM_NAME} # 查看警报历史 aws cloudwatch describe-alarm-history \ --alarm-name ${ALARM_NAME} \ --max-records 10 ``` ## DevOps Agent 集成 使用此演示基础设施配置和测试 AI 驱动的 DevOps Agent。 ### 设置 Agent 环境 #### 1. AWS 凭证(建议只读) 授予您的 Agent IAM 权限: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudwatch:DescribeAlarms", "cloudwatch:GetMetricStatistics", "ec2:DescribeInstances", "elasticloadbalancing:DescribeTargetHealth", "elasticloadbalancing:DescribeLoadBalancers", "logs:GetLogEvents" ], "Resource": "*" } ] } ``` 对于 Agent 修复测试,添加: ``` { "Effect": "Allow", "Action": [ "ssm:SendCommand", "ec2:StartInstances", "ec2:RebootInstances" ], "Resource": "*", "Condition": { "StringEquals": { "aws:RequestedRegion": "us-east-1" } } } ``` #### 2. 资源发现 配置 Agent 通过标签发现基础设施: ``` # 获取环境标签进行过滤 ENVIRONMENT=$(terraform output -raw environment_tag) # 发现 EC2 实例 aws ec2 describe-instances \ --filters "Name=tag:Environment,Values=${ENVIRONMENT}" \ --query 'Reservations[*].Instances[*].[InstanceId,State.Name,Tags[?Key==`Name`].Value|[0]]' # 获取警报名称 terraform output -json cloudwatch_alarm_names ``` **资源标签**: - `Environment`:dev/qa/prod(用于过滤) - `ManagedBy`:Terraform(自动化配置) - `Name`:描述性资源名称 #### 3. 警报配置 向 Agent 提供用于监控的警报名称: ``` terraform output cloudwatch_alarm_names # 示例输出: # { # "unhealthy_hosts": "dev-devops-demo-unhealthy-hosts", # "high_response_time": "dev-devops-demo-high-response-time", # "http_5xx_errors": "dev-devops-demo-5xx-errors" # } ``` ### 测试事件检测工作流 **目标**:验证 Agent 可以检测和诊断事件 #### 步骤 1:触发事件 ``` # 触发不健康主机事件 curl "${ALB_URL}/simulate/unhealthy" echo "Incident triggered at $(date)" ``` #### 步骤 2:等待警报(2-4 分钟) ``` # 监控警报状态 ALARM_NAME=$(terraform output -json cloudwatch_alarm_names | jq -r '.unhealthy_hosts') while true; do STATE=$(aws cloudwatch describe-alarms \ --alarm-names ${ALARM_NAME} \ --query 'MetricAlarms[0].StateValue' \ --output text) echo "[$(date +%H:%M:%S)] Alarm state: ${STATE}" [ "$STATE" == "ALARM" ] && break sleep 10 done ``` #### 步骤 3:观察 Agent 检测 您的 Agent 应该: 1. **检测**:识别警报状态变化(轮询或 EventBridge) 2. **识别**:确定受影响的资源(EC2 实例、ALB 目标组) 3. **诊断**:将警报与健康检查失败相关联 4. **提议**:建议修复操作 #### 步骤 4:验证建议的修复 **预期的 Agent 输出**: ``` Incident Detected: Unhealthy Host Alarm - Alarm: dev-devops-demo-unhealthy-hosts - Metric: UnHealthyHostCount = 1 - Affected Instance: i-0123456789abcdef0 - Root Cause: Health check endpoint returning 503 Proposed Remediation: 1. Restart application: systemctl restart webapp 2. Or restore via API: curl http://localhost/simulate/healthy 3. Or wait for auto-recovery (5 minutes) ``` ### 预期的 Agent 能力 | 能力 | 描述 | 验证方法 | |------------|-------------|-------------------| | **警报检测** | 检测 CloudWatch 警报状态变化 | 触发事件,验证 Agent 日志 | | **资源关联** | 识别受影响的 EC2/ALB 资源 | 检查 Agent 是否识别正确的实例 | | **根因分析** | 诊断健康检查失败 | 验证 Agent 确定 503 响应 | | **修复提议** | 建议修复操作 | 审查提议的命令 | | **操作执行** | 执行 SSM 命令或 API 调用 | 使用读写 IAM 权限进行测试 | | **恢复验证** | 验证警报返回 OK 状态 | 确认 Agent 监控修复后状态 | ### 测试自动修复操作 对于具有修复能力的 Agent(需要 IAM 权限): #### 通过 SSM 重启应用程序 ``` # Agent 执行 INSTANCE_ID="
标签:AIOps, AWS, CloudWatch, DPI, ECS, GitHub Actions, Lambda, LNA, Python, Terraform, 基础设施, 故障模拟, 无后门, 测试平台, 混沌工程, 漏洞利用检测, 能力评估, 自动化运维, 自动笔记, 蓝队演练, 足迹分析, 运维监控, 逆向工具