监控系统夜莺分布式部署方案
监控系统的典型架构其实非常清晰,之前的章节中有下面这段话:
架构上来说,指标监控系统除了依赖一个时序库,还必然需要一个采集器去采集各种指标数据,其次就是告警引擎和可视化展示,典型的系统架构如下:
当然,如果引入流计算和智能告警逻辑,架构会复杂得多,这里我们先就一个简单的架构来讲,会更容易上手。
采集器
采集器有很多,这里罗列一些常见的采集器,并做一些简单的主观评价,帮助各位选型。
telegraf
telegraf 是 influxdb 生态的产品,因为 influxdb 是支持字符串数据的,所以 telegraf 采集的很多 field 是字符串类型,另外 influxdb 的设计,允许 labels 是非稳态结构,比如 result 标签,有时其 value 是 success,有时其 value 是 timeout,在 influxdb 中都可以接受。但是上面两点,在类似 prometheus 的时序库中,处理起来就很麻烦。
exporters
prometheus 生态有各种 exporters,但是设计逻辑都是一个监控类型一个 exporter,甚至一个实例一个 exporter,生产环境可能会部署特别多的 exporters,管理起来略麻烦。不过这种方式架构最简单,最适合落地 IaC。
grafana-agent
大家只知道 Grafana 是绘图神器,可能未必知道 Grafana 其实还提供了一个客户端采集器。
grafana-agent import 了大量 exporters 的代码,对 exporter 有些改动,不过有些中间件,仍然是一个 grafana-agent 一个目标实例,管理起来也略麻烦。
不过 grafana-agent 主打的是三合一采集,不止 metrics,也可以采集 logs、traces。
datadog-agent
datadog-agent 确实是集大成者,但是大量代码是 python 的,整个发布包也比较大,有不少历史包袱,而且生态上是自成一派,和社区相对割裂。
datadog 毕竟是商业公司,估值几百亿美金,整体是非常成熟的,在采集侧落地了很多最佳实践,值得看一下。
prometheus
prometheus 在某个版本开始,引入了 agent mode 模式,可以作为一个采集器使用,针对 Kubernetes 平台的监控,prometheus 提供了 kubernetes 的服务发现机制,非常方便。
categraf
categraf 是我们团队近期开源的一款采集器,我们做的事情有些类似 grafana-agent,想做一个 all-in-one 的采集器。集成多种 exporter 的能力,同时,也希望集成一些进程、端口、插件、日志采集能力,在物理机虚拟机环境下,这些能力还是很关键的。同时,也希望设计成类似 datadog 那样,一个采集器可以采集很多个实例,而非一对一的关系。
上面这些采集器,相对比较开放,有些采集器可能只是服务于自己的体系,比如 zabbix-agentd,这里就不罗列了。
UI
说完采集器,我们直接跳到最上面的 UI 层(先把简单的易于理解的模块说完~)。UI 层提供一个用户和系统交互的接口(用于看图、配置告警规则等),比如 Zabbix 的那个 PHP 写的 WEB 模块、比如夜莺的 Webapi 模块,比如 Datadog 的 Cloud UI,Prometheus 也有,是集成到自己的唯一二进制中了。
UI 侧的功能非常直观,最核心就是看图、做配置、查看事件,比如配置各种 Dashboard、配置告警规则、屏蔽规则等,查看告警事件。
UI 模块通常和数据库打交道,把用户的配置写入数据库,也会和时序库打交道,因为要看图就要拉取时序库的数据,比如 Zabbix 的 WEB 模块要读取数据库的时序数据,把配置写入数据库,比如夜莺的 Webapi 模块,要读取时序库的数据,同时把用户配置的信息写入关系库。
引擎侧
监控系统通常有个可以水平扩展的服务端引擎,用于判断监控数据是否触发阈值,生成告警事件。比如 Zabbix 的 Server 模块,比如 Open-Falcon 的 judge 模块,比如夜莺的 Server 模块,当然,Datadog 这种云服务我们看不到架构,但是理论上,肯定也是类似的架构。
引擎侧要想处理告警规则,那首先得从某个地方拿到这些规则,显然是从数据库获取的,但是每次频繁查询数据库又会对数据库造成压力,所以一般都是选择周期性同步,在内存里缓存的方式。
引擎侧产生告警事件之后,可以自己去发送,也可以交给单独的模块处理,比如夜莺是 Server 生成事件直接就发送了,Open-Falcon 则是把事件交给 alarm 模块去做后续处理。Prometheus 生成的事件是交给 alertmanager 做后续处理。
对于单独有个模块处理后续事件这种架构,可以在这个模块里做一些聚合降噪类的事情,像 Bigpanda 这种产品,就是专门做这个事情的。
时序库
时序库是监控系统架构的重要组成部分,比如 Prometheus 内置的时序库,VictoriaMetrics、M3DB、Open-Falcon 的 Graph 模块、TDEngine、InfluxDB 等,还有像 Zabbix 这种直接使用 MySQL、PG 作为时序库。
不同的时序库架构不同,但既然是存取数据的,有些通用的问题是必须要解决的,比如数据分片逻辑、副本管理、wal、随机写转换为顺序写等等。这里我们拿 VictoriaMetrics(简称 VM) 来举例:
VM 的架构非常简单清晰,会有其局限取舍,但简单的架构确实更稳定,上图就是 VM 的架构,核心有 3 个模块,vmselect、vmstorage、vminsert,每个模块都可以部署多个实例,vmselect 和 vminsert 都是无状态的,前面架设负载均衡,vmselect 用于响应查询请求,vminsert 用于响应插入请求。vmstorage 是用于存储数据的。
VM 的架构之所以简单,是因为其 merge read 机制,不关心数据迁移问题。比如某个机器的 CPU.UTIL 数据,有些数据分布在 vmstorage01 节点,有些分布在 vmstorage02、vmstorage03 节点,查询的时候,会同时发请求给这 3 个节点,拿到查询结果之后,merge 在一起返回给 client。所以,扩容很方便,接收到数据之后做分片完全可以不用维持一个稳态的对应关系(指 series 监控数据和 vmstorage 的对应关系)。如果某个节点挂了,会丢失一部分数据,如果是 3 副本的,就还会有其他副本在其他机器上,仍然可以读取。
夜莺分布式部署方案
上面的内容是非常通用的讲解,下面我们以夜莺为例,做一些落地讲解。夜莺 5.0 版本开始,架构已经非常简单,核心包括三个组件:采集器 categraf、和前端交互的模块 webapi、数据转发和告警引擎模块 server。
categraf:采集器,用于采集监控数据,比如 OS 的 CPU、内存、IO 相关指标,数据库的指标,中间件的指标等等,都统一使用 categraf 来采集,当然,也可以使用 telegraf、datadog-agent、grafana-agent 等社区的其他采集器。categraf 要采集 OS 的指标,通常要在所有目标机器上都要部署一个,对于中间件、数据库的监控数据采集,大都是通过远程查询的方式,categraf 倒是不必一定和中间件、数据库部署在同一台机器上
webapi:用于和前端 JavaScript 交互的模块,对数据库做增删改查,webapi 可以水平扩展,部署多个实例,一般是部署在中心 IDC,前面放置 nginx 或者 lvs,这样如果有某个 webapi 模块挂掉了,nginx 或 lvs 可以自动感知并摘除故障实例,对用户无感
server:server 模块是随着时序库走的,一套时序库对应一套 server,server 核心有两个作用,一个是接收监控数据的推送,转发给时序库,另一个是作为告警引擎,从数据库同步告警规则,然后为每个告警规则启动 goroutine,周期性的查询时序库,判断是否应该生成告警事件。
除了夜莺自身的 3 个组件,夜莺还依赖 MySQL 和 Redis,MySQL 用于存放各类用户配置,比如监控大盘、告警规则、屏蔽规则、订阅规则等,Redis 有两个作用,一个是存放 jwt token,另一个是作为一个注册中心,存放存活的 server 和 ident 列表,各个 server 模块就可以从 Redis 这里,知道全局活着的 server 列表,知道有哪些 ident 存活,便于生成 target_up 的指标数据。
单机部署方案
这个方案在之前的章节已经讲解过了,不过为了内容完整性,这里再重复一下。对于绝大部分公司,机器规模小于 1000 台,基本上单机部署方案就够用了,如果单机扛不住可以升配,运维成本是最低的。
虚线框的部分就是要在单机部署的组件,n9e-server 和 n9e-webapi 是夜莺的核心模块,MySQL、Redis、Prometheus 是依赖的其他开源项目。
在所有要监控的目标机器上,安装 agent,采集监控数据,agent 自然是首推 categraf,当然,也可以用 telegraf、grafana-agent、datadog-agent。习惯使用 exporter 的朋友,也可以继续使用各类 exporter 作为采集器。
中心集群部署方案
很多公司都是使用公有云的服务,公有云大都提供托管的 rds、redis、prometheus,我们可以直接使用,这样就只需要自己创建虚拟机部署夜莺的 server 和 webapi 模块即可,假设我们有 3 台机器,部署方案就是在每台机器上分别部署 server 和 webapi 模块,然后在 server 和 webapi 前面分别配置负载均衡。
server 的负载均衡地址暴露给 agent,agent 用来推送监控数据,webapi 的负载均衡地址可以配置一个域名,让终端用户通过域名访问夜莺的 UI。此时,前端静态资源文件是由 n9e-webapi 来 serve,也可以搭配一个小的 nginx 集群,把 webapi 作为 nginx 的 upstream,前端静态资源文件由 nginx 来 serve。
或者,时序库不采用云平台托管的,自己来搭建时序库集群,此时就需要有能支持分布式部署的时序库,且兼容 Prometheus 的查询接口,常用的是 M3DB 和 VictoriaMetrics,前文已经有介绍,建议使用 VictoriaMetrics,相对更简单一些。
多地域拆分简单方案
实际工作环境下,很多公司会把 Prometheus 拆成多个集群,按照业务线或者按照地域来拆分,此时就相当于夜莺接入多个 Prometheus 数据源。中心端部署 webapi 模块,而 server 模块是随着时序库走的,所以,时序库在哪个机器上,server 模块就部署在哪个机器上就好,架构图如下:
多地域拆分集群方案
最后一种部署方式,最为复杂,是把 server 和 webapi 模块都做了集群高可用,也就是 github 放的那张架构图:
中心端是 webapi 集群、redis、mysql,每个地域是时序库、redis、server 集群,redis 实际可以复用中心的那个,但是不推荐,担心网络链路可能不好影响通信,最好是和 server 集群放到一个地域。
版权声明: 本文为 InfoQ 作者【CTO技术共享】的原创文章。
原文链接:【http://xie.infoq.cn/article/9cd8f5acaa413bb988439d22d】。未经作者许可,禁止转载。
评论