当前位置: 首页 > 科技观察

为什么我们放弃Zabbix而采用Prometheus?

时间:2023-03-13 19:36:02 科技观察

2017年之前,我们运维系统的监控主要以Zabbix为主流方案。当时这部分数据库的监控服务也是由监控运维团队提供的。图片来自Pexels总体来说,Zabbix还是很强大的,使用起来也比较简单。基本上,编写脚本就可以实现对指定应用的监控。PS:不再是Zabbix了。运维团队基于Open-Falcon定制开发了统一的运维监控系统。当然,这是后话了。我们在2016年尝试了MySQL的容器化,2017年开始大规模应用,容器化后,MySQL的数量大幅增加,通过平台化管理。原来的Zabbix已经不能满足需求了:监控指标太多了,如果都接在Zabbix上,服务器承受不了(当时服务器资源情况下)。数据库运维平台对监控告警的管理需要联动处理。在数据库运维平台上添加或删除实例时,监控系统需要自动发现实例。有趋势预测和快速数据统计的需求。绘制监控指标有自定义需求。因此,我们DB团队要选择一个监控系统来支持以上需求。技术选择关于数据库的监控,我们不想投入太多的人力在维护上。毕竟监控系统不是我们的主要工作。因此,需要选择部署简单、服务器资源占用率低、并能结合报警功能的监控系统。虽然开源的监控系统还是很多的,但是经过最后的评测,我们还是选择了更轻量的Prometheus,能够快速的满足我们的数据库监控需求。①易用性二进制文件启动,轻量级Server,易于迁移维护,PromQL计算功能丰富,统计维度广。②高性能监控数据更多的是基于时间统计。时序数据库更适合存储监控数据,时间索引性能更高,监控指标百万级,每秒处理数十万个数据点。③可扩展性Prometheus支持联邦集群,允许多个Prometheus实例生成一个逻辑集群。当PrometheusServer单个实例处理的任务过多时,可以使用功能分区(Sharding)+联邦集群(Federation)进行扩展。④易集成Prometheus社区还提供了大量第三方实现的监控数据采集支持:JMX、EC2、MySQL、PostgresSQL、SNMP、Consul、Haproxy、Mesos、Bind、CouchDB、Django、Memcached、RabbitMQ、Redis、Rsyslog、ETC。。⑤可视化自带PrometheusUI,通过它可以直接查询数据。结合Grafana,可灵活构建精美细致的监控趋势图。⑥强大的聚合语法内置查询语言,可以通过PromQL函数查询和聚合数据。同时可以基于PromQL快速定制告警规则。实践监控的目的在构建监控系统之前,首先要明确监控的目的。在总结相关内容时,偶然在网上看到CNCF基金会认证Kubernetes管理员郑云龙先生根据《SRE:Google 运维解密》对监控目的的总结。总结的很到位,直接引用了。引用来源:https://www.bookstack.cn/read/prometheus-book/AUTHOR.md长期趋势分析:通过对监测样本数据的持续采集和统计,对监测指标进行长期趋势分析。比如通过判断磁盘空间的增长速度,我们可以提前预知未来什么时候需要扩容资源。告警:当系统发生或即将发生故障时,监控系统需要快速响应并通知管理员,以便快速处理问题或提前预防问题,避免对业务造成影响。故障分析与定位:当出现问题时,需要排查处理。通过对不同监控和历史数据的分析,找到问题的根源,解决问题。数据可视化:通过可视化的仪表盘,可以直接获取系统运行状态、资源使用情况、服务运行状态等直观信息。一个监控系统满足了以上几点,包括采集、分析、报警、图形显示,完美的涵盖了一个监控系统应该具备的功能。下面介绍一下我们是如何基于Prometheus搭建数据库监控系统的。我们的监控系统架构介绍我们是2016年底开始使用的,中间经历了几次架构演进。但考虑到阅读体验,此处不再详述替换方案。我们将重点关注当前的架构设计和使用。先来看一下整体架构:下面一一介绍一下上面架构图的内容:①Agent这是我们用Golang开发的一个监控信息收集代理,负责收集监控指标和实例日志。监控指标包括宿主机(实例、容器)的信息。因为我们是容器化部署,所以单机实例数大概是4-20个。随着运维平台实例的增删,主机上的实例信息可能会发生变化。所以我们需要Agent能够感知到这种变化,并决定收集哪些信息。另外,采集间隔为10s,监控粒度可以做得更细,防止监控指标突然抖动而漏掉。②Pushgateway这是我们使用的官方组件,因为Prometheus是通过Pull来获取数据的。如果让PrometheusServer去各个节点拉取数据,那么监控服务的压力会很大。我们在监控上千个实例的情况下实现了10s的采集间隔(当然也可以采用联邦集群的方式,但是这需要部署PrometheusServer,加入告警相关的东西后,整个架构就会变得更复杂。复杂)。所以Agent拿数据推送到pushgateway,然后PrometheusServer再去pushgateway拉取数据。这样在满足PrometheusServer的写入性能的情况下,单机就可以承载整个系统的监控数据。考虑到跨机房采集监控数据的问题,我们可以在每个机房部署pushgateway节点,同时缓解单个pushgateway的压力。③PrometheusServer设置PrometheusServer从pushgateway拉取数据的时间间隔为10s。如果有多个推送网关,只需配置多个组即可。为了保证PrometheusServer的高可用,可以在异地容灾机房再放置一台PrometheusServer,配置与之前的PrometheusServer相同。如果监控需要长期保存,也可以配置一个采集间隔较大的PrometheusServer,比如5分钟一次,数据保存1年。④Alertmanager在使用Alertmanager之前,需要在PrometheusServer上定义告警规则。因为我们的监控系统是面向DBA的,所以告警指标的种类可以统一管理。但是,不同的集群或实例也定义了不同的告警阈值。我这里就讲讲如何实现灵活配置。为了解决Alertmanager的单点问题(高可用见下图),我们可以配置三点,Alertmanager引入了Gossip机制。Gossip机制提供了一种在多个Alertmanager之间传递信息的机制。当多个Alertmanager分别收到相同的告警信息时,确保只向Receiver发送一个告警通知。Alertmanager支持多种类型的配置。自定义模板,例如发送HTML电子邮件;告警路由,根据标签匹配决定如何处理告警;收件人,支持邮件、微信、Webhook等多种告警方式;inhibit_rules,通过合理的配置,可以减少垃圾告警的产生(比如机器宕机,可以忽略机器上所有实例的告警信息,防止告警风暴)。我们的告警是将触发的告警通过Webhook推送到指定的API,然后通过该接口的服务进行二次处理。Prometheus和Alertmanager的高可用⑤Filter&Rewrite模块该模块的作用是实现MySQL集群告警规则的过滤功能和告警内容的改写。先说告警规则过滤,因为上面说了告警规则是统一设置的,如果DBA需要调整个别集群的告警阈值会很麻烦。为了解决这个问题,我们在Alertmanager背后构建了一个Filter模块。模块收到告警内容后,会判断告警信息是否超过DBA为集群或实例设置的阈值范围(实例优先级高于集群),如果超过则触发发送动作。警报根据其级别以不同的方式发送。比如我们定义了P0、P1、P2三个级别,从高到低:P0,随时触发,同时触发电话和微信告警。P1,8:00-23:00只发送微信告警,其他时间连续触发3次触发发送。P2、8:00-23:00发送微信报警,其他时间触发不发送。下图是集群和实例的告警阈值管理页面(这是数据库运维平台集成的功能)。每个集群和实例都可以独立管理。创建新集群时,会根据选择的CPU内存进行配置。生成一组与配置相对应的警报阈值。集群告警规则管理入口实例告警规则管理入口告警规则管理然后看告警内容Rewrite,比如上图中看到的附加接收者,除了DBA,有些开发同学也想接收告警。但是如果你给他们发一个Thread_running大于多少的警告,他们可能不明白这是什么意思,或者在什么情况下会出现这个警告,需要注意什么。我们需要做的就是重写告警的内容,让开发能够看懂。下图是我们改写的。告警内容重写也??有告警关联。比如某台主机的磁盘IO很高,但是可能需要定位是哪个实例引起的。那么我们可以通过这个告警,然后分析监控系统中可能导致高IO的实例。并管理警报。如图:IO告警关联实例信息最后说一下告警收敛。例如宿主机宕机,宿主机上的MySQL实例会触发宕机告警(如果MySQL实例连续三个索引上报周期都没有数据,则判断为Instanceexception),大量告警数量会压倒重要告警,所以需要做告警收敛。这是我们的做法。宕机后宿主机的告警信息会带出实例的相关信息。一条告警可以看到所有的信息,这样我们就可以通过一条告警信息的内容知道哪些集群实例受到了影响。.如图:主机宕机关联实例⑥图(绘图)Prometheus完美支持Grafana,我们可以通过PromQL语法结合Grafana快速实现监控图的展示。为了与运维平台关联,运维平台可以通过URL参数传递直接打开指定集群和指定实例的监控图。实例监控图集群监控图⑦V-DBA这是一个自动化的DBA程序,可以依赖告警信息来实现一些指定的操作。这是过载保护的示例。我们的过载保护并不总是启用,只有在触发thread_running警报时才启用。它将与过载保护动作相关联。具体解决方案如下图所示:⑧告警管理在运维平台上,我们有专门的告警管理页面,我们在手机端也做了适配,方便DBA随时连接平台查看和处理警报。从下图中可以看到当前触发的告警列表。不带颜色的表示已经应答(是维护报警,应答后不会发送),带颜色的表示未应答(图中属于P2级报警).另外可以注意到,这里的告警内容并没有被改写,因为是给DBA读取的。基于PC端和移动端的告警日志,我们结合ES和Kibana实现了告警数据分析功能。这种交互式的数据分析展示,可以帮助DBA轻松完成大规模数据库运维下的日常巡检,快速定位问题。聚类并及时优化。告警分析是基于Prometheus的其他实践,在Prometheus解决方案的基础上,我们还扩展了其他与监控告警相关的功能。①集群打分因为我们对告警进行了分类,大部分告警都是P2级别的,也就是白天发送的,这样可以减少晚上的告警次数。但是这种方式可能会漏掉一些告警,导致问题没有被及时暴露,所以实现了集群打分功能来分析集群的健康状态。并针对一个月的评分做趋势展示,方便DBA快速判断集群是否需要优化。如下图所示:ClusterScore点击Details进入集群详情页面。可以查看CPU、内存、磁盘的使用情况(这里的磁盘空间已经达到262%,也就是超过配额)。另外还有昨天和7天前的QPS、TPS、Thread_running同比曲线,用来观察集群请求量的变化。底部的注释也会指出哪些点被扣除以及它们是哪些示例。详情页②指标预测预测磁盘空间将在7天内小于200G。因为是多实例部署,所以需要计算当前宿主机上实例当前的数据大小、日志大小,以及每天的增长趋势。DBA可以快速定位到需要迁移扩容的节点实例。实现方法是使用Prometheus的predict_linear来实现的(具体用法可以参考官方文档)。磁盘空间警告日志相关①SlowLogSlowLog管理,我们通过一个系统来收集分析,因为要得到原始日志,所以没有使用pt-query-digest。架构如下:通过Agent采集,然后格式化原始日志以LPUSH方式写入Redis(因为数据量不大,所以没有使用Kafka或者MQ),然后通过slow_log_reader读取出来通过BLPOP编程,处理后写入ES。这一步主要实现提取SQL指纹,将分片库名改写为逻辑库名等操作。写入ES后,就可以使用Kibana查询数据了。对接面向开发的数据库一站式平台,业务开发同学可以自主权限查询数据库。同时我们还集成了小米开源的SOAR,可以查看SQL优化建议。通过ES聚合,用户可以订阅慢查询报告,选择性查看相关库的TOP慢SQL信息,进行针对性的镜像优化。②Processlist、InnoDBStatus数据采集为了能够在故障回溯或失败时查看session快照和InnoDBStatus,我们在监控Agent中内置了这个功能,也是10秒一次。不同的是它会判断当前ThreadRunning是否达到阈值。数据将被收集,否则不被收集。这个设置不仅解决了无用日志过多的问题,也解决了性能异常时获取状态信息的问题。下图展示了日志收集和处理的逻辑。日志处理模块与慢查询处理在同一个程序中,session快照的处理逻辑与慢查询类似,这里不再赘述。综上所述,监控系统没有谁好谁不好。最重要的是适合自己的团队,可以合理的用最小的成本去解决问题。我们从2016年开始使用1.x版本到离线使用2.x版本。目前基于Prometheus的监控系统承载了对整个平台所有实例、主机、容器的监控。采集周期为10秒,Prometheus在1分钟内平均每秒采集的样本数为9-10W。一台物理机(不包括高可用灾备资源)可以承载当前流量,还有很大的容量空间(CPU\Memory\Disk)。如果以后单机无法支撑,可以扩展成联邦集群模式。另外,本文提到的监控系统只是我们运维平台中的一个模块,并不是一个独立的系统。从我们的实践经验来看,最好是集成到运维平台中,实现技术栈融合和系统集成。产品化和平台化降低了使用的复杂性。最后说一下我们未来在监控方面想做的事情。目前我们有监控数据,但是告警只发送指标的内容。具体的rootcause还是需要DBA去分析监控信息。我们计划在第一阶段实现告警指标的关联分析后,可以根据多个监控指标给出结论,帮助DBA快速定位问题;在第二阶段,我们可以分析结果并给出处理建议。最终依靠整个监控体系来降低运维的复杂度,打通运维与业务发展的沟通障碍,提升运维效率和服务质量。作者:严晓宇简介:同程艺龙数据库技术专家,在互联网行业拥有多年??DB运维经验,曾在游戏、O2O、电商行业从事过DBA运维工作。2016年加入同程艺龙,目前负责团队数据库架构设计与优化、运维自动化、MySQL监控系统搭建、DB私有云平台设计与开发。