Prometheus+grafana 监控系统

序言

当初在 TX 做 Gerzi,给其他部门做测试,接触了 Prometheus + grafana 的监控系统。那可真是一段痛苦的服务日子啊。虽说难以解构实际的技术栈,但是这个监控系统给我留下了不少印象,目前就进行一下重现。

简单来说,这套监控系统就是通过 Exporter 来进行对应后台系统或者微服务系统进行指标数据收集,然后汇集到 Prometheus 这个基于时序数据库的开源工具中,而后通过 Grafana 工具进行可视化展示。需要说一下的是 Prometheus 的原作者是 Matt T.Proud ,可以的话可以去观摩一下。

prometheus安装部署

Prometheus 是 SoundCloud 这个在线音乐分享平台进行开发的,官方博客中针对这个监控系统 Prometheus 有文章 Prometheus: Monitoring at SoundCloud ,这篇文章里介绍了它们所需要的监控系统需要满足的特性(也就是 Prometheus 会 #技术分享满足的):

  • 多维度数据模型
  • 方便的部署和维护
  • 灵活的数据采集
  • 强劲的语言查询

用户可以根据个人使用体验来判断这些条件是否满足,如果不满足可以思考给他们提意见或者自己搞一个,或许你就是明日之星呢。Prometheus 作为监控系统的一部分,它更是一个时序数据库。针对 Prometheus 的目标数据(目标 service)采集,往往采取在目标 service 处开放一个 Http 接口来直接供给 Prometheus ,或者使用一个 Exporter (数据采集组件)来进行目标 service 的数据采集,再对 Prometheus 提供一个 Http 接口来进行数据汇总(听说 Prometheus 使用 Pull 来进行数据采集,而不是 Push )。

解压安装

回归正题,下面来进行 Prometheus 的安装部署,第一是在个人的 ubuntu 中进行直接安装,这种安装方式是下载压缩包到本地进行安装,比较传统:

# 在https://prometheus.io/download/官网中有着对应安装包,选择合适的进行wget到本地即可

$ wget https://github.com/prometheus/prometheus/releases/download/v3.5.0/prometheus-3.5.0.linux-amd64.tar.gz

$ tar -xvfz prometheus-3.5.0.linux-amd64.tar.gz $ cd prometheus-3.5.0.linux-amd64 $ ./prometheus --version prometheus, version 3.5.0

prometheus 的运行,编写其路径下 prometheus.yml 如下:

global:
  scrape_interval:     15s

scrape_configs: - job_name: 'prometheus'

scrape_interval: 5s

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

prometheus 配置主要是 global 全局配置项、 alerting 通知配置项、 rule_files 报警规则配置项和最后的 scrape_config 指标数据收集任务配置项。

保存好后来运行即可:

$ ./prometheus --config.file=prometheus.yml

到了这一步,prometheus 就算可用了,不过为了方便,还是需要进行一下调整,随个人喜爱移动 prometheus 路径到 share 或者 local 都可以,然后添加其 prometheus 的可执行文件路径到环境变量中即可。

docker部署

对于目前来说,实则更多还是应用 prometheus 到 docker 中,为了方便 docker 使用,在拉取 prometheus 的镜像前,需要先安装了 docker :

$ apt install docker.io

这之后就可以进行正常的镜像获取和应用了:

$ docker run 
    --name prometheus-service 
    -p 9090:9090 
    -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml 
    -d prom/prometheus

特定路径编辑好配置 yml 后来如上进行挂载应用,docker run 初次执行就会自动获取对应镜像了,-v 参数是把本地 /path/to/prometheus.yml 挂载到运行起来的 prometheus 容器中的
/etc/prometheus/prometheus.yml ;-p 参数则是端口挂载,比较简单。

除了上面参数,还有着其他的 docker 参数应用可以参考这篇:

docker 命令参数

上面的运行结果就是,Prometheus 通过自己暴露的 metrics 接口进行自我数据收集,当真是自己吃自己了,想要查看这些数据,如下:

$ $ curl http://localhost:9090/metrics

# HELP go_gc_cycles_automatic_gc_cycles_total Count of completed GC cycles generated by the Go runtime. Sourced from /gc/cycles/automatic:gc-cycles.

# TYPE go_gc_cycles_automatic_gc_cycles_total counter

go_gc_cycles_automatic_gc_cycles_total 6

# HELP go_gc_cycles_forced_gc_cycles_total Count of completed GC cycles forced by the application. Sourced from /gc/cycles/forced:gc-cycles.

# TYPE go_gc_cycles_forced_gc_cycles_total counter

go_gc_cycles_forced_gc_cycles_total 0

# HELP go_gc_cycles_total_gc_cycles_total Count of all completed GC cycles. Sourced from /gc/cycles/total:gc-cycles.

# TYPE go_gc_cycles_total_gc_cycles_total counter

go_gc_cycles_total_gc_cycles_total 6

# HELP go_gc_duration_seconds A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.

# TYPE go_gc_duration_seconds summary

go_gc_duration_seconds{quantile="0"} 6.6802e-05 ...

prometheus 安装部署完毕后,就可以通过 web 进行简单访问了,直接访问 http://localhost:9090/ 就可以得到如下页面,这里采取的是 ubuntu 进行部署,同一局域网下 windows 进行编辑访问,所以:

如上为默认跳转的查询页面,在这里可以通过提供的 Status 页面查看数据采集方(各种 exporter 或者直接后台)的状态的 Target health ,但是这里不关注这些,这里只关注 Graph 页面提供的强劲查询功能,通过特殊表达式来对监控数据进行查询,这个表达式就是 PromQL 。目前还不算正式应用,姑且搁置一下。

Grafana安装部署

和 prometheus 一样,Grafana 同样有着两种部署方式,第一种就是本地安装了:

# 安装基本工具,如果已经有了wget可以忽略

$ sudo apt-get install -y apt-transport-https software-properties-common wget

# 添加gpg密钥

$ sudo mkdir -p /etc/apt/keyrings/ $ wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null

# 添加respository

$ echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list

# 更新一下源然后安装

$ sudo apt update $ sudo apt install grafana

另外的部署方式就是 docker 部署了,如下:

$ docker run -d 
    --name grafana-service 
    -p 3000:3000
    grafana/grafana

简单粗暴,如此运行起来后,直接访问 http://localhost:3000/ ,上来就是 Grafana 登录页面:

默认登录为 admin/admin ,成功后来就会要求设置初始管理员密码,完了后来就可以进去了,到这里,grafana 服务算是起来了,但却还不算用起来,由于它还么设置 prometheus 数据源,只是一个提供 web 页面的空的 grafana 服务。下面设置一下数据源,搜索 [Data sources] 进入 [Data sources] 页面,然后在这里可以进行 [Add data source] 操作,不过目前 grafana 并不止于 Prometheus 这一数据源,点击后会发现有许多可选项,不过这里还是采用的 prometheus :

如上进行设置也是够了的,更多的就看个人对于 prometheus 是否有更多的私密设置之类的了,这时候才需要在上面配置上进行添加,列如 添加了用户 cookie 的 metrics 接口 。

添加完数据源后来,还需要定制一下 dashboards ,也就是数据格式 json 的引入,这个搁在后面数据 Exporter 一起谈。

实操碰到的小问题

在实际应用中,本来由于本地测试 prometheus 采用 curl 本地 localhost 得以成功,象征性完成联通测试了,但在 grafana 数据源中采取 localhost 作为数据源 host ,则是会出现连通性问题。为了解决这个问题,需要将这两个 service 置于同一个 docker 网段中:

# 创建一个test-net的docker网段

$ docker network create test-net

# 将这两个servcice添加到test-net网段中

$ docker network connect test-net prometheus-service $ docker network connect test-net grafana-service

这样一来,在 grafana-service 中就可以利用 prometheus-service 来对这 service 进行访问了,不然就只能通过其分配的 docker ip 进行访问了,到这之后,前面的 grafana 数据源的设置就能正常进行了,会有如下结果:

Exporter数据收集

到这里,只是确定了数据统一的 prometheus 和数据可视化 grafana 的简单应用,尚未投入实际的项目监控中,这里就针对项目中常用的 CPU 负载 、内存占用 、IO 开销 、流量统计 等。这类向 Prometheus 提供监控样本数据的 Exporter ,Prometheus 会定期向 Exporter 轮询监控数据,通过 Exporter 暴露的 metrics 接口。

针对这类指标收集,就需要特殊的 Exporter 来进行,关于 Exporter 的列表可以在 prometheus 官网中进行查看,根据自己需要进行选择:

Exporter 列表

从这上面,可以找到各种官方提供的关于 Database 数据库 、Hardware 硬件 、Storage 存储 、Messages System 消息队列 、HTTP 服务 、API 服务 、logging 日志 、另外的监控系统 等等常用的一些个常见的也是比较常用的相关 Exporter ,另外还有着其他针对特定语言的支持,列如对于 Golang 、python 等等,使其可以在对应代码项目中实现 metrics 接口,如此操作,项目也就无需另外的 Exporter ,但也给项目增添了额外的负担。

回归正题,下面使用基础的 node-exporter 来作为 Exporter 进行系统层面的数据收集,基本的本地部署当然是:

# node-exporter的github仓库中选择对应系统安装包进行wget

# 会用到科学,不然真难搞

$ wget https://github.com/prometheus/node_exporter/releases/download/v1.9.1/node_exporter-1.9.1.linux-amd64.tar.gz

# 解压

$ tar xvfz node_exporter-1.9.1.linux-amd64.tar.gz $ cd node_exporter-1.9.1.linux-amd64

# 运行

$ ./node_exporter

运行起来后就可以通过 curl
http://localhost:9100/metrics 获取本地指标数据了,另外还有 docker 的部署方式:

$ docker run -d 
  --net test-net 
  -p 9100:9100 
  --name node-exporter 
  prom/node-exporter

如上操作,运行 node-exporter 的时候添加进 test-net 的 docker 网段中,这样 prometheus-service 才能正常通过 host 来获取其信息,如上操作后,还需要修改一下 prometheus-service 的 yml 文件更改一下 target 信息,更改完成后还需要重启一下使其生效:

scrape_configs:
  - job_name: 'node'

scrape_interval: 5s

static_configs: - targets: ['node-exporter:9100']

重启一下:

$ docker restart prometheus-service

PromQL小解

上面 Prometheus 重启完成后就可以在其 web 中可以对其进行数据查询:

如上就是在 Prometheus 中进行 PromQL 查询的结果。作为 Prometheus 的核心功能,PromQL 支持用户进行监控样本数据的统计分析,同时告警监控也是依赖于 PromQL 进行实现。

Prometheus 支持四种数据类型:

  • 瞬时向量(Instant vector)
  • 区间向量(Range vector)
  • 标量数据(Scalar),浮点数
  • (String),字符串,待用

解析一下,重点关注 Instant vector 和 Range vector ,后者是多个时序序列,每个序列都是一个 Instant vector ,下面针对瞬时向量进行查询:

如上,输入指标名称,即可获取对应瞬时向量数据,这是 node-exporter 中定义的标签数据,那么范围内多时序呢?添加上一个时间范围即可:

上面查询的数据为1m 内也就是一分钟内的数据,由于 Prometheus 配置的 scrape_interval 为5s,所以共计12条数据,这就是区间数据了。类型数据是这样,除此以外,PromQL 还有着各种函数支持,这里就不加赘言了,毕竟只是要最后在 Grafana 的可视乎。

打造自己的Exporter

由于是在项目中引入,所以下面重点关注如何打造项目需要的自定义 Exporter 。Exporter 和 Prometheus 间前者暴露 metrics 接口,后者进行轮询从而收集监控数据,因此 Exporter 要实现数据的收集和转化。指标数据常见格式如下:

http_req_duration_sec_bucket{le="0.2"} 150
http_req_duration_sec_bucket{le="0.5"} 200

采用 度量名称{标签名='标签值1',…} 值 时间戳 的格式,如上为
http_req_duration_sec_bucket 的度量名的监控数据,le 为标签名,0.2 和 0.5 为标签值,150 和 200 为确切的监控数据,这里数据忽略了时间戳。对于代码层面的调用,往往是定义四种 prometheus-client 库所提供的 Counter 计数器、Gauge 变化度量、Histogram 直方图、Summary 摘要来进行指标数据项定义。Counter 常用来记录递增指标,如请求数;Gauge 记录可变化度量值,如 CPU 利用率;Histogram 直方图记录样本分布,如请求延迟;Summary 概要则是类似 Histogram ,也记录样本分布情况,但展示更多的统计信息,诸如数量、总和、平均值等。

项目代码实现对应的指标数据,并进行记录,最后通过 metrics 接口暴露给 Prometheus 进行数据收集,整体流程就完成了。

Grafana dashboard数据样式

前面有进行数据收集和 Prometheus 中数据统计查询,但是还是没有实现最终需要的 如图所示 ,没法向领导做汇报呢,所以需要在前面 Grafana 中继续进行数据展示样式的设置,也就是 dashboard 方面的设置。关于这个,grafana 有着现成的展示板可以进行,只需要在 grafana 官网样板列表 中进行特定选择,不过第一要配合对应的 Exporter ,列如前面的 node-exporter ,就可以选择这里的 node-exporter-full 的样板进行数据展示:

如上操作,然后在 grafana-service 的 web 页面进行上面下载的 json 导入即可:

操作完成后即可看到效果:

报警和通知

好的,进行到这里,监控系统就基本成型了,但是运维人员不可能随时盯着监控的,而且监控可视化在某种程度上,情况发生的时候前台看到已经晚了,所以还是需要后台进行直接告警和通知。

前面有过介绍,关于 Prometheus 配置中有着 rule_files 的配置可以进行告警方面的配置:

rule_files:
  - alerts.yml

而后直接整个 alerts.yml :

groups:

  - name: system-alerts
    rules:

      - alert: HighCPUUsage
        expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "系统CPU使用率过高"
          description: "系统CPU使用率为 {{ $value }}%,超过85%阈值"

- alert: HighMemoryUsage
        expr: 100 * (1 - ((node_memory_MemAvailable_bytes) / (node_memory_MemTotal_bytes))) > 90
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "系统内存使用率过高"
          description: "系统内存使用率为 {{ $value }}%,超过90%阈值"

- alert: DiskSpaceLow
        expr: 100 * (1 - ((node_filesystem_avail_bytes{mountpoint="/"}) / (node_filesystem_size_bytes{mountpoint="/"}))) > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "磁盘空间不足"
          description: "根分区磁盘使用率为 {{ $value }}%,超过85%阈值"

如上就是一个报警 yml 的配置了,如上针对 node-exporter 的监控数据进行设定的系统告警,设置了 HighCPUUsage 、HighMemoryUsage 和 DiskSpaceLow 的三种情况和报警处理。

拿第一条 alert 来说,就是 expr 参数所设定的 PromQL 语句为临界条件,表明当5m 内 CPU 使用率大于85%了,这条 PromQL 的思路是使用 irate 和 avg 函数结合查询到的5分钟内的一个 node_cpu_seconds_total 数据做一个平均得到 CPU 的空闲度(100为满),而后做差,就是现有 CPU 使用度了。

labels 是自定义标签,在实际应用中,可以根据标签来进行报警情况级别分类,从而划分不同情况的处理,列如普通报警简单通知,宕机报警直接电话短信通知等;annotations 就是报警的文本内容了,这个倒是很好理解。

综上来看,一份报警 yml 是很考究开发人员对系统的指标的了解程度和 PromQL 的应用熟悉程度的,都掌握的人才能应用自如。话不多说,搞定了 yml 配置后,由于引入了新的配置文件,所以重启没法解决问题:

# 删除原有

$ docker rm -f prometheus-service

# 另起一份

$ docker run --name prometheus-service  -p 9090:9090  -v ./prometheus.yml:/etc/prometheus/prometheus.yml  -v ./alerts.yml:/etc/prometheus/alerts.yml  -d prom/prometheus

执行完毕,查看 prometheus-service 的 web 页面上 alerts 部分,就可以看到:

为了进行可行性检验,在上面 rules 中添加一条:

groups:
  - name: system-alerts
    rules:
      - alert: NodeExporterDown
        expr: up{job='node'} == 0

添加后来重启一下服务即可看到这条 rule 的生效了,另外手动停下 node-exporter 来检验它是否确切可行,这条 PromQL 语句主要是 up 函数查询 job 为 node 的状态,为0就表明挂了:

如上,根据条件语句检测得出 node-exporter 挂掉后立即更新状态为 Firing ,但有时候,这些个 service 是分布式部署在不同主机上的,如果由于网络波动,突然就报警,谁受得了?所以需要有持续时间的设定,当触发条件持续了一段时间后才发送报警信息,这也就是 for 参数的应用。

for 参数表明从第一次 alert 情况被检测到后,Prometheus 需要等待多久才进行实际报警,也就是大致多久才触发 firing 状态,否则会一直处于 pending 状态。

prometheus报警

上面说了,报警时为了不盯着监控系统,在有情况发生的时候马上收到通知是吧?好像上面还缺少了实际的通知功能的实现呢,这就需要用上 alertmanager 了,这是专门进行警报接收、聚合和用户通知用的。

先整下来镜像:

$ docker pull prom/alertmanager

而后配置一下 prometheus-service ,使其将报警推送到 alertmanager 上:

rule_files:
  - alerts.yml

alerting: alertmanagers: - static_configs: - targets: - alert-manager:9093

如上,添加 alerting 为 alert-manager 服务,其对外端口为 9093 ,针对 alert-manager 这一服务,也是需要配置的:

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.163.com:465'
  smtp_from: 'your_email.com'
  smtp_auth_username: 'your_email.com'
  smtp_auth_password: 'kdjslajlsdlfk'
  smtp_require_tls: false

route: group_by: ['alertname', 'instance', 'severity'] group_wait: 10s group_interval: 1m repeat_interval: 15m receiver: 'mail'

receivers: - name: 'mail' email_configs: - to: 'your_email.com'

这里采用的是网易163的 smtp 服务,使用比较简单,可以自行网上搜索 网易163 开启 smtp ,获取其密钥存于上面 smtp_auth_password 参数即可,我上面是 bullshit,不用在意,这里面是有不少坑的,要出慢活。

上面参数还是太简单的,就不一一说明了。搞定 yml 配置后,一键开启:

$ docker run -d 
    --name alert-manager 
    -p 9093:9093 
    -v ./alertmanager.yml:/etc/alertmanager/alertmanager.yml 
    --network=test-net 
    prom/alertmanager

拉起来后来,浏览器查看 http://localhost:9093/ 如下:

页面上 Status 可以查看到当前 Config ,通过这里可以查看对于 alert-manager 的配置文件是否挂载生效,而后可以进入到 alert-manager 和 prometheus-service 中使用 nslookup 来测试域名解析,连通性方面直接 ping ip 就好,完全莫问题的。

而后,不要忘记前面加了个 NodeExporterDown 的报警检测,所以拉起了 alert-manager 后,重走一遍流程,把 node-exporter 给挂掉,然后 prometheus-service 查看其 alerts 中对应 NodeExporterDown 是否已经进入 pending ,等待设定的 1m 到后,配置所设定的 receivers 所指邮箱是否收到对应报警邮件。

实则除了这样进行监控的报警,还可以利用 Grafana 进行报警的配置实现,简单来说,路子不止这一条。

总结

到这里了,可以总结一下了,到这为止,这套监控系统已经有 prometheus 、grafana 、alertmanager 和 node-exporter 四个 service 了,在实际中,并不需要一个一个地进行拉起和配置,毕竟目前都定型了,所以集成到一份 docker-compose.yml :

networks:
  monitoring-net:
    name: monitoring-net
    driver: bridge
    attachable: true

services:
  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    networks:
      - monitoring-net
    ports:
      - "9100:9100"

prometheus: image: prom/prometheus:latest container_name: prometheus-service networks: - monitoring-net ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - ./alerts.yml:/etc/prometheus/alerts.yml

grafana: image: grafana/grafana:latest container_name: grafana-service networks: - monitoring-net ports: - "3000:3000" environment: GF_PATHS_PROVISIONING: /etc/grafana/provisioning GF_SECURITY_ADMIN_USER: admin GF_SECURITY_ADMIN_PASSWORD: Admin123@ GF_SECURITY_DISABLE_INITIAL_ADMIN_PASSWORD_HINT: "true" volumes: - ${PWD}/grafana/grafana.ini:/etc/grafana/grafana.ini - ${PWD}/grafana/provisioning:/etc/grafana/provisioning depends_on: - prometheus

alertmanager: image: prom/alertmanager:latest container_name: alert-manager networks: - monitoring-net ports: - "9093:9093" volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml

而后是关键的几个配置文件,第一是 prometheus 方面的 prometheus.yml :

global:
  scrape_interval:     15s

rule_files: - alerts.yml

alerting: alertmanagers: - static_configs: - targets: - alert-manager:9093

scrape_configs: - job_name: 'node'

scrape_interval: 5s

static_configs: - targets: ['node-exporter:9100']

prometheus 的报警配置 rule 文件和 alert-manager 的实际报警配置就直接用上面的就好,关键是较为复杂的 grafana 部分,这里面由于要在配置挂载完成 datasource 的添加和对应 dashboard 的样板 json 添加,所以另外准备 grafana 文件夹,用来存放内部配置 grafana.ini 和 datasource 以及 dashboard 的对应 json,最后得到这样文件结构:

$ tree grafana
grafana
├── grafana.ini
└── provisioning
    ├── dashboards
    │   └── node_exporter_dashboard.json
    └── datasources
        └── prometheus.yml

上面
node_exporter_dashboard.json 直接用的前面从 grafana 的 dashboard 列表下载的 json ,太长太完备了,不放在这浪费篇幅了,关注 grafana.ini 如下:

[paths]
provisioning = /etc/grafana/provisioning

[dashboards] default_home_dashboard_path = /etc/grafana/provisioning/dashboards/node_exporter_dashboard.json

[security] admin_user = ${GF_SECURITY_ADMIN_USER} admin_password = ${GF_SECURITY_ADMIN_PASSWORD} disable_initial_admin_password_hint = true

如上 grafana 内部配置,设定了其 provisioning 路径并设定其 dashboards 的 json 路径,security 部分是为了强制使得设定的管理员账户密码生效,最后就是另外的 datasource 配置了:

apiVersion: 1

datasources: - name: Prometheus type: prometheus access: proxy url: http://prometheus-service:9090 isDefault: true version: 1 editable: false jsonData: timeInterval: "15s" httpMethod: "GET"

超级简单,而后一波拉起:

# 拉起docker-compose.yml所指定service并后台运行

$ docker compose up -d

# 关掉docker-compose.yml指示service

$ docker compose down

ok,搞定。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容