博客/工程

如何添加Kubernetes标签选择器造成停机Grafana云日志——和我们如何解决呢

2022年8月31日 10分钟

你好,我是卡勒姆。我工作在Grafana洛基,包括主持Grafana云日志提供。Grafana洛基是一个分布式的多租户系统用于存储日志数据——摄入,查询、有趣的东西。它还权力Grafana云日志。

这篇文章中概述的停机是由于在一步一个Grafana云的迁移日志集群,我们迁移的一个单独部署的键值存储,用于存储戒指为了利用嵌入式memberlist。目标是消除单点故障形式的键值存储。

作为编写移民相关的配置代码的一部分,我们不小心添加了一个额外的Kubernetes标签选择器,导致不正确的服务发现决议的豆荚没有标签选择器。这导致了压倒性的负载被定向到一些圆荚体标签选择器,降低我们写路径之一Grafana洛基环境~ 25分钟。

这篇文章解释了发生了什么,我们如何回应它,和我们所做的,以确保它不会再发生。

背景

要理解这个故障是怎么来的,你需要知道一些背景信息。

我们部署Grafana洛基使用microservices架构以允许细粒度优化各种组件根据客户使用情况和可用资源。

你可以阅读更多的信息洛基的microservices架构,但有关组件如下:

  • 经销商:用于验证速度限制、标签数据的正确性等以及复制的写入数据复制的目的。
  • 摄入:这是经销商写入的组件。经销商选择一些ingesters基于配置的复制因子和传入日志流哈希的标签和ingesters写数据。ingesters保持数据内存中的一段时间更快的查询数据,然后最终写blob存储的数据文件。
  • 环:是一种分布式哈希表中所使用的各种组件Grafana洛基知道哪些组件的副本存在决定哪些要送到,如经销商决定哪些ingesters写数据。
  • 网关:一个API gateway-like组件,还负责执行身份验证和发现经销商与Kubernetes通信API。

关于Kubernetes标签选择器

简短的解释:Kubernetes允许附加元数据对各种对象(豆荚、服务等)作为一种组织和确定这些对象通过其API。

Kubernetes服务,你可以告诉Kubernetes选择豆荚,只有一个特定的标签;这是被称为选择器。你可以创建一个部署“applicationX”并附上标签,然后有一个服务,检查标签,以确认它只有发现吊舱从部署正确的标签。您还可以使用选择器结合kubectl命令目标特定的豆荚特别的命令。

在我们的例子中,我们使用标签和选择器目标运行的所有豆荚memberlist(标签gossip_ring_member:“真正的”),并创建一个Kubernetes服务gossip_ring所有舱使用为了加入memberlist集群通过join_members在这里

看到Kubernetes文档更多细节关于Kubernetes标签选择器。

我们Kubernetes配置管理

在Grbob电竞频道afana实验室,我们使用jsonnetGrafana短歌我们的服务的配置和部署Kubernetes。我们有很多已经创建了公司内部各点的历史,你可以想象,很难保证使用一致性或功能可用性在其中的一些库,尤其是跨团队。

我们有一个函数简单地看了看代码配置部署或statefulset和生成一个服务定义通过复制所有的标签附加到部署/ statefulset和创建选择器标签服务。这个函数已经被更新以适应边界情况,包括这篇文章中讨论的一个。

这一事件

这一事件是由几件事的组合。首先,创建一个Kubernetes服务部署添加所有标签选择器。当时,我没有注意到另一个团队这个问题已经标记,我没有提供新的可选参数的构造函数(固定在这里)来过滤掉一些标签选择器。第二,新/更新Kubernetes服务导致增加新的标签部署组件和服务为我们的经销商。最后,这一切意味着Kubernetes服务经销商只会决心吊舱与这个新标签。

步骤1的迁移从现有KV存储memberlist导致的这个新标签经销商豆荚和服务,以及一个小配置变化。这意味着需要推出,Kubernetes开始卷豆荚基于我们的推广策略。在这一点上,我们的网关服务,检查验证然后转发写数据到经销商,只有能够看到新的豆荚以来他们的新的标签和经销商服务有选择器筛选豆荚。

我们最终把我们写的100%流量的10%我们的经销商们看看。结果是一个循环的这些新经销商,收到太多的负荷根据CPU和内存限制,内存(伯父)杀了,因此,他们不能完成他们的健康和准备检查。这些检查Kubernetes用来确定先前的豆荚推出很健康,它可以重新启动下一组老豆荚。所以推出是无法继续与这个新标签,开始更多的豆荚,意义相同的10%的经销商继续打击。

幸运的是,我们能够开始恢复之前识别问题。计算成本便宜的相对于长时间的服务中断,在停机的情况下,似乎伯父崩溃的结果,我们的第一反应是经销商规模部署水平,增加更多的副本。这些副本都想出了新标签,因此是豆荚IPs的一部分服务可以解决,这意味着目前负载传播更多的分销商之一。用更少的分销商伯父崩溃,Kubernetes看到更多的分销商健康继续滚老豆荚。最后,我们又迁移到完全的改变这一步解决故障,有时间调查根本原因。

调查

幸运的是我们收集大量的指标和日志以及Kubernetes从我们所有的服务。第一条线索是,kubectl得到豆荚和Kubernetes规圆荚体复制的数量已经更新自上次配置变化显示,只有10%的经销商豆荚被重新启动。最初,我们认为因为日志流分片和复制的某些子集的豆荚,可能会有一个特别高体积流吞吐量的增加,或更多的额外流已经创建,我们只部署一个不合时宜的时候发生的。

图显示Kubernetes度量kube_deployment_status_replicas_updated。

在上面的图中,Kubernetes度量kube_deployment_status_replicas_updated表明我们的停机期间,16/140的经销商是“更新”状态。

然而,我们度量了传入的写请求的速率以及活动流的数量和指标都没有立即改变之前的事件。我们现在怀疑有什么改变了把请求路由到分销商和正在寻找确认。使用的指标loki_request_duration_seconds_count报告的每个分销商仓,我们可以看看传入请求的速率率> 0的路线写在系列的事件,数一数,也表明16/140经销商副本接受写请求。

仪表板显示Kubernetes分销商0每秒请求服务。
~ 75%的上面我们可以看到,这张图的时间我们有经销商报告说,他们0每秒请求服务。
线图显示Kubernetes分销商表现不佳。
这里我们可以看到成功的经销商服务请求数量明显低于正常,甚至在某些点0。
图显示正常Kubernetes推出。
作为一个参考点,上面的图表显示了我们的正常电看起来像这个环境。所有分销商都运行~ 15分钟内更新配置。

上面的图是一样的loki_request_duration_seconds_count从上面的查询。在这里你可以看到,我们基本上没有经销商成功服务请求的数量下降因为它们能够快速启动正常。基准轴的底部附近的图是140年的数量。上面的图是140的原因是普罗米修斯速度查询使用时间范围的行为及时回头。

现在我们需要找到原因。幸运的是我们有自动化生成Kubernetes体现所有拉请求之间的差别会导致更改任何环境。这些差别是发布到PRs,甚至是存储在一个单独的存储库。看着这些差别,我们可以确定选择器添加到经销商服务,导致经销商的娱乐服务,Kubernetes集群内/名称空间。这是通常并不是部署的一部分。阅读Kubernetes标签和选择器的文档之后,我们知道这是原因。

代码添加Kubernetes标签选择器。
Kubernetes标签选择器被添加到我们的经销商服务。

现在你可能会问,为什么我们没有赶上这个开发或登台环境?这是由于我的疏忽。这不是不寻常的看到一个非常小的(微量)的错误当我们做推广的环境,因为移动块的数量,需要相互通信,但所有开始在不同的时间。戒指是一个因素的复杂性。正因为如此,我们看到一些小错误时推出迁移在其他环境中,不认为什么是不寻常的。

但同样的迁移步骤的原因没有造成停机在另一个环境是值得注意的。它归结为这一特定环境的经销商被横向比例远远高于其他环境。而在其他环境中,尤其是相似规模的,包括一些垂直扩展内存限制资源的经销商。在其他环境中,这意味着有更时间用于经销商来完全和服务增加的百分比写负载和他们通常服务之前,他们可能会遇到内存限制。简而言之,Kubernetes实际上是能够继续滚动老经销商新的和负载继续展开。

修复

这是一个简单的修复,只是回到我们的配置和注意到另一个团队包括配置选项在以前天真的创建一个服务部署/ statefulset忽略某些标签上部署/ statefulset当创建服务,而不是盲目地复制选择器到服务。

TL;修复是博士service_ignored_labels: [._config.gossip_member_label美元],并通过服务构造函数k.util.serviceFor(美元)。overrides_exporter_deployment ._config.service_ignored_labels美元)

结论

意外Kubernetes标签选择器添加到豆荚的一部分我们memberlist推出引起的服务使用Kubernetes服务找经销商豆荚DDOS在推出新的/更新的豆荚。这对这个细胞导致停机,因为分销商或多或少的入口点数据和查询到整个Grafana洛基架构。

因为Grafana洛基已经测试的日志,指标,甚至痕迹,我们能够从Kubernetes结合使用这些指标来确定不同期间推出memberlist和识别问题的根源。

总的来说,通过发布这篇文章,我们希望其他人考虑部署使用Kubernetes标签选择器可以从自己的错误中学习。