摘要:在云原生 + 微服务的体系下, 服务观测是治理服务的重要依据和抓手,知之才能治之。在观测领域的三架马车中,监控 (Metrics) 无疑是最为重要的, 它是最常被查看的, 同时稳定性和准确性要求也是最严格的。
背 景
在云原生 + 微服务的体系下, 服务观测是治理服务的重要依据和抓手,知之才能治之。在观测领域的三架马车中,监控 (Metrics) 无疑是最为重要的, 它是最常被查看的, 同时稳定性和准确性要求也是最严格的。
作业帮的监控体系是随着云原生一起成长起来的, 支持着公司所有集群和服务的监控任务。在实践中我们认为一套优秀的监控系统需要支持以下几个点
稳定:稳定不只有系统稳定, 我们还要保障数据稳定, 尽量减少采集和传输阶段造成的数据抖动
实时:监控数据有很强的时效性, 我们要保证最新的数据最快地呈现在用户前面
全面: 全面的观测才是好的观测, 我们要保证监控数据是多维度, 能够广泛覆盖
高吞吐:监控的数据量与监控对象的数量成正比, 在做全面监控的时候必然会有庞大的数据量. 我们需要支持大数据量的存储和访问
长期存储: 监控数据虽然有很强的时效性, 但也有访问历史数据的需求;我们需要有一个合适的方式来保存这些冷数据。
作业帮监控现状
目前作业帮高峰每秒有 800w 的监控数据采集和写入,活跃时间序列达到 300w,每天新增 800GB 监控数据写入。
随着作业帮业务的持续拓展,监控规模也在迅速扩大,这给监控系统带来了极高的挑战性,意味着监控系统需要处理大量的实时监控数据,保证数据的准确性和及时性,同时能够有效可靠地存储和分析这些数据,因此需要建设更强大灵活且具有成本优势的监控系统支撑公司业务的持续发展。
作业帮选择使用 prometheus 作为监控的采集组件,并使用 VictoriaMetrics 作为监控存储,选型 Prometheus+VictoriaMetrics 搭建监控系统的主要原因在于:
Prometheus 是一个开源的监控系统,具有高度可扩展性和灵活性,支持多种数据模型,能够适应不同类型和规模的监控需求。
VictoriaMetrics 具有高效的存储和查询性能,可以快速处理大规模的时间序列数据,而且具有较低的存储和计算成本,能够降低系统的总体成本和复杂度。
VictoriaMetrics 作为 Prometheus 数据的存储和查询引擎,其高效的时间序列数据库,能够快速存储和查询大规模的时间序列数据。因此,这两者的结合可以满足作业帮大规模监控数据的存储、查询和分析需求。
同时 VictoriaMetrics 对 Prometheus 的良好兼容,使其可以无缝对接 Prometheus,并与其他常用的监控工具和系统集成,如 Grafana 等,为作业帮提供更全面、灵活的监控解决方案。
作业帮多云多地域的监控体系是如何构建
作业帮的服务部署是多云多地域的,除了数个核心集群外,还有多个小集群分散在多个地域上,我们的监控系统需要完成所有集群的监控覆盖。整体架构如下图:
架构图
监控系统可以分为以下 3 个部分
监控采集
我们采用了 prometheus 作为监控数据采集组件,并按实际需求往集群中部署对应的 prometheus 实例负责采集。每个集群中的 prometheus 只负责采集本集群中的监控数据,并统一通过 remote-write 写入到监控数据存储(VictoriaMetrics)中。同时还存在部分小集群只能走公网通信的情况,为此我们会部署一个代理组件,负责承接公网监控流量,完成鉴权后再代理写入到存储中去。
Prometheus 在集群中的部署我们采用了横向 + 纵向拆分的模式。每个采集任务会按监控数据类型拆分到不同类的 prometheus 实例中去,同一类的 prometheus 会通过 hashmod 方式进行分片,从而将所有采集对象均匀分配。
监控存储
Prometheus 只支持单机部署,无法集群化, 在大数据量的场景下无法作为监控数据的存储中心,因此我们选择了 VictoriaMetrics 来存储监控数据。
在实际使用中,VictoaMetrics 在性能表现上十分优秀,单核可以支持 5W/S 的指标写入,查询的平均耗时在 50ms 左右,P99 在 2s 以内。
监控访问
我们的监控数据会在以下 3 个场景提供访问:
监控大盘:我们选择 grafana 作为监控数据的展示面,收敛所有的可视化需求。
指标告警:告警上我们复用了 grafana 的告警能力,从而在告警时做到与可视化界面的联动。
服务巡检:我们提供了巡检系统定期扫描服务的健康度,通过可信任的 API 来访问监控数据, 从而提前发现提前治理。
根因分析:当线上服务遇到问题时,我们提供了根因分析服务来快速分析定位问题。根因分析系统会通过可信任的 API 获取日志、监控、追踪和事件等数据,按策略进行分析定位。
多维度的监控指标采集是怎么建设的
我们将监控层级从下到上分为 4 层, 并按所属层次划分管理对应的采集任务,每一层的指标会由对应的 prometheus 实例来负责采集。
系统指标建设
系统指标里主要包括 K8S 集群,网络,基础组件,pod,Node 的各种指标。
通过这一层的指标我们了解系统的运行状态,通过监控数据知晓系统中的各种问题。
存储指标建设
存储是整个系统中极为重要的一部分,我们会为每类存储建立它们的指标数据。
存储指标里主要包括了 mysql,redis,ES,MQ 等各种存储的指标,以感知它们的运行情况。
另外我们会读取服务与存储的请求关系,为每个存储绑定服务依赖关系,从而完成存储与服务监控指标数据的联动。
服务指标建设
服务是整个系统的核心部分,我们会围绕着服务建立各类监控指标,自动完成指标的采集和汇聚,从而向用户提供全面的服务监控指标。
当前主要包含以下几类数据:
服务入流量指标
服务出流量指标
存储(mysql、redis、es 等)访问指标
MQ 生产 / 消费指标
服务运行时指标(Runtime)
服务指标建设致力于提供覆盖服务的通用指标数据,上线的服务无需额外配置就可以看到自己的大盘数据。
业务指标建设
服务运行时有很多业务指标需要观测,这些指标我们无法直接观测到,需要服务主动暴露出来。这种监控需求之前一般是通过服务增加打点日志然后进行统计分析完成的。这种实践方式会有几个问题在:
依赖日志链路:可用性和准确性强依赖日志链路,而日志的可用性保证一般会低于服务的可用性保证。
依赖分析服务:对分析统计的服务强依赖,并且这个依赖会带来额外的资源开销。
使用门槛高:需要额外配置日志解析和数据统计的规则,有一定的使用门槛。
在业务指标的实践上,我们建议服务通过 prometheus sdk 来统计关心的业务指标数据,并通过 metrics 接口暴露出来最后交由 proemtheus 自动完成采集。这种方式有几个优点:
更高的可靠性:RPC 请求比日志投递的方式,在数据传输上更加可靠,延迟也更低
更好的灵活性:服务可以在代码里撰写数据统计逻辑,不用受限于分析服务能力范围。
如何高效可靠地保存监控数据, 同时降低存储成本为原来的 1/6
在使用 VcitoriaMetrics 的过程中我们遇到了两个问题
副本与可用性: 可用性依赖于副本, 不过额外的副本会提高整体成本
历史数据: 监控数据需要保存一定时间, 但额外的磁盘占用会提高整体存储成本
为了解决上述问题, 我们自研了 vm-proxy, 作为 VictoriaMetrics 集群的读写代理,并采用了一套新的存储架构。如下图:
我们将 VictoriaMetrics 分为了标准集群和降准集群, 其中标准集群负责存储最近一个月的标准精度数据,而降准集群则负责存储降低精度后的历史数据。vm-proxy 主要起到以下作用:
数据写入复制
数据采样降精度
数据读取路由
vm-write-proxy
vm-write-proxy 会承接 prometheus 的所有 remote-write 流量,然后再将监控数据往标准集群和降准集群都写入一份数据。
标准数据策略:不对监控数据做额外处理,原样写入到标准集群中
降准数据策略:
按一定比例对监控数据进行降采样,再写入到标准集群中
过滤部分数据指标(高基数的指标和不要求长期保存的数据),不再写入降准集群
数据降准
观测数据都有冷热之分, 最近的数据访问频率越大, 而历史数据访问频率则会显著降低,于此我们需要对历史数据选择一种合适的方法存储以降低整体成本。在日志场景下我们一般会采用压缩的方式处理日志数据,而在监控场景里则会采取降准的方式处理监控数据。
在做监控数据采集的时候, 我们会为不同的数据设置一个合适采集的频率,而数据采集的频率则直接影响着监控的精度。如果一个指标的采集频率是 10s 和 60s, 我们可以看到 10s 采集频率的监控曲线会更细致, "分辨率"更高。
而我们数据降准的实现十分直接,就是降采样,比如将原本 10s 精度的数据降采样为 60s 精度的监控数据。vm-write-proxy 组件在接受到监控数据写入的时候, 会对时序数据进行采样,按比例剔除掉部分时序数据后再写入到降准集群中。
vm-read-proxy
vm-read-proxy 会承接 grafana 和 API 过来的所有查询流量, 并遵循以下策略进行流量分发
时间路由: 一个月内的查询请求会被发送到标准集群进行查询, 而一个月前的查询请求会被发送到降准集群。
降级路由: 当标准集群不可用, 所有查询请求会被重新路由到降准集群上。这样的操作会导致查询结果精度降低,但可以保证监控系统可以继续提供服务。
在将请求发送到降准集群时, 因为数据精度的不同, vm-read-proxy 会自动将查询语句调整为合适精度的查询, 从而保证监控数据连续。
流量鉴权
所有查询流量都会通过 vm-read-proxy 进行,因此我们在 proxy 上打通了公司的用户系统和权限系统,从而实现了监控数据用户身份 + 服务粒度的自动鉴权能力,从底层上杜绝了权限混乱的问题。
故障转移和恢复
实际运行中我们发现 VictoriaMetrics 单集群稳定性不足, 当集群负载较高、大流量进入时可能会导致部分节点不可用,而 VictoriaMetrics 的 Reroute 机制会自动将流量分摊到其余节点上,如果剩余节点无法承担全部流量则可能会引起雪崩,从而影响整个集群的可用性。通过双集群部署 VictoriaMetrics,我们通过构建数据副本的方式来保证存储的高可用,如果遇到单集群故障, 我们采用以下方式进行故障转移和恢复
标准集群故障:当集群中故障节点超过冗余数量时,vm-read-proxy 会自动进行降级路由,将所有的查询请求路由至降准集群,同时 vm-write-proxy 不再对降准集群的数据进行采样处理而是原样写入,此时对标准集群进行扩容或者观察流量过去标准集群恢复后,再将读流量切回至标准集群,同时恢复降准集群的采样策略。
降准集群故障:当降准集群故障时,不会影响实时监控数据展示,因此不需要切流量,直接进行集群恢复即可。
收益
之前我们的监控系统的瓶颈主要在磁盘上, 历史数据和副本数据占用了大量空间。而在使用了这套架构后, 整体的机器成本下降到了之前的 1/6, 并且历史数据的查询速度也有显著的提升,集群双活部署能保证监控数据的高可用,SLA 达到 99.95%。
大量的监控指标如何进行治理
监控数据的来源多种多样,我们当前有源于机器、组件、服务、业务、日志的各种指标。在其中存在着许多指标冗余, 设计不合理, 精度不合理的情况。这些不仅会导致查询耗时长,资源消耗大,也会导致数据存储空间的浪费。
我们如果想保证监控系统高效、稳定、成本可控,就需要对我们大量的指标数据进行治理,做到去芜存菁。一般可以通过以下三种方式做指标的治理:
高基数指标巡检
时序数据的设计支持了灵活的 label 属性, 但如果指标的 label 设计不合理, 就会造成指标数据量的极大膨胀。
针对这个问题, victoriaMetrics 提供了 vmui 组件, 我们可以借助这个组件来发现基数过大的指标。
而针对这些基数过大的指标, 我们可以看看这个 label 是否有被使用到, 也可以去优化 label 设计减少数据量。
监控数据是动态变化,所以我们会周期巡检并做周期性的高基数指标治理,以我们的经验一般每次治理可以去掉 10%~20% 左右的无效指标数据。
指标长度限制
此外还有另外一个指标设计不合理的情况, 就是 label 的 key 或者 value 设置得过长, 如果数据量比较大的话同样会影响存储和查询。
为此我们在 vm-write-proxy 中增加了功能,来实现过长指标的监视和裁剪,所有 label 长度默认都会限制在 256 字节内。
指标老化
作业帮监控系统中的数据有很大一部分是来源于对日志的解析。日志数据会由处理程序解析后汇聚成 Exporter 数据,再输出给 prometheus。我们发现部分指标数据存在生命周期过长的问题, 比如 pod 维度和 url 维度的数据 (pod 销毁后基于日志的监控数据没有跟随一起停止, 部分 url 只请求过寥寥几次却同样有着全时段的时序数据)。
针对这种情况,我们重写了 prometheus 采集和汇聚的逻辑,给每个时间序列记录生命周期,定期清理掉不活跃的指标数据。在上线指标老化能力,整体的时间序列写入量下降了 20%。
监控系统如何更加贴近研发
自动适配的服务监控大盘
作业帮所有容器化的服务,监控系统都会默认根据服务语言、资源依赖等为服务生成通用监控大盘,纳涵所有服务核心指标,包括服务资源、出 / 入流量、存储 /MQ 等外部依赖、语言运行时、网关监控等,无需研发手动配置直接提供统一监控视图。基于这个大盘,研发可以直接了解自己服务的运行状态,健康程度。
自定义的业务监控大盘
对于一些业务强相关的指标,服务通用监控无法进行观测,为此我们提供了业务监控大盘来满足此类监控需求。
对于业务监控数据,我们采用 prometheus 的标准做业务自定义指标的采集。服务可以在服务内部将业务指标进行统计汇聚,然后通过 metrics 接口暴露指标采集数据。之后研发可以通过工单来申请 prometheus 采集和创建监控面板,最后便可以创建出符合业务需求的业务监控大盘。
基于模版和推荐的告警体系
为保障服务持续健康运行,针对服务核心监控指标预设报警规则,用户可基于推荐快速应用,降低配置成本。
我们为各种服务提供了基础的告警模版, 用户可以一键应用模版快速给服务创建告警规则, 保证了对服务核心指标的关注,也支持对告警规则进行微调,用户可按需灵活配置。同时会自动生成服务维度的告警统计报表,帮助研发了解服务状态,关注告警原因并实际解决问题。
此外服务是持续演化的,我们发现会存在监控告警无法及时覆盖的情况,比如服务新接入消息队列但却忘了添加对应的监控告警。针对这种情况,我们的服务巡检系统会持续关注服务的监控告警设置,并基于服务的模版和配置进行监控告警项的推荐,研发老师可以按需应用。
监控系统联动其他观测工具
为提升问题排查效率,我们将监控系统与其他观测工具如日志检索、根因分析工具等进行打通。
当用户在查看监控面板时,会自动提取对应指标的关键信息,如服务名称、集群、URL、状态码等生成日志检索链接,研发可直接点击跳转到日志查看对该监控指标的详细日志。
当报警触发时,监控系统会提取报警关键信息一在告警卡片提供日志、监控、追踪数据的快速入口,提升问题定位效率。
同时告警事件会推送到根因分析服务,完成分析后分析结果也会自动推送给研发以协助线上问题定位。
今日好文推荐
Redis 之父:哪怕被喷我也得说,AI 远远落后于人类程序员!开发者跟评:用大模型气得我自己写代码都有劲儿了
传字节跳动内部开始禁用Cursor了
模型下载量12亿,核心团队却几近瓦解:算力分配不均、利润压垮创新?
印度国家级大模型上线两天仅 300 余次下载,投资人直呼“尴尬”:韩国大学生模型都有20万!
来源:InfoQ