Prometheus语法PromQL和告警

一.PromQL语法

1.常用语法

PromQL Web UI 的 Graph 选项卡提供了简单的用于查询数据的入口,对于 PromQL 的编写
和校验都可以在此位置,如图所示:


输入 up,然后点击 Execute,就能查到监控正常的 Target:

通过标签选择器过滤出 job 为 node-exporter 的监控,语法为:up{job=”node-exporter”}:

注意此时是 up{job=”node-exporter”}属于绝对匹配,PromQL 也支持如下表达式:
➢ !=:不等于;
➢ =~:表示等于符合正则表达式的指标;
➢ !~:和=~类似,=~表示正则匹配,!~表示正则不匹配。
如果想要查看主机监控的指标有哪些,可以输入 node,会提示所有主机监控的指标:

假 如 想 要 查 询 Kubernetes 集 群 中 每 个 宿 主 机 的 磁 盘 总 量 , 可 以 使 用
node_filesystem_size_bytes:

查询指定分区大小 node_filesystem_size_bytes{mountpoint=”/”}:

或者是查询分区不是/boot,且磁盘是/dev/开头的分区大小(结果不再展示):

node_filesystem_size_bytes{device=~"/dev/.*", mountpoint!="/boot"}

查询主机 k8s-master01 在最近 5 分钟可用的磁盘空间变化:

node_filesystem_avail_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"}[5m]


目前支持的范围单位如下:
➢ s:秒
➢ m:分钟
➢ h:小时
➢ d:天
➢ w:周
➢ y:年
查询 10 分钟之前磁盘可用空间,只需要指定 offset 参数即可:

node_filesystem_avail_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"} offset 10m

查询 10 分钟之前,5 分钟区间的磁盘可用空间的变化:

node_filesystem_avail_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"}[5m] offset 10m

2.PromQL操作符

通过 PromQL 的语法查到了主机磁盘的空间数据,查询结果如下:


可以通过以下命令将字节转换为 GB 或者 MB:

node_filesystem_avail_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"} / 1024 / 1024 / 1024

也可以将 1024 / 1024 / 1024 改为(1024 ^ 3):

node_filesystem_avail_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"} / (1024 ^ 3)

查询结果如下图所示,此时为 31GB 左右:


此时可以在宿主机上比对数据是否正确:

[root@k8s-master02 ~]# df -Th | grep /dev/mapper/centos-root
/dev/mapper/centos-root xfs        36G  3.9G   32G  11% /

上述使用的“/”为数学运算的“除”,“^”为幂运算,同时也支持如下运算符:
➢ +: 加
➢ -: 减
➢ *: 乘
➢ /: 除
➢ ^: 幂运算
➢ %: 求余
查询 k8s-master01 根区分磁盘可用率,可以通过如下指令进行计算:

node_filesystem_avail_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"} / 
node_filesystem_size_bytes{instance="k8s-master01", mountpoint="/", 
device="/dev/mapper/centos-root"}

查询所有主机根分区的可用率:

node_filesystem_avail_bytes{mountpoint="/"} / 
node_filesystem_size_bytes{mountpoint="/"}


也可以将结果乘以 100 直接得到百分比:

(node_filesystem_avail_bytes{mountpoint="/"} / 
node_filesystem_size_bytes{mountpoint="/"} ) * 100


找到集群中根分区空间可用率大于 90%的主机,只找到一台:

(node_filesystem_avail_bytes{mountpoint="/"} / 
node_filesystem_size_bytes{mountpoint="/"} ) * 100 > 60


PromQL 也支持如下判断:
➢ ==: (相等)
➢ != :(不相等)
➢ >:(大于)
➢ < :(小于) ➢ >= :(大于等于)
➢ <= :(小于等于)
磁盘可用率大于 30%小于等于 60%的主机:

30 < (node_filesystem_avail_bytes{mountpoint="/"} / 
node_filesystem_size_bytes{mountpoint="/"} ) * 100 <= 60

也可以用 and 进行联合查询:

(node_filesystem_avail_bytes{mountpoint="/"} / 
node_filesystem_size_bytes{mountpoint="/"} ) * 100 > 30 and 
(node_filesystem_avail_bytes{mountpoint="/"} / 
node_filesystem_size_bytes{mountpoint="/"} ) * 100 <=60

除了 and 外,也支持 or 和 unless: ➢ and: 并且
➢ or :或者
➢ unless :排除
查询主机磁盘剩余空间,并且排除掉 shm 和 tmpfs 的磁盘:

node_filesystem_free_bytes unless 
node_filesystem_free_bytes{device=~"shm|tmpfs"}

当然,这个语法也可以直接写为:

node_filesystem_free_bytes{device=~"shm|tmpfs"}

3.PromQL常用函数

使用sum函数统计当前监控目标所有主机根分区剩余的空间:

sum(node_filesystem_free_bytes{mountpoint="/"}) / 1024^3


也可以用同样方式,计算所有的请求总量:

sum(http_request_total)


根据 statuscode 字段进行统计请求数据:

sum(http_request_total) by (statuscode)


根据 statuscode 和 handler 两个指标进一步统计:

sum(http_request_total) by (statuscode, handler)


找到排名前五的数据:

topk(5, sum(http_request_total) by (statuscode, handler))

取最后三个数据:

bottomk(3, sum(http_request_total) by (statuscode, handler))

找出统计结果中最小的数据:

min(node_filesystem_avail_bytes{mountpoint="/"})

最大的数据:

max(node_filesystem_avail_bytes{mountpoint="/"})

平均值:

avg(node_filesystem_avail_bytes{mountpoint="/"})

四舍五入,向上取最接近的整数,2.79 → 3:

ceil(node_filesystem_files_free{mountpoint="/"} / 1024 / 1024)

向下取整数, 2.79 → 2:

floor(node_filesystem_files_free{mountpoint="/"} / 1024 / 1024)

对结果进行正向排序:

sort(sum(http_request_total) by (handler, statuscode))

对结果进行逆向排序:

sort_desc(sum(http_request_total) by (handler, statuscode))

函数 predict_linear 可以用于预测分析和预测性告警,比如可以根据一天的数据,预测 4 个
小时后,磁盘分区的空间会不会小于 0:

predict_linear(node_filesystem_files_free{mountpoint="/"}[1d], 4*3600) < 0

下图表示:根据一天的数据,预测1350个小时后,磁盘分区的空间会不会小于 0:


除了上述的函数,还有几个比较重要的函数,比如 increase、rate、irate。其中 increase 是
计算在一段时间范围内数据的增长(只能计算 count 类型的数据),rate 和 irate 是计算增长率。
比如查询某个请求在 1 小时的时间增长了多少:

increase(http_request_total{handler="/api/datasources/proxy/:id/*",metho
d="get",namespace="monitoring",service="grafana",statuscode="200"}[1h])

将 1h 增长的数量处于该时间即为增长率:

increase(http_request_total{handler="/api/datasources/proxy/:id/*",metho
d="get",namespace="monitoring",service="grafana",statuscode="200"}[1h]) /3600

相对于 increase,rate 可以直接计算出某个指标在给定时间范围内的增长率,比如还是计算
1h 的增长率,可以用 rate 函数进行计算:

rate(http_request_total{handler="/api/datasources/proxy/:id/*",method="g
et",namespace="monitoring",service="grafana",statuscode="200"}[1h])

二.Alertmanager告警

1.配置文件解析

官方文档https://prometheus.io/docs/alerting/latest/configuration/
中文注释文档https://github.com/dotbalo/k8s/blob/master/prometheus-operator/alertmanager.yaml
简易模板https://github.com/prometheus/alertmanager/blob/main/doc/examples/simple.yml
首先看一下一个简单的 Alertmanager 的配置示例:

# global块配置下的配置选项在本配置文件内的所有配置项下可见
global:
  # 在Alertmanager内管理的每一条告警均有两种状态: "resolved"或者"firing". 在altermanager首次发送告警通知后, 该告警会一直处于firing状态,设置resolve_timeout可以指定处于firing状态的告警间隔多长时间会被设置为resolved状态, 在设置为resolved状态的告警后,altermanager不会再发送firing的告警通知.
  resolve_timeout: 1h

  # 邮件告警配置
  smtp_smarthost: 'smtp.exmail.qq.com:25'
  smtp_from: 'dukuan@xxx.com'
  smtp_auth_username: 'dukuan@xxx.com'
  smtp_auth_password: 'DKxxx'
  # HipChat告警配置
  # hipchat_auth_token: '123456789'
  # hipchat_auth_url: 'https://hipchat.foobar.org/'
  # wechat
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: 'JJ'
  wechat_api_corp_id: 'ww'

  # 告警通知模板
templates:
- '/etc/alertmanager/config/*.tmpl'

# route: 根路由,该模块用于该根路由下的节点及子路由routes的定义. 子树节点如果不对相关配置进行配置,则默认会从父路由树继承该配置选项。每一条告警都要进入route,即要求配置选项group_by的值能够匹配到每一条告警的至少一个labelkey(即通过POST请求向altermanager服务接口所发送告警的labels项所携带的),告警进入到route后,将会根据子路由routes节点中的配置项match_re或者match来确定能进入该子路由节点的告警(由在match_re或者match下配置的labelkey: labelvalue是否为告警labels的子集决定,是的话则会进入该子路由节点,否则不能接收进入该子路由节点).
route:
  # 例如所有labelkey:labelvalue含cluster=A及altertname=LatencyHigh labelkey的告警都会被归入单一组中
  group_by: ['job', 'altername', 'cluster', 'service','severity']
  # 若一组新的告警产生,则会等group_wait后再发送通知,该功能主要用于当告警在很短时间内接连产生时,在group_wait内合并为单一的告警后再发送
  group_wait: 30s
  # 再次告警时间间隔
  group_interval: 5m
  # 如果一条告警通知已成功发送,且在间隔repeat_interval后,该告警仍然未被设置为resolved,则会再次发送该告警通知
  repeat_interval: 12h
  # 默认告警通知接收者,凡未被匹配进入各子路由节点的告警均被发送到此接收者
  receiver: 'wechat'
  # 上述route的配置会被传递给子路由节点,子路由节点进行重新配置才会被覆盖

  # 子路由树
  routes:
  # 该配置选项使用正则表达式来匹配告警的labels,以确定能否进入该子路由树
  # match_re和match均用于匹配labelkey为service,labelvalue分别为指定值的告警,被匹配到的告警会将通知发送到对应的receiver
  - match_re:
      service: ^(foo1|foo2|baz)$
    receiver: 'wechat'
    # 在带有service标签的告警同时有severity标签时,他可以有自己的子路由,同时具有severity != critical的告警则被发送给接收者team-ops-mails,对severity == critical的告警则被发送到对应的接收者即team-ops-pager
    routes:
    - match:
        severity: critical
      receiver: 'wechat'
  # 比如关于数据库服务的告警,如果子路由没有匹配到相应的owner标签,则都默认由team-DB-pager接收
  - match:
      service: database
    receiver: 'wechat'
  # 我们也可以先根据标签service:database将数据库服务告警过滤出来,然后进一步将所有同时带labelkey为database
  - match:
      severity: critical
    receiver: 'wechat'
# 抑制规则,当出现critical告警时 忽略warning
inhibit_rules:
- source_match:
    severity: 'critical'
  target_match:
    severity: 'warning'
  # Apply inhibition if the alertname is the same.
  #   equal: ['alertname', 'cluster', 'service']
  #
# 收件人配置
receivers:
- name: 'team-ops-mails'
  email_configs:
  - to: 'dukuan@xxx.com'
- name: 'wechat'
  wechat_configs:
  - send_resolved: true
    corp_id: 'ww'
    api_secret: 'JJ'
    to_tag: '1'
    agent_id: '1000002'
    api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
    message: '{{ template "wechat.default.message" . }}'
#- name: 'team-X-pager'
#  email_configs:
#  - to: 'team-X+alerts-critical@example.org'
#  pagerduty_configs:
#  - service_key: 
#
#- name: 'team-Y-mails'
#  email_configs:
#  - to: 'team-Y+alerts@example.org'
#
#- name: 'team-Y-pager'
#  pagerduty_configs:
#  - service_key: 
#
#- name: 'team-DB-pager'
#  pagerduty_configs:
#  - service_key: 
#  
#- name: 'team-X-hipchat'
#  hipchat_configs:
#  - auth_token: 
#    room_id: 85
#    message_format: html
#    notify: true

Alertmanager 的配置主要分为五大块:
Global:全局配置,主要用来配置一些通用的配置,比如邮件通知的账号、密码、SMTP
服务器、微信告警等。Global 块配置下的配置选项在本配置文件内的所有配置项下可
见,但是文件内其它位置的子配置可以覆盖 Global 配置;
Templates:用于放置自定义模板的位置;
Route:告警路由配置,用于告警信息的分组路由,可以将不同分组的告警发送给不同
的收件人。比如将数据库告警发送给 DBA,服务器告警发送给 OPS;
Inhibit_rules:告警抑制,主要用于减少告警的次数,防止“告警轰炸”。比如某个宿主机
宕机,可能会引起容器重建、漂移、服务不可用等一系列问题,如果每个异常均有告警,
会一次性发送很多告警,造成告警轰炸,并且也会干扰定位问题的思路,所以可以使用
告警抑制,屏蔽由宿主机宕机引来的其他问题,只发送宿主机宕机的消息即可;
Receivers:告警收件人配置,每个 receiver 都有一个名字,经过 route 分组并且路由后
需要指定一个 receiver,就是在此位置配置的。

2.Alertmanager路由规则

route 配置:

    "route":
      "group_by":
      - "namespace"
      - "job"
      - "alertname"
      "group_interval": "5m"
      "group_wait": "30s"
      "receiver": "Default"
      "repeat_interval": "12h"
      "routes":
      - "match":
          "alertname": "Watchdog"
        "receiver": "Watchdog"
      - "match":
          "severity": "critical"
        "receiver": "Critical"

receiver:告警的通知目标,需要和 receivers 配置中 name 进行匹配。需要注意的是
route.routes 下也可以有 receiver 配置,优先级高于 route.receiver 配置的默认接收人,
当告警没有匹配到子路由时,会使用 route.receiver 进行通知,比如上述配置中的
Default;
group_by:分组配置,值类型为列表。比如配置成[‘job’, ‘severity’],代表告警信息包含
job 和 severity 标签的会进行分组,且标签的 key 和 value 都相同才会被分到一组;
continue:决定匹配到第一个路由后,是否继续后续匹配。默认为 false,即匹配到第一
个子节点后停止继续匹配;
match:一对一匹配规则,比如 match 配置的为 job: mysql,那么具有 job=mysql 的告
警会进入该路由;
match_re:和 match 类似,只不过是 match_re 是正则匹配;
group_wait:告警通知等待,值类型为字符串。若一组新的告警产生,则会等 group_wait
后再发送通知,该功能主要用于当告警在很短时间内接连产生时,在 group_wait 内合
并为单一的告警后再发送,防止告警过多,默认值 30s;
group_interval:同一组告警通知后,如果有新的告警添加到该组中,再次发送告警通
知的时间,默认值为 5m;
repeat_interval:如果一条告警通知已成功发送,且在间隔 repeat_interval 后,该告警
仍然未被设置为 resolved,则会再次发送该告警通知,默认值 4h。

3.邮箱告警设置

找到 Alertmanager 的配置文件:

[root@k8s-master01 kube-prometheus]# cd manifests/
[root@k8s-master01 manifests]# vim alertmanager-secret.yaml

之后在 alertmanager-secret.yaml 文件的 global 添加配置如下:

...
stringData:
  alertmanager.yaml: |-
    "global":
      "resolve_timeout": "5m"
      smtp_from: "qtorm1@163.com"
      smtp_smarthost: "smtp.163.com:465"
      smtp_hello: "163.com"
      smtp_auth_username: "qtorm1@163.com"
      smtp_auth_password: "XXXX" #SMTP邮箱密码
      smtp_require_tls: false
...

之后将名称为 Default 的 receiver 配置更改为邮件通知,修改 alertmanager-secret.yaml 文件
的 receivers 配置如下:

...
"receivers":
    - "name": "Default"
      "email_configs":
      - to: "609346246@qq.com"
        send_resolved: true
    - "name": "Watchdog"
    - "name": "Critical"
...
➢ email_configs:代表使用邮件通知;
➢ to:收件人,此处为 notification@163.com,可以配置多个,逗号隔开;
➢ send_resolved:告警如果被解决是否发送解决通知。

然后分析一下路由规则(默认分组只有 namespace,在此添加上 job 和 alertname,当然
不添加也是可以的):

...
    "route":
      "group_by":
      - "namespace"
      - "job"
      - "alertname"
...

可以通过 Alertmanager 提供的 Web UI 查看分组信息,和 Prometheus 一致,将 Alertmanager
的 Service 更改为 NodePort:

[root@k8s-master01 manifests]# kubectl edit svc -n monitoring alertmanager-main

[root@k8s-master01 manifests]# kubectl get svc -n monitoring alertmanager-main
NAME                TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
alertmanager-main   NodePort   10.99.27.5           9093:31062/TCP   25h

然后web端访问配置文件和分组:



最后打开接收邮箱,发现能收到告警邮件

4.微信告警设置

首先登录企业微信web端:https://work.weixin.qq.com/
可以用公司的管理员账户。
企业微信配置:
注册完成后进行登录,登录后点击我的企业:


在页面的最下面找到企业 ID(corp_id)并记录,稍后会用到:

之后创建一个部门,用于接收告警通知,之后在Prom告警子部门添加相关的人员:

查看该部门 ID(to_party)并记录:

之后创建机器人应用,首先点击应用管理→应用创建:

选择一个 logo,输入应用名称和选择可见范围即可:
创建完成后,查看 AgentId 和 Secret(api_secret)并记录:

点击查看 Secret,企业微信会将 Secret 发送至企业微信:

修改 Alertmanager 配置文件,添加企业微信告警。首先修改 Global,添加一些通用配置,
wechat_api_url 是固定配置,corp_id 为企业 ID,Receivers 添加微信通知(红色字体为新添加内容):

[root@k8s-master01 manifests]# vim alertmanager-secret.yaml
....
    "global":
      "resolve_timeout": "5m"
      smtp_from: "qtorm1@163.com"
      smtp_smarthost: "smtp.163.com:465"
      smtp_hello: "163.com"
      smtp_auth_username: "qtorm1@163.com"
      smtp_auth_password: "IGKR*****"
      smtp_require_tls: false
      wechat_api_url: "https://qyapi.weixin.qq.com/cgi-bin/"
      wechat_api_corp_id: "ww68b2*****"
...
    "receivers":
    - "name": "Default"
      "email_configs":
      - to: "609346246@qq.com"
        send_resolved: true
    - name: wechat-ops
      wechat_configs:
      - send_resolved: true
        to_party: 2
        to_user: '@all'
        agent_id: 1000002
        api_secret: "r3D_Vk7*******"
...
此处配置的 receiver 名字为 wechat-ops,to_user 为@all,代表发送给所有人

更改路由配置,将 Watchdog 的告警发送给该部门:

"route":
      "group_by":
      - "namespace"
      - "job"
      - "alertname"
      "group_interval": "12h"
      "group_wait": "30s"
      "receiver": "Default"
      "repeat_interval": "12h"
      "routes":
      - "match":
          "alertname": "Watchdog"
        "receiver": "wechat-ops"
        "repeat_interval": "10m"

配置好后可以在altermanager的web端和企业微信接收告警:

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇