1、PromQL基本使用

1.1 PromQL介绍

PromQL(Prometheus Query Language) 是 Prometheus 自己开发的数据查询 DSL 语言,语言表现力

非常丰富,支持条件查询、操作符,并且内建了大量内置函数,供我们针对监控数据的各种维度进行查

询。

1.2 瞬时查询与范围查询

参考文档:https://prometheus.io/docs/prometheus/latest/querying/examples/

  1. 目标实例状态:(获取所有监控实例是否正常,1表示正常)
  2. up
  3. 查询nodeCPU利用率,指标最新样本(称为瞬时向量):
  4. node_cpu_seconds_total
  5. 可以通过附加一组标签来进一步过滤这些时间序列:
  6. node_cpu_seconds_total{job="Linux Server"}
  7. 查询指标近5分钟内样本(称为范围向量,时间单位 smhdwy):
  8. node_cpu_seconds_total{job="Linux Server"}[5m]
  9. node_cpu_seconds_total{job="Linux Server"}[1h]

实例1:获取192.168.6.31:9100实例第0核CPU上**空闲态**CPU利用率

  1. node_cpu_seconds_total{cpu="0",instance="192.168.6.31:9100",mode="idle"}

Prometheus(二) - 图1

1.3 常见的操作符与函数

1.3.1 常用操作符

参考文档:https://prometheus.io/docs/prometheus/latest/querying/operators/

Prometheus(二) - 图2

实例2:获取192.168.6.31:9100实例第0核CPU上**非空闲态**CPU利用率

  1. node_cpu_seconds_total{cpu="0",instance="192.168.6.31:9100",mode!="idle"}

实例3:求192.168.6.31:9100实例5分钟内CPU上利用率

  1. avg(irate(node_cpu_seconds_total{instance="192.168.6.31:9100"}[5m]))

Prometheus(二) - 图3

1.3.2 函数

参考文档:https://prometheus.io/docs/querying/functions/

  1. 函数:
  2. irate():计算指标在一定时间间隔内的变化速率
  3. 示例:irate(node_cpu_seconds_total{job="Linux Server",mode="system"}[5m])

2、监控指标标签管理

2.1 标签的作用

标签作用:Prometheus中存储的数据为时间序列,是由Metric的名字和一系列的标签(键值对)唯一标识的,

不同的标签代表不同的时间序列,即通过指定标签查询指定数据

2.2 Metadata标签

在Prometheus所有的Target实例中,都包含一些默认的Metadata标签信息。可以通过Prometheus UI的

Targets页面中查看这些实例的Metadata标签的内容:

address:当前Target实例的访问地址:

scheme:采集目标服务访问地址的HTTP Scheme,HTTP或者HTTPS

metrics_path:采集目标服务访问地址的访问路径

上面这些标签将会告诉Prometheus如何从该Target实例中获取监控数据。除了这些默认的标签以外,我们

还可以为Target添加自定义的标签。

Prometheus(二) - 图4

2.3 自定义标签

  1. - job_name: 'BJ Linux Server'
  2. static_configs:
  3. - targets: ['192.168.6.31:9100']
  4. labels: # 自定义标签
  5. idc: changping
  6. project: www
  7. - job_name: 'SH Linux Server'
  8. static_configs:
  9. - targets: ['192.168.6.32:9100']
  10. labels: # 自定义标签
  11. idc: sss
  12. project: blog

Prometheus(二) - 图5

查询北京昌平区机房中www项目组的主机的CPU

  1. node_cpu_guest_seconds_total{job="BJ Linux Server", idc="changping",project="www"}

Prometheus(二) - 图6

2.4 重新标记标签

重新标记目的:为了更好的标识监控指标。

在两个阶段可以重新标记:

• relabel_configs :在采集之前

• metric_relabel_configs:在存储之前

准备抓取指标数据时,可以使用relabel_configs添加一些标签、也可以只采集特定目标或过滤目标。

已经抓取到指标数据时,可以使用metric_relabel_configs做最后的重新标记和过滤。

Prometheus(二) - 图7

重新标记标签一般用途:

• 动态生成新标签

• 过滤采集的Target

• 删除不需要或者敏感标签

• 添加新标签

action:重新标记标签动作

• replace:默认,通过regex匹配source_label的值,使用replacement来引用表达式匹配的分组,分组使用$1,$2…引用

• keep:删除regex与连接不匹配的目标 source_labels

• drop:删除regex与连接匹配的目标 source_labels

• labeldrop:删除regex匹配的标签

• labelkeep:删除regex不匹配的标签

• labelmap:匹配regex所有标签名称,并将捕获的内容分组,用第一个分组内容作为新的标签名

  • 注:source_labels尽量使用Prometheus内置标签(内置标签是在存储之前就有的)

2.4.1 重命名标签

场景1:动态生成添加标签(对已有的标签重新标记)

  1. - job_name: 'Linux Server'
  2. static_configs:
  3. - targets: ['192.168.6.31:9100']
  4. relabel_configs: # 采集之前,存储之前则使用 metric_relabel_configs
  5. - action: replace # 指定动作,默认是replace
  6. source_labels: ["__address__"] # 基于那个标签进行正则匹配
  7. regex: (.*):([0-9]+) # 正则匹配标签值,( )分组
  8. replacement: $1 # 引用分组匹配的内容,$1匹配的是(.*),$2匹配的是([0-9]+)也就是端口
  9. target_label: "ip"

Prometheus(二) - 图8

2.4.2 过滤Target

场景2:选择采集的目标

  1. - job_name: 'Linux Server'
  2. static_configs:
  3. - targets: ['192.168.6.31:9100','192.168.6.32:9100']
  4. relabel_configs:
  5. - action: drop # 不采集正则匹配的服务数据,keep则是只采集匹配的
  6. source_labels: ["__address__"]
  7. regex: "192.168.6.32:9100"

Prometheus(二) - 图9

  • replacement这里也可以直接指定一个名称,自定义标签
  • 给指定标签赋予绝对值
  1. metric_relabel_configs:
  2. - action: replace
  3. replacement: "aaaa"
  4. target_label: "instance"

Prometheus(二) - 图10

2.4.3 删除标签

场景3:删除不需要或者敏感的标签,禁止某些标签入库

  1. - job_name: 'Linux Server'
  2. static_configs:
  3. - targets: ['192.168.6.31:9100','192.168.6.32:9100']
  4. metric_relabel_configs:
  5. - action: labeldrop
  6. regex: "job"

入库之前可以看到

Prometheus(二) - 图11

执行PromQL,查看入库之后:已经没有了job标签

Prometheus(二) - 图12

3、告警监控

3.1 部署Alertmanager

安装包下载

地址1:https://prometheus.io/download/

地址2:https://github.com/prometheus/alertmanager/releases

使用步骤:

  1. 部署Alertmanager

  2. 配置告警接收人

  3. 配置Prometheus与Alertmanager通信

  4. 在Prometheus中创建告警规则

  1. [Unit]
  2. Description=alertmanager
  3. [Service]
  4. ExecStart=/opt/monitor/alertmanager/alertmanager --config.file=/opt/monitor/alertmanager/alertmanager.yml
  5. ExecReload=/bin/kill -HUP $MAINPID
  6. KillMode=process
  7. Restart=on-failure
  8. [Install]
  9. WantedBy=multi-user.target
  1. ss -tnlp | grep alert

http://ip:9093

3.2 配置Prometheus与Alertmanager通信

Prometheus(二) - 图13

  1. vi prometheus.yml
  2. ...
  3. # Alertmanager configuration
  4. alerting:
  5. alertmanagers:
  6. - static_configs:
  7. - targets:
  8. - 192.168.6.31:9093 # 配置发送告警事件接口
  9. rule_files:
  10. - "rules/*.yml"
  11. ...
  1. global:
  2. resolve_timeout: 5m
  3. # 邮箱服务器 (默认使用的webhook发送告警信息)
  4. smtp_smarthost: 'smtp.163.com:25'
  5. smtp_from: 'zsg1690014753@163.com'
  6. smtp_auth_username: 'zsg1690014753@163.com'
  7. smtp_auth_password: 'UNAOCOIAGNKDFMYH' # 网易邮箱安全码(启用POP3/SMTP服务,新增授权验证码),只显示一次要记号
  8. smtp_require_tls: false
  9. # 配置路由树
  10. route:
  11. group_by: ['alertname'] # 根据告警规则组名进行分组
  12. group_wait: 15s # 分组内第一个告警等待时间,10s内如有第二个告警会合并一个告警
  13. group_interval: 15s # 发送新告警间隔时间
  14. repeat_interval: 1h # 重复告警间隔发送时间
  15. receiver: 'mail'
  16. # 接收人
  17. receivers:
  18. - name: 'mail'
  19. email_configs:
  20. - to: '1690014753@qq.com'
  21. # 抑制规则
  22. inhibit_rules:
  23. - source_match:
  24. severity: 'critical'
  25. target_match:
  26. severity: 'warning'
  27. equal: ['alertname', 'dev', 'instance']
  1. ./amtool check-config alertmanager.yml

根据指标中的标签发送不同的收件人

  1. route:
  2. - receiver: 'default-receiver'
  3. group_wait: 30s
  4. group_interval: 5m
  5. repeat_interval: 4h
  6. group_by: [cluster, alertname]
  7. routes:
  8. - receiver: 'database-pager'
  9. group_wait: 10s
  10. match_re:
  11. service: mysql|cassandra
  12. - receiver: 'frontend-pager'
  13. group_by: [product, environment]
  14. match:
  15. team: frontend
  16. receivers:
  17. - name: database-pager'
  18. email_configs:
  19. - to: 'zhenliang369@163.com'
  20. - name: ‘frontend-pager'
  21. email_configs:
  22. - to: 'zhenliang369@163.com'

3.3 在Prometheus中创建告警规则

  1. vi prometheus.yml
  2. ...
  3. # Alertmanager configuration
  4. alerting:
  5. alertmanagers:
  6. - static_configs:
  7. - targets:
  8. - 192.168.6.31:9093 # 配置发送告警事件接口
  9. rule_files:
  10. - "rules/*.yml"
  11. ...

创建告警规则

  1. vi rules/general.yml
  2. groups:
  3. - name: example #告警规则组名称
  4. rules:
  5. # 任何实例1分钟内无法访问发出告警
  6. - alert: InstanceDown # 告警规则名称
  7. expr: up == 0 # 基于PromQL的触发条件
  8. for: 1m # 等待评估时间
  9. labels: # 自定义标签(例如抑制所需的告警级别)
  10. severity: page
  11. annotations: # 指定附加信息
  12. summary: " {{ $labels.instance }} 停止工作"
  13. description: "{{ $labels.instance }}:job {{ $labels.job }} 已经停止1分钟以上."

3.4 告警状态

Prometheus(二) - 图14

Inactive:这里什么都没有发生。

Pending:已触发阈值,但未满足告警持续时间

Firing:已触发阈值且满足告警持续时间。警报发送给接受者。

3.5 告警收敛(分组、抑制、静默)

分组(group):将类似性质的警报分类为单个通知

抑制(Inhibition):当警报发出后,停止重复发送由此警报引发的其他警报

静默(Silences):是一种简单的特定时间静音提醒的机制

Prometheus(二) - 图15

3.5.1 告警收敛:分组

  • 分组(group):将类似性质的警报分类为单个通知
  • 默认已起用
  1. # 配置路由树
  2. route:
  3. group_by: ['alertname'] # 根据告警规则组名进行分组
  4. group_wait: 15s # 分组内第一个告警等待时间,10s内如有第二个告警会合并一个告警
  5. group_interval: 15s # 发送新告警间隔时间
  6. repeat_interval: 10m # 重复告警间隔发送时间
  7. receiver: 'mail'

3.5.2 告警收敛:抑制

  • 抑制(Inhibition):当警报发出后,停止重复发送由此警报引发的其他警报

例如:一个Linux服务器上部署有1个nginx服务,当Linux和nginx都挂了,通过抑制处理,最终只发送一个Linux服务挂掉的告警

  1. # 抑制规则
  2. inhibit_rules:
  3. - source_match:
  4. severity: 'critical' # 指定告警级别,也可以使用level: high来代替
  5. target_match:
  6. severity: 'warning' # 指定抑制告警级别
  7. equal: ['alertname', 'instance'] # 上面的两个抑制需要满足的条件,具有携带相同标签的信息

3.5.3 告警收敛:静默

  • 静默(Silences):是一种简单的特定时间静音提醒的机制

例如:我们将要对服务192.168.6.32主机进行重启,我们知道将会发生告警,但是又想忽略他,可以配置静默来进行处理(将忽略带有指定标签的告警)

  1. instance="192.168.6.32:9100"

Prometheus(二) - 图16

Prometheus(二) - 图17

Prometheus(二) - 图18

3.6 Prometheus一条告警怎么触发?

Prometheus(二) - 图19

3.7 编写告警规则案例

计算每个实例的CPU使用率

  1. 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m]))by(instance) * 100 )
  • irate(node_cpu_seconds_total{mode=”idle”}[5m]) 获取每个实例每核CPU5分钟的空闲速率
  • avg(irate(node_cpu_seconds_total{mode=”idle”}[5m])) 计算获取到的所有实例的CPU空闲总速率
  • avg(irate(node_cpu_seconds_total{mode=”idle”}[5m]))by(instance) 计算每个实例的空闲速率
  • 100 - (avg(irate(node_cpu_seconds_total{mode=”idle”}[5m]))by(instance) * 100 ) 计算每个实例的CPU使用率

3.7.1 根据CPU的使用率触发告警

  1. groups:
  2. - name: example #告警规则组名称
  3. rules:
  4. # 任何实例1分钟内无法访问发出告警
  5. - alert: InstanceDown # 告警规则名称
  6. expr: up == 0 # 基于PromQL的触发条件
  7. for: 1m # 等待评估时间
  8. labels: # 自定义标签
  9. severity: page
  10. annotations: # 指定附加信息
  11. summary: " {{ $labels.instance }} 停止工作"
  12. description: "{{ $labels.instance }}:job {{ $labels.job }} 已经停止1分钟以上."
  13. # 当CPU使用率高于80%触发告警
  14. - alert: CPUUsage
  15. expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m]))by(instance) * 100 ) > 80
  16. for: 1m # 等待评估时间,1分钟内CPU高于80%
  17. labels: # 自定义标签
  18. level: warnning
  19. annotations: # 指定附加信息
  20. summary: " {{ $labels.instance }} CPU使用率过高"
  21. description: "{{ $labels.instance }}:CPU使用率大于80%,(当前值是 {{ $value }}%)"

3.7.2 告警规则

general.yml

node.yml

  1. groups:
  2. - name: node.rules
  3. rules:
  4. - alert: NodeFilesystemUsage # 文件系统使用率
  5. expr: 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"} * 100) > 80
  6. for: 2m
  7. labels:
  8. severity: warning
  9. annotations:
  10. summary: "{{$labels.instance}}: {{$labels.mountpoint }} 分区使用过高"
  11. description: "{{$labels.instance}}: {{$labels.mountpoint }} 分区使用大于 80% (当前值: {{ $value }})"
  12. - alert: NodeMemoryUsage # 内存使用率
  13. expr: 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 > 80
  14. for: 2m
  15. labels:
  16. severity: warning
  17. annotations:
  18. summary: "{{$labels.instance}}: 内存使用过高"
  19. description: "{{$labels.instance}}: 内存使用大于 80% (当前值: {{ $value }})"
  20. - alert: NodeCPUUsage # CPU使用率
  21. expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) > 80
  22. for: 2m
  23. labels:
  24. severity: warning
  25. annotations:
  26. summary: "{{$labels.instance}}: CPU使用过高"
  27. description: "{{$labels.instance}}: CPU使用大于 80% (当前值: {{ $value }})"

表达式解析:

文件系统

  1. 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"} * 100) > 80
  • fstype=~”ext4|xfs” 用于过滤文件系统类型,ext4或xfs类型的才会触发告警

内存

  1. 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 > 80
  • 内存使用率应除去空闲使用和缓存使用,就是整个使用率

4、Grafana可视化展示

4.1 Grafana部署

Grafana是一个开源的度量分析和可视化系统。

官方文档:https://grafana.com/docs/grafana/latest/

部署文档:https://grafana.com/grafana/download

访问地址:http://IP:3000

用户名/密码:admin/admin # 第一次需要重置密码

Grafana只用于展示数据,但这个数据从哪里来?

需要你根据提供数据的服务选择,支持的数据源如下

使用systemd服务管理

  1. [Unit]
  2. Description=grafana
  3. [Service]
  4. ExecStart=/opt/monitor/grafana/bin/grafana-server -homepath=/opt/monitor/grafana
  5. ExecReload=/bin/kill -HUP $MAINPID
  6. KillMode=process
  7. Restart=on-failure
  8. [Install]
  9. WantedBy=multi-user.target

配置文件:

  1. # vi conf/defaults.ini
  2. [paths]
  3. data = data
  4. logs = data/log
  5. [server]
  6. protocol = http
  7. http_addr =
  8. http_port = 3000
  9. [database]
  10. type = sqlite3
  11. path = grafana.db
  12. [security]
  13. admin_user = admin
  14. admin_password = admin

4.2 自定义仪表盘

创建一个仪表盘的基本步骤:

4.2.1 导航栏

  1. 新建仪表盘

Prometheus(二) - 图20

  1. 导航栏 - 基本信息(分组)

Prometheus(二) - 图21

Prometheus(二) - 图22

添加分组变量

Prometheus(二) - 图23

  1. label_values(up,job)
  • label_values 是grafana内置的针对Prometheus的查询函数
  • 意思是根据Prometheus的up查询的实例指标,获取其中的job字段

效果如下:

Prometheus(二) - 图24

添加节点变量

Prometheus(二) - 图25

Prometheus(二) - 图26

  1. label_values(up{job="$job"},instance)
  • up{job=”$job”} 使得该node和job具有级联关系,这里的获取的指标根据前面的分组获取

效果展示:

Prometheus(二) - 图27

4.2.2 图表 - CPU核心数

图表的类型:

Prometheus(二) - 图28

  1. 添加面板

Prometheus(二) - 图29

默认为曲线图(这里先选择单个统计 - CPU核数)

Prometheus(二) - 图30

Prometheus(二) - 图31

PromQL:计算实例节点的CPU核心数

  1. count(node_cpu_seconds_total{instance="$node",mode="idle",job="$job"})

4.2.3 图表 - 内存

  • Prometheus中存储的内存单位默认是字节
  • node_memory_MemTotal_bytes字节=node_memory_MemTotal_bytes/1024 Kb /1024 Mb /1024 Gb
  • grafana中可以通过设置字段的数据类型直接进行转化

Prometheus(二) - 图32

  • 设置单位直接搜索Standard options,在单位(Unit)下的data中,第一个(bytes(IEC))一般就是内存的
  1. node_memory_MemTotal_bytes{instance="$node",job="$job"}

4.2.4 图表 - CPU使用率

Prometheus(二) - 图33

PromQL:CPU使用率

  1. 100 - (avg(irate(node_cpu_seconds_total{instance="$node",job="$job",mode="idle"}[1m]))*100)

4.2.5 图表 - 内存使用率

Prometheus(二) - 图34

PromQL:内存使用率

  1. 100 - ((node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100)
  2. 100 - ((node_memory_MemFree_bytes{instance="$node",job="$job"}+node_memory_Cached_bytes{instance="$node",job="$job"}+node_memory_Buffers_bytes{instance="$node",job="$job"}) / node_memory_MemTotal_bytes{instance="$node",job="$job"} * 100)

4.2.5 图表 - 文件系统更分区使用率

Prometheus(二) - 图35

PromQL:文件系统更分区使用率

  1. 100 - node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs"} * 100
  2. 100 - node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs",instance="$node",job="$job"} * 100

4.2.6 图表 - CPU使用率(曲线图)

Prometheus(二) - 图36

Prometheus(二) - 图37

PromQL:CPU使用率

  1. # 用户态
  2. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="user"}[1m]))
  3. # 内核态
  4. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="system"}[1m]))
  5. # 空闲
  6. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="idle"}[1m]))
  7. # io等待
  8. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="iowait"}[1m]))
  9. # 中断请求(硬中断(Hardware IRQ)占用CPU的百分比)
  10. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="irq"}[1m]))
  11. # Hypervisor分配给运行在其它虚拟机上的任务的实际CPU时间
  12. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="steal"}[1m]))
  13. # 中断请求(软中断(Software Interrupts)占用CPU的百分比)
  14. avg(irate(node_cpu_seconds_total{instance=~"$node",job="$job",mode="softirq"}[1m]))

4.2.7 图表 - 各分区可用空间

Prometheus(二) - 图38

  1. # A
  2. node_filesystem_size_bytes{instance=~'$node',fstype=~"ext4|xfs"}-node_filesystem_avail_bytes {instance=~'$node',fstype=~"ext4|xfs"}
  3. # B
  4. node_filesystem_size_bytes{instance=~'$node',fstype=~"ext4|xfs"}
  5. # C
  6. 1-(node_filesystem_free_bytes{instance=~'$node',fstype=~"ext4|xfs"} / node_filesystem_size_bytes{instance=~'$node',fstype=~"ext4|xfs"})
  7. # D 空

4.3 仪表盘导入导出

Prometheus(二) - 图39