使用区域感知加快 Ingister 部署
Grafana Labs 使用 Loki 区域感知 Ingister 来更轻松地推出大型 Loki 部署。您可以将它们视为三个逻辑区域,但是通过一些额外的 Kubernetes 配置,您可以将它们部署在独立的区域中。
默认情况下,传入日志流的日志会复制到 3 个随机的 Ingister。除了副本扩缩容的情况外,给定流始终会复制到相同的 3 个 Ingister。这意味着如果其中一个 Ingister 重启,不会丢失数据。但是,两个或多个 Ingister 同时重启可能会导致数据丢失,并且由于环状态不健康而影响系统摄取日志的能力。
启用区域感知后,传入的日志行将复制到每个区域的一个 Ingister。这意味着我们不仅无需担心多个区域中的 Ingister 同时重启,现在还可以一次性推出或丢失整个区域,而不会影响写入。这使得拥有大量 Ingister 的部署能够更快地推出。
在 Grafana Labs,我们还利用 rollout-operator 来优雅地管理对 3 个 StatefulSet 的部署。rollout-operator 会查找 StatefulSet 上的标签以了解哪些 StatefulSet 属于某个部署组,并协调每次只从组中的单个 StatefulSet 部署 Pod。有关更深入的解释,请参阅 rollout-operator 仓库中的 README。
迁移
从单个 Ingister StatefulSet 迁移到 3 个区域感知 Ingister StatefulSet。无论部署方法如何,迁移都遵循几个通用步骤。
- 将您现有的 Ingister 配置为一个区域的一部分,例如
zone-default
,这将使我们能够在允许优雅关闭的同时,稍后将它们从写入路径中排除。 - 通过增加允许租户使用的活动流数量,为活动流的增加(由于流在 Ingister 之间拆分的方式导致)做准备。
- 添加并扩展您的新的区域感知 Ingister StatefulSet,使每个 StatefulSet 都拥有您希望运行的总副本数的 1/3。
- 通过将 distributors 和 rulers 的
distributor.zone-awareness-enabled
设置为true
来在写入路径上启用区域感知。 - 等待一段时间,确保新的区域感知 Ingister 拥有要查询的时间段的数据(
query_ingesters_within
)。 - 通过将 queriers 的
distributor.zone-awareness-enabled
设置为 true 来在读取路径上启用区域感知。 - 配置 distributors 和 rulers 使用
distributor.excluded-zones
排除zone-default
中的 Ingister,以便这些 Ingister 不再接收写入流量。 - 使用 shutdown 端点刷新 default Ingister 中的数据,然后缩减并移除相关的 StatefulSet。
- 清理迁移过程中残留的任何配置。
详细迁移步骤
以下是将现有 Loki 部署从单个 Ingister StatefulSet 实时迁移(无停机)到 3 个区域感知 Ingister StatefulSet 的步骤。
这些说明假设您正在使用此仓库中的区域感知 Ingister jsonnet 部署代码,请参阅此处。如果您不使用 jsonnet,请参阅某些步骤中描述如何手动执行该步骤的相关注释。
通过设置
multi_zone_default_ingester_zone: true
将现有 Ingister StatefulSet 的区域配置为zone-default
,这将使我们能够稍后从写入路径中过滤掉该区域。将 ingester-pdb 的
maxUnavailable
配置为 0,并通过设置以下内容部署 3 个副本数为 0 的区域感知 StatefulSet_config+:: { multi_zone_ingester_enabled: true, multi_zone_ingester_migration_enabled: true, multi_zone_ingester_replicas: 0, // These last two lines are necessary now that we enable zone aware ingester by default // so that newly created cells will not be migrated later on. If you miss them you will // break writes in the cell. multi_zone_ingester_replication_write_path_enabled: false, multi_zone_ingester_replication_read_path_enabled: false, },
如果您不使用 jsonnet,新的 Ingister StatefulSet 应该有一个标签
rollout-group: ingester
,注释rollout-max-unavailable: x
(此处放置一个占位符值,之后您应该将其值设置为 StatefulSet 总副本数的某个比例,例如在 jsonnet 中,我们将其模板化,使得每个 StatefulSet 运行总副本数的 1/3,并且最大不可用副本数是每个 StatefulSet 副本数的 1/3),并将更新策略设置为OnDelete
。对比 ingester 和 ingester-zone-a StatefulSet,并确保所有配置匹配
kubectl get statefulset -n loki-dev-008 ingester -o yaml > ingester.yaml kubectl get statefulset -n loki-dev-008 ingester-zone-a -o yaml > ingester-zone-a.yaml diff ingester.yaml ingester-zone-a.yaml
在 diff 中预期会出现以下值:创建时间和修订号、区域、rollout operator 使用的字段、副本数、与 kustomize/flux 相关的任何内容,以及 WAL 的 PVC(因为容器尚不存在)。
对于当前使用超过 50% 限制的用户,临时将最大时间序列限制翻倍,查询如下所示(酌情添加标签选择器)
sum by (tenant)(sum (loki_ingester_memory_streams) by (cluster, namespace, tenant) / on (namespace) group_left max by(namespace) (loki_distributor_replication_factor)) > on (tenant) ( max by (tenant) (label_replace(loki_overrides{limit_name="max_global_streams_per_user"} / 2.5, "tenant", "$1", "user", "(.+)")) )
(sum (loki_ingester_memory_streams) by (cluster, namespace, tenant) / on (namespace) group_left max by(namespace) (loki_distributor_replication_factor) ) / ignoring(tenant) group_left max by (cluster, namespace)(loki_overrides_defaults{limit_name="max_global_streams_per_user"}) > 0.4) unless on (tenant) ( (label_replace(loki_overrides{limit_name="max_global_streams_per_user"},"tenant", "$1", "user", "(.+)")))
扩展区域感知 StatefulSet,直到每个 StatefulSet 拥有 1/3 的副本。在较小的单元中,您可以一次性完成,在较大的单元中,分批进行更安全。您需要更改的配置值是
multi_zone_ingester_replicas: 6
,该值将分配到三个 StatefulSet。在这种情况下,每个 StatefulSet 将运行 2 个副本。如果您不使用 jsonnet,这一步您还需要将注释
rollout-max-unavailable
设置为一个小于或等于每个 StatefulSet 运行副本数的值。通过设置
multi_zone_ingester_replication_write_path_enabled: true
在写入路径上启用区域感知,这将导致 distributors 和 rulers 将时间序列重新分发到每个区域的 distributors。请务必检查所有 distributors 和 rulers 是否已正确重启。如果您不使用 jsonnet,通过将 distributors 和 rulers 的
distributor.zone-awareness-enabled
设置为 true 来在写入路径上启用区域感知。等待
query_ingesters_within
配置的时间。默认是3h
。这确保当我们查询一个新的 Ingister 时不会丢失数据。但是,由于我们每隔至少 30 分钟(由于chunk_idle_period
)就会切割 chunk,因此很可能可以缩短这个时间。检查迁移后规则评估是否仍然正确,查找名称带有以下后缀的指标的速率是否增加
rule_evaluations_total rule_evaluation_failures_total rule_group_iterations_missed_total
在读取路径上启用区域感知复制
multi_zone_ingester_replication_read_path_enabled: true
。如果您不使用 jsonnet,将 queriers 的distributor.zone-awareness-enabled
设置为 true。检查查询是否仍在正确执行,例如查看
loki_logql_querystats_latency_seconds_count
,以确定特定查询类型的延迟或错误计数没有显著增加。通过设置
multi_zone_ingester_exclude_default: true
配置 distributor/ruler 排除zone-default
中的 Ingister,以便这些 Ingister 不再接收写入流量。如果您不使用 jsonnet,请在 distributors 和 rulers 上设置distributor.excluded-zones
。此时最好再次检查规则评估,并确认区域感知 Ingister StatefulSet 现在正在接收所有写入流量,您可以比较
sum(loki_ingester_memory_streams{cluster="<cluster>",job=~"(<namespace>)/ingester"})
和sum(loki_ingester_memory_streams{cluster="<cluster>",job=~"(<namespace>)/ingester-zone.*"})
如果您正在使用像 flux 这样的自动化协调或部署系统,如果可能的话,现在只针对 default ingester StatefulSet 禁用它(例如使用 flux ignore)。
关闭并刷新 default ingester,将它们从环中注销,您可以通过 port-forward 每个 Ingister Pod 并使用以下端点来实现:
"http://url:PORT/ingester/shutdown?flush=true&delete_ring_tokens=true&terminate=false"
手动将 default ingester StatefulSet 缩减到 0 个副本,我们通过
tk apply
来执行此操作,但您也可以通过修改 yaml 来实现。合并一个 PR 到您的中心配置仓库,以保持 StatefulSet 为 0 个副本,然后移除 flux ignore。
清理迁移中残留的任何临时配置,例如
multi_zone_ingester_migration_enabled: true
不再需要。确保所有旧的 default ingester PVC/PV 都已被移除。