首页 > 解决方案 > Kubernetes 服务选择器更改不会对连接的客户端生效

问题描述

我想在部署过程中显示在 Kubernetes 下运行的应用程序的维护页面,在这个“维护”窗口中,我备份数据库,然后应用架构更改,然后部署新版本。

我想也许我可以做的是更改服务选择器,以便它指向一个 nginx 容器,在部署过程中提供一个简单的维护页面。部署成功后,我将切换回选择器以指向执行实际工作的 pod。

我的问题是,除非我关闭并重新打开当前正在查看该站点的浏览器,否则我永远看不到维护页面;我猜浏览器保持连接打开。公共服务地址在整个过程中不会改变。

我正在使用一种类型的 NodePort 在 Docker Kubernetes 安装上进行本地测试。

关于如何让它工作的任何想法,还是我用这种方法鞭打一匹死马?

问候李

标签: dockernginxkubernetesservice

解决方案


发生这种情况是由于浏览器和 k8s 服务的工作方式相结合。

浏览器缓存到服务器的 TCP 连接:当请求一个页面时,它们将保持 TCP 连接打开,如果用户稍后从同一个域请求更多页面,浏览器将重用已经打开的 TCP 连接以节省时间。

k8s 服务负载均衡运行在 TCP 层。当接收到一个新的 TCP 连接时,它会从 Service 分配给一个 pod,并在整个 TCP 连接的生命周期内一直与该 pod 通信。

所以,问题是你的浏览器保持 TCP 连接对你的旧 pod 开放,即使你修改了服务。

我们如何解决这个问题?

非解决方案#1:让浏览器不缓存连接。据我所知,没有办法做到这一点,而且你也不想要它,因为它会使你的网站变慢。此外,HTTP 缓存标头对此没有影响。浏览器总是缓存 TCP 连接。无缓存标头将使浏览器再次请求页面,但通过已经打开的连接。

非解决方案#2:在更新服务时让 k8s 终止 TCP 连接。这是不可能的,也是不可取的,因为这种行为是使“正常关闭/请求耗尽”部署策略起作用的原因。见问题

解决方案 #1:使用第 7 层 (HTTP) 负载平衡而不是第 4 层 (TCP) 负载平衡,例如nginx-ingress。L7 负载平衡将流量路由到“每个 HTTP 请求”而不是“每个 TCP 连接”的 pod,因此即使浏览器保持 TCP 连接打开,您也不会遇到此问题。

解决方案 #2:从您的应用程序而不是 k8s 执行此操作。例如,有一个“in-maintenance”数据库标志,在每个请求上检查它,如果它被设置,则提供维护页面。


推荐阅读