《Prometheus监控实战》读书笔记

《Prometheus监控实战》

Prometheus是一个开源的监控系统。


Prometheus架构

一、监控简介

监控不仅仅只是系统的技术指标,还可以是业务指标。确保为客户提供可靠恰当的产品。
在生产系统中,监控是必须的,它应该和应用程序一起构建和部署。帮助我们了解系统的环境、进行诊断故障、制定容量计划,为组织提供系统的性能、成本和状态等信息。

监控模式

  1. 务必在项目最开始阶段就把监控考虑进去,它和安全性一样,都是应用的核心功能。
  2. 根据服务价值设计自上而下的监控系统是一个很好的方式。先是业务逻辑,再是应用程序,最后才是基础设施操作系统。
  3. 需要找准监控项,及时发现错误
  4. 通过多样化的数据,如查看数据窗口等更智能的技术分析指标与阀值
  5. 增加监控的频率
  6. 尽可能实现监控系统部署实施自动化

监控机制

  1. 探针与内省:监控应用程序的两种方法。
    探针:在应用程序的外部,查询应用程序的外部特征。如Nagios。
    内省:查看应用程序的内部内容,经过检测,返回其状态、内部组件等的度量。可用作健康检查接口,由监控工具收集。
  2. 拉取与推送:执行监控检查的两种方式。
    拉取:提取或检查远程应用程序。如Prometheus。
    推送:应用程序发送事件给监控系统接收。

监控数据类型

  1. 指标:软件和硬件组件属性的度量。
    指标类型:测量型 Gauge、计数型 Counter、直方图 Histogram
  2. 日志:应用程序发出的事件(通常是文本类型)。

监控方法论

  1. Brendan Gregg的USE方法 主机级监控
    USE:使用率、饱和度、错误。针对每个资源(如CPU),检查使用率(如CPU使用百分比)、饱和度(如等待CPU的进程数)和错误(如错误事件的计数)。
  2. Google四个黄金指标 应用程序级监控
    延迟(如服务请求时间)、流量(如每秒HTTP请求数)、错误(如响应时间走过30ms的请求视为错误)、饱和度(如内存IO)。
  3. RED方法
    Rate(你的服务所服务的每秒的请求数)、Errors(每秒失败的请求数)、Duration(每个请求所花费的时间,用时间间隔表示)

通知系统

通知系统需要关注以下几点:

  1. 通知清晰、准确、可操作。人易读。
  2. 通知添加上下文,通知应包含组件的其他相关信息。
  3. 仅发送有意义的通知。

二、Prometheus是什么?

Prometheus灵感来自于谷歌的Borgmon。这由前谷歌SRE Matt T. Proud开发。Proud加入SoundCloud后,两天Julius Volz合作开发了Prometheus。于2015年1月发布。
Prometheus主要用于提供近实时的、基于动态云环境和容器的微服务、服务和应用的内省监控。Prometheus专注于当前的事件,大多数监控查询和警报都是从最近(通常为一天内)的数据中生成。
Prometheus通过拉取应用程序中暴露的时间序列数据来工作。时间序列数据通常由应用程序本身通过客户端库或exporter的代理来作为HTTP端点暴露。

Prometheus架构

Prometheus有一个推送网关,可用于接收少量数据。


Prometheus架构

名词解释

endpoint:端点,Prometheus抓取的指标来源
target:目标,定义执行抓取所需的信息,如链接,身份验证,抓取方式
job:一组目标,具有相同角色的目标组

监控资源服务发现

  1. 用户提供静态资源列表。
  2. 基于文件的发现。例如使用配置管理工具生成在Prometheus中可以自动更新的资源列表。
  3. 自动发现。例如,查询consule等数据存储。

聚合和警报

Prometheus服务器可以查询和聚合时间序列数据,创建规则来记录常用的查询和聚合。
Prometheus可以定义警报规则。为系统配置的在满足条件时触发警报的标准。将警报从Prometheus推送到警报管理器(Alertmanager)的单独服务器。
AlertManager可以管理、整合、分发各种警报到不同的目的地。

查询、可视化

Prometheus提供了一套内置查询语言PromQL、一个表达式浏览器及浏览数据的图形界面。
Prometheus可以与开源DashBoard Grafana集成,同时也支持其他的DashBoard。
为了速度与可靠性,Prometheus服务器充分使用内存和SSD磁盘

冗余和高可用性

部署Prometheus的高可用模式,可以使用两个以上配置相同的Prometheus服务器来收集时间序列数据,并且生成的警报由Alertmanager集群来处理。

Prometheus数据模型

total_website_visits{site="MegaApp", location="NJ", instance="webserver:9090", job="web"}
  • 指标名称:total_website
  • 标签:site="MegaApp"等,通常都有一个instance标签和job标签
    标签分为两类:1,插桩标签;2,目标标签
    插桩标签:来自被监控的资源
    目标标签:通常与架构相关,由Prometheus在抓取期间和之后添加。
  • 时间序列由名称和标签标识,如果在时间序列中添加或更改标签,Prometheus会将其视为新的时间序列。

三、安装部署Prometheus

安装Prometheus

Linux上安装Prometheus

  1. 下载Prometheus的二进制文件
$ wget https://github.com/prometheus/prometheus/releases/download/v2.14.0/prometheus-2.14.0.linux-amd64.tar.gz
  1. 解压文件到相关目录,安装promtool
$ tar -xzf prometheus-2.14.0.linux-amd64.tar.gz
$ sudo cp prometheus-2.14.0.linux-amd64/prometheus /usr/local/bin/
$ sudo cp prometheus-2.14.0.linux-amd64/promtool /usr/local/bin/
  1. 执行prometheus --version查看版本验证安装。

Ansible安装Promethues

相关的role路径为:https://github.com/cloudalchemy/ansible-prometheus

OpenShift上安装Prometheus

OpenShift官方部署脚本支持Prometheus的安装。在OpenShift 3.11部署的时候,prometheus默认是安装的,如果要禁止安装则需将inventory中的配置openshift_cluster_monitoring_operator_install设置为false
相关的开源软件地址为:https://github.com/openshift/cluster-monitoring-operator

配置Prometheus

Prometheus通过YAML文件来配置。Prometheus的解压的目录中自带有配置文件prometheus.yml。

global:
  scrape_interval:     15s # 应用程序或服务抓取数据的时间间隔,默认为1min
  evaluation_interval: 15s # Prometheus评估规则(记录规则、警报规则)的频率,默认为1min
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# 一次性加载规则,并且每隔evaluation_interval时间对规则进行评估'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# 指定Prometheus抓取的所有目标
# 下面是监控Prometheus本身
scrape_configs:
  # job名字将会被加到监控的指标中`job=<job_name>` 
  - job_name: 'prometheus'

    # metrics_path 默认为 '/metrics'
    # scheme 默认为 'http'.

    static_configs:
    - targets: ['localhost:9090']

global:全局配置
alerting:设置Prometheus的警报。Prometheus支持Alertmanager服务发现功能。
rule_files:指定包含记录规则或警报规则的文件列表。
scrape_configs:指定Prometheus抓取的所有目标。

运行Prometheus

  1. 将配置文件prometheus.yml移到合适的位置
$ sudo mkdir -p /etc/prometheus
$ sudo cp prometheus.yml /etc/prometheus/
  1. 运行prometheus应用
$ prometheus --config.file "/etc/prometheus/prometheus.yml"
  1. 如果发生异常,可以使用promtool来验证配置文件
$ promtool check config prometheus.yml
Checking prometheus.yml
    SUCCESS: 0 rule files found

查询数据

  1. 查看指定指标值
go_gc_duration_seconds{quantile="0.5"}  1.6166e-05
  1. 过滤一些匹配标签
go_gc_duration_seconds{quantile!="0.5"}  
  1. 聚合数据求和
sum(promhttp_metric_handler_requests_total) # 求和
  1. PromQL通过子名by,按特定维度聚合
sum(promhttp_metric_handler_requests_total) by (job)
  1. 转换成速率
sum(rate(promhttp_metric_handler_requests_total[5m])) by (job)

rate()函数计算一定范围内时间序列的每秒平均增长率,适合缓慢变化的计数器(counter)。
irate()函数计算指定时间范围内的最近两个数据点来算速率,适合快速变化的计数器(counter)。
rate()与irate()函数都必须与计数器一起使用。

  1. 增加数量
increase(promhttp_metric_handler_requests_total[1h])

指标1小时内增长的值。

容量规划

  1. 内存

通过以下查询语句查看样本的收集率。显示最后一分钟添加到数据库的每秒样本率。

rate(prometheus_tsdb_head_samples_appended_total[1m])

查询收集的指标数量,通过以下语句

sum(count by (__name__)({__name__-\~"\.\+"}))

每个样本大小通常为1到2字节,假设在12小时内每秒收集100000个样本,那么内存使用情况为

100000 * 2 bytes * 43200秒 约为 8.64GB内存

约为 8.64GB内存,还需要考虑查询与记录规则方面内存的使用情况。
可以通过查看process_resident_memory_bytes指标查看Prometheus进程的内存使用情况。

  1. 磁盘

默认情况下,指标会在本地数据库中存储15天。具体时间由命令行选项控制。
--storage.tsdb.path: 设置数据存储目录,默认为Prometheus的目录中。
--storage.tsdb.retention: 设置时间序列保留期,默认为15天。
建议采用SSD作为时间序列数据库的磁盘
每秒10万个样本的示例,每个样本磁盘上占用约1~2字节,保留15天数据算,大约需要259GB磁盘。

四、监控主机和容器

Prometheus通过使用exporter工具来暴露主机和应用程序的指标。常用的exporter列表可在以下网站上查看。

https://prometheus.io/docs/instrumenting/exporters/

监控主机

Node Exporter 是用GO语言编写的,收集各种主机指标数据(CPU/内存/磁盘等)。同时还有一个textfile收集器,允许导出静态指标。

  1. 安装Node Exporter
    Node Exporter的下载地址如下:
https://github.com/prometheus/node_exporter

下载并解压安装

$ wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz
$ tar -xzf node_exporter-*
$ sudo cp node_exporter-*/node_exporter /user/local/bin/
  1. 配置Node Exporter
    node_exporter是通过执行命令时传入参数来配置。
$ node_exporter --help

默认情况下node_exporter在端口9100上运行,路径为/metrics。可通过--web.listen-address和--web.telemetry-path来设置

$ node_exporter --web.listen-address=":9600" --web.telemetry-path="/node_metrics"

同时可以通过参数控制启动的收集器,默认的收集器可在以下地址中查看

https://github.com/prometheus/node_exporter#enabled-by-default

例如,想要禁用/proc/net/arp统计信息,只需要启动node_exporter时添加--no-collector.arp配置项。

  1. 配置textfile收集器
    textfile收集器可以帮助我们暴露自定义指标。node_exporter通过参数--collector.textfile.directory参数指定textfile的目录,它会扫描该目录下的所有文件,提取所有格式为Prometheus指标的字符串,然后暴露它们。
$ mkdir -p /var/lib/node_exporter/textfile_collector
$ echo 'metadata{role="docker_server", datacenter="NJ"} 1' | sudo tee /var/lib/node_exporter/textfile_collector/metadata.prom
  1. 启用systemd收集器
    systemd收集器记录systemd中的服务和系统状态。首先需要通过参数--collector.systemd启用该收集器,同时如果不希望收集所有的服务,只收集部分关键服务。node_exporter在启动时可以使用--collector.systemd.unit-whitelist参数配置。
  2. 运行Node Exporter
    启动node_exporter的实例
$ node_exporter --collector.textfile.director /var/lib/node_exporter/textfile_collector --collector.systemd --collector.systemd.unit-whitelist-{(docker|ssh|rsyslog).service"
  1. 抓取Node Exporter
    配置新作业来抓取Node Exporter导出的数据。prometheus.yml文件中的scrape_configs部分添加job
scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'node'
    static_configs:
      - targets: ['192.168.0.3:9100', '192.168.0.4:9100', '192.168.0.5:9100']

添加了新的job 'node',添加了三台主机的node_exporter监控,默认路径为/metrics。
重启Prometheus服务,将会加载最新的配置,新监控项将会被收集到prometheus数据中。

  1. 过滤收集器
    Prometheus提供了限制抓取过来的数据指标的机制。使用params块中的collect[]来指定收集的指标。
scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['192.168.0.3:9100', '192.168.0.4:9100', '192.168.0.5:9100']
    params:
      collect[]:
        - cpu
        - meminfo
        - diskstats
        - netdev
        - netstat
        - filefd
        - filesystem
        - xfs
        - systemd

使用以下命令来模拟测试

$ curl -g -X GET http://192.168.0.3:9100/metrics?collect[]=cpu

监控Docker容器

推荐使用Google的cAdvisor工具来监控Docker。cAdvisor作为Docker容器运行,单个cAdvisor容器返回针对Docker守护进程和所有正在运行的容器的指标。

  1. 运行cAdvisor
$ docker run \
-v /:/rootfs:ro \
-v /var/run:/var/run:rw \
-v /sys:/sys:ro \
-v /var/lib/docker/:/var/lib/docker:ro \
-v /dev/disk/:/dev/disk:ro \
-p 8080:8080 \
-d --name=cadvisor \
google/cadvisor:latest

通过浏览器访问http://192.168.0.3:8080/containers/可查看

cAdvisor

通过浏览器访问http://192.168.0.3:8080/metrics查看暴露的内置Prometheus指标
cAdvisor指标

  1. 抓取cAdvisor
    配置新作业来抓取cAdvisor导出的数据。prometheus.yml文件中的scrape_configs部分添加job
scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
  - job_name: 'node'
    static_configs:
      - targets: ['192.168.0.3:9100', '192.168.0.4:9100', '192.168.0.5:9100']
  - job_name: 'docker'
    static_configs:
      - targets: ['192.168.0.3:8080', '192.168.0.4:8080', '192.168.0.5:8080']

添加了新的job 'docker',添加了三台主机的node_exporter监控,默认路径为/metrics。

Prometheus抓取数据的生命周期

Prometheus抓取数据的生命周期简化版

可以看到在Prometheus抓取数据的生命周期中,有两处重新标记指标的部分,一个在抓取前,一个是在抓取后。

标签

标签提供了时间序列的维度,可以定义目标,并为时间序列提供上下文。最重要的是,结合指标名称,它们构成了时间序列的标识。
更改或者添加标签会创建新的时间序列

  1. 标签分类:拓扑标签、模式标签
    拓扑标签:通过其物理或者逻辑组成来切割服务组件。每个指标都天然带着job和instance两个拓扑标签。instance标签可以标识目标,通常是目标的IP地址和端口,并且来自address标签。
    模式标签:url、error_code或者user之类,允许将拓扑中同一级别的时间序列匹配在一起。
    如果需要添加额外的标签,可以考虑以下的层次结构
    标签层次结构参考
  2. 重新标记
    控制标签。有两个阶段可以重新标记标签。抓取前的relabel_configs和抓取后的metric_relabel_configs模式。
  • 删除不必要的指标
  • 从指标中删除敏感或不需要的标签
  • 添加、编辑、修改指标的标签值或标签格式

在拉取了cAdvisor的指标数据后,删除container_tasks_statecontainer_memory_failures_total指标数据

 - job_name: 'docker'
    static_configs:
      - targets: ['192.168.0.3:8080', '192.168.0.4:8080', '192.168.0.5:8080']
    metric_relabel_configs:
      - source_labels: [__name__]
        separator: ';'
        regex: '(container_tasks_state|container_memory_failures_total)'
        action: drop

separator默认值为';',多个标签通过separator连接在一起。
如果指定多个源标签,可以使用;隔开每个正则表达式。
action: drop将会在数据存储之前删除指标,keep则会保留与正则匹配的指标,删除所有其他指标。

正则配置id指标中的数据,并将匹配的值放入新的标签container_id中。

 - job_name: 'docker'
    static_configs:
      - targets: ['192.168.0.3:8080', '192.168.0.4:8080', '192.168.0.5:8080']
    metric_relabel_configs:
      - source_labels: [id]
        regex: '/docker/([a-z0-9]+);'
        replacement: '$1'
        target_label: container_id

没有指定action操作,因为metric_relabel_configs的action默认操作为replace。
honor_labels默认值为false,如果target_label的标签已经存在,则会在其前面添加exported_前缀来做区分。

删除标签kernelVersion

 - job_name: 'docker'
    static_configs:
      - targets: ['192.168.0.3:8080', '192.168.0.4:8080', '192.168.0.5:8080']
    metric_relabel_configs:
      - regex: 'kernelVersion'
        action: labeldrop

action: labeldrop,删除匹配的标签
action: labelkeep,保留匹配的标签,删除所有其他标签

Node Exporter和cAdvisor指标

  1. CPU使用率
100 - avg(irate(node_cpu_seconds_total{job="node", mode="idle"}[5m])) by (instance) * 100
  1. CPU饱和度
node_load1 > on (instance) 2 * count by (instance)(node_cpu_seconds_total{mode="idle"})
  1. 内存使用率
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Cached_bytes + node_memory_Buffers_bytes)) / node_memory_MemTotal_bytes * 100
  1. 内存饱和度
1024 * sum by (instance) ((rate(node_vmstat_pgpgin[1m]) + rate(node_vmstat_pgpgout[1m])))
  1. 磁盘使用率
(node_fileystem_size_bytes{mountpoint=~"/|/run"} - node_filesystem_free_bytes{mountpoint=~"/|/run"}) / node_filesystem_size_bytes{mountpoint=~"/|/run"} * 100

Prometheus支持预测

predict_linear(node_fileystem_size_bytes{job="node"}[1h], 4*3600) < 0

使用1个小时窗口数据,预测所有磁盘4个小时后的磁盘会不会用完。

  1. 服务状态
node_systemd_unit_state{name="docker.service", state="active"}
  1. exporter的可用性和up指标
up {job="node", instance="192.168.0.3:9100"}
  1. textfile收集器metadata指标
metadata{datacenter != "NJ"}
node_systemd_unit_state{name="docker.service"} == 1 and on (instance, job) metadata{datacenter = "SF"}

on:一对一匹配
group_left:多对一
group_right:一对多
详情:https://prometheus.io/docs/prometheus/latest/querying/operators/#vector-matching

查询持久化

三种方式使查询持久化

  • 记录规则:根据查询创建新指标
  • 警报规则:从查询生成警报
  • 可视化:使用Grafana等仪表板可视化查询

记录规则
prometheus.yml中的配置项evaluation_interval设置为自动计算记录的规则。

global:
  scrape_interval: 15s
  evaluation_interval: 15s

在prometheus.yml文件的同一文件夹下,创建名为rules的子文件夹,用于保存记录规则。同时在prometheus.yml配置文件中的rule_files块中添加文件rules/node_rules.yml

$ mkdir -p rules && cd rules
$ cat > node_rules.yml <<EOF
groups:
- name: node_rules
  interval: 10s
  rules:
  - record: instance:node_cpu:avg_rate5m
    expr: 100 - avg(irate(node_cpu_seconds_total{job="node", mode="idle"}[5m])) by (instance) * 100
    labels:
      metric_type: aggregation
EOF

创建了名为"node_rules"的规则组,顺序执行规则,后面的规则可以重用前面的规则。规则组间是并行运行的,因此不建议跨组使用规则。
interval:10s 可以设置interval覆盖默认的evaluation_interval值。
record:应该仔细为新的时间序列取名,以便快速识别它的含义,一般推荐的格式是: level:metric:operations
expr:保存生成新时间序列的查询
labels:向新序列添加新的标签

可视化 Grafana

  1. 安装Grafana
$ wget https://dl.grafana.com/oss/release/grafana-6.5.1-1.x86_64.rpm
$ sudo yum localinstall grafana-6.5.1-1.x86_64.rpm

使用ansible role安装:https://galaxy.ansible.com/list#roles/3563
使用Docker镜像安装:https://hub.docker.com/search/?q=grafana

  1. 启动与配置Grafana
    配置文件位于/etc/grafana/grafana.ini
$ systemctl start grafana-server
  1. 浏览器访问http://localhost:3000,默认用户名和密码为admin和admin。
    Grafana仪表盘实例查看地址:https://grafana.com/grafana/dashboards
    Grafana

五、Prometheus服务发现

对于主机数少的情况下,Prometheus可以使用静态配置目标。当规模较大的集群时,就不适用了。服务发现可以通过以下三种机制实现:

  • 配置管理工具生成的文件中接收目标列表
  • 查询API以获取目标列表
  • 使用DNS记录以返回目标列表

基于文件的服务发现

适合配置管理工具。Prometheus会按指定时间计划从这些文件重新加载目标,文件格式支持yaml、Json格式,它们包含了目标列表。

- job_name: node
  file_sd_configs:
    - files:
      - targets/nodes/*.json
        refresh_interval: 5m
- job_name: docker
  file_sd_configs:
    - files:
      - targets/docker/*.yml
        refresh_interval: 5m

新建nodes与docker目录,并添加对应的配置文件

$ cd /etc/prometheus
$ mkdir -p targets/{nodes,docker}
$ cat > targets/nodes/nodes.json <<EOF
[{
  "targets": [
    '192.168.0.3:9100', 
    '192.168.0.4:9100', 
    '192.168.0.5:9100'
  ]
}]
EOF
$ cat > targets/docker/daemons.yml <<EOF
- targets:
  - '192.168.0.3:8080'
  - '192.168.0.4:8080'
  - '192.168.0.5:8080'
  labels:
    datacenter: NJ
EOF

基于API的服务发现

当前API的服务发现支持以下平台:

  • AWS EC2
  • Azure
  • Consul
  • Google Compute Cloud
  • Kubernetes

基于DNS的服务发现

- job_name: webapp
  dns_sd_configs:
    - names: ['_prometheus._tcp.example.com']

Prometheus在查询目标时,通过DNS服务器查找example.com域,然后在该域下搜索名为_prometheus._tcp.example.com的SRV记录,返回该条目中的服务记录。
还可以使用DNS服务发现来查询单个A或AAAA记录。

- job_name: webapp
  dns_sd_configs:
    - names: ['example.com']
      type: A
      port: 9100

返回example.com域根目录下的所有A记录。

六、Alert Manager报警管理

监控是为了了解系统的状态,以便于及时发现问题。当指标出现异常时,我们应该第一时间知道,便及时处理,但是我们又无法实时关注在每个监控指标,这时我们就需要告警机制。没有告警机制的监控,像是摆在家里的花瓶,它很美但用处不大。
一个好的警报应该是,在正确的时间、发给正确的人、恰当的量、包含准确(不多也不少)的信息。

  • 适当数量的警报
  • 设置正确的警报优先级
  • 警报应包括适当的上下文

Alertmanager如何工作

Prometheus服务器向Alertmanager发送警报,当然Alertmanager也可以接收其他工具的警报。Alertmanager对警报进行去重、分组,然后路由到不同的接收器:email,sms等。

  • 在Prometheus服务上编写警报规则
  • 当指标达到阈值时,会生成警报推送到Alertmanager。
  • 一个或多个Prometheus服务器可以将警报定向到单个Alertmanager下
  • Alertmanager处理警报,并根据其标签进行路由。

Alertmanager安装、配置、运行

  1. Alertmanager安装
$ wget https://github.com/prometheus/alertmanager/releases/download/v0.20.0-rc.0/alertmanager-0.20.0-rc.0.linux-amd64.tar.gz
$ tar -xzf alertmanager-0.20.0-rc.0.linux-amd64.tar.gz
$ sudo cp alertmanager-0.20.0-rc.0.linux-amd64/alertmanager /usr/local/bin/
$ sudo cp alertmanager-0.20.0-rc.0.linux-amd64/amtool /usr/local/bin/
  1. 配置Alertmanager
    https://prometheus.io/docs/alerting/configuration/
$ sudo mkdir -p /etc/alertmanager
$ sudo cat > /etc/alertmanager/alertmanager.yml <<EOF
global:
  smtp_smarthost: 'localhost:25'
  smtp_from: 'alertmanager@example.com'
  smtp_require_tls: false

templates:
- '/etc/alertmanager/template/*.tmpl'

route:
  receiver: email

receivers:
- name: 'email'
  email_configs:
  - to: 'alerts@example.com'
EOF

global:全局设置,为其他模块的默认值
template:保存警报模板
route:警报根据规则进行匹配,采取相应的操作
receivers:接收器列表,每个接收器有唯一的名字及配置。email_configs来指定电子邮件选项,webhook_configs可以扩展Alertmanager的接收器。

  1. 运行Alertmanager
$ alertmanager --config.file alertmanager.yml

通过浏览器访问alertmanager,http://localhost:9093

Prometheus配置Alertmanager

  1. 在prometheus.yml配置中设置alerting模块。
alerting:
  alertmanagers:
  - static_configs:
    -targets:
      - alertmanager:9093
  1. 监控Alertmanager
    Alertmanager服务暴露了自身的相关指标,创建一个Prometheus Job就可以监控Alertmanager
- job_name: 'alertmanager'
  static_configs:
    - targets: ['localhost:9093']
  1. 添加警报规则
    与记录规则一样,警报规则在Prometheus服务器配置中加载的规则文件内也使用Yaml语句定义。
    在prometheus.yml配置文件中的rule_files块中添加文件rules/node_alerts.yml
    在rules目录下创建文件node_alerts.yml来保存节点报警规则。
$ cat > rules/node_alerts.yml <<EOF
groups:
- name: node_alerts
  rules:
  - alert: HighNodeCPU
    expr: instance:node_cpu:avg_rate5m > 80
    for: 60m
    labels:
      severity: warning
    annotations:
      summary: High Node CPU for 1 hour
      console: You might want to check the Node Dashboard at http://grafana.example.com/dashboard/db/node-dashboard
EOF

alert:规则名
expr:触发规则
for:控制在触发警报之前测试表达式必须为true的时长
labels与annotations:装饰警报

警报有三种状态:
Inactive:警报未激活
Pending:警报已满足测试表达式条件,但仍在等待for子句中指定的持续时长
Firing:警报(如果没有设置for,则一旦触发条件,立刻Firing)

Pending、Firing状态下的警报可以在Prometheus的指标中查看到ALERTS。
新的警报与模板示例

groups:
- name: node_alerts
  rules:
  - alert: DiskWillFillIn4Hours
    expr: predict_linear(node_fileystem_size_bytes{mountpoing="/"}[1h], 4*3600) < 0
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: Disk on {{ $labels.instance }} will fill in approximately 4 hours.
  - alert: InstanceDown
    expr: up{job="node"} == 0
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: Host {{ $labels.instance }} of {{ $labels.job }} is down!
  - alert: NodeServiceDown
    expr: node_systemd_unit_state{state="active"} != 1
    for: 60s
    labels:
      severity: critical
    annotations:
      summary: Service {{$labels.name}} on {{ $labels.instance }} is no longer active!
      description: Service Down
  - alert: InstanceGone
    expr: absent(up{job="node"})
    for: 10s
    labels:
      severity: critical
    annotations:
      summary: Host {{ $labels.instance }} is no logger reporting!
      description: 'OMG Where are my instances'
- name: prometheus_alerts
  rules:
  - alert: PrometheusConfigReloadFailed
    expr: prometheus_config_last_reload_successful == 0
    for: 10m
    labels:
      severity: warning
    annotations:
      description: Reloading Prometheus configuration has failed on {{ $lables.instance }}.
  - alert: PrometheusNotConnectedToAlertmanagers
    expr: prometheus_notifications_alertmanagers_discovered < 1
    for: 10m
    labels:
      severity: warning
    annotations:
      description: Prometheus {{ $labels.instance }} is not connected to any Alertmanagers.

路由

Alertmanager的配置文件alertmanager.yml中添加一些路由配置。

route:
  group_by: ['instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 3h
  receiver: email
  routes:
  - match:
      severity: critical
    receiver: pager
  - match_re:
      severity: ^(warning|critical)$
    receiver: support_team

receivers:
- name: 'email'
  email_configs:
  - to: 'alert@example.com'
    send_resolved: true
- name: 'support_team'
  email_configs:
  - to: 'support@example.com'
- name: 'pager'
  email_configs:
  - to: 'alert-pager@example.com'
  pagerduty_configs:
  - service_key: TEAFDSFEWS

group_by:对Alertmanager警报指定分组方式,如按照instance来分组
group_wait:如果进行分组,Alertmanager会等待group_wait指定的时间,以便在触发报警前查看是否收到该组中的其他报警
group_interval:如果发出警报后,Alertmanager收到该分组的下一次评估的新警报后,会等待group_interval时间后再发送新警报,以免警报泛滥
repeat_interval:适用于单个警报,等待重新发送相同警报的时间段
receiver:默认接收器
send_resolved: 恢复后发送通知
routes:路由规则。如果需要routers还可以分支。如:

routes:
- match:
    severity: critical
  receiver: pager
  routes:
  - match:
      service: application1
    receiver: support_team

通知模板

模板目录:/etc/alertmanager/templates

$ cat > /etc/alertmanager/templates/slack.tmpl <<EOF
{{ define "annotation.summary.text" }}{{ .CommonAnnotations.summary}}{{end}}
EOF

对应的slack_configs receiver配置

  slack_configs:
  - api_url: https://hooks.slack.com/services/ABC123/fsdaf、
EXAMPLE
  channel: #monitoring
  text: '{{template "annotation.summary.text" .}}

使用模板通知来填充text字段,使用上下文通知。

silence和维护

报警静默设置。当服务进行维护时,不需要发出告警,使用silence进行控制。两种方法进行设置:

  • 通过Alertmanger Web控制台
  • 通过amtool命令工具
  1. 使用amtool添加silence。默认为1h过期时间,可以指定--expires和--expire-on参数指定更长的时间与窗口
$ amtool --alertmanager.url=http://localhost:9093 silence add alertname=InstancesGone service=application1
  1. 使用query命令查询silence列表
$ amtool  --alertmanager.url=http://localhost:9093 silence query
  1. 指定silence过期
$ amtool  --alertmanager.url=http://localhost:9093 silence expire $SILENCE_ID
  1. 使用正则创建silence
$ amtool  --alertmanager.url=http://localhost:9093 silence add --comment "App1 maintenance" alertname=~'Instance.*' service=application1

七、Prometheus高可用性

Prometheus通过运行两个配置相同的Prometheus服务器,并且它们同时处于活动状态来实现容错。该配置生成的重复警报交由上游Alertmanager使用其分组功能进行处理。所以一个推荐的做法是关注Alertmanager的高可用,而不是Prometheus服务。
通过创建一个Alertmanager集群来实现高可用,所有Prometheus服务器将告警发送到Alertmamanager集群,而Alertmanager负责去除重复数据。

设置Alertmanager集群

Alertmanager包含由HashiCorp Memberlist库提供的集群功能。

  1. 在多台主机上安装Alertmanager
  2. 启动Alertmanager,传入参数--cluster.listen-address
    第一台主机启动Alertmanager命令如下:
$ alertmanager --config.file alertmanager.yml --cluster.listen-address 192.168.0.3:8001

剩下的主机启动Alertmanager命令如下:

$ alertmanager --config.file alertmanager.yml --cluster.listen-address 192.168.0.4:8001 --cluster.peer 192.168.0.3:8001
  1. 在Alertmanager的控制台状态页面/status上查看集群状态
  2. 为Prometheus配置Alertmanager集群
  alerting:
    alertmanagers:
      - static_configs:
        - targets:
          - 192.168.0.3:9093
          - 192.168.0.4:9093
          - 192.168.0.5:9093

三个Alertmanager服务都会收到告警信息,保证告警可达。

可扩展性

Prometheus federation API抓取每个工作节点的聚合指标
一个很好的例子是:基于区域的主节点和工作节点,基于区域的主节点视为全局的工作节点,然后向全局的主节点进行报告。
因为是金字塔级结构,主节点可能会有延时,所以尽量通过工作节点向Alertmanager发送告警。
水平分片通常是最后的选择。每个目标都有数万个指标或者大量时间序列。

Prometheus work0配置

global:
  external_labels:
    worker: 0
rule_files:
  - "rules/node_rules.yml"
scrape_configs:
  - job_name: 'node'
    file_sd_configs:
    - files:
      - targets/nodes/*.json
        refresh_interval: 5m
    relabel_configs:
    - source_labels: [__address__]
      modulus: 3
      target_label: __tmp_hash
      action: hashmod
    - source_labels: [__tmp_hash]
      regex: ^0$
      action: keep

该过程是使用hashmod模块对__address__标签的值对3取Mod,如果余数为0,则保留。
同样的方法配置好work1与work2节点。

Prometheus 主节点配置

scrap_configs:
- job_name: 'node_workers'
  file_sd_configs:
    - files:
      - 'targets/workers.json'
      refresh_interval: 5m
  honor_labels: true
  metrics_path: /federate
  params:
    'match[]':
      - '{__name__="^instance:.*"}'

其中targets/workers.json内容为

[{
  "targets": [
    "worker0:9090",
    "worker1:9090",
    "worker2:9090",
  ]
}]

Prometheus支持使用/federate API根据指定的匹配参数来查询服务器指标。

八、日志监控

使用mtail作为日志处理工具,它是Google开发的,非常轻巧。它专门用于从应用程序日志中提取要导出到时间序列数据库中的指标。

  1. 安装mtail
$ wget https://github.com/google/mtail/releases/download/v3.0.0-rc33/mtail_v3.0.0-rc33_linux_amd64 -O mtail
$ chmod 0755 mtail
$ sudo cp mtail /usr/local/bin/
  1. 使用mtail
    mtail通过命令进行配置,指定日志文件列表,以及运行的程序目录。每个mtail程序都以.mtail为后缀名。
$ sudo mkdir /etc/mtail
$ cat > /etc/mtail/line_count.mtail <<EOF
counter line_count

/$/ {
  line_count++
}
EOF

程序定义了一个名为line_count的计数器(计数器 counter,测量型 gauge)。这些计数与测量通过mtail导出到定义的任何目的地。

  1. 运行mtail
$ sudo mtail --progs /etc/mtail --logs '/var/log/*.log' 

--progs:指定mtail程序所在目录
--logs:指定日志文件
执行后,mtail将在3903端口上启动Web服务(使用--address和--port参数设置IP与端口)。http://localhost:3903/metrics路径可以被Prometheus获取相关监控数据。

处理Web服务器访问日志

# LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer|i\" \"%}User-agent|i\"
counter apache_http_requests_total by request_method, http_version, request_status
counter apache_http_bytes_total by request_method, http_version, request_status

/^/ +
/(?P<hostname>[0-9A-Za=z\.-]+) / + # %h
/(?P<remote_logname>[0-9A-Za=z\.-]+) / + # %l
/(?P<remote_username>[0-9A-Za=z\.-]+) / + # %u
/(?P<timestamp>\[\d{2}\/\w{3}\/\d{4}:\d{2}:\d{2}:\d{2} (\+|-)\d{4}\]) / + # %u
/"(?P<request_method>[A-Z]+) (?P<URI>\S+) (?P<http_version>HTTP\/[0-9\.]+)" / + # \"%r\"
/(?P<request_status>\d{3}) / + # %>s
/(?P<response_size>\d+) / + # %b
/"(?P<referer>\S+)" / + # \"%{Referer}i\"
/"(?P<user_agent>[[:print:]]+)"/ + # \"%{User-agent}i\"

/$/ {
  apache_http_requests_total[$request_method][$http_version][$request_status]++
  apache_http_bytes_total[$request_method][$http_version][$request_status] += $response_size
}

by:指定要添加到指标的其他维度,它们将会添加到指标的标签中。
每个维度包含在[ ]中。
运行mtail程序

$ sudo mtail --progs /etc/mtail --logs '/var/log/apache/*.access'

解析Rail日志到直方图

counter rails_requests_started_total
counter rails_requests_started by verb
counter rails_requests_completed_total
counter rails_requests_completed by status
counter rails_requests_completed_milliseconds_sum by status
counter rails_requests_completed_milliseconds_count by status
counter rails_requests_completed_milliseconds_bucket by le,status

/^Started (?P<verb>[A-Z]+) ./*/ {
  rails_requests_started_total++
  rails_requests_started[$verb]++
}

/^Completed (?P<status>\d{3}) .+ in (?P<request_milliseconds>\d+)ms .*$/ {
rails_requests_completed_total++
rails_requests_completed[$status]++

rails_requests_completed_milliseconds_sum[$status] += $request_milliseconds
rails_requests_completed_milliseconds_count[$status] ++

$request_milliseconds <= 10{
    rails_requests_completed_milliseconds_bucket["10"][$status] ++
  }
$request_milliseconds <= 50{
  rails_requests_completed_milliseconds_bucket["50"][$status] ++
}
}

尽量为每个应用单独部署日志监控,对于K8S上的应用,可以使用sidecar的方式运行mtail来实现日志监控。
例子代码:https://github.com/google/mtail/tree/master/examples

九、探针监控

使用Blackbox exporter来对外部服务探测监控。

  1. 安装Blackbox exporter
$ wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.16.0/blackbox_exporter-0.16.0.linux-amd64.tar.gz
$ tar -xzf blackbox_exporter-0.16.0.linux-amd64.tar.gz
$ sudo cp blackbox_exporter-0.16.0.linux-amd64/blackbox_exporter /usr/local/bin/
  1. 配置Blackbox exporter
    使用/etc/prober/prober.yml文件配置exporter
$ sudo mkdir -p /etc/prober
$ sudo touch /etc/prober/prober.yml
$ cat > /etc/prober/prober.yml <<EOF
modules:
  http_2xx_check:
    prober: http
    timeout: 5s
    http:
      valid_status_codes: []
      method: GET
  icmp_check:
    prober: icmp
    timeout: 5s
    icmp:
      preferred_ip_protocol: "ip4"
  dns_examplecom_check:
    prober: dns
    dns:
      preferred_ip_protocol: "ip4"
      query_name: "www.example.com"
EOF
  1. 启动exporter
$ sudo blackbox_exporter --config.file="/etc/prober/prober.yml"

默认在端口9115下运行服务:http://localhost:9115/metrics

  1. Prometheus创建作业,调用Blackbox Exporter服务
scrape_configs:
  - job_name: 'blackbox'
    metrics_path: /probe
    params:
      module: [http_2xx_check]  # Look for a HTTP 200 response.
    static_configs:
      - targets:
        - http://prometheus.io    # Target to probe with http.
        - https://prometheus.io   # Target to probe with https.
        - http://example.com:8080 # Target to probe with http on port 8080.
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115 

Blackbox Exporter的配置Job方式与其他作业不同,这的targets是作为Blackbox Exporter检测的目标地址。而Blackbox Exporter的服务地址,通过relabel_configs替换掉address标签的方式设置。

十、Pushgateway方式推送监控数据

Prometheus主要是基于拉取的架构来运行作业,同时也提供了Pushgateway服务来支持Push方式。
Pushgateway位于发送指标的应用程序与Prometheus服务器之间,接收指标,同时作为目标被抓取。
Pushgateway只能用作有限的解决方案使用,特别是监控其他无法访问的资源。

  1. 安装Pushgateway
$ wget https://github.com/prometheus/pushgateway/releases/download/v1.0.0/pushgateway-1.0.0.linux-amd64.tar.gz
$ tar -xzf pushgateway-1.0.0.linux-amd64.tar.gz
$ sudo cp pushgateway-1.0.0.linux-amd64/pushgateway /usr/local/bin
  1. 配置和运行Pushgateway
$ pushgateway --web.listen-address="0.0.0.0:9091" --persistence.file="/tmp/pushgateway_persist" --persistence.interval=5m

--web.listen-address:指定服务端口。pushgateway默认端口是9091.
--persistence.file:指标持久化到路径。默认情况下,pushgateway所有指标存储在内存中,如果pushgateway停止服务或者重新启动,所有数据将会丢失。
--persistence.interval:指标持久化写入周期。默认5m

  1. 向pushgateway服务发送指标
$ echo "batchjob1_user_counter 2" | curl --data-binary @- http://localhost:9091/metrics/job/batchjob1/instance/sidekiq_server

将为作业batchjob1添加一个新的指标
batchjob1_user_counter{instance="sidekiq_server"} 2

$ cat <<EOF | curl --data-binary @- http://localhost:9091/metrics/job/batchjob1/instance/sidekiq_server
# TYPE batchjob1_user_counter counter
# HELP batchjob1_user_counter A metric from BatchJob1.
batchjob1_user_counter{job_id="123ABC"} 2

也可以同时发送多个指标。

  1. 在pushgateway上查看指标
$ curl http://localhost:9091/metrics
  1. 删除pushgateway上的指标
$ curl -x DELETE localhost:9091/metrics/job/batchjob1 #删除job batchjob1下的所有指标
$ curl -x DELETE localhost:9091/metrics/job/batchjob1/instance/sidekiq_server # 删除job batchjob1下标签满足instance=sidekiq_server的指标
  1. Promethes上添加Pushgateway Job
- job_name: 'pushgateway'
    honor_labels: true
    static_configs:
      - targets: ['localhost:9091']

honor_labels设置为true,Prometheus使用Pushgateway上的job和instance标签,否则会在前面加上exported_前缀。

十一、监控OpenShift

OpenShift平台的监控方案默认为Prometheus开源监控方案,它不仅带有一整套完成的监控,而且还预配置了一组告警,以及一组丰富的Grafana仪表盘。

OpenShift Prometheus架构

可以通过Prometheus Operator方便地创建、配置和管理Prometheus及Alertmanager。
从上图可以看到,除了Prometheus与Alertmanager服务,OpenShift的监控方案中还装了node exporter与kube-state-metrics获取集群的状态指标。
OpenShift使用ansible安装时,默认会安装的cluster monitoring operator。除非在inventory中指定openshift_cluster_monitoring_operator_install为false。

OpenShift中Prometheus默认监控目标Targets
OpenShift中Prometheus默认添加的告警规则

扩展资料

Awesome Prometheus alerts
Rich Exporter
Exporter Operator

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容