什么 Azure Kubernetes (AKS) 'Time-out' 断开我集群中 Pod 的连接 in/out?

What Azure Kubernetes (AKS) 'Time-out' happens to disconnect connections in/out of a Pod in my Cluster?

我有一个工作集群,其中的服务都在 Azure AKS 上安装了 Ingress nGinx 运行 的 helm 后进行响应。 这最终是特定于 Azure 的。

My question is: Why does my connection to the services / pods in this cluster periodically get severed (apparently by some sort of idle timeout), and why does that connection severing appear to also coincide with my Az AKS Browse UI connection getting cut?

这是为了获得最终答案,究竟是什么触发了导致本地 'Browse' 代理 UI 与我的集群断开连接的超时(关于我为什么要问的更多背景信息跟随)。

从 Az CLI 使用 Azure AKS 时,您可以使用以下命令从终端启动本地浏览器 UI:

az aks browse --resource-group <resource-group> --name <cluster-name>

这工作正常并弹出浏览器 window 看起来像这样 (yay):

在您的终端中,您会看到类似以下内容的内容:

  1. http://127.0.0.1:8001/ 上的代理 运行 按 CTRL+C 关闭隧道...
  2. 转发自 127.0.0.1:8001 -> 9090 转发自
  3. [::1]:8001 -> 9090 8001 的处理连接 8001 的处理连接 8001 的处理连接

如果您将与集群的连接闲置几分钟(即,您不与 UI 交互),您应该会看到以下打印信息,表明连接已超时:

E0605 13:39:51.940659 5704 portforward.go:178] lost connection to pod

我仍然不明白的一件事是集群内部的其他 activity 是否可以延长此超时,但是无论您看到上面的内容,您基本上都在同一个地方......这意味着我们可以谈论这样一个事实,即看起来我在该服务器中从 pods 退出的所有其他连接也已被负责切断与 AKS 浏览器 UI 的联系的任何超时进程关闭。

那么问题是什么?

这对我来说是个问题的原因是我有一个服务 运行 一个 Ghost 博客 pod,它使用名为 'Knex' 的 npm 包连接到远程 MySQL 数据库。碰巧的是,较新版本的 Knex 有一个错误(尚未解决),如果 Knex 客户端和远程数据库服务器之间的连接被切断并需要恢复 - 它不会重新连接并且只是无限负载。

nGinx 错误 503 网关超时

在我的情况下,导致 nGinx Ingress 给我错误 503 网关超时。这是因为在空闲超时切断 Knex 连接后 Ghost 没有响应 — 因为 Knex 不能正常工作并且不能正确恢复断开的服务器连接。

很好。 我回滚了 Knex,一切正常。

But why the heck are my pod connections being severed from my Database to begin with?

因此这个问题希望能节省一些未来的人天来尝试解决与 Kubernetes 相关的幻影问题(可能是 Azure 特定的,可能不是)在服务/ pod 空闲一段时间后切断连接。

简答:

Azure AKS automatically deploys an Azure Load Balancer (with public IP address) when you add a new ingress (nGinx / Traefik... ANY Ingress) — that Load Balancer has its settings configured as a 'Basic' Azure LB which has a 4 minute idle connection timeout.

空闲超时既是标准也是必需的(尽管您可以修改它,请参见此处:https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-tcp-idle-timeout)。也就是说,对于从负载均衡器 IP 向外流出的任何流量,无法完全消除它——目前支持的最长持续时间为 30 分钟。

没有本地 Azure 方法来绕过被切断的空闲连接。

因此,根据最初的问题,处理此问题的最佳方法(我认为)是将超时保留在 4 分钟(因为无论如何它都必须存在),然后设置您的基础架构以优雅地断开连接在达到负载平衡器超时之前的方式(空闲时)。

我们的解决方案

对于我们的 Ghost 博客(命中 MySQL 数据库),我能够如上所述回滚,这使得 Ghost 进程能够处理数据库断开/重新连接的情况。

那Rails呢?

是的。同样的问题。

对于单独的基于 Rails 的应用程序,我们还在 AKS 上 运行 连接到远程 Postgres 数据库(不在 Azure 上),我们最终实现了 PGbouncer(https://github.com/pgbouncer/pgbouncer) as an additional container on our Cluster via the awesome directions found here: https://github.com/edoburu/docker-pgbouncer/tree/master/examples/kubernetes/singleuser

通常,任何试图从 AKS 访问远程数据库的人都可能需要实施中间连接池解决方案。池服务位于中间(对我们来说是 PGbouncer)并跟踪连接空闲了多长时间,这样您的工作进程就不需要关心它了。

如果您开始接近负载平衡器超时,连接池服务将丢弃旧连接并创建一个新连接(重置计时器)。这样,当您的客户端沿着管道发送数据时,它会按预期到达您的数据库服务器。

收盘中

这是一个非常令人沮丧的错误/案例。我们花费了至少 2 天的开发运营时间来找出第一个解决方案,但即使知道这可能是同一个问题,这次我们又花费了 2 天时间。

即使将计时器延长到超过 4 分钟的默认值也无济于事,因为这只会使问题更难以解决。我想我只是希望任何在从 Azure AKS / Kubernetes 连接到远程数据库时遇到问题的人都比我更擅长谷歌搜索,并且可以避免一些痛苦。

感谢 MSFT 支持(Kris,你是最棒的)关于 LB 计时器的提示以及将 PGbouncer 放在容器中的家伙,这样我就不必重新发明轮子了。