监控系统由哪些模块组成,各个模块是如何相互协同的。业界监控系统数量较多,如果我们一上来就陷入某个具体的系统中,容易一叶障目,不见泰山。这里我把众多监控系统的架构做了一个统一的抽象和概括,后面你再看到任何一个监控系统,都能快速理解了。

1 典型架构

打造一流监控体系,这就是你需要的架构!_PostgreSQL

采集器负责采集监控数据,采集到数据后传输给服务端,一般直接写入时序库。然后对时序库的数据进行分析和可视化,分析部分最典型的就是告警规则判断(复杂一些的会引入统计算法和机器学习的能力做预判),即图上的告警引擎,告警引擎产生告警事件后交给告警发送模块做不同媒介的通知。

可视化(数据展示),通过各种图表来合理地渲染各类监控数据,便于用户查看比较、日常巡检。

2 每个模块的职能和设计

2.1 采集器

负责采集监控数据,两种典型部署方式:

  • 跟随监控对象部署,如所有的机器上都部署一个采集器,采集机器的 CPU、内存、硬盘、IO、网络相关的指标
  • 远程探针式,如选取一个中心机器做探针,同时探测很多个机器的PING连通性,或者连到很多MySQL实例上去,执行命令采集数据

2.1.1 开源采集器选型

① Telegraf

Telegraf 是InfluxData公司的产品,主要配合 InfluxDB 使用。也可将监控数据推给 Prometheus、Graphite、Datadog、OpenTSDB 等很多其他存储。

InfluxDB 支持存储字符串,而Telegraf 采集的很多数据都是字符串类型,但若把这类数据推给 Prometheus 生态的时序库,如 VictoriaMetrics、M3DB、Thanos等,就会报错。因为这些时序库只能存储数值型时序数据。

Telegraf 采集的很多数据在成功和失败的时候会打上不同标签,如:

  • 成功时打 result=success 标签
  • 失败时打 result=failed 标签

在 InfluxDB 中这种情况可以,但 Prometheus 生态里,标签变化就表示不同指标,这种叫 标签非稳态结构,使用 Prometheus 生态的时序库与 Telegraf 对接时需要 把这类标签丢弃掉

Telegraf 是指标领域的All-In-One采集器,支持各种采集插件,只需使用 Telegraf 这一个采集器,就能解决绝大部分采集需求。

② Exporters

专门用于Prometheus生态的组件,Prometheus 生态的采集器较零散,每个采集目标都有对应 Exporter 组件:

  • MySQL的mysqld_exporter
  • Redis的redis_exporter
  • 交换机的snmp_exporter
  • JVM的jmx_exporter

这些 Exporter 的核心逻辑,就是去这些监控对象里采集数据,然后暴露为 Prometheus 协议的监控数据。如:

  • mysqld_exporter就是连上 MySQL,执行类似 show global statusshow global variablesshow slave status 的命令,拿到输出,再转换为 Prometheus 协议的数据
  • redis_exporter连上 Redis,执行类似 info 的命令,拿到输出,转换为 Prometheus 协议的数据

很多中间件都内置支持Prometheus,直接通过自身 /metrics 接口暴露监控数据,不用再单独伴生 Exporter,简化了架构。如 k8s 的各类组件:kube-apiserver、kube-proxy、kube-scheduler等,etcd还有新版本ZooKeeper、 RabbitMQ、HAProxy,都能直接暴露 Prometheus 协议的监控数据,无需 Exporter。

PULL 模型:不管 Exporter 还是直接内置支持 Prometheus 协议的各类组件,都提供 HTTP 接口(通常是 /metrics )暴露监控数据,让监控系统来拉。

PUSH 模型:Telegraf 采集了数据之后调用服务端的接口来推送数据。

Telegraf及Grafana-Agent也可直接抓取 Prometheus 协议的监控数据,然后统一推给时序库,架构较清晰,总之跟数据采集相关的都由采集器负责。

③ Grafana-Agent

Grafana-Agent 是 Grafana 公司推出的一款 All-In-One 采集器:

  • 不但可 采集指标数据
  • 采集日志数据和链路数据

Grafana-Agent如何快速集成各类采集能力?

Grafana-Agent 写了个框架,方便导入各类 Exporter,把各个 Exporter 当Lib使用,常见Node-Exporter、Kafka-Exporter、Elasticsearch-Exporter、Mysqld-Exporter都已完成集成。就不用到处去找各类 Exporter,只使用Grafana-Agent这一个二进制就搞定众多采集能力。

Grafana-Agent 这种集成 Exporter 的方式,完全兼容 Exporter 的指标体系,如 Node-Exporter。如果我们的场景不方便使用PULL的方式来抓取数据,就可换成Grafana-Agent,采用PUSH的方式推送监控数据,完全兼容Node-Exporter的指标。当然,Exporter种类繁多,Grafana-Agent不可能全部集成,对于默认没有集成进去的Exporter,Grafana-Agent也支持用PULL的方式去抓取其他Exporter的数据,然后再通过Remote Write的方式,将采集到的数据转发给服务端。

  • 日志采集,Grafana-Agent集成Loki生态的日志采集器Promtail
  • 链路数据,Grafana-Agent集成OpenTelemetry Collector

相当于把可观测性三大支柱的采集能力都建全了。一个Agent搞定所有采集能力,便于附加一些通用标签,如某个机器的所有可观测性数据,都统一打上机器名的标签,后面就可以使用这种统一的标签做关联查询,这个关联能力是这类All-In-One采集器带来的最大好处。

Categraf

Categraf 快猫团队开源的一款监控采集器。为何还要再造轮子?Categraf定位类似Grafana-Agent,支持metrics、logs、traces的采集,未来也支持事件采集,对同类监控目标的多个实例的场景,又希望做出Telegraf的体验。同时对于所有的采集插件,不但会提供采集能力,也会提供监控大盘、告警规则,开箱即用。

Categraf偏重Prometheus生态,标签是稳态结构,只采集数值型时序数据,通过Remote Write方式推送数据给后端存储,所有支持Remote Write协议的时序库都可以对接,比如Prometheus、VictoriaMetrics、M3DB、Thanos 等等。

习惯使用Prometheus的用户,Categraf也支持直接读取prometheus.yml中的scrape配置,对接各类服务发现机制,实现上就是把 Prometheus agent mode 的代码引入。

其他方案如 Datadog-Agent、Metricsbeat。落地倒也不是非黑即白,一定要选择某个。很多时候,一个采集器可能搞不定所有业务需求,使用一款主力采集器,辅以多款其他采集器是大多数公司选择。

  • 机器层面的监控,推荐 Telegraf 和 Categraf,内置监控脚本、进程/端口监控,CPU、内存之类的也都很完备
  • 探针类的监控自由度就很高,不同中间件、数据库监控,习惯用哪个采集器就用啥

打造一流监控体系,这就是你需要的架构!_PostgreSQL_02

采集器采集到数据后,要推给服务端:

  • 直接推给时序库
  • 先推给Kafka,再经由Kafka写到时序库
  • 一些复杂的情况,可能会在Kafka和时序库之间加一个流式计算引擎,如Flink做一些预聚合计算。但绝大部分公司都用不到,所以这里我们先不管复杂流式计算的问题,重点看时序库。

3 时序库

老牌监控系统直接复用关系型数据库,如Zabbix直接使用MySQL存储时序数据,MySQL擅长处理事务场景,没有针对时序场景优化,容量上有明显瓶颈:

  • Open-Falcon用RRDtool攒了个分布式存储组件Falcon-Graph,但RRDTool本身设计有问题,散文件很多,对硬盘IO要求太高,性能较差
  • Falcon-Graph是分布式的,可以通过堆机器来解决大规模的问题,但显然不是最优解。

后来,各种专门解决时序存储问题的数据库横空出世,比较有代表性的有:OpenTSDB、InfluxDB、TDEngine、M3DB、VictoriaMetrics、TimescaleDB等。下面我们逐一介绍一下。

OpenTSDB

OpenTSDB 2010年就有了,其指标模型有别于老一代监控系统死板的模型设计,非常灵活,给业界带来好的引导。

OpenTSDB基于HBase封装,也有基于Cassandra封装版本。

架构图:

底层存储基于HBase,一般小公司都玩不转,国内受众较少,当下再选型时序数据库时,很少有人选。

InfluxDB

来自InfluxData,创业公司做的项目,2019年D轮融资6000万美金,做的产品非常不错。

InfluxDB针对时序存储场景专门设计存储引擎、数据结构、存取接口,国内使用范围比较广泛,而且InfluxDB可以和Grafana、Telegraf等良好整合,生态非常完备。不过InfluxDB开源版本单机,未开源集群版本。毕竟是商业公司,需要赚钱实现良性发展。

TDEngine

TDEngine姑且可以看做国产版InfluxDB,GitHub的Star数上万,针对物联网设备的场景优化,性能很好,也可和Grafana、Telegraf整合,对偏设备监控场景,TDEngine不错。

TDEngine集群版开源。TDEngine不止是做时序数据存储,还内置支持流式计算,可让用户少部署一些组件。

你可能比较关注TDEngine是否可以和Prometheus生态良好打通。通过TDEngine的官网可以得知,TDEngine是支持Prometheus的remote_read和remote_write接口的。不过不支持Prometheus的Query类接口,这点需要注意。

注:Thanos、M3DB、VictoriaMetrics都直接兼容Prometheus的Query类接口,上层程序可以把这些时序库当做Prometheus来使用。

TDEngine的创始人是陶建辉,有非常高的技术热情,在开源社区非常活跃,TDEngine也拿到了很高的融资,有粮草,未来可期。

M3DB

M3DB是来自Uber的时序数据库,M3声称在Uber抗住了66亿监控指标,这个量非常庞大。而且M3DB是全开源的,包括集群版,不过架构原理比较复杂,CPU和内存占用较高,在国内没有大规模推广起来。M3DB的架构代码中包含很多分布式系统设计的知识,是个可以拿来学习的好项目。

VictoriaMetrics

VictoriaMetrics,简称VM,架构非常简单清晰,采用merge read方式,避免了数据迁移问题,搞一批云上虚拟机,挂上云硬盘,部署VM集群,使用单副本,是非常轻量可靠的集群方式。你可以看一下我给出的VM架构图。

VM实现了Prometheus的Query类接口,即 /api/v1/query/api/v1/query_range/api/v1/label/<label-key>/values 相关的接口,是Prometheus一个非常好的Backend,甚至可以说是Prometheus的一个替代品。其实VM的初衷就是想要替换掉Prometheus的。

TimescaleDB

TimescaleDB是 timescale.inc 开发的一款时序数据库,作为一个PostgreSQL的扩展提供服务。

它是基于PostgreSQL设计而成的,而PostgreSQL生态四十年的积累,就是巨人的肩膀,很多底层的工作PostgreSQL其实已经完成了。就拿保障数据安全来说吧,因为程序可能随时会崩溃,服务器可能会遇到电源问题或硬件故障,磁盘可能损坏或者夯住,这些极端场景都需要完善的解决方案来处理。PostgreSQL社区已经有了现成的高可用特性,包括完善的流复制和只读副本、数据库快照功能、增量备份和任意时间点恢复、wal支持、快速导入导出工具等。而其他时序库,这些问题都要从头解决。

但是传统数据库是基于btree做索引的,数据量到百亿或者千亿行,btree会大到内存都存不下,产生频繁的磁盘交换,数据库性能会显著下降。另外,时序数据的写入量特别大,PostgreSQL面对大量的插入,性能也不理想。TimescaleDB 就要解决这些问题。目前Zabbix社区在尝试对接到TimescaleDB,不过国内应用案例还比较少。

数据一旦进入时序库,后面就可以对接告警引擎和可视化。

4 告警引擎

告警引擎的核心职责就是 处理告警规则,生成告警事件。通常来讲,用户会配置数百甚至数千条告警规则,一些超大型的公司可能要配置数万条告警规则。每个规则里含有数据过滤条件、阈值、执行频率等,有一些配置丰富的监控系统,还支持配置规则生效时段、持续时长、留观时长等。

4.1 架构

4.1.1 数据触发式

服务端接收到监控数据之后,除了存储到时序库,还会转发一份数据给告警引擎,告警引擎每收到一条监控数据,就要判断是否关联了告警规则,做告警判断。因为监控数据量比较大,告警规则的量也可能比较大,所以告警引擎是会做分片部署的,即部署多个实例。这样的架构,即时性很好,但是想要做指标关联计算就很麻烦,因为不同的指标哈希后可能会落到不同的告警引擎实例。

注:分片的常见做法是根据指标标识hash。

4.1.2 周期轮询式

架构简单,通常是一个规则一个协程,按照用户配置的执行频率,周期性查询判断即可,因为是主动查询的,做指标关联计算就会很容易。像Prometheus、Nightingale、Grafana等,都是这样的架构。

生成事件之后,通常是交给一个单独的模块来做告警发送,这个模块负责事件聚合、收敛,根据不同的条件发送给不同的接收者和不同的通知媒介。告警事件的处理,是一个非常通用的需求,而且非常零碎、复杂,每个监控系统都去实现一套,通常不会做得很完备。于是就有了专门处理这类需求的产品,最典型的比如 PagerDuty,可以接收各类事件源的事件,用户就只需要在 PagerDuty 做 OnCall 响应即可,非常方便。

5 数据展示

监控数据的可视化也是一个非常通用且重要的需求,业界做得最成功的当数Grafana。Grafana采用插件式架构,可以支持不同类型的数据源,图表非常丰富,基本可以看做是开源领域的事实标准。很多公司的商业化产品中,甚至直接内嵌了Grafana,可见它是多么流行。当然,Grafana新版本已经修改了开源协议,使用 AGPLv3,这就意味着如果某公司的产品基于Grafana做了二次开发,就必须公开代码,有些厂商想要Fork Grafana,然后进行闭源商业分发,就行不通了。

监控数据可视化,通常有两类需求,一个是即时查询,一个是监控大盘(Dashboard)。即时查询是临时起意,比如线上有个问题,需要追查监控数据,还原现场排查问题,这就需要有个方便我们查看的指标浏览功能,快速找到想要的指标。监控大盘通常用于日常巡检和问题排查,由资深工程师创建,放置了一些特别值得重点关注的指标,一定程度上可以引发我们思考,具有很强的知识沉淀效果。如果想要了解某个组件的原理,这个组件的监控大盘通常可以带给你一些启发。

6 总结

  • 采集器:收集监控数据,业界有不少开源解决方案,大同小异,总体分为推拉两种模式,各有应用场景。Telegraf、Exporters用得最广泛,Grafana-Agent和Categraf是后来者,当然还有Datadog-Agent这种商业解决方案,我的建议是优先考虑Categraf,相对而言,它使用起来更加便捷。如果有些场景Categraf没有覆盖,可以考虑辅以一些特定的Exporter。
  • 时序库:存储时序数据,是一个非常内卷的行业,有很多开源方案可供选择。如果规模比较小,1000台机器以下,通常一个单机版本的Prometheus就够用了。如果规模再大一些,建议你考虑VictoriaMetrics,毕竟架构简单,简单的东西可能不完备,但是出了问题容易排查,更加可控。
  • 告警引擎:做告警规则判断,生成告警事件。这是监控系统的一个重要组成部分,通常是基于固定阈值规则来告警。当然,随着时代的发展,也有系统支持统计算法和机器学习的方式做告警预判,我觉得是可以尝试的。AiOps概念中最容易落地,或者说落地之后最容易有效果的,就是告警引擎。不过Google SRE的观点是不希望在告警中使用太多magic的手段,这个就见仁见智了。
  • 数据展示:渲染展示监控数据。最常见的图表就是折线图,可以清晰明了地看到数据变化趋势,有些人会把监控大盘配置得特别花哨,各种能用的图表类型都用一下,这一点我不敢苟同,我还是觉得实用性才是最核心的诉求。很多监控系统会内置看图功能,开源领域最成熟的就是Grafana,如果某个存储无法和Grafana对接,其流行性都会大打折扣。

打造一流监控体系,这就是你需要的架构!_PostgreSQL_03