伴随着企业的快速发展,以及用户的飞速增长,在面对数亿注册用户及数千万DAU的场景下,如何保证数万级服务器和数千级的应用服务稳定性,是运维人员面临一个重大挑战。好的服务稳定性需要有强健的服务支持,同时也需要有强健的监控系统来进行守护,本文将分享如何使用Thanos架设高性能、高可用的分布式Prometheus监控系统。

通常Prometheus高可用部署方案为联邦集群+HA的方式部署,如图所示:


在联邦+HA部署中,在每个数据中心或者VPC内以HA的方式进行Prometheus Server部署,采集当前所在数据中心或VPC内的监控目标数据,然后由一个全局的Prometheus Server负责聚合多个数据中心或VPC的监控数据,提供统一接口给用户查询,这样的部署架构看似满足高可用,但也存在诸多问题。
1)HA双副本或者更多副本运行的Prometheus Server收集的数据如何去重?
2)副本故障或副滚动升级造成数据出现断点,如何将多个副本数据进行互补,保证监控数据完整性?
3)中心Prometheus Server既要收集全局监控数据,又要提供给用户查询。
a.如何把控中心Server的负载 ? b.如何将监控数据高性能的方式提供给企业内部其它团队进行查询和汇聚?
4) 各数据中心监控数据如何长期存放?那么如何部署Prometheus,能够解决如上问题呢?

答案有很多,我们在这里采用了Prometheus+Thanos+对象存储。Thanos是一家英国游戏公司Improbable开源的prometheus长期存储软件;主要有Bucket、Check、Compact、Query、Rule、Sidecar、Store7大组件,参考架构如下:

组件介绍

Sidecar:主要是用来部署在每一个Prometheus实例所在的服务器或者Pod上,上传prometheus TSDB 的chunks存储块至OSS上或者其他的对对象存储桶上,同时接收Query组件转发的指标查询请求。
Store:实现了对象存储上历史数据查询的API

Query:实现了Prometheus HTTP v1 的API查询接口,接收用户指标查询请求,根据不同的label把请求转发至相应的Sidecar和Store ,聚合查询结果,并通过gossip协议去重,将结果返回给用户,同时可以将同一prometheus多副本滚动升级或者副本故障后造成的数据断点进行多副本数据聚合,返回正确数据给用户。

Compact:主要负责将对象存储上的历史数据进行压缩降准,将大于40小时的数据进行5分钟一个时序点进行压缩标记,将大于10天的数据进行一小时一个时序点进行压缩标记,这样会大大提高Store对对象存储上历史数据的查询效率。

Check、Bucket、Rule :分别用来检查,web查看,及全局设置告警使用。

在哈啰,伴随着公司快速的发展,应用服务、服务器的不断增加、不同环境和服务之间的网络隔离或VPC隔离以及容器化场景的不断推进,我们监控场景变得尤为复杂,对监控系统的稳定性和可扩展性要求更高。面对如此复杂的监控场景,我们希望:
1)所有不同的网络环境的监控数据可以通过一个统一的接口对外输出;

2)监控工具服务尽可能保证稳定性和可用性;

3)对外输出接口有足够好的性能提供给其他内部其他团队使用;

4)监控服务故障影响范围降到最小;

5)监控历史数据长期保留且可供查询。

上述诉求,传统zabbix和常用Prometheus联邦集群似乎不太满足,最终结合Thanos,我们对Prometheus部署架构进行优化,采用功能分区和环境分区且多副本进行部署,参考架构如下:

注:参考架构图,非最终架构图。

分区说明:

1)功能分区主要包括:服务器层、基础服务层(kubernetes)、应用层;
2)环境分区主要包括:生产环境、测试环境、开发环境、预发布环境等。

部署说明:

1)Prometheus Server 部署:分别在三个VPC中部署ECS监控prometheus Server HA、K8S监控 prometheus Server HA、APP 监控prometheus Server HA,3vpc累计9套Prometheus HA集群,且给每个Prometheus HA 配置唯一的externalLabels 用于查询区分不同的prometheus(如:env: pro)。
2)Query部署:由于各vpc网络隔离,因此可以在每个VPC内部署一组Query作为gossip使用。
3)Store、Compact部署:按照需求进行多个部署。


优化点说明:
Query组件:由于全局Query组件和各Sidecar之间是grpc方式进行通信,同时两个组件之间是跨越了VPC或者网络隔离,Query只能通过负载均衡的方式链接Sidecar,但这样存在一个问题,全局Query上每一次请求只能发送到后端一个Sidecar,当后端Prometheus发生故障或滚动升级的时候,可能造成数据断点。采用联邦方式部署,在每一个VPC内部署一组Query作为gossip使用,然后每个VPC环境内的sidecar都会注册到同网络环境下的Query,当接收到全局Query发来请求时,Query可以将请求分别发送到后端sidecar,然后聚合完整数据返回给客户端。参考下图:

Store、Compact组件:随着时间的推移,对象存储bucket上接收存储的Prometheus越来越多及数据越来越大,为了让每一次查询和压缩提高效率,排除本次查询不涉及到的存储块,减小网络和其他资源开销,因此可以根据prometheus external labels配置relabel-config,使用Dorp或Keep方法,按需部署多组Store、Compact服务。

最后,通过如上架构的部署,各组件的配合,解决了开始提出的一些疑问,同时水平功能拆分Prometheus,降低了单节点资源负载,使用Sidecar 直接查询TSDB数据,让Prometheus Server更专注监控,通过实际场景,4C8G2、8C16G2、8C16G*4 对Query组件进行扩展并查询实时监控指标,最终得到了一组很不错的数据: