写点什么

Prometheus 实战 - 从 0 构建高可用监控平台(四)

  • 2023-05-08
    广东
  • 本文字数:5540 字

    阅读完需:约 18 分钟

当今的互联网应用系统越来越复杂,其中涉及的组件和服务越来越多,需要进行高效、可靠的监控,以保证系统的稳定性和性能。Prometheus 是一款功能强大的开源监控系统,可以实时监控多个维度的指标数据,并支持强大的查询语言和告警机制,是目前广泛使用的云原生应用监控系统之一。


本文档合集《Prometheus 实战:从 0 构建高可用监控平台》将从零开始,手把手教您如何构建一套高可用的 Prometheus 监控平台,涵盖了以下内容:


  1. Prometheus 集群搭建:实现高可用和可扩展的监控系统

  2. 动态监控指标:自动发现和注册要监控的目标

  3. 告警机制配置:灵活配置告警规则、分组、过滤、抑制,实时通知异常情况

  4. Grafana 可视化展示:直观了解系统运行状态和趋势


本文档合集的目标读者是具有一定 Linux 系统和网络知识的系统管理员和 DevOps 工程师。通过本文档合集的学习,您将掌握 Prometheus 的核心概念和实践技巧,能够快速搭建一套高效、可靠的监控平台,帮助您更好地管理和维护复杂的互联网应用系统。


本文以下内容是基于 Alertmanager 灵活配置告警规则、分组、过滤、抑制。

Alertmanager

Alertmanager 是 Prometheus 生态系统中的一个组件,用于处理告警信息。Alertmanager 的主要作业包括以下几个方面:


  1. 接收告警信息:Alertmanager 从 Prometheus 或其他数据源接收告警信息,并对其进行处理。

  2. 分组和去重:Alertmanager 可以根据标签对告警信息进行分组,并去除重复的告警信息。

  3. 通知:Alertmanager 可以通过电子邮件、钉钉、飞书、Webhook 等方式发送告警通知。

  4. 告警静默:Alertmanager 允许用户对某些告警规则进行静默处理,以避免过多的告警信息干扰用户。


Alertmanager 是 Prometheus 监控系统中非常重要的一个组件。如果保证它的高可用有以下两种方式:


1 多实例部署


可以将多个 Alertmanager 实例部署在不同的节点上,并使用负载均衡器(例如 Nginx、HAProxy 等)将请求分发到这些实例上。多实例部署可以提高 Alertmanager 的可用性,当某个 Alertmanager 实例故障时,请求可以自动转发到其他正常工作的实例。


2 原生 HA 方案


从 Alertmanager v0.16.0 版本开始,Alertmanager 提供了一种原生的高可用方案,即使用 Raft 算法进行状态同步和故障转移。在原生 HA 方案中,多个 Alertmanager 实例会形成一个 Raft 集群,其中一个实例会被选举为 leader,负责处理请求和写入状态。其他实例则作为 follower,从 leader 同步状态,并在 leader 故障时自动切换为新的 leader。


安装之前的规划,我们这里使用多实例部署的方式完全都能够满足我们的需求。

部署 Alertmanager 服务

node2 和 node3 部署 Alertmanager 服务 操作一样,配置文件也一样。


cd /usr/local/src/https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.tar.gz
tar xf alertmanager-0.24.0.linux-amd64.tar.gz -C /usr/local/ln -sv /usr/local/alertmanager-0.24.0.linux-amd64 /usr/local/alertmanagerchown -R prometheus. /usr/local/alertmanager-0.24.0.linux-amd64
mkdir /data/alertmanagerchown -R prometheus. /data/alertmanager
cat > /etc/systemd/system/alertmanager.service <<EOF[Unit]Description=alertmanagerAfter=network.target[Service]Type=simpleUser=prometheusExecStart=/usr/local/alertmanager/alertmanager --storage.path=/data/alertmanager/data --config.file /usr/local/alertmanager/alertmanager.ymlRestart=on-failureLimitNOFILE=655350LimitNPROC=655350LimitCORE=infinity[Install]WantedBy=multi-user.targetEOF
systemctl daemon-reloadsystemctl start alertmanagersystemctl enable alertmanager
复制代码


生产在用的配置文件


[root@Q-gz-common-prod-thanos-002 alertmanager]# cat alertmanager.yml | grep  -v "^#"route:  #group_by: ['instance']  group_by: ['alertname', 'severity']  group_wait: 10s  group_interval: 3m  # 重新发送相同告警的间隔。比如我主机宕机了,一直没处理,那么就一直有告警,发完第一次后以后每次都要等repeat_interval时间才会发送第二次。  repeat_interval: 5m  # 比如一个分组同时有A、B两个告警,A先到达进去group_wait里面等着,在group_wait期间,B也进来了,两个合并成一组,并发送一个告警消息出去;发完后A、B的问题还未解决,还持续触发告警,然后分组内又来了个新告警C,这就触发了group_interval,由于同组的状态发生了变化,A、B、C会在group_interval内被快速推送告警,不会等到group_interval后再发;如果发完后,A、B、C三者都持续无变化,那么就会在repeat_interval周期性发送告警信息。  receiver: 'web.hook.prometheusalert'  routes:  - receiver: txsms    continue: true    group_wait: 30s    matchers:    - severity="critical"  #- receiver: flashcat   #  continue: true  #  group_wait: 30s  #  matchers:  #  - severity="error"  # 配置其他级别的告警通知  - receiver: web.hook.prometheusalert    continue: true    group_wait: 10s    matchers:    - severity=~".*"
receivers: - name: 'web.hook.prometheusalert' webhook_configs: - url: 'http://10.2.0.27:18080/prometheusalert?type=fs&tpl=prometheus-fs&fsurl=https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx'
- name: 'txsms' webhook_configs: - url: 'http://10.2.0.27:18080/prometheusalert?type=txdx&tpl=prometheus-dx&phone=1xxxx1,1xxxx2' send_resolved: true
- name: 'flashcat' webhook_configs: - url: 'https://api.flashcat.cloud/event/push/alert/prometheus?integration_key=11111' send_resolved: true
inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'error|warning|info|notice' equal: ['instance', 'alertname'] - source_match: severity: 'error' target_match: severity: 'warning|info|notice' equal: ['instance', 'alertname'] - source_match: severity: 'warning' target_match: severity: 'info|notice' equal: ['instance', 'alertname']
复制代码


下面要基于这个配置说明几个场景

告警级别规划
    致命  critical    严重  error    警告  warning    提醒  notice    通知  info
复制代码
Alertmanager 主备模式配置

按照之前的规划, 使用 keepalived+haproxy 的方式,实现 Alertmanager 主备模式,在发生故障的时候进去主备切换。


frontend alertmanager-in    bind     *:19093    maxconn  20000    default_backend alertmanager-out
backend alertmanager-out server alertmanager-1 10.2.0.10:9093 maxconn 20480 weight 10 check inter 10s rise 1 fall 2 server alertmanager-2 10.2.0.41:9093 maxconn 20480 weight 10 check inter 10s rise 1 fall 2 backup
复制代码
配置告警静默规则

inhibit_rules 配置段用于配置告警静默规则,是 Alertmanager 中非常重要的一部分。通过合理配置 inhibit_rules 规则,可以避免向用户发送过多的告警信息,提高告警处理的效率。


上面定义了三个 inhibit_rules 规则,每个规则包含 source_match、target_match 和 equal 三个字段:


第一个规则:当源告警的 severity 为 'critical' 时,目标告警的 severity 为 'error|warning|info|notice',且 instance 和 alertname 相同。这个规则的作用是将严重级别为 'critical' 的告警静默处理,避免向用户发送过多的告警信息。


第二个规则:当源告警的 severity 为 'error' 时,目标告警的 severity 为 'warning|info|notice',且 instance 和 alertname 相同。这个规则的作用是将错误级别为 'error' 的告警静默处理,避免向用户发送过多的告警信息。


第三个规则:当源告警的 severity 为 'warning' 时,目标告警的 severity 为 'info|notice',且 instance 和 alertname 相同。这个规则的作用是将警告级别为 'warning' 的告警静默处理,避免向用户发送过多的告警信息。

基于标签的告警路由配置

路由配置是 Alertmanager 中非常重要的一部分,它定义了告警的路由规则,用于将告警发送到不同的接收者。通过合理配置路由规则,可以将不同级别、不同类型的告警发送到不同的接收者,实现更加灵活、高效的告警处理。


上面的配置定义了两个路由规则:


第一个路由规则将 severity 为 'critical' 的告警发送到接收者 'txsms'。其中 continue: true 表示如果告警被路由到这个接收者后,Alertmanager 会继续尝试将告警路由到其他接收者。group_wait: 30s 表示如果在 30 秒内有相同的告警被触发,则会将这些告警分组,一起发送到接收者。


第二个路由规则将所有级别的告警都发送到默认接收者 'web.hook.prometheusalert'。其中 severity=~".*" 表示匹配所有 severity 级别的告警。group_wait: 10s 表示将 10 秒内相同的告警分组发送到接收者。注意,这个路由规则的 continue: true 表示即使告警已经被路由到其他接收者,也会尝试再次发送到默认接收者。


基于业务需求,可以添加更多的通知渠道和基于不同的级别的告警选择。这里我使用了两个高级通知渠道,短信和飞书。

周期创建告警抑制

在 Alertmanager 中,可以使用 inhibit_rules 选项来创建周期性告警抑制规则。下面是一个示例配置,该配置可以在每个小时的 0 分和 30 分时,对同一个 alertname 和 job 的告警进行周期性抑制,抑制时间为 5 分钟。该配置还包括了一个默认的抑制规则,对于任何两个相同的告警,间隔小于 1 分钟的将被抑制,以避免瞬间重复触发告警。


inhibit_rules:  # 默认的抑制规则,对于任何两个相同的告警,间隔小于 1 分钟的将被抑制  - source_match:      severity: 'critical'    target_match:      severity: 'warning|info'    equal: ['alertname', 'job']    # 抑制时间为 1 分钟    duration: 1m  # 周期性抑制规则,对于同一个 alertname 和 job 的告警,在每个小时的 0 分和 30 分时,间隔小于 5 分钟的将被抑制  - source_match:      severity: 'critical'    target_match:      severity: 'warning|info'    equal: ['alertname', 'job']    # 在每个小时的 0 分和 30 分触发抑制    periods:      - start: 0m        end: 5m      - start: 30m        end: 35m
复制代码


在上面的配置中,inhibit_rules 选项包含了两个告警抑制规则。第一个规则是默认的抑制规则,它使用 duration 属性指定抑制时间为 1 分钟。第二个规则是周期性抑制规则,它使用 periods 属性指定在每个小时的 0 分和 30 分时触发抑制,抑制时间为 5 分钟。


在实际业务中我们可能需要基于标签选创建抑制,而不是每次都去修改配置文件。基于这个需要有两个方式实现。


使用 amtool


# cat amtool_mysql_silence_every_day.sh #!/bin/bash
# 获取明天的日期并将其与固定时间组合成友好的日期和时间格式tomorrow_date=$(date -d "+1 day" +%Y-%m-%d)start_time='01:00:00'end_time='06:00:00'datetime_start="$tomorrow_date $start_time"datetime_end="$tomorrow_date $end_time"start_point=$(date -d "$datetime_start" +"%Y-%m-%dT%H:%M:%S%:z")end_point=$(date -d "$datetime_end" +"%Y-%m-%dT%H:%M:%S%:z")
# 定义正则表达式模式,抑制创建者和抑制描述或注释regex_pattern="module=~mysql.*"author="admin"comment="for test"
# 创建amtool命令command="amtool silence add '$regex_pattern' --start='$start_point' --end='$end_point' -a '$author' -c '$comment'"
# 运行amtool命令echo "Running command: $command"eval "$command"
复制代码


使用 api 方式


#author len#This script for create alertmanager silence every day api!# shell 占位符, 每天凌晨1点到5点mysql告警静默
AlertmanagerUrl="http://10.2.0.10:9093/api/v2/silences"SILEBCE_DATA_TEL='{"matchers":[{"name":"alertname","value":"UnusualDiskIOutil","isRegex":false,"isEqual":true}],"startsAt":"%sT17:00:00.000Z","endsAt":"%sT21:00:00.000Z","createdBy":"admin","comment":"mysql_silence","id":null}'
#SILEBCE_MYSQL_TEL='{"matchers":[{"name":"module","value":"mysql.*","isRegex":true}],"startsAt":"%sT17:00:00.000Z","endsAt":"%sT21:00:00.000Z","createdBy":"admin","comment":"mysql_silence","id":null}'SILEBCE_MYSQL_TEL='{"matchers":[{"name":"module","value":"mysql.*","isRegex":true}],"startsAt":"%sT08:00:00.000Z","endsAt":"%sT09:00:00.000Z","createdBy":"admin","comment":"mysql_silence","id":null}'
TODAY=$(date +%Y-%m-%d)SILEBCE_DATA=`printf ${SILEBCE_DATA_TEL} ${TODAY} ${TODAY}`SILEBCE_MYSQL=`printf ${SILEBCE_MYSQL_TEL} ${TODAY} ${TODAY}`

echo ${SILEBCE_MYSQL}
function createSilence() { curl "${AlertmanagerUrl}" -H "Content-Type: application/json" \ --data "${SILEBCE_DATA}" \ --compressed \ --insecure}
function createMysqlSilence() { curl "${AlertmanagerUrl}" -H "Content-Type: application/json" \ --data "${SILEBCE_MYSQL}" \ --compressed \ --insecure}
createSilencecreateMysqlSilence
复制代码


注意,这边使用的主备模式,故原则上两个 Alertmanager 节点都需要创建一样的周期告警抑制, 这样才能保证,主节点挂了后, 从节点没有对应的抑制规则造成大量的告警信息。

发布于: 17 小时前阅读数: 2
用户头像

还未添加个人签名 2018-12-12 加入

还未添加个人简介

评论

发布
暂无评论
Prometheus实战-从0构建高可用监控平台(四)_Linux_小毛驴的烂笔头_InfoQ写作社区