如何在不终止连接的情况下更新码头工人网络应用程序?



我有一个docker-compose.yml有两个服务:数据库和我的Go应用程序。我的 CI/CD 管道调用托管此 docker 容器并运行此 bash 脚本的服务器:

git fetch &> /dev/null
diffs=$(git diff master origin/master)
if [ ! -z "$diffs" ]
then
echo "Pulling code from GitHub..."
git checkout master
git pull origin master
# update server
docker-compose up --build -d
# kill all unused docker containers
docker system prune -f
else
echo "Already up to date"
fi

这样做的问题是,如果有任何未完成的 http 连接到我的容器,它们将被终止。我使用"gopkg.in/tylerb/graceful.v1"在终止之前等待未完成的连接完成,但如果客户端不断发出单独的重叠请求,这在技术上永远不会停止。

此服务位于nginx反向代理后面:

upstream goapp {
server 127.0.0.1:8080;
}

我的一个想法是将docker应用程序部署到一个新端口上(不确定是否可能使用docker-compose(,然后告诉nginx向upstream添加新服务器(例如server 127.0.0.1:8081;) for all new incoming connections. Then allow the container on8080to gracefully close (then somehow delete from the上游'(。这是可能的还是有更好的方法可以做到这一点?

使用单个主机(如使用 docker-compose 所示(同时关注高可用性对我来说似乎很奇怪。稍后会详细介绍。

注意以下内容被简化,部分内容大致相同。此外,为了简单起见,术语在这里和那里都关闭了。

但是,有一个服务的概念,它可用于docker swarm和Kubernetes。服务是一个虚拟负载均衡器/透明的反向代理,可以感知其后端,可以在 Kubernetes parlay 中由基本上任意数量的容器或 pod 支持(以下缩短为容器,因为这在技术上对于 Kubernetes 来说也不是错误的(。当然,这些容器每个都运行您的应用程序。引擎知道容器是否正在关闭或变得不可用,并将请求路由到处于活动状态的容器。目前为止,一切都好。

现在,两个引擎都有不同的概念,称为"滚动更新"。实际发生的是,如果您的服务由多个容器支持,则如下所示:

嗨,我是你的编排引擎! 呃,您要更新支持服务 X 的容器的映像吗? 让我们看看...好吧,X 有两个支持容器,所以我们可以做一个滚动 更新。呃,对服务的新请求:将其发送到第二个 容器。在处理时,我用新的 图像。。。需要一段时间...来了!将所有新请求发送到 更新的容器。现在关闭第一个旧容器...下!使用新映像启动第二个容器... 做!太好了,现在将所有新请求发送到更新的容器。 试图停止剩余的旧容器...等到它处理完毕 请求,但最多 30 秒,然后我会杀了它......啊,不需要, 已经关闭了...

我很高兴地通知您,我已成功更新服务 X 以使用具有您应用程序的闪亮新版本的新容器!

小秘密

Docker-compose在技术上应该能够执行相同的操作,如果将服务扩展到> 1,然后更改撰写文件,然后执行

docker-compose up

然而,所有这些关于不失去连接然后在一台机器上运行的模糊似乎都像试图在划艇上安装战舰大炮。我的建议:如果你的服务实际上使用临时容器(如果你以任何方式、形状或形式使用挂载,你很可能没有(,请使用 docker swarm。否则,请使用 Kubernetes。虽然它的学习曲线可能有点陡峭(一开始,它很快就会变平(,但在更复杂的设置中是值得的。

编辑保留单个会话(包括当前上传(是完全不同的事情,虽然并非完全不可能,但需要相当复杂的反向代理和/或同样复杂的应用程序设置。通常,宣布维护时段更容易。

最新更新