maharshi97/ai-devops-copilot-incident-response
GitHub: maharshi97/ai-devops-copilot-incident-response
基于LLM的K8s运维副驾驶,自动分析Alertmanager警报并通过Slack人工审批执行修复,缩短MTTR并减少噪音干扰。
Stars: 0 | Forks: 0
# AI DevOps Copilot — LLM 驱动的事件响应
一个 AI 辅助的待命副驾驶,接收 Alertmanager webhooks,请求 LLM 将警报分诊为结构化的、可由机器检查的决策(严重性、可能原因、建议的修复步骤),以交互式 Block Kit 消息的形式将其发布到 Slack,并使用命名空间范围的 RBAC 对 Kubernetes 执行经批准的修复操作。
## 业务问题
待命工程师在每次收到页面时都要浪费前 5-10 分钟阅读警报、检查仪表板并决定*是否*采取行动。对于 P2/P3 噪音,这相当于每周损失数小时的专注时间。对于 P1 警报,这会导致 SLA 燃尽。
本项目构建了一个优秀的待命人员想要的助手:
- 在警报触发时立即阅读每一条 Alertmanager 警报。
- 对其进行分类(P1-P4),指出可能原因,估算影响。
- 建议一个可逆的修复步骤排序列表,并附带解释。
- 在 10 秒内将所有内容发布到 Slack,并带有批准/拒绝按钮。
- 绝不自行采取破坏性操作 —— 人类仍然掌握着触发权。
目标 SLO:
- 从 webhook 到达后,分诊信息发布到 Slack 的时间 **< 10 s p95**。
- **100% 的修复操作需要人工批准**(每个事件都有可审计的时间线)。
- webhook 端点 **99.9% 的可用性**(PDB + HPA + 多可用区)。
## 架构
```
flowchart LR
AM[Alertmanager] -->|webhook| COP[ai-copilot
FastAPI] COP -->|LangChain
JsonOutputParser| LLM[OpenAI
gpt-4o-mini] COP -->|typed TriageResult| REDIS[(Redis
incident state)] COP -->|Block Kit| SLK[Slack] SLK -->|button click| COP COP -->|patch/delete
pods & deploys| K8S[Target K8s
Namespaces] COP -->|post-incident| PM[Postmortem
Generator] PM --> REDIS PM --> LLM COP -->|/metrics| PROM[Prometheus] PROM --> GRAF[Grafana] ``` ## 技术栈 | 层级 | 工具 | 版本 | 用途 | |-------|------|---------|---------| | 分诊大脑 | OpenAI `gpt-4o-mini` via LangChain | 0.3.10 | 结构化 JSON 分诊输出 | | Copilot API | FastAPI + Pydantic v2 | 0.115.5 | 警报入口 + Slack 回调 | | 事件状态 | Redis | 7.4 | 指纹去重 + 事件 TTL | | ChatOps | Slack Bolt / Web API | 1.21.2 | 交互式分诊消息 | | 修复 | Kubernetes Python client | 31.0.0 | Pod 重启、扩缩容、滚动重启、封锁节点 | | 复盘 | LangChain + gpt-4o-mini | 0.3.10 | 无责的 Google SRE 风格 markdown | | 基础设施 | Terraform + AWS (EKS, IAM, Secrets, SQS) | 1.10 | VPC, EKS 1.31, IRSA, Secrets Manager | | 部署 | Kustomize (dev/staging/prod overlays) | 5.x | 每个环境的副本/资源 | | 可观测性 | Prometheus + Grafana + OpenTelemetry | kube-prometheus-stack | 指标 + 追踪 | | CI/CD | GitHub Actions + Trivy + kubeconform | v4+ | Lint、类型检查、扫描、部署 | ## 项目结构 ``` ai-devops-copilot-incident-response/ ├── app/ │ ├── copilot/ # FastAPI service — triage, Slack, remediation │ └── postmortem-generator/ # FastAPI worker — blameless postmortem generator ├── terraform/ │ ├── versions.tf, variables.tf, main.tf, outputs.tf, backend.tf │ └── modules/ {vpc, eks, iam, secrets, sqs} ├── kubernetes/ │ ├── base/ # namespace, SA, RBAC, deploy, svc, ingress, HPA, PDB, NP, redis │ └── overlays/ {dev, staging, prod} ├── .github/workflows/ # ci.yml, deploy.yml, terraform-plan.yml ├── monitoring/ │ ├── prometheus/ rules.yaml + servicemonitor.yaml │ └── grafana/ ai-copilot-dashboard.json ├── docs/ │ ├── adr/ 0001, 0002 │ ├── runbooks/ copilot-down.md, llm-fallback-surge.md │ ├── security.md, cost-estimation.md ├── linkedin/ generate_*.py + linkedin-post.docx + linkedin-post-image.png ├── README.md ├── EXPLANATION.md ├── .gitignore └── LICENSE ``` ## 前置条件 - AWS 账户 + `aws` CLI v2、Terraform >= 1.10、kubectl >= 1.31、kustomize >= 5 - Python 3.12(用于在本地运行服务) - 用于构建镜像的 Docker - Slack 工作区 + 机器人应用(bot token、signing secret、`chat:write` scope、交互式端点) - OpenAI API key ## 快速开始(本地冒烟测试) ``` # 运行 Redis docker run -d --name copilot-redis -p 6379:6379 redis:7.4-alpine # 安装 deps cd app/copilot python -m venv .venv && source .venv/Scripts/activate pip install -r requirements.txt # 导出 env export OPENAI_API_KEY=sk-... export SLACK_BOT_TOKEN=xoxb-... export SLACK_SIGNING_SECRET=... export REDIS_URL=redis://localhost:6379/0 export IN_CLUSTER=false # 运行 uvicorn main:app --reload --port 8080 # 发送一个 fake alert curl -X POST http://localhost:8080/webhook/alertmanager \ -H 'content-type: application/json' \ -d @../../docs/samples/alertmanager-firing.json ``` ## 部署到 AWS ``` cd terraform terraform init terraform plan -out tfplan terraform apply tfplan aws eks update-kubeconfig --name ai-copilot-prod-eks --region us-east-1 kustomize build kubernetes/overlays/prod | kubectl apply -f - ``` ## CI/CD 流水线 `ci.yml` 在每次 PR 时运行: - 对两个 Python 服务运行 `ruff check` + `mypy`(矩阵策略) - `terraform fmt -check` + `terraform validate` - 对每个 overlay 运行 `kustomize build` + `kubeconform -strict` - `docker buildx` 构建 + Trivy 扫描(SARIF 上传到 Security 选项卡) `deploy.yml` 在合并到 `main` 时运行: - 构建并将两个镜像推送到 GHCR - 假定一个 OIDC 支持的 IAM 角色(无长期存在的 AWS 密钥) - 使用短 SHA 执行 `kustomize edit set image` - 执行 `kubectl rollout status`,超时时间为 5 分钟 - 冒烟测试通过集群内 Service 访问 `/healthz` ## 监控与可观测性 Prometheus 抓取两个服务的 `/metrics`。自定义指标: - `copilot_incidents_total{severity, dedup}` — 计数器 - `copilot_triage_latency_seconds` — 直方图(buckets: 0.5-30s) - `copilot_remediations_total{action, outcome}` — 成功/失败/拒绝 - `copilot_llm_fallbacks_total` — LLM 路径失败 - `copilot_open_incidents` — 仪表读数 `monitoring/prometheus/rules.yaml` 中的警报:`AICopilotDown`、`AICopilotHighErrorRate`、`LLMTriageLatencyHigh`、`LLMFallbackSurge`、`OpenIncidentBacklog`、`P1IncidentUnacked`。 Grafana 仪表板:统计行(开启的事件、LLM 回退率、修复成功率 %),时间序列(按严重性分类的事件、分诊延迟 p50/p95/p99、按操作 + 结果分类的修复)。 ## 成本估算 在 us-east-1 的生产环境约 $351/月 —— 完整细目请参阅 [docs/cost-estimation.md](docs/cost-estimation.md)。类似的商业 AIOps 产品通常运行费用为 $1,200-$2,500/月。 ## 关键设计决策 - **LLM 用于分诊,规则用于防护** —— LLM 做出决策;Remediator 的 Python 代码强制执行命名空间白名单并拒绝破坏性操作([ADR 0001](docs/adr/0001-llm-for-triage.md))。 - **默认为人在回路** —— 没有操作在未经 Slack 批准点击的情况下运行。`auto_remediation_enabled=false` 在配置中硬编码,且未连接到任何执行路径([ADR 0002](docs/adr/0002-human-in-the-loop-remediation.md))。 - **仅限结构化输出** —— LangChain 的 `JsonOutputParser` + Pydantic 的 `TriageResult` 意味着 Slack 渲染器永远不会遇到格式错误的 JSON。一个确定性的回退分诊器处理完全的 LLM 失败。 - **IRSA 优于节点角色 IAM** —— copilot 和 postmortem SA 各自有自己的作用域 IRSA 角色。Pod 无法继承节点权限。 - **NetworkPolicy 默认拒绝 + 显式 IMDS 阻断** —— 没有任何发生 SSRF 风格的元数据服务凭证窃取的机会。 ## 我的收获 - 如何将 LLM 变为可靠的后端组件 —— 诀窍在于严格的输出架构、确定性的回退路径,以及能让你看到模型何时开始漂移的指标。 - 如何设计一个 ChatOps 工作流,使 Slack 线程成为事件时间线的真实来源(每次按钮点击都会追加一个 `ActionRecord`)。 - 分层安全的价值:LLM 提示规则 → Pydantic 架构 → Remediator Python 白名单 → Kubernetes RBAC → IRSA。如果任何一层失败,其他层仍然能提供保护。 - 对于跨环境的副本/资源差异,Kustomize JSON 补丁比 Helm values 覆盖要整洁得多。 ## 联系我 - LinkedIn: https://www.linkedin.com/in/mpathak7/ - GitHub: https://github.com/maharshi97 ## 许可证 MIT —— 参见 [LICENSE](LICENSE)。
FastAPI] COP -->|LangChain
JsonOutputParser| LLM[OpenAI
gpt-4o-mini] COP -->|typed TriageResult| REDIS[(Redis
incident state)] COP -->|Block Kit| SLK[Slack] SLK -->|button click| COP COP -->|patch/delete
pods & deploys| K8S[Target K8s
Namespaces] COP -->|post-incident| PM[Postmortem
Generator] PM --> REDIS PM --> LLM COP -->|/metrics| PROM[Prometheus] PROM --> GRAF[Grafana] ``` ## 技术栈 | 层级 | 工具 | 版本 | 用途 | |-------|------|---------|---------| | 分诊大脑 | OpenAI `gpt-4o-mini` via LangChain | 0.3.10 | 结构化 JSON 分诊输出 | | Copilot API | FastAPI + Pydantic v2 | 0.115.5 | 警报入口 + Slack 回调 | | 事件状态 | Redis | 7.4 | 指纹去重 + 事件 TTL | | ChatOps | Slack Bolt / Web API | 1.21.2 | 交互式分诊消息 | | 修复 | Kubernetes Python client | 31.0.0 | Pod 重启、扩缩容、滚动重启、封锁节点 | | 复盘 | LangChain + gpt-4o-mini | 0.3.10 | 无责的 Google SRE 风格 markdown | | 基础设施 | Terraform + AWS (EKS, IAM, Secrets, SQS) | 1.10 | VPC, EKS 1.31, IRSA, Secrets Manager | | 部署 | Kustomize (dev/staging/prod overlays) | 5.x | 每个环境的副本/资源 | | 可观测性 | Prometheus + Grafana + OpenTelemetry | kube-prometheus-stack | 指标 + 追踪 | | CI/CD | GitHub Actions + Trivy + kubeconform | v4+ | Lint、类型检查、扫描、部署 | ## 项目结构 ``` ai-devops-copilot-incident-response/ ├── app/ │ ├── copilot/ # FastAPI service — triage, Slack, remediation │ └── postmortem-generator/ # FastAPI worker — blameless postmortem generator ├── terraform/ │ ├── versions.tf, variables.tf, main.tf, outputs.tf, backend.tf │ └── modules/ {vpc, eks, iam, secrets, sqs} ├── kubernetes/ │ ├── base/ # namespace, SA, RBAC, deploy, svc, ingress, HPA, PDB, NP, redis │ └── overlays/ {dev, staging, prod} ├── .github/workflows/ # ci.yml, deploy.yml, terraform-plan.yml ├── monitoring/ │ ├── prometheus/ rules.yaml + servicemonitor.yaml │ └── grafana/ ai-copilot-dashboard.json ├── docs/ │ ├── adr/ 0001, 0002 │ ├── runbooks/ copilot-down.md, llm-fallback-surge.md │ ├── security.md, cost-estimation.md ├── linkedin/ generate_*.py + linkedin-post.docx + linkedin-post-image.png ├── README.md ├── EXPLANATION.md ├── .gitignore └── LICENSE ``` ## 前置条件 - AWS 账户 + `aws` CLI v2、Terraform >= 1.10、kubectl >= 1.31、kustomize >= 5 - Python 3.12(用于在本地运行服务) - 用于构建镜像的 Docker - Slack 工作区 + 机器人应用(bot token、signing secret、`chat:write` scope、交互式端点) - OpenAI API key ## 快速开始(本地冒烟测试) ``` # 运行 Redis docker run -d --name copilot-redis -p 6379:6379 redis:7.4-alpine # 安装 deps cd app/copilot python -m venv .venv && source .venv/Scripts/activate pip install -r requirements.txt # 导出 env export OPENAI_API_KEY=sk-... export SLACK_BOT_TOKEN=xoxb-... export SLACK_SIGNING_SECRET=... export REDIS_URL=redis://localhost:6379/0 export IN_CLUSTER=false # 运行 uvicorn main:app --reload --port 8080 # 发送一个 fake alert curl -X POST http://localhost:8080/webhook/alertmanager \ -H 'content-type: application/json' \ -d @../../docs/samples/alertmanager-firing.json ``` ## 部署到 AWS ``` cd terraform terraform init terraform plan -out tfplan terraform apply tfplan aws eks update-kubeconfig --name ai-copilot-prod-eks --region us-east-1 kustomize build kubernetes/overlays/prod | kubectl apply -f - ``` ## CI/CD 流水线 `ci.yml` 在每次 PR 时运行: - 对两个 Python 服务运行 `ruff check` + `mypy`(矩阵策略) - `terraform fmt -check` + `terraform validate` - 对每个 overlay 运行 `kustomize build` + `kubeconform -strict` - `docker buildx` 构建 + Trivy 扫描(SARIF 上传到 Security 选项卡) `deploy.yml` 在合并到 `main` 时运行: - 构建并将两个镜像推送到 GHCR - 假定一个 OIDC 支持的 IAM 角色(无长期存在的 AWS 密钥) - 使用短 SHA 执行 `kustomize edit set image` - 执行 `kubectl rollout status`,超时时间为 5 分钟 - 冒烟测试通过集群内 Service 访问 `/healthz` ## 监控与可观测性 Prometheus 抓取两个服务的 `/metrics`。自定义指标: - `copilot_incidents_total{severity, dedup}` — 计数器 - `copilot_triage_latency_seconds` — 直方图(buckets: 0.5-30s) - `copilot_remediations_total{action, outcome}` — 成功/失败/拒绝 - `copilot_llm_fallbacks_total` — LLM 路径失败 - `copilot_open_incidents` — 仪表读数 `monitoring/prometheus/rules.yaml` 中的警报:`AICopilotDown`、`AICopilotHighErrorRate`、`LLMTriageLatencyHigh`、`LLMFallbackSurge`、`OpenIncidentBacklog`、`P1IncidentUnacked`。 Grafana 仪表板:统计行(开启的事件、LLM 回退率、修复成功率 %),时间序列(按严重性分类的事件、分诊延迟 p50/p95/p99、按操作 + 结果分类的修复)。 ## 成本估算 在 us-east-1 的生产环境约 $351/月 —— 完整细目请参阅 [docs/cost-estimation.md](docs/cost-estimation.md)。类似的商业 AIOps 产品通常运行费用为 $1,200-$2,500/月。 ## 关键设计决策 - **LLM 用于分诊,规则用于防护** —— LLM 做出决策;Remediator 的 Python 代码强制执行命名空间白名单并拒绝破坏性操作([ADR 0001](docs/adr/0001-llm-for-triage.md))。 - **默认为人在回路** —— 没有操作在未经 Slack 批准点击的情况下运行。`auto_remediation_enabled=false` 在配置中硬编码,且未连接到任何执行路径([ADR 0002](docs/adr/0002-human-in-the-loop-remediation.md))。 - **仅限结构化输出** —— LangChain 的 `JsonOutputParser` + Pydantic 的 `TriageResult` 意味着 Slack 渲染器永远不会遇到格式错误的 JSON。一个确定性的回退分诊器处理完全的 LLM 失败。 - **IRSA 优于节点角色 IAM** —— copilot 和 postmortem SA 各自有自己的作用域 IRSA 角色。Pod 无法继承节点权限。 - **NetworkPolicy 默认拒绝 + 显式 IMDS 阻断** —— 没有任何发生 SSRF 风格的元数据服务凭证窃取的机会。 ## 我的收获 - 如何将 LLM 变为可靠的后端组件 —— 诀窍在于严格的输出架构、确定性的回退路径,以及能让你看到模型何时开始漂移的指标。 - 如何设计一个 ChatOps 工作流,使 Slack 线程成为事件时间线的真实来源(每次按钮点击都会追加一个 `ActionRecord`)。 - 分层安全的价值:LLM 提示规则 → Pydantic 架构 → Remediator Python 白名单 → Kubernetes RBAC → IRSA。如果任何一层失败,其他层仍然能提供保护。 - 对于跨环境的副本/资源差异,Kustomize JSON 补丁比 Helm values 覆盖要整洁得多。 ## 联系我 - LinkedIn: https://www.linkedin.com/in/mpathak7/ - GitHub: https://github.com/maharshi97 ## 许可证 MIT —— 参见 [LICENSE](LICENSE)。
标签:AIOps, Alertmanager, API集成, AV绕过, ChatOps, DLL 劫持, EKS, FastAPI, GPT-4o, Grafana, HPA, IRSA, Kustomize, LangChain, LLM, OpenAI, PDB, RBAC, Redis, Slack, SLO, Unmanaged PE, Webhook, 事件分类, 人工审批, 人工智能, 内存规避, 力导向图, 可观测性, 告警管理, 多云架构, 大语言模型, 子域名突变, 搜索引擎查询, 故障响应, 根因分析, 模块化设计, 用户模式Hook绕过, 自动化修复, 自定义请求头, 轻量级, 运维, 逆向工具