配置 Grafana Mimir 洗牌分片
Grafana Mimir 利用分片技术,将单租户和多租户集群横向扩展,超越了单个节点的容量限制。
背景
Grafana Mimir 使用一种分片策略,将工作负载分布在运行特定组件的实例子集上。例如,在写入路径上,每个租户的序列会分片到 Ingester 的一个子集上。该子集的大小(即实例数量)通过 shard size
参数配置,默认为 0
。此默认值表示每个租户使用所有可用实例,以公平地平衡 CPU 和内存使用等资源,并最大化集群中这些资源的利用率。
在多租户集群中,此默认值 (0
) 会带来以下缺点:
- 一次中断会影响所有租户。
- 行为异常的租户(例如,导致内存不足错误的租户)会对所有其他租户产生负面影响。
将 shard size
值配置为高于 0
可启用洗牌分片。洗牌分片的目标是缩小中断的影响范围,并更好地隔离租户。
关于洗牌分片
洗牌分片是一种隔离不同租户工作负载的技术,即使它们运行在共享集群中,也能为每个租户提供单租户体验。有关 AWS 如何描述洗牌分片的更多信息,请参阅 什么是洗牌分片?。
洗牌分片为每个租户分配一个由 Grafana Mimir 实例子集组成的分片。此技术最大限度地减少了两个租户之间的重叠实例数量。洗牌分片提供以下优点:
- 某些 Grafana Mimir 集群实例或节点中断只会影响一部分租户。
- 行为异常的租户只会影响其分片实例。假设每个租户分片相对于集群中的总实例数量而言相对较小,则其他租户很可能运行在不同的实例上,或者只有一部分实例与受影响的实例匹配。
使用洗牌分片不需要更多资源,但可能导致实例负载不均衡。
低重叠实例概率
例如,在运行 50 个 Ingester 并为每个租户分配 50 个 Ingester 中的 4 个的 Grafana Mimir 集群中,通过在租户之间洗牌实例,共有 230,000 种可能的组合。
随机选择两个租户,其概率如下:
- 71% 的概率不共享任何实例
- 26% 的概率只共享 1 个实例
- 2.7% 的概率共享 2 个实例
- 0.08% 的概率共享 3 个实例
- 0.0004% 的概率实例完全重叠
Grafana Mimir 洗牌分片
Grafana Mimir 在以下组件中支持洗牌分片:
当您使用默认配置运行 Grafana Mimir 时,洗牌分片处于禁用状态,您需要通过全局或为特定租户增加分片大小来显式启用它。
注意
如果分片大小值等于或高于可用实例数量(例如,当
-distributor.ingestion-tenant-shard-size
高于 Ingester 数量时),则洗牌分片将被禁用,所有实例将再次被使用。
保证属性
Grafana Mimir 洗牌分片实现提供以下优势:
- 稳定性
给定一致的哈希环状态,洗牌分片算法总是为给定租户选择相同的实例,即使在不同的机器上也是如此。 - 一致性
从哈希环中添加或删除一个实例,最多只会导致每个租户分片中一个实例发生变化。 - 洗牌
从概率上来说,对于足够大的集群,洗牌分片可确保每个租户获得一组不同的实例,并且两个租户之间的重叠实例数量减少,从而提高了故障隔离能力。 - 区域感知
当您启用区域感知复制时,为每个租户选择的实例子集将包含每个可用区的平衡数量的实例。
Ingesters 洗牌分片
默认情况下,Grafana Mimir distributor 会将接收到的序列分配给所有正在运行的 Ingester。
当您启用 Ingester 洗牌分片时,写入路径上的 distributor 和 ruler 会将每个租户序列分配给 -distributor.ingestion-tenant-shard-size
数量的 Ingester;而在读取路径上,querier 和 ruler 只查询持有给定租户序列的 Ingester 子集。
可以通过在运行时配置的 overrides 部分设置 ingestion_tenant_shard_size
来按租户覆盖分片大小。
Ingesters 写入路径
要在写入路径上为 Ingester 启用洗牌分片,请在 distributor、ingester 和 ruler 上配置以下标志(或其相应的 YAML 配置选项):
-distributor.ingestion-tenant-shard-size=<size>
<size>
: 将大小设置为每个租户序列应分片到的 Ingester 数量。如果<size>
为0
或大于 Grafana Mimir 集群中可用 Ingester 的数量,则租户序列将分片到所有 Ingester 上。
Ingesters 读取路径
假设您已启用写入路径的洗牌分片,要在读取路径上为 Ingester 启用洗牌分片,请在 querier 和 ruler 上配置以下标志(或其相应的 YAML 配置选项):
-distributor.ingestion-tenant-shard-size=<size>
以下标志默认已设置为适当值,以在读取路径上为 Ingester 启用洗牌分片。如果您需要修改其默认值:
-querier.shuffle-sharding-ingesters-enabled=true
读取路径上 Ingester 的洗牌分片可以显式启用或禁用。- 如果启用洗牌分片,querier 和 ruler 会从最少必需的 Ingester 子集中获取内存中的序列,仅选择可能在当前时间减去
-blocks-storage.tsdb.retention-period
时间段内接收到序列的 Ingester。否则,请求将发送到所有 Ingester。
- 如果启用洗牌分片,querier 和 ruler 会从最少必需的 Ingester 子集中获取内存中的序列,仅选择可能在当前时间减去
如果您仅在写入路径上启用 Ingester 洗牌分片,则读取路径上的 querier 和 ruler 始终会查询所有 Ingester,而不是查询属于租户分片的 Ingester 子集。仅在写入路径上启用 Ingester 洗牌分片不会导致查询结果不正确,但可能会增加查询延迟。
上线策略
如果您正在运行一个禁用洗牌分片的 Grafana Mimir 集群,并想为 Ingester 启用它,请使用以下上线策略,以避免遗漏当前在 Ingester 中的任何序列查询:
- 通过
-querier.shuffle-sharding-ingesters-enabled=false
显式禁用读取路径上的 Ingester 洗牌分片,因为此选项默认是启用的。 - 在写入路径上启用 Ingester 洗牌分片。
- 等待至少通过
-blocks-storage.tsdb.retention-period
指定的时间长度。 - 通过
-querier.shuffle-sharding-ingesters-enabled=true
重新启用读取路径上的 Ingester 洗牌分片。
限制:减小租户分片大小
当前 Grafana Mimir 中的洗牌分片实现在您启用读取路径上的 Ingester 洗牌分片时存在一个限制,阻止您安全地减小租户分片大小。
如果租户的分片大小减小,querier 和 ruler 当前无法知道租户分片之前的大小,因此它们可能会遗漏包含该租户数据的 Ingester。blocks-storage.tsdb.retention-period 用于选择可能在“当前时间减去 blocks-storage.tsdb.retention-period”时间段内接收到序列的 Ingester,如果租户分片大小减小,则此参数在查找租户分片时无法正常工作。
虽然不支持减小租户分片大小,但请考虑以下变通方法:
- 通过
-querier.shuffle-sharding-ingesters-enabled=false
禁用读取路径上的洗牌分片。 - 减小配置的租户分片大小。
- 等待至少通过
-blocks-storage.tsdb.retention-period
指定的时间长度。 - 通过
-querier.shuffle-sharding-ingesters-enabled=true
重新启用读取路径上的洗牌分片。
Query-frontend 和 query-scheduler 洗牌分片
默认情况下,所有 Grafana Mimir querier 都可以执行任何租户的查询。
当您通过将 -query-frontend.max-queriers-per-tenant
(或其相应的 YAML 配置选项)设置为大于 0
且小于可用 querier 数量的值来启用洗牌分片时,只有指定数量的 querier 有资格执行给定租户的查询。
请注意,此分发发生在 query-frontend 中,如果使用了 query-scheduler,则发生在 query-scheduler 中。使用 query-scheduler 时,必须为 query-scheduler 组件设置 -query-frontend.max-queriers-per-tenant
选项。当您不使用 query-frontend 时(无论是否使用 query-scheduler),此选项不可用。
您可以通过在运行时配置的 overrides 部分设置 max_queriers_per_tenant
来按租户覆盖最大 querier 数量。
“死亡查询”的影响
如果租户发送导致 querier 崩溃的“死亡查询”,崩溃的 querier 将与 query-frontend 或 query-scheduler 断开连接,并且另一个正在运行的 querier 将立即分配给该租户的分片。
如果租户重复发送此查询,分配给租户分片的新 querier 也会崩溃,然后又有一个 querier 被分配给该分片。这种连锁故障可能导致所有正在运行的 querier 逐个崩溃,从而否定了洗牌分片能够限制死亡查询影响范围的假设。
为了减轻这种负面影响,有一些实验性配置选项允许您配置 querier 因崩溃断开连接与崩溃的 querier 被正常 querier 替换之间的时间延迟。配置时间延迟后,重复发送“死亡查询”的租户在 querier 崩溃后将以降低的 querier 容量运行。租户最终可能会没有可用的 querier,但此配置减少了崩溃影响其他租户的可能性。
延迟 1 分钟可能是合理的权衡:
- Query-frontend:
-query-frontend.querier-forget-delay=1m
- Query-scheduler:
-query-scheduler.querier-forget-delay=1m
Store-gateway 洗牌分片
默认情况下,租户的块会分配给所有 Grafana Mimir store-gateway。
当您通过将 -store-gateway.tenant-shard-size
(或其相应的 YAML 配置选项)设置为大于 0
且小于可用 store-gateway 数量的值来启用 store-gateway 洗牌分片时,只有指定数量的 store-gateway 有资格为给定租户加载和查询块。您必须在 store-gateway、querier 和 ruler 上设置此标志。
您可以通过在运行时配置的 overrides 部分设置 store_gateway_tenant_shard_size
来按租户覆盖 store-gateway 分片大小。
有关 store-gateway 的更多信息,请参阅 store-gateway。
Ruler 洗牌分片
默认情况下,租户规则组由所有 Grafana Mimir ruler 分片。
当您通过将 -ruler.tenant-shard-size
(或其相应的 YAML 配置选项)设置为大于 0
且小于可用 ruler 数量的值来启用 ruler 洗牌分片时,只有指定数量的 ruler 有资格评估给定租户的规则组。
您可以通过在运行时配置的 overrides 部分设置 ruler_tenant_shard_size
来按租户覆盖 ruler 分片大小。
Compactor 洗牌分片
默认情况下,租户块可以由任何 Grafana Mimir compactor 进行压缩。
当您通过将 -compactor.compactor-tenant-shard-size
(或其相应的 YAML 配置选项)设置为大于 0
且小于可用 compactor 数量的值来启用 compactor 洗牌分片时,只有指定数量的 compactor 有资格压缩给定租户的块。
您可以通过在运行时配置的 overrides 部分设置 compactor_tenant_shard_size
来按租户覆盖 compactor 分片大小。
Alertmanager 洗牌分片
Alertmanager 只会按租户在副本之间执行分发。状态和工作负载不会进一步划分。复制因子设置 -alertmanager.sharding-ring.replication-factor
决定了用于一个租户的副本数量。
因此,对于 Alertmanager 而言,洗牌分片实际上始终是启用的。
洗牌分片对 KV 存储的影响
洗牌分片不会给 KV 存储带来额外的开销。分片是在客户端计算的,不会存储在环中。KV 存储的大小主要取决于使用环的任何组件(例如 Ingester)的副本数量以及每个副本的 Token 数量。
但是,在某些组件中,每个租户的分片会在客户端缓存到内存中,这可能会略微增加它们的内存占用。内存占用的增加主要可能发生在 distributor 中。