jordann6/azure-incident-responder
GitHub: jordann6/azure-incident-responder
基于 Azure Monitor、n8n 工作流和 Claude Haiku 的自动化事件响应流水线,实现从告警检测到自动修复与 Slack 通知的端到端闭环。
Stars: 0 | Forks: 0
# Azure 事件响应器
这是 [aws-incident-responder](https://github.com/jordann6/aws-incident-responder) 的 Azure 对应版本。这是一个自动化的事件响应流水线,其中的 runbook 是一个 n8n 工作流,而不是充当连接作用的代码。目标 VM 上的 Azure Monitor 指标警报通过操作组 webhook 触发运行在 Azure Container Apps 上的 n8n。该工作流会要求 Claude Haiku 提供一份纯英文的事件摘要,将事件卡片发布到 Slack,通过 Azure Management API 重启 VM,然后重新检查 CPU 指标,以决定将事件标记为已解决还是进行升级处理。
## 架构

## 工作原理
```
Target VM Percentage CPU >= 80% (5 min)
-> Azure Monitor metric alert
-> Action group (common alert schema webhook)
-> n8n on Azure Container Apps (managed HTTPS FQDN)
n8n runbook:
parse common alert schema
-> Claude Haiku incident summary
-> Slack incident card
-> restart VM (Azure Management API, OAuth2 client credentials)
-> wait 90s
-> query Percentage CPU metric
-> resolved -> Slack resolved
still high -> Slack escalate
```
## 为什么这与 AWS 构建不同
这两个项目刻意建立在不同的工具链上,以展示跨云平台的适用范围,就像 [aws-developer-platform](https://github.com/jordann6/aws-developer-platform) 和 [azure-developer-platform](https://github.com/jordann6/azure-developer-platform) 的区别一样:
| 关注点 | AWS 构建 | Azure 构建 |
|---|---|---|
| 检测 | CloudWatch 警报 | Azure Monitor 指标警报 |
| 传递 | SNS HTTPS 订阅(带确认握手) | 操作组 webhook(直接,通用警报 schema) |
| TLS endpoint | ALB + ACM 证书 + Route 53 子域名 | Container Apps 托管 FQDN,开箱即用的有效证书 |
| n8n 托管 | ALB 后面的 ECS Fargate | Azure Container Apps |
| 修复授权 | 范围限定的 IAM 用户 + SigV4 | Entra service principal + OAuth2 客户端凭据 |
| 修复操作 | `RebootInstances`,通过 DescribeAlarms 验证 | VM `restart`,通过 Percentage CPU 指标验证 |
两者保持相同的形态:一个可视化的、受版本控制的 runbook 以及一个 Claude Haiku 摘要,使得 Slack 卡片读起来就像一份值班笔记。
## 组件
| 层级 | 资源 | 角色 |
|---|---|---|
| 检测 | **VM 目标** (Standard_B1s, Ubuntu 22.04) | 演示工作负载;在演示中通过 `az vm run-command` 拉高 CPU |
| 检测 | **指标警报** | 在 5 分钟窗口内 `Percentage CPU >= 80%`,每分钟评估一次 |
| 路由 | **操作组** | 将通用警报 schema 发布到 n8n webhook |
| 控制平面 | **Container Apps** | 在托管的 HTTPS FQDN 上运行 `n8nio/n8n`(即 runbook 引擎) |
| Runbook | **Claude Haiku** | 生成事件摘要和建议的下一步操作 |
| Runbook | **Slack** | 向 `#incidents` 发送事件、已解决和升级消息 |
| 修复 | **Service principal** | 仅作用于目标 VM 的 `Virtual Machine Contributor` |
| IaC | **Terraform** | RG, VNet, VM, Container Apps, 警报, 操作组;azurerm 远程状态 |
## 前置条件
- Terraform >= 1.6,Azure CLI 已登录到订阅 `9c644a73-5dc1-4bfe-9e90-91865014cdd2`
- azurerm 状态后端 (`rg-tfbackend-jordprojs` / `sttfbejordprojs8557` / `tfstate`)
- Anthropic API 密钥以及具有 `chat:write` 权限的 Slack bot token
## 部署
n8n 密钥由 Terraform (`random_password`) 生成,并且仅存在于私有状态后端中,因此没有前置步骤:
```
cd terraform
terraform init
terraform apply
```
记下输出内容 (`n8n_url`, `n8n_webhook_endpoint`, `target_vm_id`, `target_vm_name`, `alert_name`)。获取 n8n 密码:
```
terraform output -raw n8n_basic_auth_password
```
### 创建限定范围的 service principal
n8n 在最小权限身份下重启 VM,该身份是带外创建的,因此不会在 Terraform 状态中遗留任何密钥:
```
az ad sp create-for-rbac \
--name "incident-responder-n8n" \
--role "Virtual Machine Contributor" \
--scopes "$(terraform output -raw target_vm_id)"
```
### 配置 n8n
1. 打开 `n8n_url`,使用 `admin` 和上述密码登录。
2. 导入 `workflows/incident-responder-azure.json`。
3. 将 Azure 凭据添加为 **OAuth2 (client credentials)**:
- Access Token URL: `https://login.microsoftonline.com//oauth2/v2.0/token`
- Client ID / Secret: 来自 `az ad sp` 的输出 (`appId` / `password`)
- Scope: `https://management.azure.com/.default`
4. 将 Anthropic 凭据添加为 HTTP Header Auth:header 为 `x-api-key`,值为您的 API key。
5. 添加 Slack 凭据(bot token)并确认 bot 已在 `#incidents` 中。
6. 激活工作流。操作组已指向 webhook,因此无需额外的配置。
## 验证
拉高目标 VM 的 CPU 以触发警报:
```
az vm run-command invoke \
--name "$(terraform output -raw target_vm_name)" \
--resource-group rg-incident-responder \
--command-id RunShellScript \
--scripts "sudo apt-get update -y && sudo apt-get install -y stress-ng && stress-ng --cpu 0 --timeout 600s"
```
在警报窗口内,指标警报会触发,runbook 将端到端运行。确认以下几点:
- Slack `#incidents` 显示了带有 Haiku 摘要的事件卡片,随后是已解决或升级的消息。
- n8n 执行日志显示了完整路径,包括重启和指标查询。
- 该 VM 在 Azure portal 活动日志中显示最近的重新启动。
## 销毁
```
cd terraform
terraform destroy
az ad sp delete --id "$(az ad sp list --display-name incident-responder-n8n --query '[0].appId' -o tsv)"
```
销毁过程很干净:单个资源组容纳了 Terraform 创建的所有内容,而 service principal 会单独被移除。
## 成本
运行时大约为 `$0.05/hour`(包含一个 0.5 vCPU 的 Container App,一个 Standard_B1s VM,Log Analytics 数据摄取),大约为 `$1/day`。其构建旨在同一天内部署、演示并销毁,总成本远低于一美元。
## 安全加固说明
- 在生产环境中,Container App 将使用具有联合凭据的托管标识,而不是 service principal 密钥,从而消除长期有效的客户端密钥。
- n8n 在 Container App 的临时存储上运行 SQLite。为了在各个修订版本之间保持持久化,请挂载 Azure Files 或将 n8n 指向托管的 Postgres。
- 生产环境的 runbook 会在重启之前添加一个批准环节,并在升级之前设定最大重试预算。
标签:Azure, DLL 劫持, ECS, n8n, Terraform, 大语言模型, 自动化运维