我是docker的新手,在设计一个简单的实时升级解决方案时遇到了一些问题。目前,我正在使用基于fork()/exec()
的模式进行应用程序实时升级:
旧服务器在请求时是一个子服务器。
子服务器fork()
新的可执行文件,加载新的数据/配置。
旧服务器将必要的信息(套接字、内存数据等)传递给子服务器,以便它可以接管服务。
子服务器准备好后,旧服务器停止处理新请求(旧服务器不会exec()
ATM)。
如果升级成功,请手动停止旧服务器(这可能会延迟到下一次实时升级之前),否则停止子服务器并通知旧服务器重新开始处理请求。
如您所见,无论升级是否失败,这种实时升级策略通常都不会导致停机。
我们的大多数服务都是无状态的或具有非常简单的状态,所以上面的模式很容易实现,而且非常可靠。
我的问题是如何在docker中实现上述模式(或类似的模式)?也许我走错方向了,我洗耳恭听。
最佳答案
由于您的服务已经是无状态的,同时处理旧连接和新连接对于您的服务也是可能的,在您的服务前面使用负载平衡器和某种滚动升级策略可能是最适合的。
fork方法不太适合Docker和containers背后的思想。Docker映像和生成的容器应该始终包含运行服务所需的所有内容。另外,如果另一个容器是基于同一个映像启动的,那么它应该始终启动完全相同的服务。
在基于fork的升级解决方案中,容器中的二进制文件/可执行文件将在初始启动后更改。这意味着,如果出于任何原因,您决定基于同一个映像启动另一个容器,它将不会运行相同版本的服务。当然,您可以在映像中添加一些在启动时自动升级到最新版本的内容,但这会使部署复杂化。在我看来,这将违反太多的书面和不成文的规则,在码头世界,我会认为这是一个糟糕的做法。
我觉得普通的码头工人是不够的,你想用它。我建议您研究更高级的容器编排解决方案,它提供诸如服务负载平衡和滚动更新等功能。当人们有这些更高级的需求时,我首先想到的就是Kubernetes。
随着Deployment
对象的引入,Kubernetes在更新策略方面获得了很大的优势。你应该通读Kubernetes Deployments。如果与正确的运行状况检查一起使用,则Deployment
的滚动更新策略应为您提供所需的一切,包括回滚失败的部署。
Kubernetes的缺点是需要更多的精力来建立和维护集群。但是,根据应用程序的大小、基础设施和服务的数量,这可能是值得的。
关于linux - Docker应用程序实时升级,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42468788/