← 返回文章列表

Grafana 可视化与 Alertmanager 告警实战

23 分钟阅读
字号

Grafana 可视化与 Alertmanager 告警实战

本文介绍 Grafana 出图配置、Alertmanager 告警机制、告警优化策略,以及钉钉 webhook 集成。


一、Grafana 出图

1.1 官方资源

资源地址
Grafana 官网https://grafana.com/
Docker 镜像https://hub.docker.com/r/grafana/grafana/
Dashboard 模板https://grafana.com/grafana/dashboards/

1.2 推荐模板 ID

Exporter模板 ID说明
node_exporter8919、1860、15172(基于 11074 优化)主机监控(CPU、内存、磁盘、网络)
redis_exporter14615Redis 监控
mysqld_exporter7362、11323MySQL 监控
mysqld_exporter(主从)11323主从复制专项监控
mariadb_exporter13106MariaDB 监控
haproxy_exporter367、2428HAProxy 监控
nginx_exporter14900Nginx 监控
blackbox_exporter7587HTTP/TCP/ICMP 探测
jmx_exporter8563Java JVM 监控
postgres_exporter9628PostgreSQL 监控

1.3 导入 Dashboard 模板

  1. 登录 Grafana → 点击左侧 +Import
  2. 输入模板 ID(如 8919)→ 点击 Load
  3. 选择数据源(Prometheus)→ 点击 Import
  4. 模板自动生成对应监控面板

1.4 常用 PromQL 示例

CPU 使用率

# 方法一:基于 idle 计算(非idle时间 / 总时间)
(1 - sum(increase(node_cpu_seconds_total{mode="idle", instance=~"node01"}[1m])) by (instance)
 /
sum(increase(node_cpu_seconds_total{instance=~"node01"}[1m])) by (instance)
) * 100
 
# 方法二:直接用 mode!="idle"(更简洁)
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle", instance=~"node01"}[5m]))) * 100

内存使用率

# 已用内存 / 总内存
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

磁盘使用率

# 根分区使用率
100 - (node_filesystem_avail_bytes{mountpoint="/", instance=~"node01"} / node_filesystem_size_bytes{mountpoint="/", instance=~"node01"}) * 100
 
# 特定分区
100 - (node_filesystem_avail_bytes{mountpoint="/data", instance=~"node01"} / node_filesystem_size_bytes{mountpoint="/data", instance=~"node01"}) * 100

网络流量

# 入方向流量(按字节)
sum by (instance) (rate(node_network_receive_bytes_total{instance=~"node01"}[5m]))
 
# 出方向流量
sum by (instance) (rate(node_network_transmit_bytes_total{instance=~"node01"}[5m]))

Pod CPU 使用率(cAdvisor)

# Pod CPU 使用率 = Pod 实际 CPU / Node 总 CPU
sum by (pod) (rate(container_cpu_usage_seconds_total{name=~".+"}[5m])) by (pod)
/
count by (pod) (machine_cpu_cores{name=~".+"})
* 100

1.5 Grafana 变量

Dashboard 模板中常用变量实现动态筛选:

变量用途示例
$instance选择主机node_cpu_seconds_total{instance=~"$instance"}
$service选择服务up{job=~"$service"}
$bucket选择 Histogram 分桶node_network_receive_bytes_bucket{instance=~"$instance"}

设置方式:Dashboard → Settings → Variables → Add variable

1.6 如何知道有哪些指标

方法一:Prometheus Web UI

访问 http://localhost:9090/graph,点 "Insert Metric" 下拉菜单,可以看到所有指标名。

方法二:查询所有指标名

# 查看所有指标(只看名字,不看数据)
{__name__=~".+"}

方法三:命令行查看

# 直接调 Prometheus API 获取所有指标名
curl http://localhost:9090/api/v1/label/__name__/values

方法四:查 Exporter 文档

每个 Exporter 官方文档会列出所有导出的指标:

Exporter文档地址
node_exporterhttps://github.com/prometheus/node_exporter
mysqld_exporterhttps://github.com/prometheus/mysqld_exporter
redis_exporterhttps://github.com/oliver006/redis_exporter
blackbox_exporterhttps://github.com/prometheus/blackbox_exporter

1.7 常用指标名汇总

不用死记,看到名字能猜出意思即可。

node_exporter(主机监控)

# CPU
node_cpu_seconds_total           # CPU 时间(mode: idle/user/sys/idle)
 
# 内存
node_memory_MemAvailable_bytes  # 可用内存
node_memory_MemTotal_bytes      # 总内存
node_memory_MemFree_bytes       # 空闲内存
 
# 磁盘
node_filesystem_size_bytes      # 磁盘总大小
node_filesystem_avail_bytes     # 可用磁盘
 
# 网络
node_network_receive_bytes_total    # 接收字节
node_network_transmit_bytes_total   # 发送字节
 
# 负载
node_load1 / node_load5 / node_load15   # 系统负载

cAdvisor(容器监控)

container_cpu_usage_seconds_total     # 容器 CPU
container_memory_usage_bytes         # 容器内存
container_network_receive_bytes_total # 容器网络入
container_network_transmit_bytes_total # 容器网络出

自定义应用指标

通过 Prometheus Client 暴露,常见模式:

http_requests_total              # HTTP 请求总数(标签:status, handler, method)
http_request_duration_seconds   # 请求延迟
order_count_total              # 订单数(业务自定义)
payment_amount_sum             # 支付金额(业务自定义)

1.8 PromQL 入门基础

数据模型

每条数据叫时序数据,格式:

node_cpu_seconds_total{mode="idle", instance="node01", job="node_exporter"} 0.85
                              ↑                                    ↑
                            标签                                  值

基础查询

# 1. 查指标名(查所有数据)
node_cpu_seconds_total
 
# 2. 加标签筛选
node_cpu_seconds_total{mode="idle"}
 
# 3. 正则匹配(=~ 开头)
node_cpu_seconds_total{instance=~"node.*"}
 
# 4. 组合条件
node_cpu_seconds_total{mode="idle", instance=~"node.*"}

核心函数

函数作用例子
rate()计算速率(最常用rate(http_requests_total[5m])
irate()即时速率(波动大时用)irate(http_requests_total[5m])
increase()增长量increase(http_requests_total[1h])
sum()求和sum(rate(http_requests_total[5m]))
avg()平均值avg by (job)(rate(...))
histogram_quantile()分位数histogram_quantile(0.99, ...)

为什么需要 rate()

# 错误:直接查是累计值,没意义(永远是增长的)
node_cpu_seconds_total
 
# 正确:算每秒增长多少
rate(node_cpu_seconds_total{mode="idle"}[5m])

[5m] = 取最近 5 分钟的数据来算

聚合

# 求和
sum(node_cpu_seconds_total)
 
# 按 instance 分组求平均
avg by (instance) (node_cpu_seconds_total{mode="idle"})

常用公式

# CPU 使用率
(1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) * 100
 
# 内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
 
# 磁盘使用率
100 - (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100
 
# QPS 每秒请求数
sum by (status) (rate(http_requests_total[5m]))
 
# P99 延迟
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

1.9 学习建议

  1. 先会用 Grafana — Grafana 的 Explore 页面可以写 PromQL 查数据,看结果
  2. 记住 3 个公式 — CPU、内存、磁盘使用率
  3. 多练习 — 拿真实数据自己写,写多了就熟了

二、Alertmanager 告警机制

2.1 官方资源

资源地址
二进制包https://github.com/prometheus/alertmanager/releases
官方文档https://prometheus.io/docs/alerting/configuration/

2.2 告警三种状态

┌─────────────────────────────────────────────────────────┐
│                    告警生命周期                          │
├─────────────────────────────────────────────────────────┤
│                                                          │
│   inactive ──────► pending ──────► firing               │
│      │               │                │                 │
│      │               │                │                 │
│      ▼               ▼                ▼                 │
│   条件不满足      条件首次满足      持续超过 for          │
│   或从未触发      但未达 for 时长    时长,发送通知       │
│                                                          │
└─────────────────────────────────────────────────────────┘
状态含义动作
inactive告警条件不满足,或从未触发过不做任何事
pending条件满足但持续时间不足 for 阈值等待中,不发通知
firing条件满足且持续超过 for 阈值发送告警到 Alertmanager

2.3 状态转换详解

以"内存使用率 > 80%"告警为例,for 设置为 2 分钟:

时间轴:
0min ─────────────────────────────────────────────────────►
 
告警条件:内存使用率 > 80%
 
0:00 ─ 内存使用率首次超过 80%


    pending(等待 2 分钟)
 
0:00 - 2:00 ─ 内存使用率持续超过 80%

       ├─ 如果在 2:00 前恢复正常 → inactive(从未触发过)

       └─ 持续到 2:00 仍超标 → firing(发送告警)
 
2:00 ─ 发送邮件/钉钉通知


    firing(持续告警,每 repeat_interval 重复发送)
 


    内存恢复正常 2 分钟后 → inactive(发送恢复通知)

2.4 Prometheus 告警规则配置

groups:
  - name: node_alerts          # 告警组名
    interval: 30s              # 评估间隔
    rules:
 
      # 告警实例:节点宕机
      - alert: NodeDown
        expr: up{job="node_exporter"} == 0
        for: 1m                 # 宕机 1 分钟后才触发
        labels:
          severity: critical
          team: infra
        annotations:
          summary: "节点 {{ $labels.instance }} 已宕机"
          description: "{{ $labels.instance }} 已经宕机超过 1 分钟"
 
      # 告警实例:内存使用率高
      - alert: HighMemoryUsage
        expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 80
        for: 2m                 # 持续 2 分钟
        labels:
          severity: warning
        annotations:
          summary: "内存使用率过高:{{ $value }}%"
          description: "节点 {{ $labels.instance }} 内存使用率已超过 80%"
 
      # 告警实例:磁盘空间不足
      - alert: DiskWillFillIn4Hours
        expr: (node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes > 0.9
        for: 1h                 # 持续 1 小时才告警(避免临时波动)
        labels:
          severity: warning
        annotations:
          summary: "磁盘将在 4 小时内用尽"
          description: "节点 {{ $labels.instance }} 磁盘使用率:{{ $value | humanizePercentage }}"

2.5 Alertmanager 安装

# 下载(选择对应版本)
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar -xzf alertmanager-0.27.0.linux-amd64.tar.gz
mv alertmanager-0.27.0.linux-amd64 /usr/local/alertmanager
 
# 目录结构
/usr/local/alertmanager/
├── alertmanager              # 主程序
├── amtool                    # 命令行工具
├── alertmanager.yml          # 配置文件
└── data/                     # 数据目录(存储 silence 等)

2.6 Alertmanager 系统服务

# /lib/systemd/system/alertmanager.service
 
[Unit]
Description=Alertmanager
After=network.target
 
[Service]
ExecStart=/usr/local/alertmanager/alertmanager \
  --config.file=/usr/local/alertmanager/alertmanager.yml \
  --storage.path=/usr/local/alertmanager/data \
  --web.listen-address=:9093
Restart=on-failure
 
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now alertmanager

2.7 Alertmanager 配置详解

# alertmanager.yml
 
global:
  resolve_timeout: 5m          # 告警恢复后多久标记为 resolved
 
# 模板配置
templates:
  - '/etc/alertmanager/template/*.tmpl'
 
# 路由树
route:
  # 根路由:所有告警先到这里
  receiver: 'default-receiver'
  group_by: ['alertname', 'cluster', 'namespace']  # 按这些标签分组
  group_wait: 30s             # 等待 30s 收集同组告警,再发送
  group_interval: 5m          # 同组告警的发送间隔
  repeat_interval: 4h         # 重复告警间隔(避免告警疲劳)
 
  # 子路由:根据 severity 分发到不同 receiver
  routes:
    # severity=critical 立即发送,不等待
    - match:
        severity: critical
      receiver: 'critical-receiver'
      group_wait: 0s
      continue: true          # 继续匹配后续路由(可选)
 
    - match:
        severity: warning
      receiver: 'warning-receiver'
 
# 路由匹配流程
# 1. 告警进入根路由,按 group_by 分组
# 2. 遍历子路由,找到第一个匹配的
# 3. 如果 continue: true,继续匹配后续路由
# 4. 无匹配则使用根路由的 receiver
 
# 接收者配置
receivers:
  - name: 'default-receiver'
    email_configs:
      - to: 'ops@example.com'
        send_resolved: true
        headers:
          subject: '[{{ status }}] {{ .GroupLabels.alertname }}'
 
  - name: 'critical-receiver'
    pagerduty_configs:
      - service_key: 'YOUR_SERVICE_KEY'
        severity: critical
 
  - name: 'warning-receiver'
    webhook_configs:
      - url: 'http://localhost:8060/dingtalk/webhook1/send'
        send_resolved: true
 
# 抑制规则
inhibit_rules:
  - source_match:
      alertname: 'NodeDown'
    target_match_re:
      alertname: 'ServiceDown|DiskIOHigh|NetworkDown'
    equal: ['instance']

2.8 路由 continue 参数

continue: true 让告警继续匹配后续路由:

route:
  receiver: 'default-receiver'
  routes:
    # 匹配 severity=critical,继续匹配
    - match:
        severity: critical
      receiver: 'email-receiver'
      continue: true
 
    # 继续匹配 alertname
    - match:
        alertname: 'NodeDown'
      receiver: 'critical-receiver'
 
    # 所有匹配不到的一直流到 default-receiver

三、告警优化策略

告警杂乱且频繁是生产环境常见痛点,解决方案分四层:

3.1 第一层:Prometheus 规则优化

for 的作用

for 是最容易忽视但最重要的参数:

# 没有 for:条件一满足立即触发(容易误报)
- alert: HighMemory
  expr: memory_usage > 80
  # 没有 for
 
# 有 for:持续 5 分钟才触发(更稳定)
- alert: HighMemory
  expr: memory_usage > 80
  for: 5m

阈值优化

根据真实业务调整阈值,避免过于敏感:

# 过于敏感:每次高峰都触发
- alert: HighCPU
  expr: cpu_usage > 70
 
# 更合理:根据业务峰谷调整
- alert: HighCPU
  expr: cpu_usage > 85  # 非高峰期 70 足够

多条件组合

# 单一条件容易误报
- alert: HighMemory
  expr: memory_usage > 80
 
# 组合条件:内存高 + 磁盘 swap 高(更精确)
- alert: HighMemoryAndSwap
  expr: memory_usage > 80 AND (node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes) / node_memory_SwapTotal_bytes > 0.5
  for: 3m

3.2 第二层:Alertmanager 分组合并

为什么需要分组合并

假设某服务有 10 个 Pod 同时重启,会产生 10 条告警。如果不合并:

❌ 未合并:收到 10 条独立告警
- [NodeDown] instance-1 已宕机
- [NodeDown] instance-2 已宕机
- [NodeDown] instance-3 已宕机
...(刷屏)
 
✅ 已合并:只收到 1 条告警
- [NodeDown] 3 个节点已宕机 (instance-1, instance-2, instance-3)

分组合并配置

route:
  # 按 alertname + cluster 分组
  # 同一组内的告警会被合并为一条
  group_by: ['alertname', 'cluster', 'namespace']
 
  # 等待 30 秒收集同组告警
  # 30 秒内新产生的同组告警会合并到同一条里
  group_wait: 30s
 
  # 发送后,再过 5 分钟有新告警才会再发送
  group_interval: 5m
 
  # 同一个告警恢复后 4 小时再发送重复告警
  repeat_interval: 4h

实际效果

场景group_wait=30s无合并
10 个 Pod 同时重启30s 后收到 1 条合并告警立即收到 10 条
告警持续未恢复每 4h 重复一次每 5m 重复一次(告警风暴)

3.3 第三层:抑制(Inhibition)

什么是抑制

当某个告警触发时,自动压制与其相关的一些告警。

典型场景:节点宕机

节点 instance-1 宕机

       ├─► [NodeDown] instance-1 已宕机        ← 根因告警(保留)
       ├─► [ServiceDown] nginx on instance-1  ← 伴随告警(抑制)
       ├─► [ServiceDown] mysql on instance-1   ← 伴随告警(抑制)
       └─► [DiskIOHigh] disk on instance-1    ← 伴随告警(抑制)

抑制配置

inhibit_rules:
  # 当 NodeDown 触发时,抑制同 instance 的 ServiceDown
  - source_match:
      alertname: 'NodeDown'
    target_match_re:
      alertname: 'ServiceDown|DiskIOHigh|NetworkDown'
    equal: ['instance']   # instance 标签相同的才抑制
    # 注意:抑制规则只看你配置的 source_match/target_match 和 equal 标签
    # 不自动比较 severity 高低

抑制原理

Alertmanager 收到告警:


┌──────────────────┐
│ 检查 inhibition   │
│ rules             │
└────────┬─────────┘


┌──────────────────┐
│ source_match      │──否──► 发送告警
│ 满足?             │
└────────┬─────────┘
         │是

┌──────────────────┐
│ 查找同 equal 标签  │
│ 的被抑制告警        │
└────────┬─────────┘


┌──────────────────┐
│ 标记为 inhibited  │──► 不发送,仅保留记录
│ 不发送            │
└──────────────────┘

3.4 第四层:静默(Silence)

什么是静默

在特定时间段内,让某些告警"闭嘴"。

典型场景

场景效果
凌晨 2-4 点定期维护维护窗口内不发告警
已知问题处理中问题处理期间不重复发告警
业务低峰期临时提高阈值,静默低优先级告警

使用方式

两种方式:

方式一:Alertmanager Web UI

http://localhost:9093/#/silences
→ Create silence
→ 输入匹配条件(alertname=xxx, instance=yyy)
→ 设置起始和结束时间
→ 提交

方式二:amtool 命令行

# 创建静默
amtool silence create \
  --alertname=HighMemoryUsage \
  --instance=node01 \
  --start=2024-01-15T02:00:00+08:00 \
  --end=2024-01-15T04:00:00+08:00 \
  --reason="凌晨维护窗口"
 
# 查询静默
amtool silence query
 
# 删除静默
amtool silence expire <silence-id>

3.5 告警模板定制

默认模板问题

Alertmanager 默认发送的告警信息冗长,包含大量 Prometheus 自动添加的元数据,不利于快速阅读。

模板示例

// /etc/alertmanager/template/default.tmpl
 
{{ define "dingtalk.title" }}
{{ if eq .Status "firing" }}🔴 【告警{{ .GroupLabels.alertname }}{{ else }}✅ 【恢复{{ .GroupLabels.alertname }}{{ end }}
{{ end }}
 
{{ define "dingtalk.content" }}
{{ if eq .Status "firing" }}
告警级别{{ .Labels.severity }}
{{ end }}
{{ range .Alerts }}
实例{{ .Labels.instance }}
详情{{ .Annotations.description }}
开始时间{{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if eq .Status "resolved" }}恢复时间{{ .EndsAt.Format "2006-01-02 15:04:05" }}{{ end }}
{{ end }}
{{ end }}

钉钉效果

🔴 【告警】HighMemoryUsage
告警级别:warning
实例:node01
详情:内存使用率超过 80%,当前值 86.5%
开始时间:2024-01-15 10:30:00

3.6 Recording Rule 性能优化

问题背景

假设有 5 个告警规则都用了同一个表达式:

# 每个规则都重复计算同一表达式
- alert: HighCPU1
  expr: rate(node_cpu_seconds_total{instance="node01"}[5m]) * 100 > 80
 
- alert: HighCPU2
  expr: rate(node_cpu_seconds_total{instance="node01"}[5m]) * 100 > 85
 
- alert: HighCPU3
  expr: rate(node_cpu_seconds_total{instance="node01"}[5m]) * 100 > 90

Prometheus 每 15 秒评估一次,每次都重复计算 3 次同一表达式。

解决:提取为 Recording Rule

groups:
  - name: node_recording_rules
    rules:
      # 预先计算结果,存为新指标
      - record: instance:node_cpu_usage:avg_rate5m
        expr: |
          avg by (instance) (
            rate(node_cpu_seconds_total{mode!="idle"}[5m])
          ) * 100
 
  - name: node_alerts
    rules:
      # 直接复用预计算结果,不再重复计算
      - alert: HighCPU
        expr: instance:node_cpu_usage:avg_rate5m > 80
        for: 2m

效果对比

指标无 Recording Rule有 Recording Rule
每轮计算次数3 次(每条规则一次)1 次(预先算好)
CPU 开销
适用场景指标少指标多、大规模集群

四、钉钉 Webhook 集成

4.1 整体架构

┌─────────────────────────────────────────────────────────┐
│                    钉钉告警架构                          │
├─────────────────────────────────────────────────────────┤
│                                                          │
│   Prometheus Server                                      │
│        │                                                │
│        │ 告警规则触发                                     │
│        ▼                                                │
│   Alertmanager ────────────────────────────────────────►│
│        │                                                │
│        │ webhook                                        │
│        ▼                                                │
│   prometheus-webhook-dingtalk                           │
│   (中间件:转换格式 + 签名验证)                            │
│        │                                                │
│        │ HTTPS + 签名                                    │
│        ▼                                                │
│   钉钉群机器人                                           │
│        │                                                │
│        ▼                                                │
│   群成员收到通知 🔔                                       │
│                                                          │
└─────────────────────────────────────────────────────────┘

4.2 钉钉群配置步骤

第一步:创建群聊

  1. 打开钉钉 → 新建群聊
  2. 至少添加 2 人(钉钉规则)
  3. 设置群名,如"运维告警群"

第二步:添加机器人

  1. 进入群设置 → 智能群助手 → 添加机器人
  2. 选择"自定义机器人"
  3. 填写机器人名称(如 prometheus-alert)
  4. 安全设置:勾选"加签",钉钉会生成 secret
  5. 点击完成,获得 access_tokensecret
访问地址:https://oapi.dingtalk.com/robot/send?access_token=xxxxx
签名密钥:SECxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

4.3 部署 prometheus-webhook-dingtalk

下载安装

# 下载(注意选择正确版本,linux-amd64)
wget https://github.com/timonwong/prometheus-webhook-dingtalk/releases/download/v2.1.0/prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz
 
# 解压
tar -xzf prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz
mv prometheus-webhook-dingtalk-2.1.0.linux-amd64 /usr/local/prometheus-webhook-dingtalk

配置文件

# /usr/local/prometheus-webhook-dingtalk/config.yml
 
# 可以在一个配置文件里定义多个 target
targets:
  # 基础 webhook(不 @ 任何人)
  webhook1:
    url: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
    secret: YOUR_SECRET
 
  # @所有人
  webhook_mention_all:
    url: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
    secret: YOUR_SECRET
    mention:
      all: true
 
  # @指定人员(填手机号)
  webhook_mention_users:
    url: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
    secret: YOUR_SECRET
    mention:
      mobiles:
        - '18611453110'
        - '13800138000'

系统服务

# /lib/systemd/system/dingtalk.service
 
[Unit]
Description=Prometheus DingTalk Webhook
Documentation=https://github.com/timonwong/prometheus-webhook-dingtalk
After=network.target
 
[Service]
Type=simple
Restart=on-failure
RestartSec=5s
WorkingDirectory=/usr/local/prometheus-webhook-dingtalk
ExecStart=/usr/local/prometheus-webhook-dingtalk/prometheus-webhook-dingtalk \
  --web.listen-address=0.0.0.0:8060 \
  --config.file=/usr/local/prometheus-webhook-dingtalk/config.yml
ExecReload=/bin/kill -HUP $MAINPID
 
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now dingtalk
systemctl status dingtalk

验证

# 测试 webhook 是否正常
curl -X POST 'http://localhost:8060/dingtalk/webhook1/send' \
  -H 'Content-Type: application/json' \
  -d '{"msgtype": "text", "text": {"content": "测试消息"}}'

4.4 Alertmanager 对接

# alertmanager.yml
 
global:
  resolve_timeout: 5m
 
templates:
  - '/etc/alertmanager/template/*.tmpl'
 
route:
  receiver: 'dingtalk-webhook'
  group_by: ['alertname', 'cluster']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
 
receivers:
  - name: 'dingtalk-webhook'
    webhook_configs:
      # 对接多个 target
      - url: 'http://localhost:8060/dingtalk/webhook1/send'
        send_resolved: true      # 告警恢复时也发送通知
 
      - url: 'http://localhost:8060/dingtalk/webhook_mention_all/send'
        send_resolved: false     # 恢复通知不发 @all
 
inhibit_rules: []

4.5 自定义钉钉模板

// /etc/alertmanager/template/dingtalk.tmpl
 
{{ define "dingtalk.markdown" }}
## {{ if eq .Status "firing" }}🔴 告警{{ else }}恢复{{ end }}
 
**告警名称**{{ .GroupLabels.alertname }}
 
{{ range .Alerts }}
**级别**{{ .Labels.severity }}
**实例**{{ .Labels.instance }}
**描述**{{ .Annotations.description }}
**时间**{{ .StartsAt.Format "2006-01-02 15:04:05" }}
 
{{ end }}
{{ end }}

config.yml 中指定使用该模板:

targets:
  webhook1:
    url: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
    secret: YOUR_SECRET
    mention:
      all: false
    # 指定模板文件
    templates:
      - '/etc/alertmanager/template/dingtalk.tmpl'

五、完整配置示例

prometheus.yml 中启用 alertmanager

# prometheus.yml
 
global:
  scrape_interval: 15s
  evaluation_interval: 15s
 
alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - localhost:9093
 
rule_files:
  - '/etc/prometheus/rules/*.yml'

目录结构

/etc/prometheus/
├── prometheus.yml
├── alertmanager.yml
├── rules/
│   ├── node_alerts.yml
│   └── service_alerts.yml
└── template/
    └── dingtalk.tmpl
 
/usr/local/
├── prometheus-webhook-dingtalk/
│   ├── prometheus-webhook-dingtalk
│   └── config.yml

检查配置

# 检查 Prometheus 规则语法
promtool check rules /etc/prometheus/rules/*.yml
 
# 检查 Alertmanager 配置
amtool check-config /etc/alertmanager/alertmanager.yml
 
# 重新加载 Alertmanager(不重启)
curl -X POST http://localhost:9093/-/reload

六、总结

整体架构

┌─────────────────────────────────────────────────────────┐
│                     Prometheus                            │
│  ┌─────────────────────────────────────────────────┐    │
│  │ 告警规则(rule_files):什么情况算告警              │    │
│  │ - expr: cpu > 80                                │    │
│  │ - for: 2m                                       │    │
│  │ - labels: severity: critical                    │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          │ firing                       │
│                          ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Alertmanager:触发后怎么处理                    │    │
│  │  ├─ route + receiver:发给谁                     │    │
│  │  ├─ group_by:怎么合并                          │    │
│  │  ├─ inhibit_rules:怎么压制                     │    │
│  │  └─ silence:怎么静默                           │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          ▼                               │
│                 邮件 / 钉钉 / Slack                      │
└─────────────────────────────────────────────────────────┘

四个核心概念

概念作用解决什么问题
route + receiver告警发给谁critical 发电话,warning 发邮件
group_by告警怎么合并10个Pod重启 → 1条告警
inhibit_rules告警怎么压制节点宕机时只发1条,不发服务告警
silence告警怎么静默维护期间不发

告警状态

inactive → pending → firing
   │          │          │
   │          │          └─ 发送通知
   │          └─ 等待 for 时长
   └─ 条件不满足

PromQL 语法注意

# CPU 使用率(注意括号位置)
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m]))) * 100
 
# 内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
 
# 磁盘使用率
100 - (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100

常用命令

# Prometheus 端
promtool check rules /etc/prometheus/rules/*.yml     # 检查规则语法
 
# Alertmanager 端
amtool check-config /etc/alertmanager/alertmanager.yml  # 检查配置
amtool silence query                                    # 查看静默
amtool silence add --alertname=HighCPU --instance=node01  # 创建静默
curl -X POST http://localhost:9093/-/reload            # 重载配置
分享

// RELATED_POSTS

0%