前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6.Prometheus监控入门之企业监控实战警报发送

6.Prometheus监控入门之企业监控实战警报发送

作者头像
全栈工程师修炼指南
发布2022-09-29 19:16:12
2.5K0
发布2022-09-29 19:16:12
举报
文章被收录于专栏:全栈工程师修炼之路

[TOC]

0x00 Alertmanager 快速入门

1.基础介绍

描述: Alertmanager 负责接收来自所有Prometheus服务器的告警,并根据其规则将告警以邮件、聊天信息和呼叫等方式进行通知。

Tips : 注意在使用告警规则文件前必须在prometheus.yaml中设置抓取目标以及加载规则文件,使用记录告警规则可以让Prometheus定期执行PromQL表达式并记录其结果。

代码语言:javascript
复制
alerting:
  alertmanagers:
  - follow_redirects: true
    scheme: http
    timeout: 10s
    api_version: v2
    static_configs:
    - targets:
      - localhost:9093

Prometheus 告警分为两个部分进行实现监控规则匹配以及告警信息的通知。

  • 1) 首先需要在Prometheus中添加告警规则,定义告警产生的逻辑。
  • 2) 其次Alertmanager系统将触发的警报转化为通知,例如邮件、呼叫和聊天消息。

通知管道流程

  • 降噪: 选择忽略同时出现的告警,或者发送更高级别的警告。 可利用inhibition标签。
  • 静音: 通过Web界面的添加需要Silences暂时忽略的告警。
  • 路由: 以不同方式处理生产和开发环境的告警,并将告警其分别发送到指定的对象中。
  • 分组: 针对告警进行分组安装其警告级别。
  • 抑制与重复: 防止大量的相同的警告,在处理阶段重复报警,这可能会错过新的报警信息,所以我们需要设置间间隔时间参数repeat_interval
  • 通知: 将告警发送到指定的receiver标签指定的接受者,并且我们可以自定义通知模板。

告警状态 Prometheus Alert 告警状态有三种状态:Inactive、Pending、Firing

  • Inactive:非活动状态,表示正在监控,但是还未有任何警报触发。
  • Pending:表示这个警报必须被触发。由于警报可以被分组、压抑/抑制或静默/静音,所以等待验证,一旦所有的验证都通过,则将转到 Firing 状态。
  • Firing:将警报发送到 AlertManager,它将按照配置将警报的发送给所有接收者。一旦警报解除则将状态转到 Inactive如此循环。

参考来源

2.关键配置浅析

描述: 下面主要讲解接收者(receiver)、路由树(route)、分组(Groupby)、抑制重复、已处理通知、抑制警告。

接收者 描述: receiver 字段指定了告警通知哪种方式进行发送,国内常用email、webhook、钉钉或者企业微信等方式进行告警,它也支持HipChat、PagerDuty(可以进行确认警告)、Pushover、Slack、OpsGenie、VictorOps等。

路由树 描述: route 字段指定顶级它是默认路由,根路由下可以设置许多字路由(你可将其比喻作根域名),路由的匹配是当告警规则到来后根据其携带的标签进行判断,如果匹配子路由1的规则就会匹配次路由并且停止继续匹配,如果不匹配将会对子路由2的规则进行匹配,如都没匹配到则采用根路由的设置。

Tips : Prometheus 官方有提供一个可视化路由编辑器,可以显示该树以及告警遵循的路由。

分组 描述: group_by 字段允许你指定标签列表对告警进行分组,在未设置分组时该路由默认将所有路由都放入一个组中,意味着你将得到一个内容很大的通知。当在设置分组后可以按照报警等级、环境、以及location来进行拆分警告。

注意: 通常按照instance标签进行分组并不是一个好主意,因为当存在影响整个应用程序的问题时,它可能会导致大量信息。

代码语言:javascript
复制
# 个人理解(伪配置)
group_by: ['team']
  group_by: ['env','region']
  match_re: 
    severity: (page|ticket) # 重要事件&通知单

# severity标签值为ticket和page的记录也将按照region和env进行分组。
        env {page|ticket} 
team -> 
        region (page|ticket)

抑制重复 描述: 如果你不希望每次触发告警后当告警集发生改变时都将收到新的通知,这会导致大量的垃圾邮件。

此时我们可以使用 group_wait(每个来的警告组【Firing】发送等待) 与 group_interval(发送一个警告组后,下一组警告组的等待时间) 、repeat_interval(发送警告成功后,如果在上面两个参数指定的时间内没有完成时,将等待该参数时间到了,便继续发送-推荐设置4H)来设置Altermanager通知分组限制。

Tips : repeat_interval 必须要比 group_interval 大否则将无任何意义。

已处理通知 描述: send_resolved 字段,当告警问题解决后是否发送通知,启用后将在下一个通知包含此告警,如果列表中没有其它告警触发,它甚至只会发送已经解决通知的警告。

  • .Alert.Firing 将仅仅提供触发告警的列表。
  • .Alert.Resolved 将提供已解决的告警列表。

抑制警告 描述: inhibit_rules 字段 ,允许你在其它告警被触发时将某些警告视为不触发。例如数据迁移后旧的机器出现问题但由于用户数据已经转移到其它地方,那么发送此种警告便没有多大意义。

代码语言:javascript
复制
# (1) 全局设置
global:
  # - QQ企业邮件通知相关配置
  resolve_timeout: 5m
  smtp_from: 'monitor@weiyigeek.top'
  smtp_smarthost: 'smtp.exmail.qq.com:465'
  smtp_auth_username: 'monitor@weiyigeek.top'
  smtp_auth_password: 'xxxxxxxxxxxxxxx'
  smtp_require_tls: false

# (2) 告警模板&告警接收者
templates:
- '/etc/alertmanager/*.tmpl'

- name: 'email-notify'
  email_configs:
  - send_resolved: true  # 如设置为true问题已解决将发送信息,如设置false则不发送
    from: 'monitor@weiyigeek.top'
    to: '{{ template "email.to" . }}'
    html: '{{ template "email.to.html" . }}'
   
- name: 'wechat-notify'
  wechat_configs:
  - send_resolved: true
    api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
    corp_id: 'ww32cf0bf4e14b11487'
    agent_id: '1000002'
    api_secret: 'SYCdXbWj5SjdT9p1OSQnjIZ4RF_SIRqERVuZNWE1yE5g'
    to_user: '@all'
    to_party: '1'
    message: '{{ template "wechat.default.message" . }}'

- name: 'wehook-notify'
  webhook_configs:
  - url: http://webhook.weiyigeek.top:8888/alert


# 抑制告警规则: 如果存在severity标签值为critical告警,将会抑制带有severity标签值为warning以及service标签的警告。
inhibit_rules:
- source_match:
    severity: 'critical'
  target_match:
    severity: 'warning'
  equal: ['service']

# (3) 路由树
route:
  # 路由默认通知接收器为邮箱通知
  receiver: 'email-notify'  
  group_by: ['team'] # 默认路由告警按照team标签进行分组,如没有该标签的告警将不会进行后续匹配。
  group_wait: 30s    # 当传入警报创建新的警报组时,请至少等待“group_wait”以发送初始通知。
  group_interval: 5m  # 发送第一个通知时,请等待“group_interval”以发送一批新警报,这些警报已开始为该组触发。
  repeat_interval: 4h # 如果警报已成功发送,请等待“重复间隔”发送警报。
  # continue: true    # 当匹配一个路由后它不会停止继续向下查找,主要用于将告警记录记录到另外一个系统。
  # 非常注意: 所有上述属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。

  # * 子路由设置 
  routes:
  # 前端团队,开发测试环境主机(team/severity)分别是在告警规则文件中设置的标签。
  - match:
      team: frontend
      env: dev
    group_by: ['region','env'] # frontend 团队根据region和env标签对告警进行分组,它针对后续子路有效,因此它们severity标签值为ticket和page的记录也将按照region和env进行分组。
    group_interval: 6m       # 组警告之间的间隔时间
    receiver: 'email-notify' # 没有匹配到下述条件的告警将发送给该接收者。
    # 还可嵌套子路由
    routers:
    - match: 
        severity: page  # 重要事件
      receiver: 'frontend-pager'
      group_wait: 1m        # 组警告等待
    - match: 
        severity: ticket # 通知单
      receiver: 'frontend-pager'

  # 后端团队,开发测试环境主机
  - match:
      team: backend
      env: dev
    receiver: 'email-notify'
    # 还可嵌套子路由
    routers:
    - match: 
        severity: page  # 重要事件
      receiver: 'backend-pager'
    - match: 
        severity: ticket # 通知单
      receiver: 'backend-pager'

  # 全团队,线上环境
  - match:
      env: prod
    receiver: 'wechat-notify'
    # 还可嵌套子路由
    routers:
    - match: 
        severity: critical     # 极为严重
      receiver: 'wechat-notify-manager'
    # 支持正则匹配就不用写多行标签了。
    - match_re: 
        severity: (page|ticket) # 重要事件&通知单
      receiver: 'wechat-notify-devops'

0x01 Alertmanager 规则与模板

描述: 我们知道 Alertmanager 要进行警告必须需要编写对应的告警规则,然后以告警自定义模板文件进行通知接收者。

1.告警规则最佳实践

  • 1) 编写完prometheus.ymlrule.yml文件后分别使用promtool check (config|rules) 进行检测。
  • 2) 规则名称必须唯一,命名规则level:metric:operations如是job_name:up:rate5m
  • 3) 提高查询效率降低基数大小,针对相同的指标使用不同的标签集来制定聚合规则。
  • 4) 对于记录规则,应该避免在表达式中进行过滤,因为时间序列的出现或消失都很难处理。

Tips : 对于告警规则过滤是必不可少的,评估告警表达式返回空的瞬时向量不会触发任何告警规则,但如果任何样本返回每个都将成为告警。

基础告警规则配置:

代码语言:javascript
复制
groups:
- name: node-alert
  rules:
  - alert: "监控节点丢失或宕机"
    expr: avg without()(up) < 1
    for: 2m
    labels:
      severity: 'critical'
    annotations:
      message: "服务器实例 [{{ $labels.instance }}]节点丢失或宕机,"
      description: "请系统管理员尽快进行人工干预处理!"
  - alert: "L-五分钟内CPU使用率大于90%"
    expr: (node_load5 /ignoring(mode) count without(cpu)(node_cpu_seconds_total{mode="idle"}) * 100) > 90
    for: 3m
    labels:
      severity: warning
    annotations:
      message: "服务器实例 {{ $labels.instance }} CPU 使用率 告警通知"
      description: "{{ $labels.instance }}CPU使用率已超过90%, 当前值: {{ $value }}%"

  - alert: "L-内存可用容量小于 10%"
    expr: ((node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes) / (node_memory_MemTotal_bytes )) * 100 > 80
    for: 2m
    labels:
      severity: warning
    annotations:
      message: "服务器实例 {{ $labels.instance }} 内存不足 告警通知"
      description: "{{ $labels.instance }} 内存可用资源已不足 10%,当前值: {{ $value }} %"

  - alert: "L-磁盘可用容量小于 10%"
    expr: round(100 - ((node_filesystem_avail_bytes{mountpoint=~".*",fstype=~"nfs|ext4|xfs|ext2|ext3"} * 100) / node_filesystem_size_bytes {mountpoint=~".*",fstype=~"nfs|ext4|xfs|ext2|ext3"}) > 90)
    for: 3m
    labels:
      severity: warning
    annotations:
      message: "服务器实例 {{ $labels.instance }} 磁盘不足 告警通知"
      description: "{{ $labels.instance }} 磁盘 {{ $labels.device }} 资源 已不足 10%, 当前值: {{ $value }}%"

  - alert: "W-内存可用容量小于 10%"
    expr: round((1 - (windows_os_physical_memory_free_bytes / windows_cs_physical_memory_bytes)) * 100) > 90
    for: 2m
    labels:
      severity: warning
    annotations:
      message: "服务器实例 {{ $labels.instance }} 内存不足 告警通知"
      description: "{{ $labels.instance }} 内存可用资源已不足 10%,当前值: {{ $value }}"

  - alert: "W-磁盘可用容量小于 10%"
    expr: round((1 - windows_logical_disk_free_bytes{volume=~"C:|D:|E:|F:"} / windows_logical_disk_size_bytes{volume=~"C:|D:|E:|F:"} ) * 100 > 90)
    for: 3m
    labels:
      severity: warning
    annotations:
      message: "服务器实例 {{ $labels.instance }} 磁盘不足 告警通知"
      description: "{{ $labels.instance }} 磁盘 {{ $labels.volume }} 资源 已不足 10%, 当前值: {{ $value }}%"

  - alert: "W-五分钟内CPU使用率大于 90%"
    expr: round(100 - ((avg without(core,mode)(irate(windows_cpu_time_total{mode="idle"}[5m]))) * 100) > 90)
    for: 3m
    labels:
      severity: warning
    annotations:
      message: "服务器实例 {{ $labels.instance }} CPU 使用率 告警通知"
      description: "{{ $labels.instance }}CPU使用率已超过90%, 当前值: {{ $value }}%"

  - alert: "Website-网站服务访问状态异常"
    expr: probe_success{job="HTTP-Check"} < 1
    for: 5m
    labels:
      severity: warning
    annotations:
      message: "网站地址 {{ $labels.http }} ,无法正常提供服务"
      description: "请检查并恢复网站名称为 {{ $labels.site }} 应用服务,当前值: {{ $value }}%"

2.通知模板编写格式

描述: alertmanager带有默认模板同时支持我们编写自定义报警通知模板,并且发送给接收者的通知是通过模板构建。除了文本字段可以模板化以外,还可模板化通知的目的地,通过传递在告警规则中添加指定接受用户标签,便可以在模板总引用并发生(非常Nice)。

Tips : 注意 Alertmanager 模板与 Prometheus 中的模板不同, Prometheus 模板还包括警报规则标签/注释中的模板

参考地址: https://prometheus.io/docs/alerting/latest/notifications/

Syntax

描述: 以下是警报和相应的 Alertmanager 配置文件设置 (alertmanager.yml) 的所有不同示例。

代码语言:javascript
复制
# 模板代码块必须使用 {{ var }} 包含

# 1.定义包含
{{ define "wechat.custom.message" }} 
  app: {{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}
# 2.条件判断(运算符:gt/lt/eq/gte/lte)
  {{- if gt (len .Alerts.Firing) 0 -}}
# 3.条件循环
    {{- range $index, $alert := .Alerts -}}
        告警序号: {{ $index }}
        告警类型: {{ $alert.Labels.alertname }}
        告警级别: {{ $alert.Labels.severity }}
        告警详情: {{ $alert.Annotations.summary }}
# 4.此处格式的时间字符串是Go诞生时间。
        故障时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
        恢复时间: {{ $alert.EndsAt.Format "2006-01-02 15:04:05" }}
    {{ end }}
  {{ end }}
{{ end}}

Tips : 更多语法请参照使用 Go 模板系统(https://golang.org/pkg/text/template)。

Data Structures

描述: 数据是传递给通知模板和 webhook 推送的结构。

Name

Type

Notes

Receiver

string

定义通知将发送到的接收者名称(slack、电子邮件等)。

Status

string

如果至少有一个警报被触发,则定义为触发,否则已解决。

Alerts

Alert

该组中所有警报对象的列表:Alerts.Firing 返回该组中当前触发的警报对象的列表 Alerts.Resolved 返回此组中已解决警报对象的列表

GroupLabels

KV

这些警报分组所依据的标签。

CommonLabels

KV

所有警报通用的标签。

CommonAnnotations

KV

所有警报的通用注释集,用于有关警报的更长的附加信息字符串。

ExternalURL

string

反向链接到发送通知的 Alertmanager。

简单使用示例:

代码语言:javascript
复制
# 实例instance标签
{{ .GroupLabels.instance }} 

# 告警数量
{{ .Alerts | len }} 
{{ (len .Alerts.Firing) }}
Alert

Alert 包含一个通知模板的警报。

Name

Type

Notes

Status

string

定义警报是否已解决或当前是否触发。

Labels

KV

要附加到警报的一组标签。

Annotations

KV

警报的一组注释。

StartsAt

time.Time

警报开始触发的时间。 如果省略当前时间由 Alertmanager 分配。

EndsAt

time.Time

仅在已知警报的结束时间时设置。 否则设置为自上次收到警报以来的可配置超时时间。

GeneratorURL

string

标识此警报的原因实体的反向链接。

Fingerprint

string

可用于识别警报的指纹。

代码语言:javascript
复制
{{- range $index, $alert := .Alerts -}}
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}
告警详情: {{ $alert.Annotations.summary }}
故障时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
恢复时间: {{ $alert.EndsAt.Format "2006-01-02 15:04:05" }}
{{- end }}
Functions

描述: 请注意 Go 模板也提供的默认功能。

Name

Arguments

Returns

Notes

title

string

strings.Title,将每个单词的第一个字符大写。

toUpper

string

strings.ToUpper,将所有字符转换为大写。

toLower

string

strings.ToLower,将所有字符转换为小写。

match

pattern, string

正则表达式.MatchString。使用 Regexp 匹配字符串。

reReplaceAll

pattern, replacement, text

Regexp.ReplaceAllString 正则表达式替换,未锚定。

join

sep string, s []string

strings.Join,连接 s 的元素以创建单个字符串。 分隔符字符串 sep 放置在结果字符串中的元素之间。 (注意:参数顺序颠倒以便在模板中更容易流水线化。)

safeHtml

text string

html/template.HTML,将字符串标记为不需要自动转义的 HTML。

stringSlice

…string

将传递的字符串作为字符串切片返回。


0x02 AlertManager 告警实践

描述: 在前面几章的学习中都没有讲解AlertManager报警管理系统的使用,博主专门把他放在本章进行讲解,因为其实现报警通知的方式有多种多样。

Email_config 配置参考: https://prometheus.io/docs/alerting/latest/configuration/#email_config

代码语言:javascript
复制
# - 注意此处非全局所以没有smtp前缀
# Whether or not to notify about resolved alerts.
[ send_resolved: <boolean> | default = false ]

# The email address to send notifications to.
to: <tmpl_string>

# The sender address.
[ from: <tmpl_string> | default = global.smtp_from ]

# The SMTP host through which emails are sent.
[ smarthost: <string> | default = global.smtp_smarthost ]

# The hostname to identify to the SMTP server.
[ hello: <string> | default = global.smtp_hello ]

# SMTP authentication information.
[ auth_username: <string> | default = global.smtp_auth_username ]
[ auth_password: <secret> | default = global.smtp_auth_password ]
[ auth_secret: <secret> | default = global.smtp_auth_secret ]
[ auth_identity: <string> | default = global.smtp_auth_identity ]

# The SMTP TLS requirement.
# Note that Go does not support unencrypted connections to remote SMTP endpoints.
[ require_tls: <bool> | default = global.smtp_require_tls ]

# TLS configuration.
tls_config:
  [ <tls_config> ]

# The HTML body of the email notification.
[ html: <tmpl_string> | default = '{{ template "email.default.html" . }}' ]
# The text body of the email notification.
[ text: <tmpl_string> ]

# Further headers email header key/value pairs. Overrides any headers
# previously set by the notification implementation.
[ headers: { <string>: <tmpl_string>, ... } ]

实践目标:

  • 1.配置并使用腾讯企业邮箱进行邮件发送警告
  • 2.配置并使用自定义邮箱报警样式模板
  • 3.配置并使用企业微信发送报警通知

1.配置并使用腾讯企业邮箱进行邮件发送警告

Step 1.首先我们需要配置 Prometheus.yml 抓取目标、加载规则文件,并与Alertmanager通信设置。

代码语言:javascript
复制
global:
  scrape_interval: 2m
  scrape_timeout: 10s
  # - 每分钟进行报警规则的评估 (建议根据实际情况进行修改)
  evaluation_interval: 1m
  external_labels:
    monitor: 'prom-demo'

alerting:
  # - 设置报警管理系统的目标地址 (可以配置多个AlertManager)
  alertmanagers:
  - scheme: http
    static_configs:
    - targets:
      - '192.168.12.107:30093'

rule_files:
  # - 指标监控告警规则 (可以根据不同的场景进行报警规则)
  - /etc/prometheus/conf.d/rules/*.rules

  # - 采集监控的静态目标和自动化发现目标
scrape_configs:
  - job_name: 'prom-Server'
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'cAdvisor'
    static_configs:
      - targets: ['192.168.12.111:9100']
  - job_name: 'linux_exporter'
    scrape_interval: 30s
    file_sd_configs:
    - files:
      - /etc/prometheus/conf.d/discovery/k8s_nodes.yaml
      # - 自动刷新自动发现配置文件
      refresh_interval: 1m

Step 2.配置 Prometheus 报警规则此次判断采集节点的状态和节点主机负载情况

代码语言:javascript
复制
tee alert.rules <<'EOF'
groups:
- name: node-normal
  rules:
  - alert: service_down
    expr: up {job="linux_exporter"} == 0
    # - 对于持续时间的设置在实际环境中至少建议5min,以减少噪声从而减轻固有监控各种情况,此处设置为30s便于报警情况的观察。
    for: 30s
    labels:
      severity: 'critical'
      team: node
    annotations:
      summary: "主机 {{ $labels.instance }} 监控服务已停止运行超过 15s!"
      description: "请系统管理员尽快进行人工干预处理!"
  - alert: high_load
    expr: node_load1 > 0.7
    for: 5m
    labels:
      severity: 'warning'
      team: node
    annotations:
      summary: "主机 {{ $labels.instance }} 高负载大于0.7以上运行超过 5m!"
EOF

Tips : 说明一下该 rules 目的是监测 node 是否存活 expr 为 PromQL 表达式验证特定节点 job=”linux_exporter” 是否活着,for 表示报警状态为 Pending 后等待 30s 变成 Firing 状态,一旦变成 Firing 状态则将报警发送到 AlertManager 并且 labels (标签)和 annotations(注释) 对该 alert 添加更多的标识和注解信息。

Step 3.配置 Alertmanager 报警通知,此时配置腾讯企业邮箱的方式进行邮件发送报警。

代码语言:javascript
复制
tee alertmanager.yaml <<'EOF'
# - 全局配置
global:
  resolve_timeout: 5m
  smtp_from: 'monitor@weiyigeek.top'
  # - 企业邮箱 SMTP 服务地址
  smtp_smarthost: 'smtp.exmail.qq.com:465'
  smtp_auth_username: 'monitor@weiyigeek.top'
  # - 第三方登录企业邮箱的授权码
  smtp_auth_password: xxxxxxxxxxx'
  smtp_require_tls: false
  # smtp_hello: 'qq.com'
# - 设置报警的分发策略
route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 1m
  # - 如果在10分钟内还未解除报警则进行发送告警
  repeat_interval: 10m
  receiver: 'default-email'
# -  配置告警消息接受者信息
receivers:
- name: 'default-email'
  email_configs:
  - to: 'master@weiyigeek.top'
    send_resolved: true
# - 抑制规则配置
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'instance']
EOF

Step 4.重启Prometheus和Alertmanager服务,同时关闭一台node进行触发报警发送 Email,上边我们定义的 rule 规则为监测 job=”linux_exporter” Node 是否活着,那么就可以停掉 node-exporter 服务来间接起到 Node Down 的作用,从而达到报警条件,触发报警规则。

代码语言:javascript
复制
# - 重启容器
docker restart prometheus_alertmanager prometheus_server

# - 关闭192.168.12.109机器的node_exporter服务
ssh -p 20211 weiyigeek@weiyigeek-109 "sudo -S systemctl stop node_exporter.service"
[sudo] password for weiyigeek:

Step 5.效果查看及报警流程说明,关闭后等待prometheus定时拉取各job的任务执行,其次我们可以在Targets刷新查看linux_exporter任务中状态为 unhealthy 192.168.12.109的节点状态是否变成了DOWN,等待 30s 后,alert 页面由绿色 Service_down (0 active) Inactive 状态变成了黄色 Service_down (1 active) Pending 状态,继续等待 30s 后状态变成红色 Firing 状态,向 AlertManager 发送报警信息,此时 AlertManager 则按照配置规则向接受者发送邮件告警。

代码语言:javascript
复制
linux_exporter (5/6 up)
Endpoint	State	 Error
http://192.168.12.109:9100/metrics	DOWN	Get "http://192.168.12.109:9100/metrics": dial tcp 192.168.12.109:9100: connect: connection refused

WeiyiGeek.Alert

  • Step 6.我们在 AlertManager 查看发送报警信息以及发送的报警邮箱,可以看到接收到的报警包含该节点的标签以及我们添加的Annotations注释信息。

WeiyiGeek.AlertManager-Firing

Step 7.然后我们将192.168.12.109机器的linux_exporter服务进行开启查看其恢复以及警报解除情况。在等待 30s 之后,Prometheus Alerts 页面变成绿色 Service_down (0 active) Inactive 状态,同时也收到了报警解除邮件提醒。

代码语言:javascript
复制
ssh -p 20211 weiyigeek@weiyigeek-109 "sudo -S systemctl start node_exporter.service"

WeiyiGeek.AlertManager-Resolved

Tips : 每次停止/恢复服务后 30s 之后才会发现 Alert 状态变化,是因为 prometheus.yml中 global -> scrape_interval: 30s 配置决定的,如果觉得等待 30s 时间太长,可以修改小一些可以全局修改,也可以局部修改。例如s上面就行采用局部修改 linux_exporter 等待时间为 30s。

2.配置并使用自定义邮箱报警样式模板

描述: 虽然默认的邮件报警样式模板已经包含了所有核心的信息,但是邮件格式内容可以更优雅直观一些,同时AlertManager 也是支持自定义邮件模板配置的。

Step 1.首先新建一个模板文件 email.tmpl

代码语言:javascript
复制
tee email.tmpl<<'EOF'
{{ define "email.from" }}monitor@weiyigeek.top{{ end }}
{{ define "email.to" }}master@weiyigeek.top{{ end }}
{{ define "email.to.html" }}
{{ range .Alerts }}
<b>=========start==========</b><br>
告警程序: prometheus_alert <br>
告警级别: {{ .Labels.severity }} 级 <br>
告警类型: {{ .Labels.alertname }} <br>
故障主机: {{ .Labels.instance }} <br>
告警主题: {{ .Annotations.summary }} <br>
告警详情: {{ .Annotations.description }} <br>
触发时间: {{ .StartsAt.Format "2006-01-02 15:04:05" }} <br>
<b>=========end==========</b><br>
{{ end }}
{{ end }}
EOF

Tips : 注意上述的.StartsAt.Format的格式化字符必须是"2006-01-02 15:04:05"(Go 语言诞生的时间我,我们可以简约记2006 1 2 3 4 5),否则报警的时间不对。

Step 2.其次在AlertManager主配置文件中引用模板及其定义

代码语言:javascript
复制
tee alertmanager.yaml <<'EOF'
global:
  resolve_timeout: 5m
  smtp_from: 'monitor@weiyigeek.top'
  smtp_smarthost: 'smtp.exmail.qq.com:465'
  smtp_auth_username: 'monitor@weiyigeek.top'
  smtp_auth_password: 'xxxxxxxxxxxxxxx'
  smtp_require_tls: false
  # smtp_hello: 'qq.com'

# - Tips 上面的全局邮件参数无法从email.tmpl中读取{{ template "email.username" . }}坑(排错一下午)
templates:
- '/alertmanager/email.tmpl'

route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 1m
  repeat_interval: 10m
  receiver: 'default-email'

receivers:
- name: 'default-email'
  email_configs:
  - to: '{{ template "email.to" . }}'
    html: '{{ template "email.to.html" . }}'
    # 如果问题已解决将发送信息如设置false则不发送
    send_resolved: true

inhibit_rules:
- source_match:
    severity: 'critical'
  target_match:
    severity: 'warning'
  equal: ['alertname', 'instance']
EOF
代码语言:javascript
复制
温馨提示:全局中的邮件参数无法从email.tmpl中读取定义的模板参数,例如{{ template "email.username" .}}坑(排错一下午)只有以下对象可以读取:

email_config:
- to: <tmpl_string>
  from: <tmpl_string>
  html: <tmpl_string>  | text: <tmpl_string>  {{ template "email.default.html" . }}

Tips:官方email_config配置参考地址(https://prometheus.io/docs/alerting/latest/configuration/#email_config)

  • Step 3.重启alertmanager服务docker restart prometheus_alertmanager, 然后同样停止192.168.12.109的node_exporter服务ssh -p 20211 weiyigeek@weiyigeek-109 "sudo -S systemctl stop node_exporter.service"然后等待prometheus拉取的时间30s,此时为pending状态,再等待30s此时为Firing状态并发送告警邮件,并且在10分钟外如果还收到该报警信息便会再次进行发送。

WeiyiGeek.自定义邮件模板

  • Step 4.至此自定义的Email通知模板的使用到此结束,但是此模板还有不够完善的地方例如当计算机恢复后的通知信息没有进行判断。

3.配置并使用企业微信发送报警通知

描述: Alertmanager 已经内置了对企业微信的支持,我们可以通过企业微信来管理报警,更进一步可以通过企业微信和微信的互通来直接将告警消息转发到个人微信上,在前面的Alertmanager.yaml配置文件参数进行了解也可以从prometheus的官网 中给出了企业微信的相关配置说明如下:

代码语言:javascript
复制
# Whether or not to notify about resolved alerts.
[ send_resolved: <boolean> | default = false ]

# The WeChat API URL.
[ api_url: <string> | default = global.wechat_api_url ]

# 企业微信账号唯一 ID, 可以在我的企业中查看。
[ corp_id: <string> | default = global.wechat_api_corp_id ]
# 第三方企业应用的密钥,可以在自己创建的第三方企业应用详情页面查看。
[ api_secret: <secret> | default = global.wechat_api_secret ]
# 第三方企业应用的 ID,可以在自己创建的第三方企业应用详情页面查看。
[ agent_id: <string> | default = '{{ template "wechat.default.agent_id" . }}' ]
# 在后台通讯录查看需要发送的组的部门ID ( PartyID1 | PartyID2)
[ to_party: <string> | default = '{{ template "wechat.default.to_party" . }}' ]
# 发送的成员 @all 表示所有的成员
[ to_user: <string> | default = '{{ template "wechat.default.to_user" . }}' ]
# 发送给特点 tag 标记的,
[ to_tag: <string> | default = '{{ template "wechat.default.to_tag" . }}' ]
# 
[ message: <tmpl_string> | default = '{{ template "wechat.default.message" . }}' ]

Tips : 企业微信相关概念说明请参考企业微信API说明,可以在企业微信的后台中建立多个应用,每个应用对应不同的报警分组,由企业微信来做接收成员的划分。

操作流程步骤:

  • Step 1.访问企业微信网站有账号的直接扫码登陆如果没有就注册一个即可,登陆后访问企业应用进行创建自建应用,点击创建应用按钮->填写应用相关信息(包括应用名称、或应用介绍以及可用范围)。

WeiyiGeek.创建自建应用

Step 2.查看的获得 AgentId 以及 Secret 将其记录下来以及部门ID:to_party(需要发送的组),在后面的AlertManager.yml配置文件中使用。

代码语言:javascript
复制
# - 例如:博主的AgentId和Secret的格式如下
企业ID: ww32cf0bf4e4b11487
agent_id: 1000002
api_secret: SYCdXbWj5SjdT9pOSQnjIZ4RF_SIRqERVuZNWE1yE5g
to_party: 1

WeiyiGeek.AgentId和Secret

Step 3.编辑Alertmanager.yaml主配置文件设置企业微信通知相关参数。

代码语言:javascript
复制
tee alertmanager.yaml <<'EOF'
global:
  resolve_timeout: 2m

templates:
- '/alertmanager/*.tmpl'

route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 1m
  repeat_interval: 10m
  receiver: 'wechat'

receivers:
- name: 'default-email'
  email_configs:
  - from: 'monitor@weiyigeek.top'
    smarthost: 'smtp.exmail.qq.com:465'
    auth_username: 'monitor@weiyigeek.top'
    auth_password: 'xxxxxxxxxxxxxxx'
    require_tls: false
    # smtp_hello: 'qq.com'
    to: '{{ template "email.to" . }}'
    html: '{{ template "email.to.html" . }}'
    send_resolved: true
  
- name: 'wechat'
  wechat_configs:
  - send_resolved: true
    api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
    corp_id: 'ww32cf0bf4e4b11487'
    agent_id: '1000002'
    api_secret: 'SYCdXbWj5SjdT9pOSQnjIZ4RF_SIRqERVuZNWE1yE5g'
    to_user: '@all'
    to_party: '1'
    message: '{{ template "wechat.default.message" . }}'
   
inhibit_rules:
- source_match:
    severity: 'critical'
  target_match:
    severity: 'warning'
  equal: ['alertname', 'instance']
EOF
  • Step 4.重启Alertmanager服务docker restart prometheus_alertmanager以后,我们先来查看默认的企业微信报警信息通知。

WeiyiGeek.Webchat报警查看

Step 5.采用自定义的Wechat报警模块(包括Firing和Resolved)的信息通知

代码语言:javascript
复制
tee wechat.tmpl <<'EOF'
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 -}}
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}
=====================
{{- end }}
===告警详情===
告警详情: {{ $alert.Annotations.summary }}
告警描述: {{ $alert.Annotations.description }}
故障时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
===参考信息===
{{ if gt (len $alert.Labels.instance) 0 -}}故障实例ip: {{ $alert.Labels.instance }};{{- end -}}
{{- if gt (len $alert.Labels.namespace) 0 -}}故障实例所在namespace: {{ $alert.Labels.namespace }};{{- end -}}
{{- if gt (len $alert.Labels.node) 0 -}}故障物理机ip: {{ $alert.Labels.node }};{{- end -}}
{{- if gt (len $alert.Labels.pod_name) 0 -}}故障pod名称: {{ $alert.Labels.pod_name }}{{- end }}
=====================
{{- end }}
{{- end }}

{{- if gt (len .Alerts.Resolved) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 -}}
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}
=====================
{{- end }}
===告警详情===
告警详情: {{ $alert.Annotations.summary }}
故障时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
恢复时间: {{ $alert.EndsAt.Format "2006-01-02 15:04:05" }}
===参考信息===
{{ if gt (len $alert.Labels.instance) 0 -}}故障实例ip: {{ $alert.Labels.instance }};{{- end -}}
{{- if gt (len $alert.Labels.namespace) 0 -}}故障实例所在namespace: {{ $alert.Labels.namespace }};{{- end -}}
{{- if gt (len $alert.Labels.node) 0 -}}故障物理机ip: {{ $alert.Labels.node }};{{- end -}}
{{- if gt (len $alert.Labels.pod_name) 0 -}}故障pod名称: {{ $alert.Labels.pod_name }};{{- end }}
=====================
{{- end }}
{{- end }}
{{- end }}
EOF

Step 6.将alertmanager主配置yaml文件下面的, 采用注释的#去掉即可启用自定义模板信息,将192.168.12.109机器的node_exporter进行关闭测试模板情况,等待3m将把警告进行发送。

代码语言:javascript
复制
# message: '{{ template "wechat.default.message" . }}'
apt 
# 重启 
docker restart prometheus_alertmanager
# 日志查看
docker logs --tail 50 -f prometheus_alertmanager

WeiyiGeek.prometheus&alertmanager

  • Step 7.异常告警(Alerts.Firing)以及异常恢复(Alerts.Resolved)通知发送结果查看。

WeiyiGeek.Firing&Resolved

补充说明:

1.Wechat 模板示例学习与改进。

代码语言:javascript
复制
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 }}
==========异常告警==========
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}
告警详情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}};{{$alert.Annotations.summary}}
故障时间: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{- if gt (len $alert.Labels.instance) 0 }}
实例信息: {{ $alert.Labels.instance }}
{{- end }}
{{- if gt (len $alert.Labels.namespace) 0 }}
命名空间: {{ $alert.Labels.namespace }}
{{- end }}
{{- if gt (len $alert.Labels.node) 0 }}
节点信息: {{ $alert.Labels.node }}
{{- end }}
{{- if gt (len $alert.Labels.pod) 0 }}
实例名称: {{ $alert.Labels.pod }}
{{- end }}
============END============
{{- end }}
{{- end }}
{{- end }}
{{- if gt (len .Alerts.Resolved) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 }}
==========异常恢复==========
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}
告警详情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}};{{$alert.Annotations.summary}}
故障时间: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
恢复时间: {{ ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{- if gt (len $alert.Labels.instance) 0 }}
实例信息: {{ $alert.Labels.instance }}
{{- end }}
{{- if gt (len $alert.Labels.namespace) 0 }}
命名空间: {{ $alert.Labels.namespace }}
{{- end }}
{{- if gt (len $alert.Labels.node) 0 }}
节点信息: {{ $alert.Labels.node }}
{{- end }}
{{- if gt (len $alert.Labels.pod) 0 }}
实例名称: {{ $alert.Labels.pod }}
{{- end }}
============END============
{{- end }}
{{- end }}
{{- end }}
{{- end }}

0x03 实现Prometheus安全认证配置

描述: 由于 export 并没有提供任何认证支持,所需要借助 Nginx 作为反向代理服务器,添加 HTTP Basic Auth 功能,此时只有授权的用户才能采集监控指标, 可以极大避免未授权访问的情况出现。

操作流程

1.我们采用Nginx镜像作为演示搭建与.htpasswd配置生成。

代码语言:javascript
复制
# 镜像拉取与镜像运行
docker pull nginx:1.21.0
docker run --name auth -d nginx:1.21.0
docker exec -it auth bash

# 使用 `apache2-utils` 提供的 `htpasswd` 工具创建一个用户文件,该镜像中没自带所以我们下载即可
apt install apache2-utils
# 运行 htpasswd 生成一个或多个认证用户
htpasswd -bc htpasswd.auth weiyigeek password
Adding password for user weiyigeek
htpasswd -b htpasswd.auth prometheus password
Adding password for user prometheus
htpasswd -b htpasswd.auth monitor password
Adding password for user monitor
  • 2.准备映射到nginx容器中相关文件
代码语言:javascript
复制
# 拷贝容器中nginx配置
docker cp auth:/etc/nginx /monitor/nginx

# 拷贝生成htpasswd.auth 到宿主机
docker cp auth:/tmp/htpasswd.auth /monitor/nginx

# Nginx 配置文件
root@prometheus:/monitor/nginx/conf# cat conf.d/default.conf
server {
  listen       8080;
  listen  [::]:8080;
  server_name  monitor.weiyigeek.top;

  #access_log  /var/log/nginx/host.access.log  main;
  add_header X-Frame-Options SAMEORIGIN;
  auth_basic "weiyigeek Prometheus Metrics";
  auth_basic_user_file /etc/nginx/auth/htpasswd.auth;
  #这里放的是认证文件位置

  location / {
    proxy_pass http://monitor.weiyigeek.top:9090;
    proxy_redirect          off;
    proxy_set_header        X-Real-IP       $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        Host            $host;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
    access_log  /var/log/nginx/prometheus_access.log;
  }
}

3.启动nginx反代容器的参数及状态查看

代码语言:javascript
复制
# - 容器启动
docker run -d --name=prometheus_proxy -p 8080:8080 -v /monitor/nginx/conf:/etc/nginx -v /monitor/nginx/logs:/var/log/nginx/ nginx:1.21.0

# - 容器状态
docker ps
  <!-- CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS         PORTS                                               NAMES
  6347a6498e69   nginx:1.21.0            "/docker-entrypoint.…"   6 minutes ago   Up 6 minutes   80/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   prometheus_proxy -->

4.系统防火墙策略设置(安装最小访问权限设置)

代码语言:javascript
复制
# 启动防火墙 & 查看状态
systemctl enable ufw && systemctl restart ufw
ufw status && systemctl status ufw

# 允许所有的机器访问 80(Grafana),8080(Nginx Proxy Prometheus Server)
sudo ufw allow proto tcp to port 80,8080

# 可以通过ip addr查看网卡的网段以便后续docker或者本地访问。
ip addr

# 只允许从本地和docker0网卡访问 9090,9093,9094,9115 端口
sudo ufw allow proto tcp from 127.0.0.1 to any port 9090,9093,9094,9115
ufw delete allow proto tcp from 172.17.0.1/16 to any port 9090,9093,9094,9115

0x04 辅助工具

promtool 命令 - Prometheus 附带的一个实用工具。

描述: 普罗米修斯监控系统的工具,包含在Prometheus安装包之中。我们可以使用amtool check-config来检查alertmanager.yml文件以及警报查询和Silences。

语法参数:

代码语言:javascript
复制
usage: promtool [<flags>] <command> [<args> ...]

Flags:
-h, --help     Show context-sensitive help (also try --help-long and --help-man).

Commands:
  help [<command>...] Show help.

  check config <config-files>... # Check if the config files are valid or not.
  check web-config <web-config-files>... # Check if the web config files are valid or not.
  check rules <rule-files>... # Check if the rule files are valid or not.
  check metrics # Pass Prometheus metrics over stdin to lint them for consistency and correctness.

  query instant [<flags>] <server> <expr>  # Run instant query.
  query range [<flags>] <server> <expr> # Run range query.
  query series --match=MATCH [<flags>] <server> #  Run series query.
  query labels [<flags>] <server> <name> # Run labels query.

  debug pprof <server> # Fetch profiling debug information.
  debug metrics <server> # Fetch metrics debug information.
  debug all <server> # Fetch all debug information.

  test rules <test-rule-file>... # Unit tests for rules.

  tsdb bench write [<flags>] [<file>] # Run a write performance benchmark.
  tsdb analyze [<flags>] [<db path>] [<block id>] #  Analyze churn, label pair cardinality.
  tsdb list [<flags>] [<db path>] #  List tsdb blocks.
  tsdb dump [<flags>] [<db path>] # Dump samples from a TSDB.
  tsdb create-blocks-from openmetrics <input file> [<output directory>] #  Import samples from OpenMetrics input and produce TSDB blocks. Please refer to the storage docs for more details.
  tsdb create-blocks-from rules --start=START [<flags>] <rule-files>... # Create blocks of data for new recording rules.

基础示例:

代码语言:javascript
复制
# - 1.验证指标输出是否有效并执行格式检查。
$ cat metrics.prom | promtool check metrics
$ curl -s http://localhost:9090/metrics | promtool check metrics
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00 Alertmanager 快速入门
    • 1.基础介绍
      • 2.关键配置浅析
      • 0x01 Alertmanager 规则与模板
        • 1.告警规则最佳实践
          • 2.通知模板编写格式
            • Syntax
            • Data Structures
            • Alert
            • Functions
        • 0x02 AlertManager 告警实践
          • 1.配置并使用腾讯企业邮箱进行邮件发送警告
            • 2.配置并使用自定义邮箱报警样式模板
              • 3.配置并使用企业微信发送报警通知
              • 0x03 实现Prometheus安全认证配置
              • 0x04 辅助工具
                • promtool 命令 - Prometheus 附带的一个实用工具。
                相关产品与服务
                Prometheus 监控服务
                Prometheus 监控服务(TencentCloud Managed Service for Prometheus,TMP)是基于开源 Prometheus 构建的高可用、全托管的服务,与腾讯云容器服务(TKE)高度集成,兼容开源生态丰富多样的应用组件,结合腾讯云可观测平台-告警管理和 Prometheus Alertmanager 能力,为您提供免搭建的高效运维能力,减少开发及运维成本。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档