Prometheus - 告警通知集成:邮件 / 钉钉 / 企业微信 / 短信配置全解

👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Prometheus这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
Prometheus - 告警通知集成:邮件 / 钉钉 / 企业微信 / 短信配置全解 🚨
在现代云原生架构中,监控系统已成为保障服务稳定性的核心组件。Prometheus 作为 CNCF 毕业项目,凭借其强大的时序数据库、灵活的查询语言(PromQL)和活跃的社区生态,已成为事实上的监控标准。然而,仅有数据采集与可视化远远不够——及时、准确、多渠道的告警通知机制,才是将监控价值真正落地的关键。
本文将深入探讨如何将 Prometheus 的告警能力与主流通知渠道(邮件、钉钉、企业微信、短信)无缝集成,提供完整的配置方案、原理剖析及 Java 代码示例,助你构建高可靠、低延迟的告警闭环体系。
一、Prometheus 告警架构解析 🔍
要高效集成外部通知渠道,首先需理解 Prometheus 告警系统的整体架构。它并非由 Prometheus Server 直接发送通知,而是采用 “规则评估 + 告警分发” 的两阶段模型:
核心组件说明:
- Prometheus Server:负责采集指标、执行 PromQL 查询,并根据
alerting rules判断是否触发告警。一旦条件满足,它会将告警实例(Alert)推送给 Alertmanager。 - Alertmanager:专为处理告警而设计的独立服务。它接收来自 Prometheus(或其他兼容系统)的告警,执行:
- 分组(Grouping):将相似告警合并为一条通知,避免信息轰炸。
- 抑制(Inhibition):当某告警触发时,自动抑制其他相关告警(如主机宕机时抑制其上所有服务告警)。
- 静默(Silencing):临时屏蔽特定告警,用于维护窗口。
- 路由(Routing):根据标签将告警分发到不同接收器(Receiver)。
- 通知(Notification):通过 Webhook、邮件等方式发送告警。
💡 关键点:所有外部通知渠道的集成,本质上都是配置 Alertmanager 的
receivers,使其能调用对应渠道的 API 或协议。
二、环境准备与基础配置 🛠️
在开始具体集成前,请确保以下基础环境已就绪:
- Prometheus Server 已安装并运行(版本 ≥ 2.0)。
- Alertmanager 已安装并运行(建议与 Prometheus 同版本)。
- Prometheus 配置文件
prometheus.yml中已指定 Alertmanager 地址:
# prometheus.yml
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093'] # Alertmanager 默认端口
- Alertmanager 配置文件
alertmanager.yml结构清晰,我们将在此文件中定义路由和接收器。
📌 提示:Alertmanager 支持热重载配置。修改后可通过
POST /-/reload触发重载,无需重启服务:curl -X POST http://localhost:9093/-/reload
三、邮件通知集成 ✉️
邮件是最传统但也最通用的告警渠道,适用于大多数运维场景。Alertmanager 内置 SMTP 支持,配置相对简单。
1. 配置 Alertmanager
编辑 alertmanager.yml,添加邮件相关的 global 设置和 receiver:
global:
smtp_smarthost: 'smtp.exmail.qq.com:465' # 以腾讯企业邮为例
smtp_from: 'alert@yourcompany.com'
smtp_auth_username: 'alert@yourcompany.com'
smtp_auth_password: 'your_email_password_or_auth_code'
smtp_require_tls: false # 若使用465端口(SSL),设为false;587端口(STARTTLS)设为true
route:
receiver: 'email-notifications'
receivers:
- name: 'email-notifications'
email_configs:
- to: 'ops-team@yourcompany.com'
send_resolved: true # 告警恢复时也发送通知
2. 关键参数说明
smtp_smarthost:SMTP 服务器地址和端口。常见邮箱端口:- QQ 邮箱/企业邮:465 (SSL) 或 587 (STARTTLS)
- Gmail:465 (SSL) 或 587 (STARTTLS)
- Outlook/Hotmail:587 (STARTTLS)
smtp_require_tls:务必根据端口选择。465 通常使用 SSL,不启用 STARTTLS;587 则需启用。send_resolved:强烈建议开启,以便知晓问题已解决。
3. 测试告警规则
创建一个简单的 CPU 使用率过高告警规则 cpu_alerts.yml:
groups:
- name: example
rules:
- alert: HighCPUUsage
expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 2m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "{{ $labels.instance }} CPU usage is above 80% (current value: {{ $value }}%)"
在 prometheus.yml 中引入该规则:
rule_files:
- "cpu_alerts.yml"
重启 Prometheus 或热重载后,若 CPU 超过阈值,你将收到类似如下邮件:
Subject: [FIRING:1] HighCPUUsage (instance=192.168.1.100:9100 severity=warning)
Body:
[FIRING] High CPU usage on 192.168.1.100:9100
192.168.1.100:9100 CPU usage is above 80% (current value: 85.2%)
四、钉钉通知集成 📱
钉钉作为国内主流办公协同工具,其机器人 Webhook 功能非常适合集成告警通知。Alertmanager 本身不直接支持钉钉,但可通过 Webhook 接收器 + 自定义中间件 实现。
1. 创建钉钉机器人
- 在钉钉群聊中点击 “智能群助手” → “添加机器人” → “自定义”。
- 设置机器人名称(如
Prometheus Alert),安全设置建议选择 “加签”(更安全)。 - 复制生成的 Webhook URL 和 Secret。
2. 编写钉钉 Webhook 服务(Java)
由于 Alertmanager 的 Webhook 接收器只发送标准 JSON,而钉钉要求特定格式,我们需要一个轻量级 Java 服务做转换。
Maven 依赖 (pom.xml)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
核心代码 (DingTalkWebhookController.java)
import org.springframework.web.bind.annotation.*;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@RestController
public class DingTalkWebhookController {
private static final String DINGTALK_WEBHOOK_URL = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_ACCESS_TOKEN";
private static final String SECRET = "YOUR_DINGTALK_SECRET"; // 从钉钉机器人获取
@PostMapping("/dingtalk")
public String handleAlert(@RequestBody JsonNode alertPayload) {
try {
String message = buildMarkdownMessage(alertPayload);
String signedUrl = getSignedUrl();
sendToDingTalk(signedUrl, message);
return "OK";
} catch (Exception e) {
e.printStackTrace();
return "ERROR";
}
}
private String buildMarkdownMessage(JsonNode alerts) {
StringBuilder sb = new StringBuilder();
sb.append("## Prometheus 告警通知\n\n");
for (JsonNode alert : alerts.get("alerts")) {
String status = alert.get("status").asText();
String summary = alert.get("annotations").has("summary")
? alert.get("annotations").get("summary").asText()
: "无摘要";
String description = alert.get("annotations").has("description")
? alert.get("annotations").get("description").asText()
: "无描述";
String instance = alert.get("labels").has("instance")
? alert.get("labels").get("instance").asText()
: "未知实例";
sb.append("- **状态**: ").append(status.toUpperCase()).append("\n");
sb.append("- **实例**: ").append(instance).append("\n");
sb.append("- **摘要**: ").append(summary).append("\n");
sb.append("- **详情**: ").append(description).append("\n\n");
}
return "{\"msgtype\": \"markdown\", \"markdown\": {\"title\": \"Prometheus告警\", \"text\": \"" + sb.toString().replace("\"", "\\\"") + "\"}}";
}
private String getSignedUrl() throws Exception {
Long timestamp = Instant.now().toEpochMilli();
String stringToSign = timestamp + "\n" + SECRET;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(SECRET.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = Base64.getEncoder().encodeToString(signData);
return DINGTALK_WEBHOOK_URL + "×tamp=" + timestamp + "&sign=" + java.net.URLEncoder.encode(sign, "UTF-8");
}
private void sendToDingTalk(String url, String message) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/json");
post.setEntity(new StringEntity(message, "UTF-8"));
HttpResponse response = httpClient.execute(post);
String responseString = EntityUtils.toString(response.getEntity());
System.out.println("DingTalk Response: " + responseString);
httpClient.close();
}
}
3. 配置 Alertmanager
在 alertmanager.yml 中添加 Webhook 接收器:
route:
receiver: 'dingtalk-notifications'
receivers:
- name: 'dingtalk-notifications'
webhook_configs:
- url: 'http://your-java-service-host:8080/dingtalk'
send_resolved: true
🌐 参考链接:钉钉机器人官方文档 提供了详细的签名算法和消息格式说明。
启动 Java 服务后,当告警触发,钉钉群将收到结构化 Markdown 消息,包含状态、实例、摘要等关键信息。
五、企业微信通知集成 💼
企业微信(WeCom)同样提供 Webhook 机器人功能,集成方式与钉钉类似,但消息格式略有不同。
1. 创建企业微信机器人
- 在企业微信客户端进入目标群聊 → 点击右上角 “…” → “群机器人” → “添加机器人”。
- 设置名称(如
Prometheus Bot),复制 Webhook URL(形如https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx)。
2. 修改 Java 服务支持企业微信
复用上一节的 Java 项目,新增一个 Controller 方法:
@PostMapping("/wecom")
public String handleWeComAlert(@RequestBody JsonNode alertPayload) {
try {
String message = buildWeComMessage(alertPayload);
sendToWeCom("YOUR_WECOM_WEBHOOK_URL", message);
return "OK";
} catch (Exception e) {
e.printStackTrace();
return "ERROR";
}
}
private String buildWeComMessage(JsonNode alerts) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = mapper.createObjectNode();
root.put("msgtype", "text");
StringBuilder content = new StringBuilder("【Prometheus告警】\n");
for (JsonNode alert : alerts.get("alerts")) {
String status = alert.get("status").asText();
String summary = alert.get("annotations").has("summary")
? alert.get("annotations").get("summary").asText()
: "无摘要";
content.append("状态: ").append(status.toUpperCase())
.append("\n摘要: ").append(summary)
.append("\n-------------------\n");
}
root.putObject("text").put("content", content.toString());
return root.toString();
}
private void sendToWeCom(String url, String message) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/json");
post.setEntity(new StringEntity(message, "UTF-8"));
HttpResponse response = httpClient.execute(post);
System.out.println("WeCom Response: " + EntityUtils.toString(response.getEntity()));
httpClient.close();
}
3. 配置 Alertmanager
receivers:
- name: 'wecom-notifications'
webhook_configs:
- url: 'http://your-java-service-host:8080/wecom'
send_resolved: true
企业微信机器人无需签名(除非启用 IP 白名单),因此实现更简单。消息将以纯文本形式发送到群聊。
🌐 参考链接:企业微信机器人文档 详细说明了支持的消息类型和限制。
六、短信通知集成 📞
短信适用于高优先级告警(如核心服务宕机),确保关键人员即使离线也能及时响应。由于短信涉及运营商网关和费用,通常通过第三方云服务(如阿里云、腾讯云)实现。
1. 选择短信服务商
以 阿里云短信服务 为例(需开通服务并申请签名、模板):
- 签名:如
[YourCompany] - 模板:如
【告警】实例${instance}发生${alertname},当前值${value}。 - 获取 AccessKey ID 和 AccessKey Secret
2. Java 短信发送服务
使用阿里云 SDK 发送短信:
Maven 依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.2.1</version>
</dependency>
核心代码
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.fasterxml.jackson.databind.JsonNode;
@RestController
public class SmsWebhookController {
private static final String ACCESS_KEY_ID = "YOUR_ACCESS_KEY_ID";
private static final String ACCESS_KEY_SECRET = "YOUR_ACCESS_KEY_SECRET";
private static final String SIGN_NAME = "YourCompany";
private static final String TEMPLATE_CODE = "SMS_XXXXXX"; // 你的模板CODE
private static final String[] PHONE_NUMBERS = {"13800138000", "13900139000"}; // 告警接收人手机号
@PostMapping("/sms")
public String handleSmsAlert(@RequestBody JsonNode alertPayload) {
try {
for (JsonNode alert : alertPayload.get("alerts")) {
if ("firing".equals(alert.get("status").asText())) { // 仅对触发中的告警发短信
sendSmsAlert(alert);
}
}
return "OK";
} catch (Exception e) {
e.printStackTrace();
return "ERROR";
}
}
private void sendSmsAlert(JsonNode alert) throws ClientException {
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
IAcsClient client = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setPhoneNumbers(String.join(",", PHONE_NUMBERS));
request.setSignName(SIGN_NAME);
request.setTemplateCode(TEMPLATE_CODE);
// 构建模板参数
String instance = alert.get("labels").has("instance") ? alert.get("labels").get("instance").asText() : "N/A";
String alertName = alert.get("labels").has("alertname") ? alert.get("labels").get("alertname").asText() : "Unknown";
String value = alert.get("value").asText();
request.setTemplateParam(String.format("{\"instance\":\"%s\",\"alertname\":\"%s\",\"value\":\"%s\"}", instance, alertName, value));
SendSmsResponse response = client.getAcsResponse(request);
System.out.println("SMS Response: " + response.getMessage());
}
}
3. 配置 Alertmanager
receivers:
- name: 'sms-notifications'
webhook_configs:
- url: 'http://your-java-service-host:8080/sms'
send_resolved: false # 短信通常不发送恢复通知,避免骚扰
⚠️ 注意:
- 短信费用较高,建议仅用于
severity: critical的告警。- 在
route中通过match或match_re限定仅高优先级告警走短信通道。- 阿里云短信有发送频率限制,需在代码中加入限流逻辑(如 Guava RateLimiter)。
七、高级路由与多渠道协同 🧩
实际生产环境中,往往需要根据告警严重程度、服务类型等维度,将告警分发到不同渠道。Alertmanager 的 路由树(Routing Tree) 机制完美支持这一需求。
示例:分级告警策略
route:
receiver: 'default-email' # 默认接收器
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 3h
# 子路由:按严重程度分发
routes:
- match:
severity: critical
receiver: 'critical-sms-and-dingtalk'
repeat_interval: 15m # 高优先级告警重复频率更高
- match:
severity: warning
receiver: 'warning-email-and-wecom'
receivers:
- name: 'default-email'
email_configs:
- to: 'fallback@yourcompany.com'
- name: 'critical-sms-and-dingtalk'
webhook_configs:
- url: 'http://alert-service:8080/sms'
- url: 'http://alert-service:8080/dingtalk'
- name: 'warning-email-and-wecom'
email_configs:
- to: 'warnings@yourcompany.com'
webhook_configs:
- url: 'http://alert-service:8080/wecom'
抑制规则示例
当主机宕机时,抑制其上所有服务的告警:
inhibit_rules:
- source_match:
alertname: HostDown
target_match:
severity: warning
equal: ['instance']
八、告警模板定制化 🎨
默认的告警消息可能信息不足或格式混乱。Alertmanager 支持使用 Go 模板语法自定义通知内容。
邮件模板示例 (email.tmpl)
{{ define "email.title" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }}{{ end }}
{{ define "email.html" }}
<h1>Prometheus Alert</h1>
<ul>
{{ range .Alerts }}
<li>
<strong>{{ .Labels.alertname }}</strong> ({{ .Labels.severity | upper }})
<br>Instance: {{ .Labels.instance }}
<br>Description: {{ .Annotations.description }}
<br>Value: {{ .Value }}
<br><a href="{{ .GeneratorURL }}">View in Prometheus</a>
</li>
{{ end }}
</ul>
{{ end }}
在 alertmanager.yml 中引用:
templates:
- '/etc/alertmanager/templates/*.tmpl'
receivers:
- name: 'email-notifications'
email_configs:
- to: 'ops@yourcompany.com'
html: '{{ template "email.html" . }}'
title: '{{ template "email.title" . }}'
🌐 参考链接:Alertmanager 官方模板文档 提供了完整的模板变量和函数列表。
九、安全与最佳实践 🔒
1. 敏感信息保护
- 不要在配置文件中明文存储密码、密钥。使用:
- Vault:HashiCorp Vault 集成
- Kubernetes Secrets:若部署在 K8s
- 环境变量:Alertmanager 支持
$ENV_VAR引用
global:
smtp_auth_password: '$EMAIL_PASSWORD' # 从环境变量读取
2. 网络安全
- 限制 Alertmanager Web UI 访问(默认端口 9093)
- Webhook 服务应部署在内网,或通过 API 网关增加认证
- 钉钉/企业微信机器人启用 IP 白名单
3. 告警疲劳预防
- 合理设置
for持续时间:避免瞬时抖动触发告警 - 启用分组:
group_by减少通知数量 - 设置静默期:
repeat_interval避免重复轰炸 - 定期 Review 规则:删除无效或低价值告警
十、故障排查指南 🛠️
常见问题及解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 邮件未收到 | SMTP 配置错误、防火墙阻断 | 检查 smtp_smarthost 端口、smtp_require_tls 设置;使用 telnet 测试连通性 |
| 钉钉无消息 | 签名错误、URL 过期 | 检查 Java 服务日志;确认 Secret 与钉钉后台一致;测试 Webhook URL |
| 短信发送失败 | 模板未审核、余额不足 | 登录阿里云控制台查看审核状态和余额;检查模板参数是否匹配 |
| 告警未触发 | PromQL 表达式错误、规则未加载 | 在 Prometheus UI 执行 expr 验证;检查 rule_files 路径 |
调试技巧
- 查看 Alertmanager 日志:
docker logs alertmanager-container - 使用 Alertmanager API 测试:
# 模拟发送告警 curl -H "Content-Type: application/json" -d '[{"labels":{"alertname":"TestAlert"}}]' http://localhost:9093/api/v1/alerts - 启用 Webhook 服务调试日志:在 Java 代码中打印接收到的原始 JSON。
结语 🌈
通过本文的详细讲解,你已掌握 Prometheus 与邮件、钉钉、企业微信、短信四大主流通知渠道的集成方法。从基础配置到高级路由,从安全加固到故障排查,这套告警体系将为你构建坚如磐石的监控防线。
记住,告警不是目的,快速恢复才是。合理的告警策略应聚焦于可行动的事件,避免噪音干扰。持续优化你的告警规则和通知流程,让每一次告警都成为提升系统稳定性的契机。
🚀 行动建议:立即检查你的 Alertmanager 配置,尝试为关键服务添加多渠道通知,并设置分级路由策略。让告警真正成为你的“数字哨兵”!
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)