为什么要监控?

监控的几点原则

  • 监控是基础设施,目的是为了解决问题,不要只朝着大而全去做,尤其是不必要的指标采集,浪费人力和存储资源
  • 需要处理的告警才发出来,发出来的告警必须得到处理
  • 简单的架构就是最好的架构,业务系统都挂了,监控也不能挂

监控的目标

在《SRE: Google运维解密》一书中指出,监控系统需要能够有效的支持白盒监控和黑盒监控。通过白盒能够了解其内部的实际运行状态,通过对监控指标的观察能够预判可能出现的问题,从而对潜在的不确定因素进行优化。而黑盒监控,常见的如HTTP探针,TCP探针等,可以在系统或者服务在发生故障时能够快速通知相关的人员进行处理。通过建立完善的监控体系,从而达到以下目的:

  • 长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们可以提前预测在未来什么时间节点上需要对资源进行扩容。
  • 对照分析:两个版本的系统运行资源使用情况的差异如何?在不同容量情况下系统的并发和负载变化如何?通过监控能够方便的对系统进行跟踪和比较。
  • 告警:当系统出现或者即将出现故障时,监控系统需要迅速反应并通知管理员,从而能够对问题进行快速的处理或者提前预防问题的发生,避免出现对业务的影响。
  • 故障分析与定位:当问题发生后,需要对问题进行调查和处理。通过对不同监控监控以及历史数据的分析,能够找到并解决根源问题。
  • 数据可视化:通过可视化仪表盘能够直接获取系统的运行状态、资源使用情况、以及服务运行状态等直观的信息。

为什么是Prometheus?

竞品对比:https://toutiao.io/posts/fsjq8t/preview

Prometheus概述

Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。

Prometheus是一个开源的完整监控解决方案,其对传统监控系统的测试和告警模型进行了彻底的颠覆,形成了基于中央化的规则计算、统一分析和告警的新模型。 相比于传统监控系统Prometheus具有以下优点:

  • 易于管理:只有一个单独的二进制文件,不存在任何的第三方依赖,采用Pull的方式拉取数据
  • 强大的数据模型:每一条时间序列由指标名称(Metrics Name)以及一组标签(Labels)唯一标识
  • 强大的查询语言PromQL:内置了一个强大的数据查询语言PromQL,可以实现多种查询、聚合
  • 高性能:单实例可以处理数以百万的监控指标、每秒处理数十万的数据点
  • 易扩展:支持sharding和联邦集群,实现多数据中心
  • 易集成:支持多种语言的SDK进行应用程序数据埋点,社区有丰富插件
  • 可视化:自带Prometheus UI,可以进行查询与展示,Grafana也完整支持Prometheus。
  • 开放性:使用sdk采集的数据可以被其他监控系统使用,不一定非要用Prometheus

架构图

Prometheus architecture

  • Prometheus Server 负责从 Exporter 拉取和存储监控数据,并提供一套灵活的查询语言(PromQL)

    • Retrieval: 采样模块
    • TSDB: 存储模块默认本地存储为tsdb
    • HTTP Server: 提供http接口查询和面板,默认端口为9090
  • Exporters/Jobs 负责收集目标对象(host, container…)的性能数据,并通过 HTTP 接口供 Prometheus Server 获取。支持数据库、硬件、消息中间件、存储系统、http服务器、jmx等。只要符合接口格式,就可以被采集一般来说可以将Exporter分为2类:

    • 直接采集:这一类Exporter直接内置了对Prometheus监控的支持,比如cAdvisor,Kubernetes,Etcd,Gokit等,都直接内置了用于向Prometheus暴露监控数据的端点。
    • 间接采集:间接采集,原有监控目标并不直接支持Prometheus,因此我们需要通过Prometheus提供的Client Library编写该监控目标的监控采集程序。例如: Mysql Exporter,JMX Exporter,Consul Exporter等。
  • Short-lived jobs 瞬时任务的场景,无法通过pull方式拉取,需要使用push方式,与PushGateway搭配使

  • PushGateway 可选组件,主要用于短期的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。为此,这次 jobs 可以直接向 Prometheus server 端推送它们的 metrics。这种方式主要用于服务层面的 metrics,对于机器层面的 metrices,需要使用 node exporter。

  • Alertmanager 从 Prometheus server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对收的接受方式,发出报警。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook 等。

  • Service Discovery

    服务发现,Prometheus支持多种服务发现机制:文件,DNS,Consul,Kubernetes,OpenStack,EC2等等。基于服务发现的过程并不复杂,通过第三方提供的接口,Prometheus查询到需要监控的Target列表,然后轮训这些Target获取监控数据。可以参考这篇文章:https://yasongxu.gitbook.io/container-monitor/yi-.-kai-yuan-fang-an/di-2-zhang-prometheus/prometheus-de-pei-zhi-yu-fu-wu-fa-xian

基本原理

Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。输出被监控组件信息的HTTP接口被叫做exporter 。

服务过程

  1. Prometheus server 定期从配置好的 jobs 或者 exporters 中拉 metrics(每个抓取目标需要暴露一个http服务的接口给它定时抓取),或者接收来自 Pushgateway 发过来的 metrics,或者从其他的 Prometheus server 中拉 metrics。(Prometheus支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目标。)
  2. Prometheus server 在本地存储收集到的 metrics,并运行已定义好的 alert.rules,记录新的时间序列或者向 Alertmanager 推送警报。
  3. Alertmanager 根据配置文件,对接收到的警报进行处理,发出告警。
  4. Prometheus通过PromQL和其他API可视化地展示收集的数据。Prometheus支持很多方式的图表可视化,例如Grafana、自带的Promdash以及自身提供的模版引擎等等。Prometheus还提供HTTP API的查询方式,自定义所需要的输出。

存储原理及数据备份还原

数据存储

本地

prometheus将采集到的样本以时间序列的方式保存在内存(TSDB 时序数据库)中,并定时保存到硬盘中。每2小时为一个时间单位,按照block块的方式来存储数据。最新写入的数据保存在内存block中,达到2小时后写入磁盘。为了防止程序崩溃导致数据丢失,实现了WAL(write-ahead-log)机制,启动时会以写入日志(WAL)的方式来实现重播,从而恢复数据。这些2小时的block会在后台压缩成更大的block,数据压缩合并成更高level的block文件后删除低level的block文件

删除数据时,删除条目会记录在独立的tombstone文件中,而不是立即从chunk文件删除。

prometheus本地存储会保存15天,超过15天以上的数据将会被删除,若要永久存储数据,有两种方式:

  1. 修改prometheus的配置参数 "storage.tsdb.retention.time=10000d"
  2. 方式二:将数据引入存储到Influcdb中

prometheus采用的存储方式称为时间分片,每个block都是一个独立的数据库。

prometheus的存储层使用了全文检索中的“倒排索引”概念,将每个时间序列视为一个小文档。而metric和label对应的是文档中的单词。

本地存储的特点决定了它不能用于long-term数据存储,只能用于短期窗口的timeseries数据保存和查询,并且不具有高可用性(宕机会导致历史数据无法读取)。

远程

Prometheus默认是自己带有存储的,保存的时间为15天。但本地存储也意味着Prometheus无法持久化数据,无法存储大量历史数据,同时也无法灵活扩展。 为了保证Prometheus的简单性,Prometheus并没有从自身集群的维度来解决这些问题,而是定义了两种接口,remote_write/remote_read,将数据抛出去,你自己处理。

prometheus通过下面两种方式来实现与其他的远端存储系统对接:

  • Prometheus 按照标准的格式将metrics写到远端存储
  • Prometheus 按照标准格式从远端的url来读取metrics

img

数据备份

  • 完全备份

  备份prometheus的data目录可以达到完全备份的目的,但效率较低。

  • 快照备份

  prometheus提供了一个功能,是通过API的方式,快速备份数据。

  实现方式:

  首先,修改prometheus的启动参数,新增以下两个参数:

--storage.tsdb.path=/usr/local/share/prometheus/data --web.enable-admin-api    

  重启prometheus

  调用API

curl -XPOST http://prometheusIP:端口/api/v1/admin/tsdb/snapshot
返回结果:
{"status":"success","data":{"name":"20191220T012427Z-21e0e532e8ca3423"}}

  此时,数据将快速的备份到 data/snapshots下。

完整的调用方式为:

# 不跳过内存中的数据,即同时备份内存中的数据
curl -XPOST http://127.0.0.1:9090/api/v2/admin/tsdb/snapshot?skip_head=false
# 跳过内存中的数据
curl -XPOST http://127.0.0.1:9090/api/v2/admin/tsdb/snapshot?skip_head=true

数据还原

利用api方式制作成snapshot后,还原时将snapshot中的文件覆盖到data目录下,重启prometheus即可!

添加定时备份任务(每周日3点备份)

crontable -e   #注意时区,修改完时区后,需要重启 crontab  systemctl restart cron
0 3 * * 7 sudo /usr/bin/curl -XPOST -I http://127.0.0.1:9090/api/v1/admin/tsdb/snapshot >> /home/bill/prometheusbackup.log

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%数据。

合理选择指标

4个黄金指标

Four Golden Signals是Google针对大量分布式监控的经验总结,4个黄金指标可以在服务级别帮助衡量终端用户体验、服务中断、业务影响等层面的问题。主要关注与以下四种类型的指标:延迟,通讯量,错误以及饱和度:

  • 延迟:服务请求所需时间。

记录用户所有请求所需的时间,重点是要区分成功请求的延迟时间和失败请求的延迟时间。 例如在数据库或者其他关键祸端服务异常触发HTTP 500的情况下,用户也可能会很快得到请求失败的响应内容,如果不加区分计算这些请求的延迟,可能导致计算结果与实际结果产生巨大的差异。除此以外,在微服务中通常提倡“快速失败”,开发人员需要特别注意这些延迟较大的错误,因为这些缓慢的错误会明显影响系统的性能,因此追踪这些错误的延迟也是非常重要的。

  • 通讯量:监控当前系统的流量,用于衡量服务的容量需求。

流量对于不同类型的系统而言可能代表不同的含义。例如,在HTTP REST API中, 流量通常是每秒HTTP请求数;

  • 错误:监控当前系统所有发生的错误请求,衡量当前系统错误发生的速率。

对于失败而言有些是显式的(比如, HTTP 500错误),而有些是隐式(比如,HTTP响应200,但实际业务流程依然是失败的)。

对于一些显式的错误如HTTP 500可以通过在负载均衡器(如Nginx)上进行捕获,而对于一些系统内部的异常,则可能需要直接从服务中添加钩子统计并进行获取。

  • 饱和度:衡量当前服务的饱和度。

主要强调最能影响服务状态的受限制的资源。 例如,如果系统主要受内存影响,那就主要关注系统的内存状态,如果系统主要受限与磁盘I/O,那就主要观测磁盘I/O的状态。因为通常情况下,当这些资源达到饱和后,服务的性能会明显下降。同时还可以利用饱和度对系统做出预测,比如,“磁盘是否可能在4个小时候就满了”。

RED和USE

实际操作中可以使用 Use 或 Red 方法作为指导,Use 用于资源,Red 用于服务

  • Use 方法:Utilization、Saturation、Errors等
  • Red 方法:Rate、Errors、Duration等

Prometheus 采集中常见的服务分三种:

  • 在线服务:如 Web 服务、数据库等,一般关心请求速率,延迟和错误率即 RED 方法

  • 离线服务:如日志处理、消息队列等,一般关注队列数量、进行中的数量,处理速度以及发生的错误即 Use 方法

  • 批处理任务:和离线任务很像,但是离线任务是长期运行的,批处理任务是按计划运行的,如持续集成就是批处理任务,对应 Kubernetes 中的 Job 或 CronJob, 一般关注所花的时间、错误数等,因为运行周期短,很可能还没采集到就运行结束了,所以一般使用 Pushgateway,改拉为推。

RED方法是Weave Cloud在基于Google的“4个黄金指标”的原则下结合Prometheus以及Kubernetes容器实践,细化和总结的方法论,特别适合于云原生应用以及微服务架构应用的监控和度量。主要关注以下三种关键指标:

  • (请求)速率:服务每秒接收的请求数。

  • (请求)错误:每秒失败的请求数。

  • (请求)耗时:每个请求的耗时。

在“4大黄金信号”的原则下,RED方法可以有效的帮助用户衡量云原生以及微服务应用下的用户体验问题。

USE方法全称"Utilization Saturation and Errors Method",主要用于分析系统性能问题,可以指导用户快速识别资源瓶颈以及错误的方法。正如USE方法的名字所表示的含义,USE方法主要关注与资源的:使用率(Utilization)、饱和度(Saturation)以及错误(Errors)。

  • 使用率:关注系统资源的使用情况。 这里的资源主要包括但不限于:CPU,内存,网络,磁盘等等。100%的使用率通常是系统性能瓶颈的标志。
  • 饱和度:例如CPU的平均运行排队长度,这里主要是针对资源的饱和度(注意,不同于4大黄金信号)。任何资源在某种程度上的饱和都可能导致系统性能的下降。
  • 错误:错误计数。例如:“网卡在数据包传输过程中检测到的以太网网络冲突了14次”。

通过对资源以上指标持续观察,通过以下流程可以知道用户识别资源瓶颈:

img

prometheus 大内存问题

解决办法:加内存或者集群分片减少单机指标

原因:

  • prometheus 的内存消耗主要是因为每隔2小时做一个 block 数据落盘,落盘之前所有数据都在内存里面,因此和采集量有关。
  • 加载历史数据时,是从磁盘到内存的,查询范围越大,内存越大。这里面有一定的优化空间
  • 一些不合理的查询条件也会加大内存,如 group、大范围rate

高可用方案

几种方案:

  • 基本 HA:即两套 prometheus 采集完全一样的数据,外边挂负载均衡
  • HA + 远程存储:除了基础的多副本prometheus,还通过Remote write 写入到远程存储,解决存储持久化问题
  • 联邦集群:即federation,按照功能进行分区,不同的 shard 采集不同的数据,由Global节点来统一存放,解决监控数据规模的问题。
  • 使用thanos 或者victoriametrics,来解决全局查询、多副本数据 join 问题。

采集组件all in one

prometheus 体系中 exporter 都是独立的,每个组件各司其职,如机器资源用 node-exporter,gpu 有NVIDIA exporter等等,但是 exporter 越多,运维压力越大,尤其是对 agent做资源控制、版本升级。我们尝试对一些exporter进行组合,方案有二:

  1. 通过主进程拉起n个exporter 进程,仍然可以跟着社区版本更新

  2. 用telegraf来支持各种类型的 input,n 合 1

    Telegraf 是一个用 Go 编写的代理程序,可收集系统和服务的统计数据

以上资料来源于网络,可参考:

https://yasongxu.gitbook.io/container-monitor/

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