本文为「DevOps全链路实战」系列重制版,基于 2026 年最新 kube-prometheus-stack (v0.85+) 与 Alertmanager v0.28 重新撰写,涵盖钉钉企业版 Webhook v2 签名验证、邮件 TLS 1.3 配置及告警分组与抑制策略。

引言
在 Kubernetes 生产环境中,可观测性的最后一环就是告警。Prometheus 采集的指标再多、Grafana 看板再精美,如果没有一套可靠、及时、低噪声的告警通知体系,线上故障就无法第一时间被感知。本篇是系列的第 13/19 天,我们将在前面已经部署好的 kube-prometheus-stack 基础上,完成 Alertmanager 的深度配置——包括钉钉机器人通知(带加签验证)、邮件告警通道(TLS 加密),以及告警分组、抑制、路由规则等高阶玩法。
与原版相比,本重制版重点更新了以下内容:
- kube-prometheus-stack Helm Chart v0.85+ 的 Alertmanager 配置方式(从 Secret 管理转为 Helm values 直配)
- 钉钉企业版 Webhook v2 新增的加签模式(timestamp + secret HMAC-SHA256),替代旧的 token-only 模式
- Alertmanager v0.28 的
keep_firing_for字段与active_time_interval调度窗口 - 邮件通道升级至 SMTP TLS 1.3 与 STARTTLS 双向认证
核心概念
Alertmanager 架构与工作流
Alertmanager 是 Prometheus 生态中独立告警路由与通知组件,其核心工作流为:
- 告警接收:Prometheus Server 根据
alerting.alertmanagers配置,将ALERTING(已触发)的告警推送到 Alertmanager - 分组(Grouping):按
group_by指定的标签(如alertname、cluster)将相同标签的告警合并为一条通知 - 抑制(Inhibition):当高优先级告警触发时,自动静默相关低优先级告警,避免告警风暴
- 路由(Routing):根据
routes中定义的标签匹配规则,将告警分发到不同的 receiver - 通知发送(Notify):到达
group_wait+group_interval+repeat_interval计时条件后,触发 webhook/email/slack 等通知渠道
关键时间参数
# Alertmanager 路由参数说明
route:
group_by: ['alertname', 'cluster'] # 分组维度
group_wait: 30s # 首次告警等待时间,聚合同组告警
group_interval: 5m # 同组后续告警的间隔
repeat_interval: 4h # 相同告警重复发送间隔
# v0.28 新增:保持触发状态展示
receiver: 'webhook-default'
这三个时间参数是控制告警噪声与及时性的关键旋钮。group_wait 太短会导致告警碎片化,太长则延迟首次通知;repeat_interval 太短会造成告警骚扰,太长可能让人遗忘未解决的故障。
实战步骤
第一步:部署钉钉 Webhook 转发服务
钉钉机器人 Webhook v2 的加签模式要求请求体在发送时附带 timestamp 和 sign 参数。由于 Alertmanager 原生 webhook 只支持固定 URL + JSON body,我们需要一个轻量转发层。社区中最常用的是 dingtalk-prometheus 中间件,这里我们用 Helm 部署:
# 添加 dingtalk helm 仓库
helm repo add dingtalk https://cowboy-bebop.github.io/dingtalk-charts
helm repo update
# 部署钉钉转发服务
helm upgrade –install dingtalk-webhook dingtalk/dingtalk-py
–namespace monitoring
–set dingtalk.token="SEC-your-dingtalk-token"
–set dingtalk.secret="SEC-your-dingtalk-secret"
–set dingtalk.phone="13800138000,13900139000"
–set replicaCount=2
# 验证服务状态
kubectl get pods -n monitoring -l app.kubernetes.io/name=dingtalk-py
部署完成后,转发服务会在集群内部暴露 http://dingtalk-py.monitoring.svc.cluster.local:8765/alertmanager 端点,Alertmanager 的 webhook receiver 指向这个地址即可。
第二步:配置 Alertmanager Helm Values
在 kube-prometheus-stack v0.85+ 中,Alertmanager 的配置直接通过 Helm values 中的 alertmanager.config 字段注入,无需再手动管理 Secret:
# alertmanager-values.yaml — 基于 kube-prometheus-stack v0.85
alertmanager:
config:
global:
smtp_smarthost: 'smtp.exmail.qq.com:465'
smtp_from: 'alerts@yourcompany.com'
smtp_auth_username: 'alerts@yourcompany.com'
smtp_auth_password: 'your-smtp-password'
smtp_require_tls: false # 465端口用隐式TLS
resolve_timeout: 5m
templates:
– '/etc/alertmanager/templates/*.tmpl'
route:
group_by: ['alertname', 'cluster', 'namespace']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'dingtalk'
routes:
# 紧急告警 → 钉钉 + 邮件双通道
– matchers: ['severity="critical"']
receiver: 'dingtalk-and-email'
group_wait: 10s
repeat_interval: 1h
# 告警静默窗口:非工作时间降低频率
– matchers: ['severity="warning"']
receiver: 'dingtalk'
active_time_intervals:
– 'business-hours'
repeat_interval: 8h
# v0.28 新增:工作时间区间定义
time_intervals:
– name: 'business-hours'
time_intervals:
– weekdays: ['monday:friday']
times:
– start_time: '09:00'
end_time: '22:00'
inhibit_rules:
# 节点宕机时抑制该节点的容器告警
– source_matchers: ['alertname="NodeDown"']
target_matchers: ['alertname=~"PodDown|ContainerCrashLoopBackOff"']
equal: ['node']
# 集群不可达时抑制所有子告警
– source_matchers: ['alertname="APIServerDown"']
target_matchers: ['namespace="monitoring"']
equal: []
receivers:
– name: 'dingtalk'
webhook_configs:
– url: 'http://dingtalk-py.monitoring.svc.cluster.local:8765/alertmanager'
send_resolved: true
max_alerts: 50
– name: 'email'
email_configs:
– to: 'ops-team@yourcompany.com'
send_resolved: true
headers:
Subject: '【告警】{{ .CommonLabels.alertname }} – {{ .CommonLabels.cluster }}'
– name: 'dingtalk-and-email'
webhook_configs:
– url: 'http://dingtalk-py.monitoring.svc.cluster.local:8765/alertmanager'
send_resolved: true
email_configs:
– to: 'ops-team@yourcompany.com,oncall@yourcompany.com'
send_resolved: true
应用配置:
# 更新 Helm Release
helm upgrade –install kube-prometheus-stack prometheus/kube-prometheus-stack
–namespace monitoring
-f alertmanager-values.yaml
–version 65.x
# 确认 Alertmanager 配置已热加载
kubectl exec -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0
— wget -qO- localhost:9093/api/v1/status | python3 -m json.tool | grep configYaml
第三步:配置钉钉加签验证模板
钉钉 Webhook v2 的加签算法需要对 timestamp + "n" + secret 进行 HMAC-SHA256 并 Base64 编码。转发服务在发送 HTTP 请求前自动计算签名并附加到 URL query 参数中。下面是转发服务的核心签名逻辑(Python 实现):
import time
import hmac
import hashlib
import base64
import urllib.parse
import requests
def build_dingtalk_url(webhook_url: str, secret: str) -> str:
"""构建带加签参数的钉钉 Webhook URL"""
timestamp = str(round(time.time() * 1000))
string_to_sign = f"{timestamp}n{secret}"
hmac_code = hmac.new(
key=secret.encode("utf-8"),
msg=string_to_sign.encode("utf-8"),
digestmod=hashlib.sha256
).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
return f"{webhook_url}×tamp={timestamp}&sign={sign}"
def send_dingtalk(alert_data: dict, webhook_url: str, secret: str) -> bool:
"""解析 Alertmanager Webhook 并发送钉钉消息"""
url = build_dingtalk_url(webhook_url, secret)
alerts = alert_data.get("alerts", [])
status_emoji = {"firing": "🔴", "resolved": "✅"}
title = f"[{alert_data.get('status', 'firing').upper()}] {len(alerts)} 条告警"
markdown_lines = [f"### {title}n"]
for alert in alerts[:20]:
labels = alert.get("labels", {})
annotations = alert.get("annotations", {})
emoji = status_emoji.get(alert.get("status", "firing"), "⚠️")
name = labels.get("alertname", "Unknown")
namespace = labels.get("namespace", "N/A")
desc = annotations.get("description", "")
summary = annotations.get("summary", "")
markdown_lines.append(f"{emoji} **{name}** ({namespace})n> {summary}n> {desc}n")
payload = {
"msgtype": "markdown",
"markdown": {"title": title, "text": "n".join(markdown_lines)},
}
resp = requests.post(url, json=payload, timeout=10)
return resp.json().get("errcode") == 0
第四步:编写 Prometheus 告警规则
以下告警规则覆盖了 K8s 集群最核心的告警场景,使用 PrometheusRule CRD 定义:
# prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: devops-core-alerts
namespace: monitoring
labels:
prometheus: kube-prometheus-stack-prometheus
spec:
groups:
– name: k8s-node-alerts
interval: 30s
rules:
– alert: NodeDown
expr: up{job="node-exporter"} == 0
for: 3m
labels:
severity: critical
cluster: prod-cluster
annotations:
summary: "节点 {{ $labels.node }} 宕机"
description: "节点 {{ $labels.node }} ({{ $labels.instance }}) 已离线超过 3 分钟"
– alert: HighCPUUsage
expr: |
100 – (avg by (node) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 10m
labels:
severity: warning
cluster: prod-cluster
annotations:
summary: "节点 {{ $labels.node }} CPU 使用率过高"
description: "节点 {{ $labels.node }} CPU 使用率 {{ $value | printf "%.1f" }}% 超过阈值 85%"
– name: pod-alerts
interval: 30s
rules:
– alert: PodCrashLooping
expr: |
increase(kube_pod_container_status_restarts_total[15m]) > 5
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.pod }} 频繁重启"
description: "命名空间 {{ $labels.namespace }} 中的 Pod {{ $labels.pod }} 在 15 分钟内重启 {{ $value }} 次"
# v0.28 新字段:keep_firing_for
– alert: PersistentVolumeSpaceLow
expr: |
kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes > 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "PV {{ $labels.persistentvolumeclaim }} 空间不足"
description: "PVC 剩余空间低于 15%"
keep_firing_for: 30m
应用告警规则:
kubectl apply -f prometheus-rules.yaml
# 验证规则已加载
kubectl exec -n monitoring kube-prometheus-stack-prometheus-0
— wget -qO- localhost:9090/api/v1/rules | python3 -m json.tool | grep name
第五步:验证端到端告警链路
使用 Prometheus HTTP API 手动触发一条告警来验证通知链路是否通畅:
# 1. 检查 Alertmanager 中是否有告警
kubectl exec -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0
— wget -qO- localhost:9093/api/v2/alerts | python3 -m json.tool
# 2. 检查 Alertmanager 配置状态
kubectl exec -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0
— wget -qO- localhost:9093/api/v2/status | python3 -c "
import sys, json
data = json.load(sys.stdin)
print('Config loaded:', data['config'].get('original', '')[:80] + '…')
print('Version:', data['versionInfo']['version'])
print('Uptime:', data['uptime'])
"
# 3. 模拟告警:临时降低 NodeDown 的 for 时间来触发
# 或直接使用 amtool 发送测试告警
kubectl exec -n monitoring alertmanager-kube-prometheus-stack-alertmanager-0
— amtool alert add
alertname=TestAlert severity=warning
–annotation=summary='Test Alert'
–annotation=description='End-to-end alert test'
–alertmanager.url=http://localhost:9093
# 4. 检查钉钉群是否收到测试告警消息
# 检查转发服务日志
kubectl logs -n monitoring -l app.kubernetes.io/name=dingtalk-py –tail=20
常见问题
问题一:钉钉消息发送失败,返回 errcode 310000
这是钉钉 Webhook v2 加签校验失败。根本原因是时间偏差:钉钉服务端要求 timestamp 与服务端时间偏差不超过 60 分钟,但实际推荐偏差在 1 分钟内。解决方法:
- 确认 Pod 所在节点的 NTP 时间同步正常:
chronyc tracking - 检查转发服务中的
secret是否与钉钉机器人配置页完全一致 - 确认使用的是 HMAC-SHA256 而非 SHA1 或 MD5
问题二:告警一直不触发,但 Prometheus 中能看到指标
常见原因:for 持续时间未达到,或者 PrometheusRule 的 prometheus label 不匹配。用以下命令排查:
# 查看 Prometheus 当前加载的规则
kubectl exec -n monitoring kube-prometheus-stack-prometheus-0
— wget -qO- 'localhost:9090/api/v1/rules?type=alert'
| python3 -c "import sys,json; [print(r['name']) for r in json.load(sys.stdin)['data']['groups']]"
# 查看告警评估结果
kubectl exec -n monitoring kube-prometheus-stack-prometheus-0
— wget -qO- 'localhost:9090/api/v1/alerts' | python3 -m json.tool | grep -A2 state
问题三:告警风暴导致钉钉被限流
钉钉机器人默认每分钟最多发送 20 条消息。当大规模故障(如集群网络抖动)触发几十条告警时,后续消息会被丢弃。解决方法:
- 合理使用
group_by将同类型告警合并 - 设置
inhibit_rules让高优先级告警抑制低优先级告警 - 在转发服务中增加消息队列缓冲和限流逻辑
- 对于关键告警同时配置邮件通道作为兜底
问题四:Alertmanager 配置不生效
kube-prometheus-stack v0.85 改变了 Alertmanager 配置管理方式。如果通过 kubectl edit secret 修改了旧的 Secret,Helm 升级时会覆盖。务必通过 Helm values 的 alertmanager.config 字段管理配置,然后执行 helm upgrade 触发滚动更新。
总结
本篇重制版基于 2026 年最新版本重新梳理了 Alertmanager 的完整配置链路,覆盖了从钉钉加签 webhook 转发、邮件 TLS 通道、告警分组与抑制策略,到 PrometheusRule CRD 定义、端到端验证的完整流程。相比原版,重点更新了:
- Alertmanager v0.28 新增的
keep_firing_for(告警恢复后继续展示 30 分钟)和active_time_interval(工作时间调度窗口) - kube-prometheus-stack v0.85 的 Helm values 直配模式,替代手动 Secret 管理
- 钉钉 Webhook v2 加签模式的完整 Python 实现
- 更完善的告警抑制规则,避免告警风暴
一套好的告警体系的标准是:故障发生时你能在 1 分钟内收到通知,但正常运维期间你不会被噪声打扰。分组、抑制和时间窗口调度正是实现这一目标的关键工具。
下期预告
下一篇我们将进入渐进式交付的世界——第 14 天:Argo Rollouts 安装与基础概念:CRD 与 Rollout 资源定义,开始将前面搭建的 CI/CD 管道升级为支持金丝雀发布的先进交付系统。
系列大纲
- 全链路架构总览:从代码提交到灰度发布的完整管道设计
- K8s 集群与网络基础:kubeadm 离线部署与 Cilium 网络插件
- Harbor 私有镜像仓库部署与验证:Helm 安装与镜像推送
- GitLab CE 自托管部署:代码仓库与项目管理平台
- GitLab Runner 配置:K8s Executor 与 RBAC 权限设置
- GitLab CI 流水线搭建:.gitlab-ci.yml 与 Kaniko 无守护进程构建
- Harbor 镜像版本管理与 Tag 策略配置
- Argo CD 部署与 GitOps 配置仓库创建
- CI 与 CD 联动:从代码提交到部署的全自动闭环
- SonarQube 代码质量检查:SonarQube 部署与 GitLab CI 集成
- Prometheus 部署:kube-prometheus-stack 与 ServiceMonitor 指标采集
- Grafana 看板搭建:K8s 标准面板与自定义业务看板
- 告警规则与 Alertmanager:钉钉/邮件通知渠道配置(重制版)(今天)
- Argo Rollouts 安装与基础概念:CRD 与 Rollout 资源定义
- 金丝雀发布实战:setWeight 流量分割与 pause 步骤
- AnalysisTemplate 指标分析与自动回滚机制
- 全链路端到端演示:代码提交→构建→代码检查→灰度→监控→告警完整流程
- 生产化加固要点:Harbor/GitLab/Argo CD/SonarQube 高可用方案
- 供应链安全闭环:Trivy 扫描 + cosign 签名 + Kyverno 验签

















暂无评论内容