通用技术 prometheus 监控测试服务器集群

xinxi · 2020年02月14日 · 最后由 goodpassion 回复于 2021年01月28日 · 1004 次阅读
本帖已被设为精华帖!

背景

公司有几台测试服务器,由于公司运维也帮忙去做服务器报警,但是由于测试服务器本来性能和线上机器硬件就不一样,所以让运维老师去掉了测试服务器报警,我们自己使用 prometheus 监控几台测试服务器,当出现故障的时候把报警数据发送到企业微信中.

prometheus 介绍

Prometheus(普罗米修斯)是一套开源的监控&报警&时间序列数据库的组合,起始是由 SoundCloud 公司开发的。随着发展,越来越多公司和组织接受采用 Prometheus,社会也十分活跃,他们便将它独立成开源项目,并且有公司来运作。Google SRE 的书内也曾提到跟他们 BorgMon 监控系统相似的实现是 Prometheus。现在最常见的 Kubernetes 容器管理系统中,通常会搭配 Prometheus 进行监控。

Prometheus 基本原理是通过 HTTP 协议周期性抓取被监控组件的状态,这样做的好处是任意组件只要提供 HTTP 接口就可以接入监控系统,不需要任何 SDK 或者其他的集成过程。这样做非常适合虚拟化环境比如 VM 或者 Docker 。

Prometheus 应该是为数不多的适合 Docker、Mesos、Kubernetes 环境的监控系统之一。

输出被监控组件信息的 HTTP 接口被叫做 exporter 。目前互联网公司常用的组件大部分都有 exporter 可以直接使用,比如 Varnish、Haproxy、Nginx、MySQL、Linux 系统信息 (包括磁盘、内存、CPU、网络等等),具体支持的源看:https://github.com/prometheus

与其他监控系统相比,Prometheus 的主要特点是:

一个多维数据模型(时间序列由指标名称定义和设置键/值尺寸)。
非常高效的存储,平均一个采样数据占~3.5bytes 左右,320 万的时间序列,每 30 秒采样,保持 60 天,消耗磁盘大概 228G。
一种灵活的查询语言。
不依赖分布式存储,单个服务器节点。
时间集合通过 HTTP 上的 PULL 模型进行。
通过中间网关支持推送时间。
通过服务发现或静态配置发现目标。
多种模式的图形和仪表板支持。

prometheus 架构概览

image

它的服务过程是这样的 Prometheus daemon 负责定时去目标上抓取 metrics(指标) 数据,每个抓取目标需要暴露一个 http 服务的接口给它定时抓取。

Prometheus

支持通过配置文件、文本文件、zookeeper、Consul、DNS SRV lookup 等方式指定抓取目标。支持很多方式的图表可视化,例如十分精美的 Grafana,自带的 Promdash,以及自身提供的模版引擎等等,还提供 HTTP API 的查询方式,自定义所需要的输出。

Alertmanager

是独立于 Prometheus 的一个组件,可以支持 Prometheus 的查询语句,提供十分灵活的报警方式。

PushGateway:这个组件是支持 Client 主动推送 metrics 到 PushGateway,而 Prometheus 只是定时去 Gateway 上抓取数据。

如果有使用过 statsd 的用户,则会觉得这十分相似,只是 statsd 是直接发送给服务器端,而 Prometheus 主要还是靠进程主动去抓取。

prometheus 的数据模型

Prometheus 从根本上所有的存储都是按时间序列去实现的,相同的 metrics(指标名称) 和 label(一个或多个标签) 组成一条时间序列,不同的 label 表示不同的时间序列。为了支持一些查询,有时还会临时产生一些时间序列存储。

metrics name&label 指标名称和标签

每条时间序列是由唯一的” 指标名称” 和一组” 标签(key=value)” 的形式组成。

指标名称:一般是给监测对像起一名字,例如 http_requests_total 这样,它有一些命名规则,可以包字母数字之类的的。通常是以应用名称开头监测对像数值类型单位这样。例如:push_total、userlogin_mysql_duration_seconds、app_memory_usage_bytes。

标签:就是对一条时间序列不同维度的识别了,例如一个 http 请求用的是 POST 还是 GET,它的 endpoint 是什么,这时候就要用标签去标记了。最终形成的标识便是这样了:http_requests_total{method=” POST”,endpoint=”/api/tracks”}。

记住,针对 http_requests_total 这个 metrics name 无论是增加标签还是删除标签都会形成一条新的时间序列。

查询语句就可以跟据上面标签的组合来查询聚合结果了。

如果以传统数据库的理解来看这条语句,则可以考虑 http_requests_total 是表名,标签是字段,而 timestamp 是主键,还有一个 float64 字段是值了。(Prometheus 里面所有值都是按 float64 存储)。

prometheus 四种数据类型

Counter

Counter 用于累计值,例如记录请求次数、任务完成数、错误发生次数。一直增加,不会减少。重启进程后,会被重置。

例如:http_response_total{method=” GET”,endpoint=”/api/tracks”} 100,10 秒后抓取 http_response_total{method=” GET”,endpoint=”/api/tracks”} 100。

Gauge

Gauge 常规数值,例如 温度变化、内存使用变化。可变大,可变小。重启进程后,会被重置。

例如: memory_usage_bytes{host=” master-01″} 100 < 抓取值、memory_usage_bytes{host=” master-01″} 30、memory_usage_bytes{host=” master-01″} 50、memory_usage_bytes{host=” master-01″} 80 < 抓取值。

Histogram

Histogram(直方图)可以理解为柱状图的意思,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。它特别之处是可以对记录的内容进行分组,提供 count 和 sum 全部值的功能。

例如:{小于 10=5 次,小于 20=1 次,小于 30=2 次},count=7 次,sum=7 次的求和值。

Summary

Summary 和 Histogram 十分相似,常用于跟踪事件发生的规模,例如:请求耗时、响应大小。同样提供 count 和 sum 全部值的功能。

例如:count=7 次,sum=7 次的值求值。

它提供一个 quantiles 的功能,可以按% 比划分跟踪的结果。例如:quantile 取值 0.95,表示取采样值里面的 95% 数据。

依赖镜像

docker pull prom/node-exporter
docker pull prom/prometheus
docker pull grafana/grafana

部署 prometheus

配置

mkdir /opt/prometheus
cd /opt/prometheus/
vim prometheus.yml

yml 内容

yml 中配置了一个 prometheus 自己和一台 linux 监控

global:
  scrape_interval:     60s
  evaluation_interval: 60s

scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets: ['localhost:9090']
        labels:
          instance: prometheus

  - job_name: linux
    static_configs:
      - targets: ['192.168.91.132:9100']
        labels:
          instance: localhost

启动 prometheus

启动的时候挂载了 prometheus.yml 文件

docker run  -d \
  -p 9090:9090 \
  -v /Users/qamac/Documents/script/docker_prometheus/prometheus.yml:/etc/prometheus/prometheus.yml  \
  prom/prometheus

查看目标机器

http://192.168.143.242:9090/targets

如果出现 status 是 down 的情况说明没有连接成功,需要检查对应服务是否启动成功及对应端口

image

出现下图,说明配置成功

image

查看采集 metrics

点击下面这个接口,会跳转到 metrics 页面,通过轮训的方式更新数据

http://192.168.143.242:9090/metrics

image

image

部署 node-exporter

node-exporter 启动后会在服务器上启动一个进程采集数据,prometheus 会每隔几秒通过接口获取服务器的 metrics 数据.

注意本地 mac 启动不能加--net="host"

docker run -d -p 9100:9100 \
  -v "/proc:/host/proc:ro" \
  -v "/sys:/host/sys:ro" \
  -v "/:/rootfs:ro" \
  --net="host" \
  prom/node-exporter

部署 grafana

启动 grafana

docker run -d -p 3000:3000 grafana

grafana 地址

登录账号密码:admin/admin

http://192.168.143.242:3000

grafana 配置

prometheus 配置

配置 prometheus 数据源

image

grafana 模版

导入 dashboards 模版

https://grafana.com/grafana/dashboards/8919

image

展示

image

配置多个机器监控,需要在每一台机器部署 node-exporter.

image

配置告警规则

报警规则配置

rules.yml 中配置监控服务的内存、cpu、磁盘告警策略

Server: '{{$labels.instance}}'
    summary: "{{$labels.instance}}: High Memory usage detected"
    explain: "内存使用量超过90%,目前剩余量为:{{ $value }}M"
    description: "{{$labels.instance}}: Memory usage is above 90% (current value is: {{ $value }})"

- alert: CPU报警
  expr: (100 - (avg by (instance)(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)) > 90
  for: 2m
  labels:
    team: node
  annotations:
    Alert_type: CPU报警
    Server: '{{$labels.instance}}'
    explain: "CPU使用量超过90%,目前剩余量为:{{ $value }}"
    summary: "{{$labels.instance}}: High CPU usage detected"
    description: "{{$labels.instance}}: CPU usage is above 90% (current value is: {{ $value }})"

- alert: 磁盘报警
  expr: 100.0 - 100 * ((node_filesystem_avail_bytes{mountpoint=~"/", device!="rootfs"} / 1000 / 1000 ) / (node_filesystem_size_bytes{mountpoint=~"/", device!="rootfs"} / 1024 / 1024)) > 90
  for: 2m
  labels:
    team: node
  annotations:
    Alert_type: 磁盘报警
    Server: '{{$labels.instance}}'
    explain: "磁盘使用量超过90%,目前剩余量为:{{ $value }}G"
    summary: "{{$labels.instance}}: High Disk usage detected"
    description: "{{$labels.instance}}: Disk usage is above 90% (current value is: {{ $value }})"

- alert: 服务器下线告警
    expr: up == 0
    for: 1m
    labels:
      user: admin
    annotations:
      summary: "Instance {{ $labels.instance }} down"
      description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minutes."

加载配置

prometheus.yml 加载 rule_files

# Alertmanager configuration
alerting:
   alertmanagers:
     - static_configs:
         - targets: ["192.168.1.232:9093"]
               # - alertmanager:9093


# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
   - "rules.yml"

启动 prometheus

docker run -d -p 9090:9090 --name=prometheus1 \
-v /Users/qamac/Documents/script/docker_prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
-v /Users/qamac/Documents/script/docker_prometheus/memory_over.yml:/etc/prometheus/rules.yml \
prom/prometheus 

部署 alertmanager

邮箱配置

可以通过邮件的形式发送告警邮件

global:
  smtp_smarthost: 'smtp.126.com:25'  #163服务器
  smtp_from: 'xxxxx@126.com'        #发邮件的邮箱
  smtp_auth_username: 'xxxxx@126.com'  #发邮件的邮箱用户名,也就是你的邮箱
  smtp_auth_password: 'xxxxx'        #发邮件的邮箱密码

route:
  group_by: ['alertname']

  repeat_interval: 1h

  receiver: live-monitoring

receivers:
- name: 'live-monitoring'
  email_configs:
  - to: 'xxxxx@xxxxx.com'        #收邮件的邮箱

webhook 配置

因为我司用企业微信比较多,再加上平时也不怎么看邮件.
所以想自定义一个 webhook 地址,把告警发到企业微信群中.

global:
  resolve_timeout: 5m

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'web.hook'
receivers:
- name: 'web.hook'
  webhook_configs:
  - url: 'http://127.0.0.1:5000/send'
inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']
~                                            

启动 alertmanager

docker run -d -p 9093:9093 -v /data/docker_alertmanager/simple.yml/:/etc/alertmanager/config.yml --name alertmanager1 prom/alertmanager 

alertmanager 的 web 页面

http://192.168.1.232:9093/#/status

image

下图是配置的告警方式

image

prometheus 中报警模块

http://192.168.143.242:9090/alerts

访问上面的地址,可以看到已经加载了告警规则

image

报警的几个状态

  • Inactive: 既不是 pending 也不是 firing 的时候状态变为 inactive
  • Pending:警报被激活,但是低于配置的持续时间。这里的持续时间即 rule 里的 FOR 字段设置的时间.改状态下不发送报警.
  • Firing: 警报已被激活,而且超出设置的持续时间。该状态下发送报警.

如下图的 for 字段是配置 2 分钟循环,第一次触发规则是 Pending 状态,如果超过 2 分钟就变成了 Firing 状态,才发送告警

image

webhook 服务

我们需要一个 webhook 服务接受报警的消息然后在发给企业微信群中.

这里我使用 python flask 框架开发 web 服务.

报警消息的格式

{
    "status": "firing",
    "labels": {
        "instance": "localhost",
        "job": "linux",
        "user": "admin",
        "alertname": "NodeMemoryUsage"
    },
    "endsAt": "2020-01-06T08:38:59.334190464Z",
    "generatorURL": "http://13b226ded726:9090/graph?g0.expr=%28node_memory_MemTotal_bytes+-+%28node_memory_MemFree_bytes+%2B+node_memory_Buffers_bytes+%2B+node_memory_Cached_bytes%29%29+%2F+node_memory_MemTotal_bytes+%2A+100+%3E+5&g0.tab=1",
    "startsAt ": "2020-01-05T15:33:59.334190464Z",
    "annotations": {
        "description": "localhost: Memory usage is above 80% (current value is:22.168394749407362)",
        "summary": "localhost: High Memory usage detected"
    }
}

定义 send 接口

image

解析响应数据

image

dockerfile

这里使用 docker 把服务打包成镜像部署

FROM python3.7
RUN pip3 install requests && pip3 install flask && pip3 install logzero && pip3 install gunicorn && pip3 install flask_script
EXPOSE 5000

ENTRYPOINT ["/run.sh"]

企业微信报警

image

参考

基于 docker 搭建 Prometheus+Grafana

https://www.cnblogs.com/xiao987334176/p/9930517.html

【集群监控】Docker 上部署 Prometheus+Alertmanager+Grafana 实现集群监控

https://www.cnblogs.com/caizhenghui/p/9184082.html

部署 AlertManager

https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/alert/install-alert-manager

prometheus alertmanager webhook 配置教程

https://blog.csdn.net/shida_csdn/article/details/81980021

Alertmanager 部署配置

https://www.cnblogs.com/winstom/p/11940570.html#测试触发告警

https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/quickstart/why-monitor

监控指标以及 prometheus 规则 - 不断完善中

https://blog.51cto.com/1000682/2374417

BAT 大厂都在用的 Docker。学会这三招,面试、工作轻松 hold 住

https://mp.weixin.qq.com/s/DpC3mC8XqKgrneW1HwH4Bw

共收到 16 条回复 时间 点赞

高产王,点个赞

如果我想监控任意一个 web 服务的 api,exporter 该怎么设置呢?需要侵入原来的服务代码增加取数据的 metrics 接口吗?

这个真不错啊,都不用自己写轮询和报警了。

恒温 将本帖设为了精华贴 02月16日 03:04
恒温 回复

是啊 我们组想把接口报警进去的,看看能不能减少误报率

这个应该还没到具体服务级,我理解的是需要实现一个 web 服务的 exporter.

xinxi 回复

没到具体服务级是什么意思?我不是很懂,不支持监测 web 服务的运行状态吗?如果要想监测 web 服务,看来是要侵入代码了。我能看到官网提供的 node_exporter 是监测服务器运行状态,还有类似 mysql_exporter 是监测 mysql 数据库的运行状态。

xinxi #10 · 2020年02月16日 Author

如果是 java 服务应用,有开源的 skywalking、cat 等监控工具,基于插庄监控服务

👍🏻

你可以自己做一个 opencensus node js 后端,然后把数据送过去,通过 opencensus node js 的实现, github 上也有 javascript 的实现,但是还没有正式发布,但是原理是一样的, 建议自己实现 node js 后端

我们这边集群的监控也用的这个,有很多现成的 k8s 模版可以使用,之前也自己手写过 custom node exporter 提供自定义的数据展示

不错!

实践总结的不错

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册