云原生多集群监控架构系统架构
背景
云原生时代下,系统的监控和可观测性变得越来越加重要。随着我们的集群规模越来越大,监控数据的种类和数量也越来越多,我们对监控系统也有了更高的要求。除了监控平台的高可用架构,我们也希望其能实现数据长期存储,跨集群扩展,低延时高性能等。而Prometheus与Thanos结合 的云原生分布式监控平台也逐渐成为了开源监控下的主流方案。
通常,由于公司的业务需要, 会将不同的业务会跑在不同的K8S集群上, 因此本文将分享下如何使用Thanos&Promentheus 来搭建多集群监控架构系统
架构
首先,让我们全局来看看一些适用于我们监控栈的设计:
我们有两种方式将远程的Prometheus实例链接到Thanos (即:除Application外的其他集群中的Prometheus):
- 暴露Thanos Sidecar gRPC端口: 接着可以配置 Thanos Query 连接该端点
- 配合使用Prometheus
remote_write
& Thanos Receive: Prometheus将数据发送到Application集群中的Thanos Receive组件
公司的多集群的Thanos & Prometheus 架构图如下:
具体细节
-
- Grafana通过使用一个专用的PostgreSQL数据库来保证高可用性
-
- Thanos Query Frontend使用专用的
Memcached
组件
- Thanos Query Frontend使用专用的
-
- 使用Thanos Sidecar获取和保存来自Application集群的指标
-
- 来自其他集群的指标的获取方式有以下两种:
- 远程Prometheus用
remote_write
方式向Thanos Receive发送数据 - 通过Thanos StoreAPI获取查询
-
- 虚拟机的发现是基于Prometheus EC2或AzureVM
Service discovery
- 虚拟机的发现是基于Prometheus EC2或AzureVM
-
- 警报由Prometheus实例或Thanos Ruler处理
-
- 警报推送到OpsGenie,以便稍后优化和通知用户
组件概述
通常监控平台主要有以下几个组件:
- Prometheus: 收集指标并实现短期存储
- Thanos: 聚合 Prometheus 指标 并提供长期存储方案
- Grafana: 使用 Thanos指标 绘制Dashboards以展示
- Alertmanager: 基于Thanos指标提供告警
Prometheus
我们使用 Prometheus 作为代理和短期存储来从一组目标对象(虚机,容器等)中收集指标。
大多数 Prometheus 实例是通过 Kubernetes 自定义资源ServiceMonitor
动态配置的,以便抓取 Kubernetes 服务(实际上pods的服务发现是通过services).
然后在 Prometheus Helm 配置中预先配置了一些 Prometheus job,以便使用虚拟机服务发现来监控基于 VM 的服务。
通常,Prometheus上的数据会被保留两天的时间。
具体实现:
- Prometheus通过prometheus-operator部署在Kubernetes中
- 我们使用Operator提供的分片
sharding
功能将负载分散到多个 Prometheus 分片:被监控的对象将自动分配给特定的分片 - 每个分片使用两个副本以实现高可用性
- 每个分片将其数据存储在持久卷上
注意:
虽然 Prometheus 提供了一个处理警报的规则引擎,但我们实际上更建议将他们的报警分配给 Thanos Ruler。
这是因为 Prometheus 分片功能使得某些警报无法正确处理,因为单个分片可能没有处理警报所需的所有指标。
因此,有些警报仍然可以在 Prometheus 中处理,而其他警报需要使用 Thanos Ruler 来避免误报/否定。
我们选择使用 Thanos Ruler来处理所有的告警,以使其更加统一简单。
Thanos
Thanos 是基于微服务的应用,可以很好地与 Prometheus 联结使用,并通过以下方式扩展其功能:
- 通过 S3 或 Azure Blob 存储等对象存储进行长期存储
- 单个入口点,即访问指定平台(甚至跨平台的集群)的所有 Prometheus 的所有指标
- 指标重复数据删除:解决 Prometheus HA 指标差异
- 指标downsampled:在展示数周或数月的数据指标时很有用
Thanos Query Frontend
Thanos Query Frontend 是为 Grafana 等外部客户端提供原生 Prometheus API 的入口。 它会将每个 PromQL 查询发送到 Thanos Query,并通过以下操作来优化查询性能:
- 使用某种缓存技术(内存或
memcached
):如果有缓存结果,它将提供缓存结果- 这将大大加快定期执行的查询
- 例如多人检查同一个 Grafana 仪表板
- 它将根据时间将查询分成更小的部分:例如请求多天指标的查询将被分解为请求单日结果的查询
- 这将有利于 Thanos 查询并发并减少整体延迟
Thanos Query
Thanos Query 提供了原生的 Prometheus API能力,因此它可以处理 PromQL 查询。 每个PromQL查询都将转化成 Thanos StoreAPI (gRPC
) 查询,并发送到所有其他实现 StoreAPI 的 Thanos 组件。
接着,Thanos Query 将从每个已知的“存储”中收集结果,并将重组后的 PromQL 结果发回客户端。
Thanos Sidecar
Thanos Sidecar 是与每个 Prometheus 实例一起运行的Sidecar。
它们有两个目的:
- 实现 StoreAPI:这样他们就可以应答来自 Thanos Query 的 StoreAPI 查询,并通过 Prometheus
remote_read
API 返回从 Prometheus 本地存储获取的结果。 - 他们会将 Prometheus 写入的每个数据块复制到长期long term存储中
Thanos Store Gateway
Thanos Store Gateway 也实现了 StoreAPI:它通过从long term持久化存储中获取数据来应答这些前端的查询。
根据 StoreAPI
查询参数,它可以使用原始数据或downsampled数据来提供查询结果。
为了实现跨多个副本的负载均衡,我们使用基于 relabelings 的分片功能:
- 每个 Thanos Store 副本都配置了hash在持久化存储中对应的数据块
- 每个 Thanos 存储副本只会考虑模数与自己的副本编号匹配的块
Thanos Compactor
Thanos Compactor 是一个独立的可以长期运行的组件,它用于连接到long term存储并对每个数据块执行以下操作:
- 强制数据迭代更新:Thanos Compactor 从long term存储中删除旧块
- 应用Prometheus压缩算法
- 使用downsampled数据创建新数据块:原始数据块保持原样,但使用聚合到 5m和1h时间范围的相同时间序列数据创建新数据块
Thanos Ruler
Thanos Ruler 使用与 Prometheus 相同的rule处理库(如记录和警报),但有以下区别:
- Prometheus 根据它在本地存储的本地指标制定规则
- Thanos Ruler 根据从指定的 Thanos 查询中获取的数据进行规则处理
虽然这有一些缺点(额外的复杂性、延迟和不稳定),但它也为一些问题提供了解决方案,例如:
- 在 Prometheus 实例重启期间避免基于
absent()
的警报误报 - 对来自其他集群中运行的 Prometheus 实例的指标发出警报:我们决定使用这个方案而不是直接暴露 Alertmanager 并让那些远程 Prometheus 将他们的警报发送到该服务。
从上文的架构图中看到,我们还使用多个 Thanos Ruler 实例来解决不同的问题。
Thanos Ruler Local - 集群内规则告警
自从引入 Prometheus 分片功能以来,我们在每个集群中创建本地的 Thanos Ruler 实例。 他们只能访问集群内部收集的所有指标。
这些 Thanos Ruler 可以处理 各个业务线集群创建的大部分警报,因为其中很多告警规则只需要来本地集群的数据。
理由是:
- 利用 Thanos Ruler 来简化使用 Prometheus 分片的每个集群中的警报
- 保持更高性能
- 尽可能避免跨 VPC 网络流量带来的损耗
Thanos Ruler Global - 全局规则告警
同时,一个名为Global
Thanos Ruler实例将运行在主集群中,以允许我们创建需要同时访问所有集群的警报规则。
由于此 Thanos Ruler 需要访问每个集群的每个指标,因此在创建全局规则时需要考虑到以下方面的影响:
- 延迟:Thanos 会将告警规则的 PromQL 查询发送到所有集群,即使这些集群并没有参与查询的指标。
- 成本:查询将通过 VPC 对等传输,从而产生潜在的大量网络流量
出于这些原因,强烈建议仔细检查规则是否绝对需要平台范围的指标才能工作。
一般很少有实际用例需要它:大多数时候告警规则仅限于给定的集群,即在本地 Thanos Ruler 而不是全局上运行查询。
Thanos Receive
Thanos Receive 也实现了 StoreAPI
,它充当了Thanos的一层代理中介, 使得远程的 Prometheus 可以使用 Prometheus remote_write
将其指标推送到其上。
有时出于一些原因,我们不想/不能使用 Thanos Sidecar 并授予它对持久化存储的访问权限,使用Thanos Receive可以作为 Prometheus 链接到Thanos实例的 除了Thanos Sidecar 的另一种解决方案。
Thanos Receive 将:
- 使用与本地
TSDB
相同的 Prometheus库
在本地存储那些远程集群 Prometheus 推送过来的数据 - 将这些数据块上传到持久化存储,就像 Thanos Sidecar 所做的那样
- 响应 StoreAPI 的请求,以便 Thanos Query 可以访问本地存储的数据
Grafana
Grafana 提供了基于 Prometheus 指标(和其他数据源)创建仪表板的能力。
由于 Thanos Query & Query Frontend实现了与 Prometheus 完全相同的 API:我们可以将 Grafana 链接到 Thanos ,并利用该服务在仪表板中提供指标展示。
历程:
- 之前,我们的大多数 Grafana 都以单体模式运行,没有
HA
和SQLLite
数据库的本地持久卷存储 - 最近, 我们将Grafana 升级使用专用的 PostgreSQL 数据库部署以实现
HA
Alertmanager
最后,Alertmanager 是利用 Prometheus(和 Thanos Ruler)警报并将其转化为通知的首选工具。 该组件负责将警报路由到对应的 Slack 群或 与OpsGenie 集成,使得On Call值班人员能在故障发生时或者接到告警是能及时地响应。
下篇文章,我们将具体介绍如何使用Prometheus Operator 以及Thanos helm chart 部署该监控系统到我们的集群当中。
原文关注公众号:“云原生SRE”