几周前,我的团队在 Kubernetes 中遇到了一个非常有趣的服务限制,这在我们的开发环境中造成了一个非常意想不到的问题。

我们首先看到的

我们首先注意到我们的 REST API 不可用,然后我们很快注意到我们的 pod 没有运行。开始调查,我们注意到

  1. 我们的 REST API 部署的所有 pod 都在Init:CrashLoopBackoff中。

  2. 我们计算部署中的一些 pod 有同样的问题,但其中一些 pod 工作正常。

  3. 运行良好的 pod 往往超过一天,所以我们怀疑如果 pod 重新启动它们会遇到这个问题。

我们开始调查 init 容器是否存在错误,但这最终不是问题。查看 init 容器的日志,记录的唯一行是。

standard_init_linux.go:228: exec user process caused: argument list too long

进入全屏模式 退出全屏模式

在升级到我们的 Kubernetes 团队后,他们告诉我们这个错误表明 Docker 容器无法启动,因为传递给容器的环境变量太多。

谁把所有这些环境变量放在我的 pod 中?

我们的 Kubernetes 专家告诉我们关于 Kubernetes 中的enableServiceLinks,它为每个活动服务添加了环境变量。从文档中:

当 Pod 在 Node 上运行时,kubelet 会为每个活动的 Service 添加一组环境变量。 注意 如果不需要服务环境变量(因为可能与预期的程序冲突、要处理的变量太多、仅使用 DNS 等),您可以通过在 pod 规范上将 enableServiceLinks 标志设置为 false 来禁用此模式.

为了验证这是原因,我们用enableServiceLinks: false启动了一个 pod,它开始正常。删除该行后,我们遇到了与上面相同的错误。

在工作的 pod 中,您也可以自己检查并查看正在使用的环境变量。

kubectl exec -ti my-pod -- sh -c "env | grep SERVICE | sort"

进入全屏模式 退出全屏模式

这些服务是从哪里来的?

所以,我们有太多的环境变量,因为我们的命名空间中有太多的服务。为什么我们有这么多服务?

根本问题是由我们系统中的一个动态创建部署和服务的进程引起的,并且在我们清理部署时清理服务存在错误。几个星期后,孤立的服务堆积起来,我们终于达到了导致 pod 无法启动的限制。

外卖

这是我最喜欢的事件,因为

  1. 在它投入生产之前,我们在开发中实现了这一点。

  2. 我们了解了我们基础设施的深层部分,否则我们不会知道。

那么我们学到了什么并计划下一步做什么?

  1. 如果启用enableServiceLinks(这是默认值),Kubernetes 将在您的 pod 中填充环境变量。

  2. 更快地捕捉到这一点:我们可以在命名空间中的服务数量超过该阈值之前对其进行监控。

  3. 更快地缓解:编写一份运行手册来解释问题以及我们在这种情况下如何解决它。

  4. 再次防止这种情况:当我们接近阈值时发出警报,或者如果我们再次在容器中看到日志消息。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐