如何使用容器对具有(长期)粘性会话的应用程序进行零停机滚动更新
Posted
技术标签:
【中文标题】如何使用容器对具有(长期)粘性会话的应用程序进行零停机滚动更新【英文标题】:How to do zero-downtime rolling updates for app with (long-lived) sticky sessions using containers 【发布时间】:2017-08-11 17:44:42 【问题描述】:我试图弄清楚如何根据 JSESSIONID cookie 为具有长期交互用户会话的 web 应用提供零停机滚动更新。
出于这个(和其他)原因,我正在研究容器技术,比如 Docker Swarm 或 Kubernetes。
我很难找到关于如何:
-
确保新会话使用最新版本的应用
虽然现有会话仍由任何版本的
他们启动的应用程序
在旧版本的所有会话都完成后正确清理旧版本
关闭
更多信息:
请求链接到基于 JSESSIONID cookie 的会话 会话可能会持续数天,但可以在 24 小时内从应用程序中终止它们(向用户发送通知以“再次注销/登录,因为有新版本或它们会自动记录例如,中午 12 点出门) 当然,对于每个版本的应用程序,都有多个容器已经以负载平衡的方式运行 我不介意容器总数的增长,例如,如果每个旧版本的容器都仍然启动并运行,因为它们都将托管 1 个会话,而大多数用户已经在新版本上应用版本所以,我对所需流程的想法是这样的:
-
安装新版应用
让所有新连接(没有设置 JSESSIONID cookie 的连接)都转到新版本的应用程序一次
旧版应用程序的容器未提供会话
再,移除容器/....
正如我所提到的,我正在研究 Kubernetes 和 Docker Swarm,但对其他建议持开放态度,但最终解决方案应该能够在云平台上运行(目前使用 Azure,但谷歌或亚马逊云可能用于未来)
任何指针/提示/建议或想法表示赞赏
保罗
编辑: 回答@Tarun 问题和一般说明:是的,我不想停机。我设想的方式是托管旧版本的容器将继续运行以服务所有现有会话。旧服务器上的所有会话结束后,旧服务器将被删除。
新容器只会为在新版本推出后启动应用程序的用户提供新会话。
所以,举个例子: - 我在上午 9 点启动旧版应用程序的新会话 A - 上午 10 点推出新版本。 - 我继续使用会话 A,其仍然托管在运行旧版本的容器上。 - 中午我去吃午饭然后登出 - 因为我是连接到运行旧版本的容器的最后一个会话,所以容器现在将被销毁 - 下午 1 点我回来,重新登录并获得新版本的应用程序
有道理吗?
【问题讨论】:
欢迎来到 ***。这个问题对 SO 来说太宽泛了 - 请考虑阅读 How to ask 指南以提高获得好答案的机会。 @Paul - 如果我理解正确,您需要在没有/最少停机时间的情况下进行滚动更新,并且用户会自动定向到新容器。?如果是这样(除非应用程序有特定的违反这一点的东西),您需要的流程似乎可以很容易地用 kubernetes 完成。 @Paul 这些会话存储在服务器的什么位置?还是它们仅由客户端存储为 cookie? @Tarun 我已经根据您的问题使用示例更新了我的问题。希望能澄清事情。如果这可以通过 Kubernetes 轻松完成,您能给我一些指导吗?因为我还没想好怎么做 @iamnat:客户端存储一个 JSESSIONID cookie,服务器根据 JSESSIONID cookie 的值定位每个会话有很多状态。将会话从一台服务器移动到另一台服务器是行不通的:我使用的平台的架构无法支持这一点,而且很可能永远不会 【参考方案1】:您的工作负载可能不适合 Kubernetes/容器及其当前架构。我能想出解决这个问题的最好方法是将状态移动到 PV/PVC 并将 PV 迁移到新容器,以便新容器可以具有旧会话的状态,现在如何将该会话的调用迁移到正确的节点我不确定如何有效地做到这一点。
理想情况下,您可以将数据/缓存层与服务分离成类似 redis 的东西,然后哪个节点为请求提供服务就无关紧要了。
【讨论】:
嗨,杰克,虽然我很想从服务中取出所有状态和/或将会话从一台服务器迁移到另一台服务器,但现实是我使用的堆栈不支持离开堆栈是一个(非常)长期的事情我们目前正在使用自定义入口和我们自己的升级/部署机制对此进行原型设计,但实际上这并不容易并且没有利用一些内置的-在 Kubernetes 的特性中以上是关于如何使用容器对具有(长期)粘性会话的应用程序进行零停机滚动更新的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 AWS Elastic Beanstalk 中使用应用程序控制的会话粘性吗?
如何使用 docker swarm 保持粘性会话(会话持久性)?