下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

如何使用 KEDA 自动缩放 Grafana Loki Queries

作者:匿名     来源: 云计算点击数:293发布时间: 2022-11-25 15:17:54

标签: KEDA自动缩放云平台

  为了验证我们的实现是否满足我们在真实场景中的需求,我们在内部环境中部署了自动缩放器。到目前为止,我们已经在 k6 创建所有工作负载的隔离环境中进行了实验。接下来,我们必须估计最大和最小副本数的适当值。

  介绍

  Grafana Loki (https://grafana.com/oss/loki/?pg=blog&plcmt=body-txt) 是 Grafana Labs 的开源日志聚合系统,灵感来自 Prometheus(https://prometheus.io/) 。Loki 具有水平可扩展性、高可用性和多租户特性。

  Grafana Cloud 大规模运营 Grafana Cloud Logs,集群分布在不同的区域和云平台,如 AWS、Microsoft Azure 和 Google Cloud。Grafana Cloud 每天还摄取数百 TB 的数据,并在数千个租户中查询数 PB 的数据。最重要的是,每天数据查询与处理过程中,资源消耗都会有很大的波动,这使得以对用户响应且对 Grafana Cloud 来说具有成本效益的方式手动扩展集群变得非常困难。

  在这篇博客中,我们将描述 Grafana Labs 的工程师如何使用基于 Kubernetes 的事件驱动自动缩放器 ( KEDA(https://keda.sh/) ) 来更好地处理后端的 Loki 查询。

  为什么我们需要 autoscaling

  负责处理 Grafana Cloud Logs 查询的 Loki 读取路径组件之一是 querier,它是将 LogQL(https://grafana.com/docs/loki/latest/logql/?pg=blog&plcmt=body-txt) 查询与日志匹配的组件。可以想象,我们需要很多 querier 来实现如此高的吞吐量。但是,由于我们的集群全天工作负载发生重大变化,这种需求会发生波动。直到最近,我们还是根据工作负载手动扩展 querier,但这种方法存在三个主要问题。

  1、它会适当地扩展 querier 以响应工作量的增加。

  2、我们可能会过度配置集群并使 querier 闲置一段时间。

  3、这会导致操作繁琐 (https://sre.google/sre-book/eliminating-toil/) ,因为我们必须手动上下扩展 querier。

  为了克服这些问题,我们决定在 Kubernetes 中的 querier 部署中添加自动缩放功能。

  为什么选择 KEDA

  Kubernetes 附带了一个用于水平自动缩放 Pod 的内置解决方案:HorizontalPodAutoscaler ( HPA)。您可以使用 HPA 根据来自 Kubernetes metrics-server(https://kubernetes.io/docs/tasks/debug-application-cluster/resource-metrics-pipeline/#metrics-server) 的指标为 StatefulSets 和 Deployments 等组件配置自动缩放。metrics-server 公开 pod 的 CPU 和内存使用情况,但如果需要,您可以为其提供更多指标。

  CPU 和内存使用指标通常足以决定何时扩大或缩小规模,但可能还有其他指标或事件需要考虑。在我们的案例中,我们对基于一些 Prometheus 指标的扩展感兴趣。从 Kubernetes 1.23 开始,HPA 已经支持外部指标(https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#scaling-on-custom-metrics) ,所以我们可以选择一个 Prometheus adapter 来根据 Prometheus 指标进行扩展。然而,KEDA 使这变得更加容易。

  KEDA 是最初由 Microsoft 和 Red Hat 开发的开源项目,我们已经在内部将它用于与Grafana Mimir(https://grafana.com/oss/mimir/?pg=blog&plcmt=body-txt) 类似的用例。除了熟悉之外,我们之所以选择它,是因为它更成熟,而且它允许根据来自不同来源(例如 Prometheus)的事件和指标扩展任何 Pod。KEDA 构建在 HPA 之上,并公开了一个新的 Kubernetes 指标服务器,该服务器为 KEDA 创建的 HPA 提供新指标。

  我们如何在 queriers 上使用 KEDA

  Queriers 从查询调度程序队列中提取查询并在所有 querier 上处理它们。因此,根据以下条件进行扩展是有意义的:

  •   调度程序队列大小
  •   在 querier 中运行的查询

  最重要的是,我们希望避免因短期工作负载高峰而扩大规模。在这些情况下,查询可能会比扩展所需的时间更快地处理工作负载。

  考虑到这一点,我们根据排队查询的数量加上正在运行的查询进行扩展。我们称这些为 inflight requests。查询调度程序组件将公开一个新指标 ,cortex_query_scheduler_inflight_requests 指标结果使用百分比(https://grafana.com/blog/2022/03/01/how-summary-metrics-work-in-prometheus/?pg=blog&plcmt=body-txt) 跟踪正在进行的请求。通过使用百分比,我们可以避免在指标出现短期峰值时进行扩容。

  使用结果度量,我们可以在查询中使用分位数 (Q) 和范围 (R) 参数来微调我们的缩放。Q 越高,指标对短期尖峰越敏感。随着 R 的增加,我们会随着时间的推移减少度量变化。较高的 R 值有助于防止自动缩放器过于频繁地修改副本数量。

  复制

  1.  sum(

  2.  max_over_time(

  3.  cortex_query_scheduler_inflight_requests{namespace="%s", quantile=""}[]

  4.  )

  5.  )

  然后我们需要设置一个阈值,以便我们可以根据度量值计算所需的副本数。Querier 程序处理来自队列的查询,每个 querier 配置为运行六个 worker。我们希望为高峰留出一些富余处理空间,因此我们的目标是使用这些 worker 中的 75%。因此,我们的门槛将是每个 querier 6 个 worker 的 75%,即 4 个 worker。

  这个等式定义了当前副本中所需的副本数、度量值以及我们配置的阈值:

  复制

  1.  desiredReplicas = ceil[currentReplicas * ( currentMetricValue / threshold )]

  例如,如果我们有一个副本和 20 个正在进行的请求,并且我们的目标是使用每个 worker 可用的六个 worker 中的 75%(四个),那么新的所需副本数量将是五个。

  复制

  1.  desiredReplicas = ceil[1 * (20 / 4)] = 5

  考虑到这一点,我们现在可以创建 KEDA ScaledObject 来控制查询器的自动缩放。以下资源定义将 KEDA 配置为从 http://prometheus.default:9090/prometheus 提取指标。它还可以扩展到最大 50 个 querier,缩小到最小 10 个 querier,将 75% 用于 inflight requests 指标,并在两分钟内聚合其最大值。扩展阈值仍然是每个 querier 四个 worker。

  复制

  1.  apiVersion: keda.sh/v1alpha1

  2.  kind: ScaledObject

  3.  metadata:

  4.  name: querier

  5.  namespace:

  6.  spec:

  7.  maxReplicaCount: 50

  8.  minReplicaCount: 10

  9.  pollingInterval: 30

  10.  scaleTargetRef:

  11.  kind: Deployment

  12.  name: querier

  13.  triggers:

  14.  - metadata:

  15.  metricName: querier_autoscaling_metric

  16.  query: sum(max_over_time(cortex_query_scheduler_inflight_requests{namespace=~"REDACTED", quantile="0.75"}[2m]))

  17.  serverAddress: http://prometheus.default:9090/prometheus

  18.  threshold: "4"

  19.  type: prometheus

  使用 Grafana k6 Cloud 进行测试

  在部署到我们的内部和生产环境之前,我们进行了多次实验和基准测试来验证。

  Grafana k6 Cloud 是 Grafana k6 的完全托管版本,它是一个免费、开源、以开发人员为中心且可扩展的负载测试工具,可让工程团队轻松进行性能测试。

  使用 k6 的 Grafana Loki 扩展(https://grafana.com/blog/2022/06/08/a-quick-guide-to-load-testing-grafana-loki-with-grafana-k6/?pg=blog&plcmt=body-txt) ,我们创建了一个 k6 测试 (https://gist.github.com/salvacorts/7f6fe8e53dcbdfc38606f3892918cfcc) ,该测试迭代地从多个虚拟用户(VU;有效的运行线程)向 Loki 开发集群发送不同类型的查询。我们尝试使用以下序列模拟真实的可变流量:

  1、在两分钟内,将 VU 从 5 个增加到 50 个。

  2、用 50 个 VU 保持一分钟。

  3、在 30 秒内从 50 个 VU 增加到 100 个 VU,并在另外 30 秒内增加到 50 个,以创建工作负载峰值。

  4、重复上一个尖峰。

  5、最后,在两分钟内从 50 个 VU 变为零。

  在下图中,我们可以看到测试在 k6 Cloud 中的表现,以及在测试期间进行中的请求和查询器副本的数量如何变化。首先,querier 会随着工作负载的增加而扩大,最后,querier 会在测试完成几分钟后回退。

  一个 Grafana k6 Cloud 测试,它迭代地将不同类型的查询发送到 Grafana Loki 开发集群。

  随着 inflight request 数量的增加(顶部),querier 的数量增加(底部)。在工作负载减少后的某个时间,querier 的数量也会减少。

  一旦我们确认我们的方法按预期工作,下一步就是在一些实际工作负载上进行尝试。

  部署和微调

  为了验证我们的实现是否满足我们在真实场景中的需求,我们在内部环境中部署了自动缩放器。到目前为止,我们已经在 k6 创建所有工作负载的隔离环境中进行了实验。接下来,我们必须估计最大和最小副本数的适当值。

  对于最小副本数,我们在前 7 天 75% 的时间内检查了平均 inflight request,目标是 querier 的利用率为 75%。

  复制

  1.  clamp_min(ceil(

  2.  avg(

  3.  avg_over_time(cortex_query_scheduler_inflight_requests{namespace=~"REDACTED", quantile="0.75"}[7d])

  4.  ) / scalar(floor(vector(6 * 0.75)))

  5.  ), 2)

  对于最大副本数,我们将当前副本数与在前 7 天内处理 50% 的 inflight request 所需的查询器数相结合。由于每个 querier 运行六个 worker,我们将 inflight 中的请求除以六。

  复制

  1.  clamp_min(ceil(

  2.  (

  3.  max(

  4.  max_over_time(cortex_query_scheduler_inflight_requests{namespace=~"REDACTED", quantile="0.5"}[7d])

  5.  ) / 6

  6.  >

  7.  max (kube_deployment_spec_replicas{namespace=~"REDACTED", deployment="querier"})

  8.  )

  9.  or

  10.  max(

  11.  kube_deployment_spec_replicas{namespace=~"REDACTED", deployment="querier"}

  12.  )

  13.  ), 20)

  在估计了最小和最大副本的一些数字后,我们在内部环境中部署了自动缩放器。如下图所示,我们实现了预期的结果:querier 随着工作负载的增加而扩大,在工作负载减少后缩小。

  随着我们部署中 inflight request 数量的增加(顶部),querier 的数量增加(底部)。当 worker 减少时,querier 的数量也会减少。

  您可能已经注意到由于缩放指标值的不断变化,副本数量的频繁波动(也称为抖动)(https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#flapping) 。如果您在扩展大量 pod 后过早缩减它们,最终会消耗 Kubernetes 中的大量资源来调度 pod。此外,它可能会影响查询延迟,因为我们需要经常启动新的 querier 来处理这些查询。幸运的是,HPA 提供了一种机制来配置稳定窗口(https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#stabilization-window) 以减轻这些频繁的波动,正如您可能已经猜到的那样,KEDA 也是如此。spec.advanced.horizontalPodAutoscalerConfig.behavior.scaleDown.stabilizationWindowSeconds参数允许您在 0 秒(立即缩放)和 3,600 秒(一小时)之间配置冷却时间,默认值为 300 秒(五分钟)。该算法很简单:我们使用一个跨越配置时间的滑动窗口,并将副本数设置为该时间范围内报告的最高数量。在我们的例子中,我们配置了一个 30 分钟的稳定窗口:

  复制

  1.  spec:

  2.  advanced:

  3.  horizontalPodAutoscalerConfig:

  4.  behavior:

  5.  scaleDown:

  6.  stabilizationWindowSeconds: 1800

  下图显示了图表的形状现在在副本数量方面如何更加统一。在某些情况下,querier 在缩小后不久就会扩大规模,但总会有边缘情况发生这种情况。我们仍然需要为这个参数找到一个适合我们工作负载形状的好值,但总的来说,我们可以看到峰值更少。

  配置稳定窗口后,与上图相似的工作负载相比,副本数量波动较小。

  即使我们配置的最大副本数比手动扩展 Loki 时要高得多,但添加自动扩展程序后的平均副本数会更低。较低的平均副本数转化为较低的查询器部署的拥有成本。

  启用查询器自动缩放器后,集群中运行的平均副本数减少了。

  此外,我们可以看到自动缩放器没有出现查询延迟下降的问题。下图显示了 7 月 21 日 12:00 UTC 在启用自动缩放之前和之后的查询和范围查询的 p90 延迟(以秒为单位)。

  启用查询器自动缩放器后,查询延迟并没有变差。

  最后,我们需要一种方法来知道何时增加我们的最大副本数。为此,我们创建了一个警报,当自动缩放器长时间以配置的最大副本数运行时触发。以下代码片段包含此指标,如果它在至少三个小时内输出为 true,则会触发。

  复制

  1.  name: LokiAutoscalerMaxedOut

  2.  expr: kube_horizontalpodautoscaler_status_current_replicas{namespace=~"REDACTED"} == kube_horizontalpodautoscaler_spec_max_replicas{namespace=~"REDACTED"}

  3.  for: 3h

  4.  labels:

  5.  severity: warning

  6.  annotations:

  7.  description: HPA {{ $labels.namespace }}/{{ $labels.horizontalpodautoscaler }} has been running at max replicas for longer than 3h; this can indicate underprovisioning.

  8.  summary: HPA has been running at max replicas for an extended time

  来源: 新钛云服

    >>>>>>点击进入计算专题

赞(11)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程