一 形形色色的监控系统
监控一直是it系统中的核心组成部分,负责问题的发现以及辅助性的定位。无论是传统运维、sre、devops、开发者都需要关注监控系统并参与到监控系统的建设和优化。从最开始大型机的作业系统、linux基础指标,监控系统就已经开始出现并逐渐演进,现阶段能够搜索到的监控系统不下于上百种,按照不同类别也有非常多的划分方式,例如:
- 监控对象:通用型(通用的监控方式,适应于大部分的监控对象),专一型(为某一功能定制,例如java的jmx系统、cpu的高温保护、硬盘的断电保护、ups切换系统、交换机监控系统、专线监控等);
- 数据获取方式:push(collectd、zabbix、influxdb);pull(prometheus、snmp、jmx);
- 部署方式:耦合式(和被监控系统在一起部署);单机(单机单实例部署);分布式(可以横向扩展);saas化(很多商业的公司提供saas的方式,无需部署);
- 数据获取方式:接口型(只能通过某些api拿去);dsl(可以有一些计算,例如promql、graphql);sql(标准sql、类sql);
- 商业属性:开源免费(例如prometheus、influxdb单机版);开源商业型(例如influxdb集群版、elastic search x-pack);闭源商业型(例如datadog、splunk、aws cloud watch);
二 pull or push
对于建设一套公司内部使用的监控系统平台,相对来说可选的方案还是非常多的,无论是用开源方案自建还是使用商业的saas化产品,都有比较多的可选项。但无论是开源方案还是商业的saas产品,真正实施起来都需要考虑如何将数据给到监控平台,或者说监控平台如何获取到这些数据。这里就涉及到数据获取方式的选型:pull(拉)还是push(推)模式?
基于pull类型的监控系统顾名思义是由监控系统主动去获取指标,需要被监控的对象能够具备被远端访问的能力;基于push类型的监控系统不主动获取数据,而是由监控对象主动推送指标。两种方式在非常多的地方都有区别,对于监控系统的建设和选型来说,一定要事先了解这两种方式各自的优劣,选择合适的方案来实施,否则如果盲目实施,后续对监控系统的稳定性和部署运维代价来说将是灾难性的。
三 pull vs push概览
下面将从几个方面来展开介绍,为了节约读者时间,这里先用一个表格来做概要性的论述,细节在后面会展开:
四 原理与架构对比
如上图所示,pull模型数据获取的核心是pull模块,一般和监控的后端一起部署,例如prometheus,核心组成包括:
- 服务发现系统,包括主机的服务发现(一般依赖于公司内部自己的cmdb系统)、应用服务发现(例如consul)、paas服务发现(例如kubernetes);pull模块需要具备对这些服务发现系统的对接能力
- pull核心模块,除了服务发现部分外,一般使用通用协议去远端拉取数据,一般支持配置拉取间隔、超时间隔、指标过滤/rename/简单的process能力
- 应用侧sdk,支持监听某个固定端口来提供被pull的能力
- 由于各类中间件/其他系统不兼容pull协议,因此需要开发对应的exporter的agent,支持拉取这些系统的指标并提供标准的pull接口
push模型相对比较简单:
- push agent,支持拉取各类被监控对象的指标数据,并推送到服务端,可以和被监控系统耦合部署,也可以单独部署
- configcenter(可选),用来提供中心化的动态配置能力,例如监控目标、采集间隔、指标过滤、指标处理、远端目标等
- 应用侧sdk,支持发送数据到监控后端,或者发送到本地agent(通常是本地agent也实现一套后端的接口)
小结:纯粹从部署复杂性上而言,在中间件/其他系统的监控上,pull模型的部署方式太过复杂,维护代价较高,使用push模式较为便捷;应用提供metrics端口或主动push部署代价相差不大。
五 pull的分布式九游平台的解决方案
在扩展性上,push方式的数据采集天然就是分布式的,在监控后端能力可以跟上的时候,可以无限的横向扩展。相比之下pull方式扩展较为麻烦,需要:
- pull模块与监控后端解耦,pull作为agent单独部署
- pull agent需要做分布式的协同,一般最简单是做sharding,例如从服务发现系统处获取被监控的机器列表,对这些机器进行hash后取模sharding来决定由哪个agent来负责pull。
- 新增一个配置中心(可选)用来管理各个pullagent
相信反应快的同学已经看出来,这种分布式的方式还是有一些问题:
- 单点瓶颈还是存在,所有的agent都需要去请求服务发现模块
- agent扩容后,监控目标会变化,容易产生数据重复或缺失
六 监控能力对比
1 监控目标存活性
存活性是监控所需要做的第一件也是最基础的工作,pull模式监控目标存活性相对来说非常简单,直接在pull的中心端就知道能否请求到目标端的指标,如果失败也能知道一些简单的错误,比如网络超时、对端拒绝连接等。
push方式相对来说就比较麻烦,应用没有上报可能是应用挂了,也可能是网络问题,也可能是迁移到了其他的节点上了,因为pull模块可以和服务发现实时联动,但push没有,所以只有服务端再和服务发现交互才能知道具体失败的原因。
2 数据齐全度计算
数据齐全度这个概念在大型的监控系统中还是非常重要的,比如监控一千个副本的交易应用的qps,这个指标需要结合一千个数据进行叠加,如果没有数据齐全度的概念,若配置qps相比降低2%告警,由于网络波动,超过20个副本上报的数据延迟几秒,那就会触发误报。因此在配置告警的时候还需要结合数据齐全度数据进行综合考虑。
数据齐全度的计算也一样是依赖于服务发现模块,pull方式是按照一轮一轮的方式进行拉取,所以一轮拉取完毕后数据就是齐全的,即使部分拉取失败也知道数据不全的百分比是多少;
而push方式由每个agent、应用主动push,每个客户端的push间隔、网络延迟都不一样,需要服务端去根据历史情况计算数据齐全度,相对代价比较大。
3 短生命周期/serverless应用监控
在实际场景中,短生命周期/serverless的应用也有很多,尤其是对成本友好的情况下,我们会大量使用job、弹性实例、无服务应用等,例如渲染型的任务到达后启动一个弹性的计算实例,执行完毕后立马销毁释放;机器学习的训练job、事件驱动的无服务工作流、定期执行的job(例如资源清理、容量检查、安全扫描)等。这些应用通常生命周期极短(可能在秒级或毫秒级),pull的定期模型极难去监控,一般都需要使用push的方式,由应用主动推送监控数据。
为了应对这种短生命周期的应用,纯pull的系统都会提供一个中间层(例如prometheus的push gateway):接受应用主动push,再提供pull的端口给监控系统。但这就需要额外多个中间层的管理和运维成本,而且由于是pull模拟push,上报的延迟会升高而且还需要即使清理这些立即消失的指标。
4 灵活性与耦合度
从灵活性上来讲,pull模式稍微有一些优势,可以在pull模块配置到底想要哪些指标,对指标做一些简单的计算/二次加工;但这个优势也是相对的,push sdk/agent也可以去配置这些参数,借助于配置中心的存在,配置管理起来也是很简单的。
从耦合度上讲,pull模型和后端的耦合度要低很多,只需要提供一个后端可以理解的接口即可,具体连接哪个后端,后端需要哪些指标等不用关心,相对分工比较明确,应用开发者只需要暴露应用自己的指标即可,由sre(监控系统管理者)来获取这些指标;push模型相对来说耦合度要高一些,应用需要配置后端的地址以及鉴权信息等,但如果借助于本地的push agent,应用只需要push本地地址,相对来说代价也并不大。
七 运维与成本对比
1 资源成本
从整体成本上讲,两种方式总体的差别不大,但从归属方角度来看:
- pull模式核心消耗在监控系统侧,应用侧的代价较低
- push模式核心消耗在推送和push agent端,监控系统侧的消耗相比pull要小很多
2 运维成本
从运维角度上讲,相对而言pull模式的代价要稍高,pull模式需要运维的组件包括:各类exporter、服务发现、pullagent、监控后端;而push模式只需要运维:push agent、监控后端、配置中心(可选,部署方式一般是和监控后端一起)。
- 这里需要注意的一点是,pull模式由于是服务端向客户端主动发起请求,网络上需要考虑跨集群连通性、应用侧的网络防护acl等,相比push的网络连通性比较简单,只需要服务端提供一个可供各节点访问的域名/vip即可。
八 pull or push如何选型
目前开源方案,pull模式的代表prometheus的家族方案(之所以称之为家族,主要是默认单点的prometheus扩展性受限,社区有非常多prometheus的分布式方案,比如thanos、victoriametrics、cortex等),push模式的代表influxdb的tick(telegraf, influxdb, chronograf, kapacitor)方案。这两种方案都有各自的优缺点,在云原生的大背景下,随着prometheus在cncf、kubernetes带领下的大火,很多开源软件都开始提供prometheus模式的pull端口;但同时还有很多系统本身设计之初就难以提供pull端口,这些系统的监控相比而言使用push agent方式更为合理。
而应用本身到底该使用pull还是push一直没有一个很好的定论,具体的选型还需要根据公司内部的实际场景,例如如果公司集群的网络很复杂,使用push方式较为简单;有很多短生命周期的应用,需要使用push方式;移动端应用只能用push方式;系统本身就用consul做服务发现,只需要暴露pull端口就可以很容易实施。
所以综合考虑情况下对于公司内部的监控系统来说,应该同时具备pull和push的能力才是最优解:
- 主机、进程、中间件监控使用push agent;
- kubernetes等直接暴露pull端口的使用pull模式;
- 应用根据实际场景选择pull or push;
九 sls在pull和push上的策略
sls目前支持日志(log)、时序监控(metric)、分布式链路追踪(trace)的统一存储和分析。对于时序监控方案是兼容prometheus的格式标准,提供的也是标准的promql语法。面对数十万sls的用户,应用场景可能会千差万别,不可能用单一的pull或push来对应所有客户需求。因此sls在pull和push的选型上sls并没有走单一路线,而是兼容pull和push模型。此外对于开源社区和agent,sls的策略是完全兼容开源生态,而非自己去造一个闭合生态:
- pull模型:完全兼容prometheus的pull scrap能力。可以使用prometheus的remote write,让prometheus来做pull的agent;和prometheus scrap一样能力的vmagent也可以这样使用;sls自己的agent logtail也可以实现prometheus的scrap能力
- push模型:目前业界的监控pushagent生态最完善的当属telegraf,sls的logtail内置了telegraf,可以支持所有的telegraf的上百种监控插件
相比vmagent、prometheus这类pull agent以及原生telegraf,sls额外提供了最迫切的agent配置中心和agent监控能力,可以在服务端去管理每个agent的采集配置以及监控这些agent的运行状态,尽可能降低运维管理代价。
因此实际使用sls进行监控方案的搭建会非常简单:
- 在sls的控制台(web页面)去创建一个存储监控数据的metricstore;
- 部署logtail的agent(一行命令);
- 在控制台上配置监控数据的采集配置(pull、push都可以);
十 总结
本文主要介绍了监控系统中最纠结的pull or push选择问题,笔者结合数年的实际经验以及遇到的各类客户场景对pull和push的各类方向进行了比对,仅供大家在监控系统建设过程中参考,也欢迎大家留言和讨论。
作者 | 元乙
原文链接:http://click.aliyun.com/m/1000292537/
本文为阿里云原创内容,未经允许不得转载。