菜单
文档breadcrumb arrow Grafana Lokibreadcrumb arrow 管理breadcrumb arrow 区域感知 Ingister
开源

使用区域感知加快 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。无论部署方法如何,迁移都遵循几个通用步骤。

  1. 将您现有的 Ingister 配置为一个区域的一部分,例如 zone-default,这将使我们能够在允许优雅关闭的同时,稍后将它们从写入路径中排除。
  2. 通过增加允许租户使用的活动流数量,为活动流的增加(由于流在 Ingister 之间拆分的方式导致)做准备。
  3. 添加并扩展您的新的区域感知 Ingister StatefulSet,使每个 StatefulSet 都拥有您希望运行的总副本数的 1/3。
  4. 通过将 distributors 和 rulers 的 distributor.zone-awareness-enabled 设置为 true 来在写入路径上启用区域感知。
  5. 等待一段时间,确保新的区域感知 Ingister 拥有要查询的时间段的数据(query_ingesters_within)。
  6. 通过将 queriers 的 distributor.zone-awareness-enabled 设置为 true 来在读取路径上启用区域感知。
  7. 配置 distributors 和 rulers 使用 distributor.excluded-zones 排除 zone-default 中的 Ingister,以便这些 Ingister 不再接收写入流量。
  8. 使用 shutdown 端点刷新 default Ingister 中的数据,然后缩减并移除相关的 StatefulSet。
  9. 清理迁移过程中残留的任何配置。

详细迁移步骤

以下是将现有 Loki 部署从单个 Ingister StatefulSet 实时迁移(无停机)到 3 个区域感知 Ingister StatefulSet 的步骤。

这些说明假设您正在使用此仓库中的区域感知 Ingister jsonnet 部署代码,请参阅此处如果您不使用 jsonnet,请参阅某些步骤中描述如何手动执行该步骤的相关注释。

  1. 通过设置 multi_zone_default_ingester_zone: true 将现有 Ingister StatefulSet 的区域配置为 zone-default,这将使我们能够稍后从写入路径中过滤掉该区域。

  2. 将 ingester-pdb 的 maxUnavailable 配置为 0,并通过设置以下内容部署 3 个副本数为 0 的区域感知 StatefulSet

    jsonnet
    _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

  3. 对比 ingester 和 ingester-zone-a StatefulSet,并确保所有配置匹配

    bash
    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(因为容器尚不存在)。

  4. 对于当前使用超过 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", "(.+)")))
  5. 扩展区域感知 StatefulSet,直到每个 StatefulSet 拥有 1/3 的副本。在较小的单元中,您可以一次性完成,在较大的单元中,分批进行更安全。您需要更改的配置值是 multi_zone_ingester_replicas: 6,该值将分配到三个 StatefulSet。在这种情况下,每个 StatefulSet 将运行 2 个副本。

    如果您不使用 jsonnet,这一步您还需要将注释 rollout-max-unavailable 设置为一个小于或等于每个 StatefulSet 运行副本数的值。

  6. 通过设置 multi_zone_ingester_replication_write_path_enabled: true 在写入路径上启用区域感知,这将导致 distributors 和 rulers 将时间序列重新分发到每个区域的 distributors。请务必检查所有 distributors 和 rulers 是否已正确重启。

    如果您不使用 jsonnet,通过将 distributors 和 rulers 的 distributor.zone-awareness-enabled 设置为 true 来在写入路径上启用区域感知。

  7. 等待 query_ingesters_within 配置的时间。默认是 3h。这确保当我们查询一个新的 Ingister 时不会丢失数据。但是,由于我们每隔至少 30 分钟(由于 chunk_idle_period)就会切割 chunk,因此很可能可以缩短这个时间。

  8. 检查迁移后规则评估是否仍然正确,查找名称带有以下后缀的指标的速率是否增加

    rule_evaluations_total
    rule_evaluation_failures_total
    rule_group_iterations_missed_total
  9. 在读取路径上启用区域感知复制 multi_zone_ingester_replication_read_path_enabled: true。如果您不使用 jsonnet,将 queriers 的 distributor.zone-awareness-enabled 设置为 true。

  10. 检查查询是否仍在正确执行,例如查看 loki_logql_querystats_latency_seconds_count,以确定特定查询类型的延迟或错误计数没有显著增加。

  11. 通过设置 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.*"})

  12. 如果您正在使用像 flux 这样的自动化协调或部署系统,如果可能的话,现在只针对 default ingester StatefulSet 禁用它(例如使用 flux ignore)。

  13. 关闭并刷新 default ingester,将它们从环中注销,您可以通过 port-forward 每个 Ingister Pod 并使用以下端点来实现:"http://url:PORT/ingester/shutdown?flush=true&delete_ring_tokens=true&terminate=false"

  14. 手动将 default ingester StatefulSet 缩减到 0 个副本,我们通过 tk apply 来执行此操作,但您也可以通过修改 yaml 来实现。

  15. 合并一个 PR 到您的中心配置仓库,以保持 StatefulSet 为 0 个副本,然后移除 flux ignore。

  16. 清理迁移中残留的任何临时配置,例如 multi_zone_ingester_migration_enabled: true 不再需要。

  17. 确保所有旧的 default ingester PVC/PV 都已被移除。