痛点
运维团队到了一定规模,告警值班管理就成了绕不开的问题:谁该接这条告警?升级策略怎么配?值班表怎么轮转?PagerDuty、OpsGenie 这类 SaaS 工具好用,但每人每月 $21-$49 的费用,10 人团队一年下来就是 $2500-$6000。对于已经重度使用 Grafana 栈的团队,Grafana OnCall 是一个值得认真考虑的开源替代方案。
Grafana OnCall(原 Amixr)2022 年开源后持续迭代,2024 年已合并进 Grafana OSS 核心,作为内置插件随 Grafana 一起部署。它覆盖了值班轮转、告警路由、升级策略、多渠道通知等核心需求,且与 Grafana Alerting 原生集成。
方案概览
Grafana OnCall 的核心架构:
Alertmanager / Grafana Alerting
│
▼
Grafana OnCall (Integration)
│
├── Route → Escalation Chain
│ ├── Step 1: Notify on-call engineer (Slack/Telegram/Phone)
│ ├── Step 2: Wait 5min, notify backup
│ └── Step 3: Wait 10min, notify manager
│
└── Schedule (轮转值班表)
├── Layer 1: Primary on-call (weekly rotation)
└── Layer 2: Secondary backup
核心组件:
| 组件 | 作用 |
|---|---|
| Integration | 接收告警的入口(Alertmanager、Webhook、Email 等) |
| Route | 根据标签/内容将告警路由到不同升级链 |
| Escalation Chain | 升级策略:通知谁、等多久、下一步找谁 |
| Schedule | 值班轮转表,支持多层覆盖 |
| ChatOps | Slack/Telegram/MS Teams 集成,直接在聊天中 Ack/Resolve |
实操步骤
Step 1: 部署 Grafana OnCall(Docker Compose)
Grafana 11+ 已内置 OnCall 插件,但独立部署的 OnCall Engine 功能更完整(支持电话/短信通知)。推荐用 Docker Compose:
# docker-compose.yml
version: "3.8"
x-environment: &oncall-env
DATABASE_TYPE: sqlite3
BROKER_TYPE: redis
BASE_URL: http://oncall.example.com:8080
SECRET_KEY: "change-me-to-random-string-32chars"
REDIS_URI: redis://redis:6379/0
DJANGO_SETTINGS_MODULE: settings.hobby
CELERY_WORKER_QUEUE: "default,critical,long,slack,telegram,webhook,retry,celery,grafana"
GRAFANA_API_URL: http://grafana:3000
services:
engine:
image: grafana/oncall:latest
restart: always
ports:
- "8080:8080"
command: sh -c "uwsgi --ini uwsgi.ini"
environment:
<<: *oncall-env
depends_on:
redis:
condition: service_healthy
oncall-migrate:
condition: service_completed_successfully
celery:
image: grafana/oncall:latest
restart: always
command: sh -c "python manage.py start_celery"
environment:
<<: *oncall-env
depends_on:
redis:
condition: service_healthy
oncall-migrate:
condition: service_completed_successfully
oncall-migrate:
image: grafana/oncall:latest
command: sh -c "python manage.py migrate"
environment:
<<: *oncall-env
depends_on:
redis:
condition: service_healthy
redis:
image: redis:7-alpine
restart: always
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
grafana:
image: grafana/grafana:latest
restart: always
ports:
- "3000:3000"
environment:
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: grafana-oncall-app
GF_INSTALL_PLUGINS: grafana-oncall-app
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:
启动:
docker compose up -d
# 验证服务状态
docker compose ps
# 期望看到 engine/celery/redis/grafana 全部 running
Step 2: 在 Grafana 中启用 OnCall 插件并连接
# 1. 打开 Grafana: http://localhost:3000 (admin/admin)
# 2. 进入 Administration → Plugins → 搜索 "OnCall" → Enable
# 3. 配置 OnCall backend URL: http://engine:8080
连接后,在 Grafana 左侧菜单会出现 OnCall 入口。
Step 3: 配置 Integration + Escalation Chain
创建 Integration(接收 Alertmanager 告警):
在 OnCall → Integrations → New Integration → 选择 "Alertmanager",获取 Webhook URL:
http://oncall.example.com:8080/integrations/v1/alertmanager/<unique-id>/
配置 Alertmanager 将告警发送到 OnCall:
# alertmanager.yml
receivers:
- name: 'grafana-oncall'
webhook_configs:
- url: 'http://oncall.example.com:8080/integrations/v1/alertmanager/<unique-id>/'
send_resolved: true
route:
receiver: 'grafana-oncall'
group_by: ['alertname', 'namespace']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
创建 Escalation Chain:
OnCall → Escalation Chains → New Chain: "Production Critical"
Step 1: Notify users from on-call schedule "Primary"
Step 2: Wait 5 minutes
Step 3: Notify users from on-call schedule "Secondary"
Step 4: Wait 10 minutes
Step 5: Notify user group "SRE Managers"
Step 4: 配置值班轮转表
OnCall → Schedules → Create Schedule
Name: "Primary On-Call"
Type: Web-based (推荐,支持拖拽)
Layer 1 - Primary:
Rotation: Weekly
Users: engineer-A → engineer-B → engineer-C
Start: Monday 09:00 UTC
Override Layer:
用于临时换班、节假日覆盖
值班表支持导出 iCal 格式,工程师可订阅到自己的日历 App。
避坑指南
1. Celery Worker 队列必须完整
最常见的部署问题是 Celery 队列配置不全,导致通知发不出去:
# 错误:只配了 default 队列
CELERY_WORKER_QUEUE: "default"
# 正确:必须包含所有队列
CELERY_WORKER_QUEUE: "default,critical,long,slack,telegram,webhook,retry,celery,grafana"
排查方式:
docker compose logs celery | grep -i "error\|exception"
# 检查是否有 "Received unregistered task" 类报错
2. 时区问题导致值班错乱
OnCall Schedule 的时区设置影响轮转时间点。团队跨时区时,建议:
- Schedule 统一用 UTC
- 每个用户在 OnCall 个人设置中配好自己的时区
- 通知消息中会自动转为用户本地时间
# 验证服务器时区
timedatectl
# 确保容器内 TZ 环境变量正确
docker exec oncall-engine date
3. 告警风暴导致通知轰炸
默认配置下,每条告警都会触发独立通知。必须配置 Grouping:
Integration → Advanced Settings:
Grouping: 按 alertname + namespace 分组
Auto-resolve: 启用(收到 resolved 状态自动关闭)
# 或者用模板自定义分组键
Grouping Template:
{{ payload.labels.alertname }}-{{ payload.labels.cluster }}
同时在 Alertmanager 层做好 group_wait 和 group_interval,避免上游就发出大量重复告警。
与 PagerDuty 功能对比
| 功能 | Grafana OnCall (OSS) | PagerDuty |
|---|---|---|
| 值班轮转 | ✅ | ✅ |
| 升级策略 | ✅ | ✅ |
| Slack/Telegram 集成 | ✅ | ✅ |
| 电话/短信通知 | ⚠️ 需自配 Twilio | ✅ 内置 |
| 移动 App | ✅ Grafana App | ✅ 专用 App |
| Grafana 原生集成 | ✅ 零配置 | ❌ 需插件 |
| 成本 (10人) | $0 (自托管) | ~$250/月 |
| 维护成本 | 中等(需自运维) | 零 |
| SLA 保障 | 自行保障 | 99.9% |
总结
Grafana OnCall 适合以下场景:
- 已有 Grafana 栈 — 与 Grafana Alerting 无缝集成,告警从产生到通知一条链路
- 团队 5-30 人 — 规模足够需要正式值班管理,但不想付 SaaS 高额费用
- 对数据主权有要求 — 告警数据不出内网
不适合的场景:强依赖电话呼叫(Twilio 配置和可靠性需要额外投入)、需要企业级 SLA 保障、团队无人维护基础设施。
落地建议:先用 Docker Compose 在测试环境跑起来,配通 Slack/Telegram 通知 + 一条 Escalation Chain,验证告警从 Prometheus → Alertmanager → OnCall → 通知到人的全链路后,再考虑生产部署(生产环境建议将 SQLite 换为 PostgreSQL,Redis 用独立集群)。