痛点:告警疲劳与重复操作消耗运维精力
运维团队每天面对数百条 Prometheus/Grafana 告警,其中 60%+ 是可预判、可自动化处理的场景:磁盘空间不足清理日志、Pod OOM 后重启、证书即将过期续签等。传统模式下,工程师收到告警 → 登录服务器 → 执行修复命令 → 确认恢复 → 关闭工单,单次操作 5-15 分钟,但乘以每日数十次就是巨大的时间消耗。
n8n 是一款开源(Fair-code)的工作流自动化平台,支持 400+ 集成节点、可视化编排、自托管部署,天然适合构建「告警 → 诊断 → 修复 → 通知」的闭环自动化流水线。相比 Rundeck、StackStorm 等老牌工具,n8n 的优势在于:低代码可视化、原生 HTTP/SSH/Kubernetes 节点支持、以及内置 AI Agent 节点(可接入 LLM 做智能决策)。
方案:n8n 构建告警自动修复工作流
核心架构:
Prometheus AlertManager → Webhook → n8n Workflow → 诊断+修复 → 通知
关键组件: - Webhook 触发器:接收 AlertManager 的告警 JSON - Switch 节点:按告警类型(磁盘/内存/证书/Pod)路由到不同处理分支 - SSH/Kubernetes 节点:执行实际修复操作 - AI Agent 节点(可选):对未知告警做 LLM 辅助诊断 - 通知节点:修复结果推送到钉钉/Slack/企业微信
实操步骤
Step 1:Docker Compose 部署 n8n
# docker-compose.yml
version: '3.8'
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
container_name: n8n
restart: always
ports:
- "5678:5678"
environment:
- N8N_HOST=n8n.internal.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.internal.example.com/
- N8N_ENCRYPTION_KEY=your-random-32-char-key-here
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=your-secure-password
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: your-secure-password
POSTGRES_DB: n8n
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
n8n_data:
postgres_data:
启动:
docker compose up -d
# 验证服务
curl -s http://localhost:5678/healthz | jq .
Step 2:配置 AlertManager Webhook 路由
在 AlertManager 配置中添加 n8n Webhook 接收器:
# alertmanager.yml
route:
receiver: 'default'
routes:
- match:
severity: 'critical'
receiver: 'n8n-auto-remediation'
- match:
severity: 'warning'
receiver: 'n8n-auto-remediation'
receivers:
- name: 'n8n-auto-remediation'
webhook_configs:
- url: 'https://n8n.internal.example.com/webhook/alert-handler'
send_resolved: true
max_alerts: 10
Step 3:在 n8n 中构建告警处理 Workflow
创建工作流的核心逻辑(通过 n8n UI 或导入 JSON):
Webhook 触发节点配置:
- Path: /alert-handler
- Method: POST
- Authentication: Header Auth(建议加 X-Webhook-Secret)
Switch 节点路由逻辑:
// Switch 节点条件表达式
// 分支1:磁盘告警
{{ $json.alerts[0].labels.alertname === 'DiskSpaceCritical' }}
// 分支2:Pod OOM
{{ $json.alerts[0].labels.alertname === 'KubePodOOMKilled' }}
// 分支3:证书过期
{{ $json.alerts[0].labels.alertname === 'CertExpiringSoon' }}
// 分支4:兜底 - 未知告警通知人工
{{ true }}
磁盘清理分支 — SSH 执行节点:
#!/bin/bash
# 清理目标主机的过期日志和临时文件
TARGET_HOST="{{ $json.alerts[0].labels.instance }}"
# 清理 7 天前的日志
find /var/log -name "*.gz" -mtime +7 -delete
find /var/log -name "*.log.*" -mtime +7 -delete
# 清理 Docker 无用资源
docker system prune -f --filter "until=72h"
# 清理 journal 日志(保留 3 天)
journalctl --vacuum-time=3d
# 输出清理后的磁盘使用情况
df -h / | tail -1 | awk '{print "磁盘使用率: "$5}'
Pod OOM 分支 — Kubernetes 节点:
#!/bin/bash
NAMESPACE="{{ $json.alerts[0].labels.namespace }}"
POD_NAME="{{ $json.alerts[0].labels.pod }}"
DEPLOYMENT=$(kubectl -n $NAMESPACE get pod $POD_NAME -o jsonpath='{.metadata.ownerReferences[0].name}')
# 获取当前内存 limit
CURRENT_LIMIT=$(kubectl -n $NAMESPACE get deployment $DEPLOYMENT \
-o jsonpath='{.spec.template.spec.containers[0].resources.limits.memory}')
echo "当前 Pod: $POD_NAME, 内存 Limit: $CURRENT_LIMIT"
# 重启 Deployment(滚动更新触发)
kubectl -n $NAMESPACE rollout restart deployment/$DEPLOYMENT
# 等待就绪
kubectl -n $NAMESPACE rollout status deployment/$DEPLOYMENT --timeout=120s
echo "Pod 已重启完成"
Step 4:添加执行结果通知
在每条处理分支末尾,接一个 HTTP Request 节点推送到钉钉 Webhook:
{
"msgtype": "markdown",
"markdown": {
"title": "🔧 告警自动修复通知",
"text": "### 告警自动修复完成\n\n- **告警名称**: {{ $json.alerts[0].labels.alertname }}\n- **实例**: {{ $json.alerts[0].labels.instance }}\n- **修复动作**: {{ $node['SSH Execute'].json.stdout }}\n- **处理时间**: {{ $now.format('YYYY-MM-DD HH:mm:ss') }}\n- **状态**: ✅ 已自动修复"
}
}
避坑指南
1. Webhook 安全性必须加固
n8n 的 Webhook URL 一旦暴露,任何人都能触发工作流执行远程命令。必须做的防护:
# 方案1:Header 认证(n8n 内置支持)
# 在 Webhook 节点开启 Header Auth,要求携带 X-Webhook-Secret
# 方案2:网络层限制(推荐叠加)
# nginx 限制只允许 AlertManager IP 访问
location /webhook/ {
allow 10.0.1.100; # AlertManager IP
deny all;
proxy_pass http://localhost:5678;
}
2. 自动修复必须设置安全边界
不是所有操作都适合自动化。建议设置 操作白名单 + 频率限制:
// n8n Function 节点 — 频率限制逻辑
const redis = require('ioredis');
const client = new redis('redis://localhost:6379');
const alertKey = `remediation:${alertName}:${instance}`;
const count = await client.incr(alertKey);
await client.expire(alertKey, 3600); // 1小时窗口
if (count > 3) {
// 1小时内同一告警修复超过3次,转人工
return { action: 'escalate', reason: '修复次数超限,需人工介入' };
}
3. 生产环境先跑 Dry-run 模式
新工作流上线前,在 Switch 节点后加一个 Dry-run 开关:
// 环境变量控制
const DRY_RUN = $env.N8N_DRY_RUN === 'true';
if (DRY_RUN) {
return {
action: 'skip',
message: `[DRY-RUN] 将执行: ${remediationCommand}`,
target: instance
};
}
// 实际执行
return { action: 'execute', command: remediationCommand };
上线步骤:Dry-run 观察 3 天 → 低风险告警(磁盘清理)先开启 → 逐步扩展到 Pod 重启、扩容等操作。
进阶:接入 AI Agent 处理未知告警
n8n 1.30+ 内置了 AI Agent 节点,可连接 OpenAI/Anthropic/Ollama,对无法预判的告警做智能诊断:
未知告警 → AI Agent 节点 → 分析告警上下文+历史数据 → 输出修复建议 → 人工确认后执行
配置要点:
- System Prompt 中注入当前集群拓扑、常见故障模式
- 设置 Tool 节点让 AI 可以调用 kubectl describe、docker logs 获取更多上下文
- AI 输出的修复命令必须经过人工审批节点(避免 LLM 幻觉导致误操作)
总结
| 维度 | 手动处理 | n8n 自动化 |
|---|---|---|
| 响应时间 | 5-30 分钟 | < 30 秒 |
| 人工介入 | 每次都需要 | 仅复杂场景 |
| 处理一致性 | 依赖个人经验 | 标准化流程 |
| 可追溯性 | 靠记忆/工单 | 完整执行日志 |
| 夜间告警 | 叫醒 On-call | 自动处理+通知 |
n8n 的核心价值在于 低门槛 + 高灵活性:不需要写 Python 脚本从零搭建,通过可视化拖拽即可编排复杂工作流,同时支持代码节点做精细控制。对于中小团队(3-10 人运维),用 n8n 覆盖 60-80% 的重复性告警处理,可以显著释放人力投入到架构优化和稳定性建设中。
落地建议: 从最简单的「磁盘清理」和「服务重启」两个场景切入,跑通 Webhook → 执行 → 通知 的完整闭环后,再逐步扩展到证书续签、扩容、故障切换等高价值场景。