监控-Prometheus06-告警处理

  • 告警是整个监控系统中重要的组成部分,在Prometheus监控体系中,指标的采集存储与告警是分开的
  • 告警规则是在Prometheusserver端定义的,告警规则被触发后,才会将信息发送给独立组件Alertmanager上,经过Alertmanager对告警处理后,最终通过接收器(如Email)发送给用户。

1、告警概述

  • 对于管理员来说,不论是对传统业务的主机服务,还是对比较火热的Kubernetes生态圈服务,在使用Prometheus进行监控时,告警都是重要的环节。收到告警通常表明我们的应用环境中某些状态发生了变化,一般不是好消息。但告警又是一门艺术,使用恰当可使管理员事半功倍。合理的告警设置,会随时发现被监控系统或业务中出现的所有问题,管理员可以及时对问题进行处理,保证应用环境恢复到可用的稳定状态。
  • 我们在使用Prometheus进行告警时,首要的问题是,什么时候应该发出告警?一个好的告警是在正确的时刻、因正确的理由、踏着正确的节奏(告警频率)发送,并在其中放入真实有用的信息。我们发出告警的时刻一定是重要的系统或服务出现异常,导致最终用户体验不佳或无法正常使用服务,并需要人工检查。要针对最终用户的潜在痛点进行告警,才能使告警的数量保持较小,从而防止对系统或服务进行过度监控。保持小而重要的告警数量,是告警的一个关键原则,也就是说告警应该是重要的、可操作的和真实的。在实际工作中,要减少管理员在半夜接到痛苦的误报。
  • 其次是告警要包含哪些内容?当然大家对于告警内容的设定要适应自身应用环境,特别是线上重要业务接口类内容。告警应该链接到相关的仪表盘和控制台,这些仪表盘和控制台中的信息可以回答关于被警报的服务的基本问题,以便随叫随到的管理员可以快速解读潜在问题。
    • 对于面向最终用户提供内容的在线服务,通常尽可能在高延迟和错误率等条件下发出告警。
    • 对于容量建议告警,应检测容量何时耗尽,从而导致停机。
    • 对于批处理作业,在作业最近未成功时发出告警。
  • 最后,别忘记我们的监控系统本身,这也是非常重要的一个环节,因为监控系统本身启动并运行良好,才能起到监控的作用。

2、Alertmanager机制

  • 在Prometheus生态架构中,告警是由独立的两部分组成,可以通过图6-1可以清晰地了解Prometheus告警机制。Prometheus server与Alertmanager是相互分离的两个组件。
    • Prometheus server采集各类监控指标,然后基于PromQL对指标定义告警规则(Rules)。
    • Prometheus server对告警规则周期性地进行计算,如果满足告警触发条件,便生成一条告警信息,并将其推送到Alertmanager组件。
    • Alertmanager收到告警信息后,会处理告警,进行分组(grouping)并将它们路由(routing)到正确的接收器(receiver),如Email、PagerDuty和HipChat等,最终把异常事件的通知发送给接收者。

  • 在Prometheus中,不仅可以对PromQL定义的告警规则进行命名,还可以对多条相关的告警进行分组统一定义。
  • 下面先对AlertManager中告警的分组(Grouping)、抑制(Inhibition)和静默(Silences)核心特性进行简要介绍。

1、告警分组

  • 分组机制(Grouping)是指,AlertManager将同类型的告警进行分组,合并多条告警到一个通知中
    • 在实际环境中,特别是云计算环境中的业务线之间密集耦合时,若出现多台设备宕机,可能会导致成百上千个告警被触发。在这种情况下使用分组机制,可以将这些被触发的告警合并为一个告警进行通知,从而避免瞬间突发性地接收大量的告警通知,使得管理员无法对问题进行快速定位。
    • 例如,在一个Kubernetes集群中,运行着重量级规模数量的实例,即便是集群中持续一小段时间的网络延时或间歇式断开,也会引起大量应用程序无法连接数据库的故障。如果我们在Prometheus告警规则中配置为每一个服务实例都发送告警,那么最后的结果就是大量的告警被发送到Alertmanager中心。
  • 作为集群管理员,可能希望在一个通知中就能快速查看是哪些服务实例被本次故障影响了。此时,对服务所在集群或者告警名称进行分组打包配置,将这些告警紧凑在一起成为一个“大”的通知时,管理员就不会受到告警的频繁“轰炸”。
  • 告警分组、告警时间和告警接收器均是通过Alertmanager的配置文件来完成配置的

2、告警抑制

  • 抑制机制(Inhibition)是指,当某告警已经发出,停止重复发送由此告警引发的其他异常或故障的告警机制
    • 例如,在生产环境中,IDC托管机柜中,若每个机柜接入层仅仅是单台交换机,那么该机柜接入交换机故障会造成机柜中服务器非UP状态告警;再有服务器上部署的应用不可访问也会触发告警。此时,可以配置Alertmanager忽略由交换机故障造成的机柜所有服务器及其应用不可访问而产生的告警。
  • 在灾备体系中,当原集群故障宕机业务彻底无法访问时,会把用户流量切换到灾备集群中,这样为故障集群及其提供的各个微服务状态发送告警就失去了意义,此时,Alertmanager的抑制机制在一定程度上避免了管理员收到过多的触发告警通知。
  • 抑制机制也是通过Alertmanager的配置文件进行设置的

3、告警静默

  • 告警静默(Silences)提供了一个简单的机制,可以根据标签快速对告警进行静默处理。对传入的告警进行匹配检查,如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。管理员可以直接在Alertmanager的Web界面中临时屏蔽指定的告警通知。

3、部署Alertmanager

1、部署环境

  • 系统环境
    • 10.1.1.11:CentOSLinuxrelease7.7.1908(Core)
  • 软件版本
    • alertmanager:0.24.0

2、下载alertmanager

下载地址:https://prometheus.io/download/
安装包:alertmanager-0.24.0.linux-amd64.tar.gz

3、安装alertmanager

]# mkdir /apps/
]# tar zvfx alertmanager-0.24.0.linux-amd64.tar.gz -C /apps/
]# ln -s /apps/alertmanager-0.24.0.linux-amd64/ /apps/alertmanager
 
]# chown -R root:root /apps/alertmanager/

4、配置unit文件

]# vim /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=Prometheus Alertmanager Service daemon
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/apps/alertmanager/alertmanager \
  --config.file=/apps/alertmanager/alertmanager.yml \
  --storage.path=/apps/alertmanager/data/ \
  --data.retention=120h \
  --web.external-url=http://10.1.1.11:9093 \
  --web.listen-address=:9093
Restart=on-failure
[Install]
WantedBy=multi-user.target
  • alertmanager命令的参数:
    • -h, --help
    • --config.file="alertmanager.yml":Alertmanager配置文件名。
    • --storage.path="data/":存储数据的目录。
    • --data.retention=120h:要保存数据多长时间。
    • --alerts.gc-interval=30m:告警GC之间的间隔。
    • --web.config.file="":(实验)启用TLS或鉴权的配置文件路径。
    • --web.external-url=WEB.EXTERNAL-URL
      • Alertmanager对外可访问的URL(例如,如果Alertmanager通过反向代理提供服务)。用于生成返回的相对和绝对链接
      • Alertmanager本身。如果URL包含路径部分,则它将用于为Alertmanager提供的所有HTTP端点添加前缀。如果省略,相关的URL组件将自动派生。
    • --web.route-prefix=WEB.ROUTE-PREFIX:web端点内部路由的前缀。默认为--web.external-url的路径。
    • --web.listen-address=":9093":用于监听web界面和API的地址。
    • --web.get-concurrency=0:并发处理的最大GET请求数。如果为负或为零,则极限为GOMAXPROC或8,取较大的值。
    • --web.timeout=0:HTTP请求超时。如果为负或为零,则不设置超时。
    • --cluster.listen-address="0.0.0.0:9094":当前alertmanager实例监听的地址(默认是“0.0.0.0:9094”)。设置为空字符串禁用HA模式。
    • --cluster.peer=CLUSTER.PEER ...:初始化时关联的其他alertmanager实例的地址。(可能重复)。
    • --cluster.advertise-address=CLUSTER.ADVERTISE-ADDRESS:集群广播地址。
    • --cluster.peer-timeout=15s:alertmanager之间发送通知的等待时间(默认是“15s”)。
    • --cluster.gossip-interval=200ms:发送gossip消息的间隔时间。通过降低该值(更频繁),gossip消息可以更快地在集群中传播,但以增加带宽为代价。(默认是“200ms”)
    • --cluster.pushpull-interval=1m0s:gossip状态同步的时间间隔。值越小收敛越快,但消耗的带宽也会增加(默认是“1m0s”)。
    • --cluster.tcp-timeout=10s:在与其他alertmanager进行链接、读、写时TCP的超时时间(默认是“10s”)。
    • --cluster.probe-timeout=500ms:在判定其他alertmanager不可用之前的等待时间(默认是“500ms”)。
    • --cluster.probe-interval=1s:探测其他alertmanager节点的时间间隔(默认是“1s”)。该值越低(更频繁)就可以越快地检测到故障节点,但代价是增加了带宽使用量。
    • --cluster.settle-timeout=1m0s:在评估通知之前等待集群连接解决的最大时间。
    • --cluster.reconnect-interval=10s:尝试重新连接丢失的alertmanager的时间间隔。
    • --cluster.reconnect-timeout=6h0m0s:试图重新连接丢失的alertmanager的时间长度。
    • --cluster.tls-config="":(实验)可以在gossip协议中启用双向TLS的配置yaml文件路径。
    • --cluster.allow-insecure-public-advertise-address-discovery:(实验)允许alertmanager发现并监听公网IP地址。
    • --log.level=info:只记录具有给定严重性或以上级别的消息。One of: [debug, info, warn, error]
    • --log.format=logfmt:日志信息的输出格式。One of: [logfmt, json]
    • --version:显示版本。

5、启动alertmanager

//通知systemd重新加载配置文件
]# systemctl daemon-reload
 
]# systemctl enable alertmanager.service
]# systemctl start alertmanager.service
 
]# systemctl status alertmanager.service

6、验证alertmanager是否安装成功

  • 通过浏览器访问http://10.1.1.11:9093/#/status,会看到Alertmanager运行时的状态或集群状态、版本信息和默认的配置文件信息,如图6-2所示。

4、Alertmanager配置

  • 说明文档:https://prometheus.io/docs/alerting/latest/configuration/
  • Alertmanager的配置文件,是默认自带的alertmanager.yml,也是基于yaml语言格式实现的。
  • alertmanager配置文件通常包括global(全局配置)、templates(告警模板)、route(告警路由)、receivers(接收器)和inhibit_rules(抑制规则)等主要配置项模块。
  • alertmanager配置文件格式
global:
  # The default SMTP From header field.
  [ smtp_from: <tmpl_string> ]
  # The default SMTP smarthost used for sending emails, including port number.
  # Port number usually is 25, or 587 for SMTP over TLS (sometimes referred to as STARTTLS).
  # Example: smtp.example.org:587
  [ smtp_smarthost: <string> ]
  # The default hostname to identify to the SMTP server.
  [ smtp_hello: <string> | default = "localhost" ]
  # SMTP Auth using CRAM-MD5, LOGIN and PLAIN. If empty, Alertmanager doesn't authenticate to the SMTP server.
  [ smtp_auth_username: <string> ]
  # SMTP Auth using LOGIN and PLAIN.
  [ smtp_auth_password: <secret> ]
  # SMTP Auth using PLAIN.
  [ smtp_auth_identity: <string> ]
  # SMTP Auth using CRAM-MD5.
  [ smtp_auth_secret: <secret> ]
  # The default SMTP TLS requirement.
  # Note that Go does not support unencrypted connections to remote SMTP endpoints.
  [ smtp_require_tls: <bool> | default = true ]

  # The API URL to use for Slack notifications.
  [ slack_api_url: <secret> ]
  [ slack_api_url_file: <filepath> ]
  [ victorops_api_key: <secret> ]
  [ victorops_api_url: <string> | default = "https://alert.victorops.com/integrations/generic/20131114/alert/" ]
  [ pagerduty_url: <string> | default = "https://events.pagerduty.com/v2/enqueue" ]
  [ opsgenie_api_key: <secret> ]
  [ opsgenie_api_key_file: <filepath> ]
  [ opsgenie_api_url: <string> | default = "https://api.opsgenie.com/" ]
  [ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ]
  [ wechat_api_secret: <secret> ]
  [ wechat_api_corp_id: <string> ]
  [ telegram_api_url: <string> | default = "https://api.telegram.org" ]
  # The default HTTP client configuration
  [ http_config: <http_config> ]

  # ResolveTimeout is the default value used by alertmanager if the alert does
  # not include EndsAt, after this time passes it can declare the alert as resolved if it has not been updated.
  # This has no impact on alerts from Prometheus, as they always include EndsAt.
  [ resolve_timeout: <duration> | default = 5m ]

# Files from which custom notification template definitions are read.
# The last component may use a wildcard matcher, e.g. 'templates/*.tmpl'.
templates:
  [ - <filepath> ... ]

# The root node of the routing tree.
route: <route>

# A list of notification receivers.
receivers:
  - <receiver> ...

# A list of inhibition rules.
inhibit_rules:
  [ - <inhibit_rule> ... ]

# DEPRECATED: use time_intervals below.
# A list of mute time intervals for muting routes.
mute_time_intervals:
  [ - <mute_time_interval> ... ]

# A list of time intervals for muting/activating routes.
time_intervals:
  [ - <time_interval> ... ]

4.1、全局配置(global)

  • 在Alertmanager配置文件中,全局配置段中的配置项是公共设置,可以作为其他配置项的默认值,也可以被其他配置段中的配置项覆盖掉。
  • resolve_timeout用于设置处理超时时间,是声明告警状态为已解决的时间,它的时长设定有可能影响到告警恢复通知的接收时间,读者需要根据日常生产环境总结出适合自己的时长进行定义,默认为5分钟。
global:
  #如果每一次告警均需要通过电子邮件接收,可以设置用于发送电子邮件的SMTP服务器信息和通知服务
  [ smtp_smarthost: <string> ]        #邮箱SMTP服务器代理地址。示例,smtp.example.org:587
  [ smtp_from: <tmpl_string> ]        #发送邮件的名称。
  [ smtp_auth_username: <string> ]    #邮箱用户名称
  [ smtp_auth_password: <secret> ]    #邮箱密码

  #用于Slack通知的API URL。
  [ slack_api_url: <secret> ]
  [ slack_api_url_file: <filepath> ]
  [ victorops_api_key: <secret> ]
  [ victorops_api_url: <string> | default = "https://alert.victorops.com/integrations/generic/20131114/alert/" ]
  [ pagerduty_url: <string> | default = "https://events.pagerduty.com/v2/enqueue" ]
  [ opsgenie_api_key: <secret> ]
  [ opsgenie_api_key_file: <filepath> ]
  [ opsgenie_api_url: <string> | default = "https://api.opsgenie.com/" ]
  [ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ]
  [ wechat_api_secret: <secret> ]
  [ wechat_api_corp_id: <string> ]
  [ telegram_api_url: <string> | default = "https://api.telegram.org" ]
  # 默认的HTTP客户端配置
  [ http_config: <http_config> ]

  #ResolveTimeout是alertmanager使用的默认值,如果alert(告警)不包括EndsAt,经过这个时间之后,如果alert没有更新,它可以将alert声明为已解决。
  #这个配置项对Prometheus的alert没有影响,因为它们总是包括EndsAt。
  [ resolve_timeout: <duration> | default = 5m ]

4.2、告警模板(templates)

  • 告警模板可以自定义告警通知的外观格式及其包含的对应告警数据。
  • Alertmanager启动时加载该路径下的模板文件。
#templates配置项是存放告警模板的目录
templates:
  [ - <filepath> ... ]    #最后一部分可以使用通配符匹配器,例如templates/*.tmpl

4.3、告警路由(route)

  • 告警路由模块描述了在收到Prometheus server生成的告警后,将告警发送到receiver指定的目的地址的规则。
  • Alertmanager对接受到的告警进行处理,根据所定义的规则和操作进行匹配。
    • 所有路由的组合可以理解为树状结构,如果将第一个route称为根节点,那么其后的节点称为子节点。
    • 每个告警都从根节点进入路由树,按照深度优先从左向右进行遍历匹配。
      • 如果节点的continue设置为false,告警被匹配成功后,就终止对后面兄弟节点的匹配。
      • 如果节点的continue设置为true,告警被匹配成功后,也会继续对后面兄弟节点的匹配。
    • 如果告警与所有的子节点都不匹配,则根据当前节点的配置参数处理告警。
#路由树的根节点。如果子节点默认继承父节点的参数。
route:
  #配置要发送告警使用的接收器名称
  [ receiver: <string> ]
  #指定进行分组的标签。如果告警中包含的标签符合group_by中指定的标签名称,这些警告会被合并为一个通知发送给接收器,实现告警分组
  #特殊值group_by: ['...'],这会完全禁用聚合,并按原样传递所有警报。
  [ group_by: '[' <labelname>, ... ']' ]
  #接收到告警后,发送通知前要等待的间。如果在等待时间内当前goup接收到了新的告警,这些告警会被合并为一个通知进行发送。默认是30秒(通常在几分钟到几分钟之间)
  #允许等待一个抑制警报到达或为同一组收集更多的初始警报。
  [ group_wait: <duration> | default = 30s ]
  #已发送通知的gourp,再次接收到新警报后,要发送通知之前要等待的时间。默认是5分钟
  [ group_interval: <duration> | default = 5m ]
  #如果已成功为告警发送通知,再次发送完全相同的告警之前要等待的时间。默认是4小时
  [ repeat_interval: <duration> | default = 4h ]
  #(已弃用,请使用matchers)通过字符串完全匹配进行告警匹配。即当前告警中是否具有标签labelname,且等于labelvalue
  match:
    [ <labelname>: <labelvalue>, ... ]
  #(已弃用,请使用matchers)通过正则表达式进行告警匹配。即当前告警标签的值是否可以被该正则表达式匹配
  match_re:
    [ <labelname>: <regex>, ... ]
  #警报必须完成的匹配节点的匹配器列表。
  matchers:
    [ - <matcher> ... ]
  #若为false,且该告警可以匹配该节点就会终止匹配,即忽略后面的兄弟节点;若为true,告警则会继续进行后面兄弟节点的匹配
  [ continue: <boolean> | default = false ]
  #当路由应该静音的时候。它们必须与mute_time_interval部分中定义的静音时间间隔的名称相匹配。
  #当路由被静默时,它不会发送任何通知,但在其他方面会正常运行(包括在没有设置“continue”选项时结束路由匹配过程)。
  #根节点不能有任何静默时间。
  mute_time_intervals:
    [ - <string> ...]
  #路由应该处于活动状态的时间。它们必须与time_interval部分中定义的时间间隔的名称相匹配。空值表示路由始终处于活动状态。
  #根节点不能有任何活动时间。
  #路由只在激活时发送通知,其他情况下正常工作(包括在没有设置continue选项时结束路由匹配过程)。
  active_time_intervals:
    [ - <string> ...]
  #可以有零或多个子路由。
  routes:
    [ - <route> ... ]

示例:

#路由树的根节点。如果子节点默认继承父节点的参数。
route:
  receiver: 'default-receiver'
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  group_by: [cluster, alertname]
  #如果告警与下面所有子节点不匹配,就使用根节点的规则,并被发送到接收器'default-receiver'。
  routes:
  #所有带有service=mysql或service=cassandra标签的告警都被该子节点匹配,并发送到接收器'database-pager'。
  - receiver: 'database-pager'
    group_wait: 10s
    matchers:
    - service=~"mysql|cassandra"
  #所有带有team=frontend标签的告警都被该子节点匹配,并发送到接收器'frontend-pager'
  #按产品和环境分组,而不是按集群和警报名称分组。
  - receiver: 'frontend-pager'
    group_by: [product, environment]
    matchers:
    - team="frontend"
  #所有带有service=inhouse-service标签的告警都被该子节点匹配,并发送到接收器'dev-pager'
  #该节点在非工作时间和节假日时间会静默。
  #即使告警被该节点匹配,也会继续匹配后面的兄弟节点
  - receiver: 'dev-pager'
    matchers:
      - service="inhouse-service"
    mute_time_intervals:
      - offhours
      - holidays
    continue: true
  #所有带有service=inhouse-service标签的警报都被该子节点匹配,并发送到接收器'on-call-pager'
  #该节点仅在非工作时间和节假日时间段激活
  - receiver: 'on-call-pager'
    matchers:
      - service="inhouse-service"
    active_time_intervals:
      - offhours
      - holidays

4.4、告警接收器(receivers)

  • 接收器是一个统称,每个receiver需要设置一个全局唯一名称,并且对应一个或者多个通知方式,包括电子邮箱、微信、PagerDuty、HipChat和Webhook等。
receivers:
  #接收者的唯一名称。
  name: <string>
  #使用电子邮件进行告警通知
  email_configs:
    [ - <email_config>, ... ]
  opsgenie_configs:
    [ - <opsgenie_config>, ... ]
  pagerduty_configs:
    [ - <pagerduty_config>, ... ]
  pushover_configs:
    [ - <pushover_config>, ... ]
  slack_configs:
    [ - <slack_config>, ... ]
  sns_configs:
    [ - <sns_config>, ... ]
  victorops_configs:
    [ - <victorops_config>, ... ]
  #使用webhook接收器进行自定义告警通知
  webhook_configs:
    [ - <webhook_config>, ... ]
  #使用微信进行告警通知
  wechat_configs:
    [ - <wechat_config>, ... ]
  telegram_configs:
    [ - <telegram_config>, ... ]

4.5、抑制规则(inhibit_rules)

  • 在inhibit_rule模块中实现告警抑制功能,指定在特定条件下要忽略的告警条件。可以使用此选项设置首选项,例如优先处理某些告警,如果同一组中的告警同时发生,则忽略其他告警。合理设置抑制规则可以减少“垃圾”告警的产生。
  • 应该避免source_matchs和target_matchs之间的重叠,否则很难理解和维护。建议谨慎使用此功能。
    • 使用基于症状的告警时,告警之间很少需要依赖链。
    • 针对数据中心中断等大规模故障时可以保留抑制规则。
inhibit_rules:
  #要静音的目标告警必须满足的匹配器列表。
  target_matchers:
    [ - <matcher> ... ]
  #要使抑制生效,必须存在一个或多个告警的匹配器列表。
  source_matchers:
    [ - <matcher> ... ]
  #要使抑制生效,必须在源和目标告警中具有相等值的标签。
  [ equal: '[' <labelname>, ... ']' ]

  #已弃用,请使用target_matchers
  target_match:
    [ <labelname>: <labelvalue>, ... ]
  #已弃用,请使用target_matchers
  target_match_re:
    [ <labelname>: <regex>, ... ]
  #已弃用,请使用source_matchs
  source_match:
    [ <labelname>: <labelvalue>, ... ]
  #已弃用,请使用source_matchs
  source_match_re:
    [ <labelname>: <regex>, ... ]

5、Prometheus告警规则

  • 使用Prometheus的默认配置文件prometheus.yml来实现Prometheus server与alertmanager组件的关联。

5.1、与Alertmanager关联

  • Prometheus与Alertmanager进行关联是在prometheus.yml文件中配置的

1、将告警关联到Alertmanager

  • 基于文件的服务发现关联到相应的Alertmanager。
//修改prometheus.yml配置文件
]# vim /apps/prometheus/prometheus.yml
alerting:
  alertmanagers:
  - file_sd_configs:
    - files:
      - tatgets/alertmanagers.yaml
      refresh_interval: 60s

//基于文件的服务发现的YAML文件
]# vim /apps/prometheus/tatgets/alertmanagers.yaml
- targets:
  - 10.1.1.11:9093
  labels:
    "app": "alertmanager"

2、监控Alertmanager

  • 监控Alertmanager与监控nodes_exporter一样,Alertmanager公开了相关指标。
#基于文件的服务发现
]# vim /apps/prometheus/prometheus.yml
scrape_configs:
- job_name: "file_sd_Alertmanager"
  file_sd_configs:
  - files:
    - tatgets/alertmanagers.yaml
    refresh_interval: 60s

3、重新加载prometheus.yml配置文件

//检查配置文件
promtool check config /apps/prometheus/prometheus.yml
 
//重新加载配置文件
]# kill -HUP PID

4、查看是否添加成功

  • 通过浏览器访问Prometheus Web UI:
    • 查看targets:http://10.1.1.11:9090/targets
    • 查看生效的配置内容:http://10.1.1.11:9090/config

5.2、告警规则

  • 告警规则文件使用YAML格式进行定义,在Prometheus server中使用PromQL配置实际告警触发条件,Prometheus会根据告警规则及配置周期进行周期性计算,若满足触发条件则会触发告警通知。
  • 告警规则是配置在prometheus.yml文件中的
    • 默认情况下Prometheus对设置的告警规则进行计算的时间间隔是1分钟,可以使用global中的evaluation_interval配置项设置间隔时间。
  • 告警规则可以存放到指定文件中,也可以存放到指定的目录中,为了方便管理也可以把告警规则拆分成多个文件,以特定的命名格式被Prometheus.yml加载。
]# vim /apps/prometheus/prometheus.yml
rule_files:
- /apps/prometheus/rules/
- rules/second_rules.yml
  • 定义告警规则的格式
groups:
- name: <string>                          #告警规则组的名称
  rules:
  - alert: <string>                       #告警规则的名称
    expr: <string>                        #使用PromQL表达式定义触发告警的条件,如果有时间序列满足该条件就会触发告警
    [ for: <duration> | default = 0s ]    #可选参数,触发告警的条件持续多久时间后,才会发送通知
    labels:                               #自定义标签,允许指定额外的标签附加到告警上
      [ <labelname>: <labelvalue> ]
    annotations:
      [ <labelname>: <tmpl_string> ]      #可用来设置有关告警的一组信息标签,例如对告警的简要说明文字或者相关地址链接,其内容在告警产生时会一起作为参数发送到Alertmanager
  • 对一个新的服务进行监控,并添加告警规则,可分为三个步骤
    • (1)在prometheus.yml中添加target
    • (2)在Prometheus.yml中指定要加载的告警规则的文件
    • (3)创建告警规则文件

示例:

//(1)在prometheus.yml中添加target
- job_name: 'node'
  static_configs:
  - targets: ['10.1.1.13:9100']

//(2)在Prometheus.yml中指定要加载的告警规则的文件
rule_files:
- /apps/prometheus/rules/*_rules.yml

//(3)创建告警规则文件
]# vim /apps/prometheus/rules/up_rules.yml
groups:
- name: UP
  rules:
  - alert: node
    expr: up == 0
    for: 3m
    labels:
      severity: critical
    annotations:
      description: "Node has been down for more than 3 minutes."
      summary: "Node down"
  • 查看生效的告警规则:http://10.1.1.11:9090/rules

  • 查看是否有告警:http://10.1.1.11:9090/alerts

  • 一个告警信息在生命周期中可能会处于三种状态
    • Interval:没有满足触发条件,告警未激活状态。
    • Pending:已满足触发条件,但未满足告警持续时间的状态,即未满足告警中for子句中指定的持续时间。
    • Firing,已满足触发条件且已经超过for子句中指定的持续时间时的状态。
  • 带有for子句的告警将首先转换为Pending状态,然后转换为Firing状态,至少需要两个计算周期告警才被触发。从Pending状态到Firing状态的转换,确保了告警的有效性。而没有for子句的告警会自动从Inactive状态转换为Firing状态,只需要一个计算周期即可被触发。
  • 在状态转换过程中,Prometheus将为Pending或Firing状态的每个告警创建一个ALERTS指标名称,格式如下:
ALERTS{alertname="<alert name>", alertstate="<pending or firing>", <additional alert labels>}

  • Prometheus从收集监控目标信息开始,到触发一条告警的过程。
    • (1)定义规则。
      • 在Prometheus配置文件中,配置scrape_interval:15s(默认值是1min)为收集监控目标信息的采集周期,并且配置对应的告警规则。scrape_interval可以是全局设置,也可以是单metric定义。
    • (2)周期计算。
      • 对相应的表达式进行计算时,在Prometheus配置文件中配置evaluation_interval:15s(默认值是1min)为告警规则计算周期,evaluation_interval只是全局计算周期值。
    • (3)告警状态转换。
      • 当首次发现告警规则条件成立,即表达式为真,并且没有满足告警规则中for子句中指定的持续时间时,告警状态切换为PENDING。
      • 若下一个计算周期中,表达式仍然为真,并且满足告警规则中for子句中指定的持续时间时,告警状态转换成FIRING,告警被Prometheus发送到Alertmanager组件。
      • 若下下个计算周期,表达式还是为真,并且满足告警规则中for子句中指定的持续时间时,持续发送告警到Alertmanager组件。
      • 直到某个计算周期,表达式为假,告警状态会变为inactive,并且会有一个resolve被发送给Altermanger,用于说明此告警已解决。

5.3、告警规则的模板

  • 模板是在告警中使用时间序列数据的标签和值的一种方法,可以用于告警规则中的注释(annotations)和标签(labels)。
  • 模板使用标准的Go模板语法,并公开一些包含时间序列的标签和值的变量。允许将查询的值格式化以便更具可读性,甚至可以执行其他PromQL查询来向告警添加额外的内容,同时Alertmanager Web中也会根据这标签值显示告警信息。
    • 通过{{$labels.<labelname>}}变量引用当前告警实例中指定标签的值。
    • 通过{{$value}}变量引用当前PromQL表达式计算的样本值。
]# vim /apps/prometheus/rules/up_rules.yml
groups:
- name: UP
  rules:
  - alert: node
    expr: up == 0
    for: 3m
    labels:
      severity: critical
    annotations:
      summary: "Instance {{ $labels.instance }} down"
      description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 3 minutes."
  • 注意,一个稳定的Prometheus系统中,要保持适量的模板化,因为在告警中提供所有可能的调试信息不仅运行缓慢而且容易混淆调用。

6、使用Email实现告警通知

  • 电子邮件告警通知方式是管理员使用最普遍的方式,在Alertmanager组件中内置了对SMTP协议支持。
  • 分别在global和receivers段中添加一下内容。
global:
  #如果每一次告警均需要通过电子邮件接收,可以设置用于发送电子邮件的SMTP服务器信息和通知服务
  [ smtp_smarthost: <string> ]        #发送邮箱SMTP服务器代理地址。示例,smtp.example.org:587
  [ smtp_from: <tmpl_string> ]        #发送邮件的用户名称。
  [ smtp_auth_username: <string> ]    #邮箱用户名称
  [ smtp_auth_password: <secret> ]    #邮箱密码
receivers:
  name: <string>
  email_configs:
    [ send_resolved: <boolean> | default = false ]    #告警解除后是否发送通知,默认是false
    to: <tmpl_string>                                 #设置接收告警通知的email地址
    #若有自定义通知模板以下选项可以设置,系统有默认模板
    [ from: <tmpl_string> | default = global.smtp_from ]
    [ headers: { <string>: <tmpl_string>, ... } ]     #进一步的标题电子邮件标题键/值对。覆盖通知实现先前设置的任何标头。
  • 下面使用QQ邮箱实现告警通知的步骤
    • prometheus的工作流程:
      • (1)发现并监控target。(scrape_configs定义怎么发现target)
      • (2)检查告警规则,如果有触发告警的,就发送给alertmanager。(rule_files定义告警规则)
      • (3)通过关联alertmanager的配置,找到alertmanager。(alerting定义怎么关联alertmanager)
    • alertmanager的工作流程:
      • (1)alertmanager接收到来自prometheus的告警,然后根据路由树将告警发送给告警接收器。(route定义路由树)
      • (2)告警接收器使用告警模板将告警发送给邮件。(receivers定义告警接收器,templates定义告警模板)

6.1、配置prometheus

1、修改prometheus.yml配置文件

  • prometheus的工作流程:
    • (1)发现并监控target
    • (2)检查告警规则,如果有触发告警的,就发送给alertmanager。
    • (3)通过关联alertmanager的配置,找到alertmanager
]# vim /apps/prometheus/prometheus.yml
#全局配置
global:
  scrape_interval: 15s        #收集指标数据的周期
  evaluation_interval: 15s    #计算告警规则的周期
#关联alertmanager
alerting:
  alertmanagers:
  - file_sd_configs:          #使用基于文件的服务发现关联alertmanager
    - files:
      - /apps/prometheus/tatgets/alertmanagers.yaml
      refresh_interval: 60s
#告警规则
rule_files:
- /apps/prometheus/rules/*_rules.yml
#发现target
scrape_configs: 
- job_name: "prometheus"
  static_configs:
  - targets: ["localhost:9090"]
- job_name: 'node'
  static_configs:
  - targets: ['10.1.1.13:9100']

2、定义发现alertmanager服务的yaml文件

]# vim /apps/prometheus/tatgets/alertmanagers.yaml
- targets:
  - 10.1.1.11:9093
  labels:
    "app": "alertmanager"

3、定义告警规则的yaml文件

]# vim /apps/prometheus/rules/up_rules.yml
groups:
- name: UP           #告警规则组的名字
  rules:
  - alert: node      #告警规则的名称
    expr: up == 0    #使用PromQL表达式定义告警规则(触发就告警)
    for: 30s         #触发告警规则后,发送通知前要等待的时间
    labels:
      severity: "告警级别critical"
      team: "维护团队OPS"
    annotations:
      title: "告警名称Instance {{ $labels.instance }} down"
      description: "告警信息{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 3 minutes."
  • 重新加载prometheus.yml配置文件
//检查配置文件
promtool check config /apps/prometheus/prometheus.yml
 
//重新加载配置文件
]# kill -HUP PID

6.2、配置alertmanager

1、修改alertmanager.yml配置文件

]# vim /apps/alertmanager/alertmanager.yml
global:
  resolve_timeout: 5m                        #告警的状态从firing变为resolve后还要多长时间,才解除告警
  smtp_smarthost: 'smtp.qq.com:465'          #发送告警的邮箱SMTP服务器代理地址
  smtp_from: 'xxx@qq.com'                    #发送告警的邮箱用户名
  smtp_auth_username: 'xxx@qq.com'           #发送告警的邮箱用户名
  smtp_auth_password: 'xxx'                  #发送告警的邮箱的“客户端授权密码”
  smtp_require_tls: false                    #不使用tls通信
route:
  group_by: ['alertname']    #根据标签对告警进行分组
  group_wait: 10s            #接收到告警后,发送通知前要等待的间。
  group_interval: 10s        #已发送通知的gourp,再次接收到新警报后,要发送通知之前要等待的时间。
  repeat_interval: 10s       #如果已成功为告警发送通知,再次发送完全相同的告警之前要等待的时间。
  receiver: 'email'          #告警接收器
receivers:
- name: 'email'
  email_configs:
  - to: 'xxx@xxx.com.cn'           #接收告警通知的邮箱用户名
    send_resolved: true                         #告警解除后是否发送通知,默认是false
    html: '{{ template "email.default.html" . }}'
inhibit_rules:
- source_matchers:
  - severity = critical
  target_matchers:
  - severity = warning'
  equal: ['alertname', 'dev', 'instance']
templates:
- '/apps/alertmanager/template.tmpl'

2、配置邮件告警通知的模板

]# vim /apps/alertmanager/template.tmpl
{{ define "__subject" }}
{{ if gt (len .Alerts.Firing) 0 -}}
{{ range .Alerts }}
{{ .Labels.alertname }}{{ .Annotations.title }}
{{ end }}{{ end }}{{ end }}

{{ define "email.default.html" }}
{{ range .Alerts }}
告警名称: {{ .Annotations.title }} <br>
告警级别: {{ .Labels.severity }} <br>
告警主机: {{ .Labels.instance }} <br>
告警信息: {{ .Annotations.description }} <br>
维护团队: {{ .Labels.team }} <br>
告警时间:{{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }} <br>
{{ end }}{{ end }}
  • 告警通知的样式:

3、重新加载alertmanager.yml配置文件

//使用amtool检查alertmanager.yml配置文件是否正确
]# amtool check-config /apps/alertmanager/alertmanager.yml

//重新加载alertmanager.yml配置文件
]# kill -HUP PID

7、使用钉钉实现告警通知

  • 下面使用钉钉实现告警通知的步骤。
    • prometheus的工作流程:
      • (1)发现并监控target。(scrape_configs定义怎么发现target)
      • (2)检查告警规则,如果有触发告警的,就发送给alertmanager。(rule_files定义告警规则)
      • (3)通过关联alertmanager的配置,找到alertmanager。(alerting定义怎么关联alertmanager)
    • alertmanager的工作流程:
      • (1)alertmanager接收到来自prometheus的告警,然后根据路由树将告警发送给告警接收器。(route定义路由树)
      • (2)告警接收器将告警发送给webhook-dingtalk(钉钉插件)。(receivers定义告警接收器,templates定义告警模板)
      • (3)webhook-dingtalk使用告警模板将告警发送给钉钉

7.1、创建钉钉机器人

  • (1)创建一个钉钉群
  • (2)群设置(进入群聊) - 智能群助手 - 添加机器人 - 添加机器人 - 自定义

  • (3)获取Webhook和加签。
    • 群设置 - 智能群助手 - 刚刚添加的机器人

 

7.2、配置prometheus

1、修改prometheus.yml配置文件

]# vim /apps/prometheus/prometheus.yml
#全局配置
global:
  scrape_interval: 15s        #收集指标数据的周期
  evaluation_interval: 15s    #计算告警规则的周期
#关联alertmanager
alerting:
  alertmanagers:
  - file_sd_configs:          #使用基于文件的服务发现关联alertmanager
    - files:
      - /apps/prometheus/tatgets/alertmanagers.yaml
      refresh_interval: 60s
#告警规则
rule_files:
- /apps/prometheus/rules/*_rules.yml
#发现target
scrape_configs: 
- job_name: "prometheus"
  static_configs:
  - targets: ["localhost:9090"]
- job_name: 'node'
  static_configs:
  - targets: ['10.1.1.13:9100']

2、定义发现alertmanager服务的yaml文件

]# vim /apps/prometheus/tatgets/alertmanagers.yaml
- targets:
  - 10.1.1.11:9093
  labels:
    "app": "alertmanager"

3、定义告警规则的yaml文件

]# vim /apps/prometheus/rules/up_rules.yml 
groups:
- name: UP           #告警规则组的名字
  rules:
  - alert: node      #告警规则的名称
    expr: up == 0    #使用PromQL表达式定义告警规则(触发就告警)
    for: 30s         #触发告警规则后,发送通知前要等待的时间
    labels:
      severity: "告警级别critical"
      team: "维护团队OPS"
    annotations:
      title: "告警名称Instance {{ $labels.instance }} down"
      description: "告警信息{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 3 minutes."

4、重新加载prometheus.yml配置文件

//检查配置文件
promtool check config /apps/prometheus/prometheus.yml
 
//重新加载配置文件
]# kill -HUP PID

7.3、配置prometheus-webhook-dingtalk

1、安装prometheus-webhook-dingtalk

]# wget https://github.com/timonwong/prometheus-webhook-dingtalk/releases/download/v2.1.0/prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz
]# tar zvfx prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz /apps/
]# ln -s /apps/prometheus-webhook-dingtalk-2.1.0.linux-amd64 /apps/prometheus-dingtalk

]# cp /apps/prometheus-dingtalk/config{.example,}.yml

2、配置prometheus-webhook-dingtalk

]# vim /apps/prometheus-dingtalk/config.yml
templates:
- /apps/prometheus-dingtalk/contrib/templates/legacy/template.tmpl
targets:
  webhook1:    #在alertmanager.yml配置文件的url中使用
    url: https://oapi.dingtalk.com/robot/send?access_token=xxx    #钉钉群机器人的Webhook
    secret: xxx                                                   #钉钉群机器人的加签
    message:
      title: '{{ template "ops.title" . }}'
      text: '{{ template "ops.content" . }}'

3、告警通知模板

]# vim /apps/prometheus-dingtalk/contrib/templates/legacy/template.tmpl
{{ define "__ops_alert_list" }}{{ range . }}
---
**告警名称**: {{ index .Annotations "title" }} 

**告警级别**: {{ .Labels.severity }} 

**告警主机**: {{ .Labels.instance }} 

**告警信息**: {{ index .Annotations "description" }}

**维护团队**: {{ .Labels.team | upper }}

**告警时间**: {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}
{{ end }}{{ end }}

{{ define "__ops_resolved_list" }}{{ range . }}
---
**告警名称**: {{ index .Annotations "title" }}

**告警级别**: {{ .Labels.severity }}

**告警主机**: {{ .Labels.instance }}

**告警信息**: {{ index .Annotations "description" }}

**维护团队**: {{ .Labels.team | upper }}

**告警时间**: {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}

**恢复时间**: {{ dateInZone "2006.01.02 15:04:05" (.EndsAt) "Asia/Shanghai" }}
{{ end }}{{ end }}

{{ define "ops.title" }}
{{ template "__subject" . }}
{{ end }}

{{ define "ops.content" }}
{{ if gt (len .Alerts.Firing) 0 }}
**====侦测到{{ .Alerts.Firing | len  }}个故障====**
{{ template "__ops_alert_list" .Alerts.Firing }}
---
{{ end }}

{{ if gt (len .Alerts.Resolved) 0 }}
**====恢复{{ .Alerts.Resolved | len  }}个故障====**
{{ template "__ops_resolved_list" .Alerts.Resolved }}
{{ end }}
{{ end }}
  • 告警通知的样式:

4、启动prometheus-webhook-dingtalk

//可以看到监听的端口是10.1.1.11:8060
]# /apps/prometheus-dingtalk/prometheus-webhook-dingtalk --config.file=/apps/prometheus-dingtalk/config.yml

7.4、配置alertmanager

1、修改alertmanager.yml配置文件

]# vim /apps/alertmanager/alertmanager.yml 
global:
  resolve_timeout: 5m              #告警的状态从firing变为resolve后还要多长时间,才解除告警
route:
  group_by: ['alertname']          #根据标签对告警进行分组
  group_wait: 10s                  #接收到告警后,发送通知前要等待的间。
  group_interval: 10s              #已发送通知的gourp,再次接收到新警报后,要发送通知之前要等待的时间。
  repeat_interval: 10s             #如果已成功为告警发送通知,再次发送完全相同的告警之前要等待的时间。
  receiver: 'dingding.webhook1'    #告警接收器
receivers:
- name: 'dingding.webhook1'
  webhook_configs:
  - url: 'http://10.1.1.11:8060/dingtalk/webhook1/send' 
    send_resolved: true
inhibit_rules:
- source_matchers:
  - severity = critical
  target_matchers:
  - severity = warning'
  equal: ['alertname', 'dev', 'instance']

2、重新加载alertmanager.yml配置文件

//使用amtool检查alertmanager.yml配置文件是否正确
]# amtool check-config /apps/alertmanager/alertmanager.yml

//重新加载alertmanager.yml配置文件
]# kill -HUP PID

1

#                                                                                                                                      #
posted @ 2022-10-16 17:34  麦恒  阅读(346)  评论(0编辑  收藏  举报