Kubernetes 中的 Pod 优先级如何导致 Grafana Labs 停机

笔记。 翻译。:我们向您提供有关 Grafana 创建者维护的云服务最近停机原因的技术详细信息。 这是一个典型的例子,说明了一个旨在提高基础设施质量的看似极其有用的新功能...如果您不考虑其在生产现实中的应用程序的众多细微差别,可能会造成损害。 当这样的材料出现时,让你不仅可以从错误中学习,真是太好了。 详细信息请参见 Grafana Labs 产品副总裁翻译的本文。

Kubernetes 中的 Pod 优先级如何导致 Grafana Labs 停机

19 月 30 日星期五,Grafana Cloud 中的托管 Prometheus 服务停止运行约 XNUMX 分钟。 我向所有受停电影响的客户致歉。 我们的工作是提供您需要的监控工具,我们知道,如果没有这些工具,您的生活会变得更加困难。 我们非常严肃地对待这一事件。 本说明解释了发生的情况、我们如何应对以及我们正在采取哪些措施来确保类似情况不再发生。

史前

Grafana Cloud Hosted Prometheus 服务基于 Cortex — CNCF 项目创建水平可扩展、高度可用、多租户的 Prometheus 服务。 Cortex 架构由一组单独的微服务组成,每个微服务执行自己的功能:复制、存储、查询等。 Cortex 正在积极开发中,并不断添加新功能并提高性能。 我们定期将新的 Cortex 版本部署到集群,以便客户可以利用这些功能 - 幸运的是,Cortex 可以在不停机的情况下进行更新。

为了实现无缝更新,Ingester Cortex 服务在更新过程中需要额外的 Ingester 副本。 (笔记。 翻译。: 摄取者 - 皮质的基本组成部分。 它的工作是收集源源不断的样本流,将它们分组为 Prometheus 块,并将它们存储在 DynamoDB、BigTable 或 Cassandra 等数据库中。) 这允许旧的 Ingester 将当前数据转发到新的 Ingester。 值得注意的是,Ingesters 需要资源。 为了让它们工作,每个 pod 需要 4 个核心和 15 GB 内存,即在我们的 Kubernetes 集群中,基础机器的处理能力和内存为 25%。 一般来说,集群中的未使用资源通常多于 4 个核心和 15 GB 内存,因此我们可以在升级期间轻松启动这些额外的接收器。

然而,在正常操作期间,经常会发生这样的情况:没有一台机器拥有这 25% 的未使用资源。 是的,我们甚至不努力:CPU 和内存始终对其他进程有用。 为了解决这个问题,我们决定使用 Kubernetes Pod 优先级。 这个想法是给予 Ingesters 比其他(无状态)微服务更高的优先级。 当我们需要运行额外的 (N+1) 个 Ingester 时,我们会暂时取代其他较小的 Pod。 这些 Pod 被转移到其他机器上的免费资源,留下足够大的“洞”来运行额外的 Ingester。

18 月 XNUMX 日星期四,我们为集群推出了四个新的优先级: 危急, , средний и 。 他们在一个没有客户端流量的内部集群上进行了大约一周的测试。 默认情况下,接收没有指定优先级的 Pod средний 优先级,为摄取器设置了类别 优先。 危急 保留用于监控(Prometheus、Alertmanager、node-exporter、kube-state-metrics 等)。 我们的config已经开放了,你可以查看PR 这里.

事故

19 月 XNUMX 日星期五,一位工程师为一家大客户推出了一个新的专用 Cortex 集群。 该集群的配置不包括新的 pod 优先级,因此所有新 pod 都被分配了默认优先级 - средний.

Kubernetes 集群没有足够的资源用于新的 Cortex 集群,并且现有的生产 Cortex 集群没有更新(Ingesters 没有更新) 优先事项)。 由于新集群的 Ingesters 默认情况下有 средний 优先级,并且生产中的现有 Pod 完全没有优先级,新集群的 Ingester 替换了现有 Cortex 生产集群中的 Ingesters。

生产集群中被驱逐的 Ingester 的 ReplicaSet 检测到被驱逐的 pod 并创建了一个新的 pod 来维护指定数量的副本。 默认分配新的 Pod средний 优先级,生产中的另一个“旧”Ingester 失去了资源。 结果是 雪崩过程,这导致 Cortex 生产集群中的所有 Pod 都从 Ingester 中转移。

摄取器是有状态的并存储过去 12 小时的数据。 这使我们能够在将它们写入长期存储之前更有效地压缩它们。 为了实现这一目标,Cortex 使用分布式哈希表 (DHT) 对系列中的数据进行分片,并使用 Dynamo 风格的仲裁一致性在三个 Ingester 之间复制每个系列。 Cortex 不会将数据写入禁用的 Ingester。 因此,当大量 Ingester 离开 DHT 时,Cortex 无法提供足够的条目复制,并且它们会崩溃。

检测和修复

基于“错误预算”的新 Prometheus 通知(基于误差预算 — 详细信息将在以后的文章中出现)在关闭开始 4 分钟后开始拉响警报。 在接下来的五分钟左右的时间里,我们运行了一些诊断并扩展了底层 Kubernetes 集群以托管新的和现有的生产集群。

又过了五分钟,旧的 Ingester 成功写入数据,新的 Ingester 启动,Cortex 集群再次可用。

另外 10 分钟用于诊断和纠正位于 Cortex 前面的身份验证反向代理的内存不足 (OOM) 错误。 OOM 错误是由 QPS 增加十倍引起的(我们认为是由于客户端 Prometheus 服务器发出过于激进的请求)。

后果

总停机时间为 26 分钟。 没有数据丢失。 摄取器已成功将所有内存数据加载到长期存储中。 在关闭期间,Prometheus 服务器的客户端缓冲区被删除 (偏僻的) 录音使用 新 API 远程写入 基于WAL(作者: 卡勒姆·斯蒂恩 来自 Grafana Labs)并在崩溃后重复失败的写入。

Kubernetes 中的 Pod 优先级如何导致 Grafana Labs 停机
生产集群写操作

发现

重要的是要从这一事件中吸取教训,并采取必要措施避免类似事件再次发生。

事后看来,我们不应该设置默认值 средний 优先级,直到生产中的所有 Ingesters 都收到 优先权。 此外,还需要提前照顾好他们 优先事项。 现在一切都已确定。 我们希望我们的经验能够帮助其他考虑在 Kubernetes 中使用 pod 优先级的组织。

我们将对任何其他对象的部署添加额外的控制级别,这些对象的配置对于集群来说是全局的。 从现在开始,此类变更将由о更多的人。 此外,导致崩溃的修改对于单独的项目文档来说被认为太小了——它仅在 GitHub 问题中进行了讨论。 从现在开始,所有此类配置更改都将附有适当的项目文档。

最后,我们将自动调整身份验证反向代理的大小,以防止我们目睹的过载 OOM,并将审查与回退和扩展相关的 Prometheus 默认设置,以防止将来出现类似问题。

这次失败也产生了一些积极的后果:在收到必要的资源后,皮质自动恢复,无需额外干预。 我们还获得了与合作伙伴的宝贵经验 格拉法娜·洛基 - 我们的新日志聚合系统 - 这有助于确保所有 Ingester 在故障期间和故障后均正常运行。

译者PS

另请阅读我们的博客:

来源: habr.com

添加评论