Loki 如何用 KEDA 基于调度器队列指标自动伸缩 Querier?
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
Loki 的 querier 会整天面对波动明显的查询负载。如果你的 Loki 以 microservices 模式部署在 Kubernetes 上(且启用了 query-scheduler),可以用 KEDA 监听调度器的队列指标来自动伸缩 querier 副本数,让查询高峰期有足够 worker 消费队列,低谷期又不会白占资源。前提条件有三个:
- Loki 以一组 microservices 的形式运行在 Kubernetes 中;
- 使用了 query-scheduler(querier 从它的队列里拉取查询);
- 集群中已部署 KEDA(Kubernetes Event-Driven Autoscaling),Loki 官方推荐用 KEDA 基于 Prometheus 指标做自动伸缩。
注意 KEDA 本身的安装部署是 KEDA 项目的文档范畴,本文不展开。
伸缩依据:loki_query_scheduler_inflight_requests
因为查询是从 query-scheduler 的队列里拉取后在 querier worker 上执行的,所以伸缩指标应基于两点:调度器队列里排队的查询数,加上 querier worker 中正在执行的查询数。query-scheduler 暴露的loki_query_scheduler_inflight_requests指标正好把这两者加在一起追踪。
文档给出的伸缩查询是:
sum( max_over_time( loki_query_scheduler_inflight_requests{namespace="loki-cluster", quantile="<Q>"}[<R>] ) )其中<Q>和<R>是需要按你的负载微调的参数:
- Q 是取哪个分位数。Q 越高,指标对短时尖峰越敏感。
- R 是回溯窗口(range)。R 越大,指标随时间波动越小,能避免 autoscaler 过于频繁地调整副本数。
Loki 文档建议 Q 取 0.75、R 取 2 分钟。有两个约束需要注意:
- 该指标只暴露固定的分位数值:
0.5、0.75、0.8、0.9、0.95、0.99。查询其他分位值时 Prometheus 不返回任何数据,Q 必须从这份列表里选。 - 指标本身在被 Prometheus 抓取前已经在一个 60 秒的滑动窗口上做过平滑,所以 R 小于约一分钟几乎没有额外平滑效果。文档建议 R 保持一分钟或更高。
容量规划:确定副本数上下限和阈值
配置伸缩前需要定四个值:伸缩上下限的阈值、缩容稳定期、querier 副本数的最小值和最大值。
先确定单个 querier 的 worker 数。querier worker 处理队列中的查询,每个 querier 可以用-querier.max-concurrent标志(YAML 配置里是max_concurrent)设置 worker 数,默认值是4。文档建议为了留出应对负载尖峰的余量,不要使用超过 75% 的 worker,伸缩阈值相应设置为floor(0.75 * worker数)。例如每个 querier 配置 6 个 worker,阈值就是floor(0.75 * 6) = 4。
这里有一个容易踩坑的细节:-querier.max-concurrent设置的是 querier 的 worker 总数,但 querier 会把 worker 分摊到它连接的各个 query-scheduler(或 query-frontend)上。如果配置值小于 querier 连接的 query-scheduler 数量,每条连接至少分到一个 worker,实际 worker 数会高于配置值。所以在计算阈值之前,先用loki_querier_worker_concurrency指标确认实际 worker 数。
再确定最小副本数。至少运行一个 querier,算出系统 75% 的时间内处理 inflight 请求的七天均值;查询目标利用率是 75%。沿用每个 querier 6 个 worker 的例子,查询为:
clamp_min(ceil( avg( avg_over_time(loki_query_scheduler_inflight_requests{namespace="loki-cluster", quantile="0.75"}[7d]) ) / scalar(floor(vector(6 * 0.75))) ), 1)然后确定最大副本数。最大副本数等于在七天内 50% 的时间里处理全部 inflight 请求所需的 querier 数,同样按每个 querier 6 个 worker 计算:
ceil( max( max_over_time(loki_query_scheduler_inflight_requests{namespace="loki-cluster", quantile="0.5"}[7d]) ) / 6 )最后设置缩容稳定窗口,尽量避免 Loki 刚缩容就紧接着扩容。
配置 KEDA:Helm chart 路径或手写 ScaledObject
用 Helm chart 部署 Loki:让 chart 生成 ScaledObject
如果你用 Helm chart 部署 Loki,不需要自己写 KEDA ScaledObject。chart 可以替你生成一个,querier.kedaAutoscaling的默认值已经是一个基于loki_query_scheduler_inflight_requests的 Prometheus 触发器,默认 Q 为 0.75、R 为 2 分钟,且默认阈值threshold为"4"(即按 6 个 worker、75% 利用率计算的值)。
需要做的是:
- 将
querier.kedaAutoscaling.enabled设为true; - 按你的容量规划结果设置
minReplicas和maxReplicas(chart 默认最小 1、最大 10,需要按上面的 7 天查询结果覆盖); - 设置
defaults.kedaAutoscaling.prometheusAddress为你的 Prometheus 服务地址。这一项默认为空,不设置的话触发器无法查询到指标; - 如果想替换默认触发器,设置
querier.kedaAutoscaling.triggers。
完整的 values 列表见仓库内 Helm reference 文档 docs/sources/setup/install/helm/reference.md,其中querier.kedaAutoscaling一段还包含behavior(对应 ScaledObject 的horizontalPodAutoscalerConfig.behavior)、cooldownPeriod、fallback、pollingInterval等可调项;defaults.kedaAutoscaling下另有customHeaders(多租户场景可用来带X-Scope-OrgID)、unsafeSsl、ignoreNullValues、authentication等字段。
另外注意kedaAutoscaling.enabled与autoscaling.enabled互斥,两者只能启用其一。
不用 Helm chart:手写 ScaledObject
不使用 Helm chart,或需要 chart 不支持的触发器时,自己写ScaledObject。下面这个示例把自动伸缩配置在loki-cluster命名空间的 querier Deployment 上,最小副本 10、最大副本 50。每个 querier 运行 6 个 worker,目标是用掉 75%,所以阈值设为 4;指标从http://prometheus.default:9090/prometheus获取,并配置了 30 分钟的缩容稳定窗口:
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: querier namespace: loki-cluster spec: maxReplicaCount: 50 minReplicaCount: 10 scaleTargetRef: kind: Deployment name: querier triggers: - metadata: metricName: querier_autoscaling_metric query: sum(max_over_time(loki_query_scheduler_inflight_requests{namespace="loki-cluster", quantile="0.75"}[2m])) serverAddress: http://prometheus.default:9090/prometheus threshold: "4" type: prometheus advanced: horizontalPodAutoscalerConfig: behavior: scaleDown: stabilizationWindowSeconds: 1800按你自己的部署替换其中的命名空间、Deployment 名、Prometheus 地址、副本数上下限和阈值,其余结构与文档示例一致。
验证与容量告警:副本数长期打满时报警
伸缩生效与否可以从 HPA 状态判断:配置的副本数上限可能不够用,所以文档给出一条 Prometheus 告警,用来识别 querier 副本数在配置的最大值上停留过久的情况。示例把“过久”定为 3 小时(3h):
name: LokiAutoscalerMaxedOut expr: kube_horizontalpodautoscaler_status_current_replicas{namespace=~"loki-cluster"} == kube_horizontalpodautoscaler_spec_max_replicas{namespace=~"loki-cluster"} for: 3h labels: severity: warning annotations: description: HPA {{ $labels.namespace }}/{{ $labels.horizontalpodautoscaler }} has been running at max replicas for longer than 3h; this can indicate underprovisioning. summary: HPA has been running at max replicas for an extended time如果这条告警触发,说明最大副本数不足以吸收负载,需要回到容量规划一节重新用 7 天数据评估maxReplicas。
边界与限制
- 该方案只适用于 microservices 模式 + query-scheduler 的部署,单二进制部署不适用。
- 查询
loki_query_scheduler_inflight_requests时 quantile 只能取文档列出的固定值(0.5、0.75、0.8、0.9、0.95、0.99),否则查不到数据。 - 计算阈值前必须用
loki_querier_worker_concurrency核对实际 worker 数,因为连接数多于max_concurrent配置时实际 worker 会更多。 - Helm 路径下
prometheusAddress为空时触发器不工作,这是最容易漏配的一项。
【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考