Ray 分布式实验室
Prometheus作为云原生时代最流行的监控组件,已然成为社区监控的实际标准,拥有活跃的社区和丰富的周边项目。但在多集群,大集群等场景下,Prometheus由于没有分片能力和多集群支持,难以满足生产需求。本文从Prometheus的单集群监控开始,介绍包括Prometheus的基本概念,基本原理,基于联邦架构的多集群监控,基于Thanos的多集群监控,及基于Kvass的大集群监控等内容。
另外本文中的Kvass(https://github.com/tkestack/kvass)项目是我们团队近期开源的Prometheus分片技术,目前已被Thanos社区作为Thanos推荐的使用案例加入到官网文档中。欢迎大家给项目点赞,参与开发,或者提Issue给我们。
Prometheus基本原理
大家应该对Prometheus或多或少有点了解,这里简单介绍一下,Prometheus是当前最流行的开源多维监控解决方案,集采集,存储,查询,告警于一身。其拥有强大的PromSQL语句,可进行非常复杂的监控数据聚合计算,甚至支持关系型聚合。其基本架构如下图所示。
图可能有点复杂,我简单总结如下:
从配置文件加载采集配置
通过服务发现探测有哪些需要抓取的对象
周期性得往抓取对象发起抓取请求,得到数据
将数据写入本地盘或者写往远端存储
基本概念
为了大家阅读后面的内容,这里介绍一些基本的概念术语。
Job:Prometheus的采集任务由配置文件中一个个的Job组成,一个Job里包含该Job下的所有监控目标的公共配置,比如使用哪种服务发现去获取监控目标,比如抓取时使用的证书配置,请求参数配置等等。
Target:一个监控目标就是一个Target,一个Job通过服务发现会得到多个需要监控的Target,其包含一些label用于描述Target的一些属性。
relabel_configs:每个Job都可以配置一个或多个relabel_config,relabel_config会对Target的label集合进行处理,可以根据label过滤一些Target或者修改,增加,删除一些label。relabel_config过程发生在Target开始进行采集之前,针对的是通过服务发现得到的label集合。
metrics_relabel_configs:每个Job还可以配置一个或者多个metrics_relabel_config,其配置方式和relabel_configs一模一样,但是其用于处理的是从Target采集到的数据中的label。
Series:一个Series就是指标名 label集合,在面板中,表现为一条曲线。
head series:Prometheus会将近2小时的Series缓存在内测中,称为head series。
特别注意relable和metrics_relable的区别,前者在抓取前进行,是Target的属性。
基本原理
有些小伙伴可能对Prometheus原理不太了解,这节简单介绍其核心原理。
服务发现:Prometheus周期性得以pull的形式对target进行指标采集,而监控目标集合是通过配置文件中所定义的服务发现机制来动态生成的。
relabel:当服务发现得到所有target后,Prometheus会根据job中的relabel_configs配置对target进行relabel操作,得到target最终的label集合。
采集:进行完上述操作后,Prometheus为这些target创建采集循环,按配置文件里配置的采集间隔进行周期性拉取,采集到的数据根据Job中的metrics_relabel_configs进行relabel,然后再加入上边得到的target最终label集合,综合后得到最终的数据。
存储:Prometheus不会将采集到的数据直接落盘,而是会将近2小时的series缓存在内测中,2小时后,Prometheus会进行一次数据压缩,将内存中的数据落盘。
服务发现 ==> targets ==> relabel ==> 抓取 ==> metrics_relabel ==> 缓存 ==> 2小时落盘。
单集群监控方案
主流的指标
对于单个集群,社区主流的指标来源于以下几个组件,Prometheus将从他们获取数据。
Kube-state-metrics:这个组件用于监控Kubernetes资源的状态,比如Pod的状态。原理是将Kubernetes中的资源,转换成Prometheus的指标,让Prometheus来采集。比如Pod的基本信息,Serivce的基本信息。
Node-exporter:用于监控Kubernetes节点的基本状态,这个组件以DeamonSet的方式部署,每个节点一个,用于提供节点相关的指标,比如节点的cpu使用率,内存使用率等等。
cAdvisor:这个组件目前已经整合到kubelet中了,它提供的是每个容器的运行时指标,比如一个容器的CPU使用率,内存使用率等等。
Kubernetes相关组件:比如apiserver,controller-manager,scheduler,kubelet等,主要提供每个组件核心功能相关的指标,比如QPS等等。
部署架构
单集群架构非常简单,如图所示。使用这种方式,就可以将集群的节点,组件,资源状态,容器运行时状态都给监控起来。
多集群场景的特点
服务发现隔离
网络隔离
只用Prometheus能解决吗?
答案其实是能,用联邦。
Prometheus支持拉取其他Prometheus的数据到本地,称为联邦机制。这样我们就可以在每个集群内部署一个Prometheus,再在他们之上部署一个Top Prometheus,用于拉取各个集群内部的Prometheus数据进行汇总。
联邦的问题在哪?
联邦的方案也是社区所认可的,在集群规模普遍较小,整体数据量不大的情况下,联邦的方案部署简单,理解成本低,没有其他组件的引入,是一个很不错的选择。
但是联邦也有其问题。由于所有数据最终都由Top Prometheus进行存储,当总数据量较大的时候,Top Prometheus的压力将增大,甚至难抗重负,另外,每个集群中的Prometheus实际上也会保存数据(Prometheus2.x 不支持关闭本地存储),所以实际上出现了数据无意义冗余。总结而言,联邦的问题主要是:
Top Prometheus压力大
数据有无意义冗余
使用Thanos实现多集群监控
Thanos是一款开源的Prometheus 高可用解决方案,其支持从多个Prometheus中查询数据并进行汇总和去重,并支持将Prometheus本地数据传送到云上对象存储进行长期存储。官方架构图太复杂,不便于理解,这里给一个简化版本。
Query:Query代理Prometheus作为查询入口,它会去所有Prometheus,Store以及Ruler查询数据,汇总并去重。
Sidecar:将数据上传到对象存储,也负责接收Thanos Query的查询请求。
Ruler:进行数据的预聚合及告警。
Store:负责从对象存储中查询数据。
部署方案
使用Thanos来替代联邦方案,我们只需要将上图中的Prometheus和Thanos sidecar部署到Kubernetes集群中,将Thano Query等组件部署在原来Top Prometheus的位置即可。
相比联邦的优势
使用Thanos相比于之前使用联邦,拥有一些较为明显的优势:
由于数据不再存储在单个Prometheus中,所以整体能承载的数据规模比联邦大。
数据不再有不必要的冗余。
由于Thanos有去重能力,实际上可以每个集群中部署两个Prometheus来做数据多副本。
可以将数据存储到对象存储中,相比存储在本地,能支持更长久的存储。
大集群场景的特点
上边我们介绍了基于Thanos的监控系统,那如果不是多集群,而是单个大集群的场景怎么办?
大集群场景的特点很明显,那就是数据规模大,无论是target的规模,还是数据量,都是一个Prometheus无法采集的,得分片。
只用Thanos能解决吗
答案还是能,用hasmod。
Prometheus支持在配置文件中加入hashmod,通过某个label的值来进行hash,让每个Prometheus只采集部分target,例如按target的地址进行hashmod,让target采集任务分散到3个Prometheus中。这样每个Prometheus就只会采集部分target,从而达到分片效果。由于每个分片的hashmod取值不一样,所以每个分片需要使用单独的配置文件。
hashmod的方案有什么问题
虽然使用hashmod的方式在一定程度上可以将负载分散到多个Prometheus中,但是其至少存在以下问题:
配置管理复杂:由于每个分片都要有单独的配置文件,需要维护多份配置文件
配置项有侵入:需要为每个Job考虑hashmod的方式,而且需要清楚所采集数据根据那个label来hash才可能平均,对使用者相当不友好。
可能出现热点:hashmod是不保证负载一定均衡的,因为如果多个数据规模较大的target被hashmod到一个分片,这个分片就有可能OOM。
Thanos没解决的问题
那能不能只使用一个配置文件还不需要hashmod呢,这就需要使用Kvass项目提供的能力。
加入Kvass实现大集群监控
Kvass是一个Prometheus横向扩缩容解决方案,他使用Sidecar动态得根据Coordinator分配下来的target列表来为每个Prometheus生成只含特定target的配置文件,从而将采集任务分散 到各个Prometheus分片。Coordinator用于服务发现,target分配和分片扩缩容管理。Thanos(或者其他TSDB)用来将分片数据汇总成全局数据是官方文档中Thanos的典型用法:https://thanos.io/tip/operating/use-cases.md/
简单来说,就是由独立组件(Coordinator)做服务发现,并把target集合及数据规模提前探测出来,直接分配给几个Prometheus去抓,分片不再进行服务发现了。
部署方案
我们在Thanos方案中加入Kvass,就可以使用原来的配置文件去监控大集群,而不需要加入任何hashmod相关的东西吗,配置文件也不需要多个。
相比hashmod的优势
使用Kvass方案,相比于hashmod有明显的优势:
配置管理简单:无需针对配置文件做任何特殊工作,单一小集群时候怎么用,现在就怎么用。
负载可控:由于Kvass在向分片配置target的时候,会根据target的实际规模来,而不是通过hashmod来,所以每个分片的总负载会被控制在一个阈值以下,不会出现某个分片OOM的情况。
自动扩缩容:Kvass会根据当前集群的规模,动态调整分片个数。
总结
随后,针对多集群场景,我们还谈了联邦方式与Thanos方式各有什么优缺点。
面对大集群场景时,我们谈了Thanos未解决的问题,并介绍如何用hashmod的方案来监控大集群。最后,我们使用Kvass弥补了Thanos的不足,不需要hashmod就能将Prometheus进行了分片。
Q&A
Q:如果想将Prometheus用于生产环境,基于Prometheus封装自己的图形化配置工具是否有必要(比如阿里云的Prometheus服务),还是让运维学会自己手动配置文件?(纯内网环境)A:我觉得这两个不冲突。但是还是建议先学会手动配文件,这样对原生的配置会更加了解,图形化配置工具我理解价值在于简化具体监控对象的配置,比如直接选择一个Service的EP进行监控,而不需要配置复杂的服务发现。
Q:如何解决high cardinality问题?A:这个问题是由于数据源数据不合理导致,系统层面会通过限制series总数来处理,不过这次分享的架构中,不包含多组户隔离的部分哦。
Q:您在Prometheus远程存储这块儿有什么推荐吗,目前就觉得InfluxDB合适,但是InfluxDB开源的只有单机版本。A:InfluxDB确实只有单机版本,但是实际上你可以加个Proxy做分片的,或者直接使用其他DB如M3。
Q:Kubernetes中deployment的自定义label标签透传给cAdvisor,然后由Prometheus采集Metric时带入到采集项中?A:cAdvisor中不包含deployment上的label,这个需要通过PromSQL来将cAdvisor的指标和kube-state-metrics提供的相关指标聚合来获得。
Q:Prometheus磁盘空间依靠什么特性来监控?在搭一套么?A:这个可以自监控(但不推荐),如果有比较完善的基础设施(即Prometheus运行在其之上),就可以用基础设施的监控,如果没有,确实需要根据实际情况去搭建一个。
Q:现在监控指标数是什么量级?查询通过什么来做,Thanos吗?查询的速度如何?网络方向除了Node/Container的网络流量监控外,还应该关注哪些监控指标?A:我们有多个集群,目前其中一个大概2000w series左右规模,也不是最大的一个,用的Thanos Query,查询速度得看查询的数据规模,基本上排障没问题。网络的具体指标这个不好意思我不太清楚。
Q:如何处理Pod漂移问题?A:我们使用的是弹性容器来部署监控组件,没有Pod漂移问题哦。如果担心有Pod漂移,建议部署2副本。
Q:Job的数量会影响prom的内存消耗吗?发现多个Job配置服务发现时内存有暴涨的现象。A:会的,在Prometheus的实现里,每个Job服务发现是独立的,而且其实服务发现挺占内存,这就是为什么Kvass会把服务发现剥离出来用一个组件来单独做。
Q:多个Job都使用了服务发现,Prometheus内存是否增长?A:会的,在Prometheus的实现里,每个Job服务发现是独立的,而且其实服务发现挺占内存,这就是为什么Kvass会把服务发现剥离出来用一个组件来单独做。