无需停机即可更新 Docker 容器

das*_*s_j 17 uptime docker coreos

假设我有一个带有 Web 服务器的 Docker 容器(如 Apache 2)。现在我想更新它下的操作系统。这个 SF answer说最好的方法是重建基础镜像和我的 Apache 镜像。但是部署镜像意味着停机,因为我必须在创建新容器之前删除旧容器,所以只有一个容器绑定到端口 80/443。

但是,如何在零停机时间的情况下部署此更新?我应该使用负载平衡器并使用容器间通信吗?以及如何更新负载均衡器?

Mis*_*man 18

理想的目标场景

是的,您应该使用负载均衡器并一次更新一个实例。我不确定容器间通信的来源。

例如,假设您有一个负载均衡器,它为您的站点 A 提供服务。用户只能以“A”的身份连接到它,并且只知道它是“A”。负载均衡器知道有两个或多个后端(B、C 等),它们是 VM 还是容器并不重要。

然后,您要升级后端,在本例中是 Apache 实例。

  1. 从负载均衡器的合格后端中取出 B,使其不再接受任何流量。
  2. 等待当前活动的请求得到服务并关闭现有连接。
  3. 更新服务于 B 的容器或底层 VM
  4. 重启B,等待它加载并开始工作
  5. 测试 B 以确保它正确地处理新请求
  6. 将 B 添加回负载均衡器后端池以重新启用流量

然后,对 C、D 等执行相同的过程。

请注意,从 2013 年 11 月开始,有一个对 Docker 容器就地升级公开请求,但似乎没有太大进展,因此上述解决方案是您同时应该做的。

如何处理现有的实时站点

想必,您之所以这么问是因为您已经在此模型中运行了一个实时站点,并且希望在不停机的情况下对其进行升级。因此,我们需要逐步达到上述理想目标状态。

让我们假设:

  • 你有一个指向你的容器的 DNS 名称
  • 您的容器在某个 IP 地址上运行
  • 您的用户不知道容器的 IP 地址,并且它没有在任何地方进行硬编码

如果这些假设是错误的,您应该首先修复它以使其正确。

然后,按照以下步骤操作:

  1. 在新 IP 上创建负载均衡器并将其指向现有容器作为其唯一后端
  2. 更改 DNS 以指向负载均衡器而不是直接指向容器 IP
  3. 添加具有相同 VM + 容器设置的相同 Apache 后端
  4. 现在您有一个带有两个后端 B 和 C 的负载均衡器,因此请按照“理想目标方案”部分中的说明一次升级它们

如何更新负载均衡器

简单的(托管)方式

最简单的选择是不运行自己的平衡器。例如,如果您使用的是提供负载平衡即服务的云平台,请考虑使用它,然后负载平衡器的维护和更新不是问题。

手动方式

如果您正在运行自己的负载均衡器,添加另一层间接(即 DNS)会有所帮助。让我们假设以下情况:

  • 我们有一个主机名解析为我们想要更新的负载均衡器 A 的 IP
  • 我们的负载均衡器有一个 P1、P2 等后端池。

我们按以下步骤进行:

  • 使用新的软件版本创建一个新的负载均衡器 B
  • 将所有后端池实例 P1、P2 等添加到我们的新负载均衡器 B 作为后端
  • 将 B 的 IP 地址与 A 一起添加到 DNS 解析中

    • 现在我们有效地使用 DNS 作为负载均衡器
    • 如果 A 和 B 的条目未加权,则它们实际上是 50-50
    • 现在观察 B 的表现,是否有任何错误等。
    • 如果 B 有任何问题,请按如下方式撤消:

      1. 从 DNS 配置中删除 B
      2. 等待DNS中的B条目消失(即等待TTL过期)
      3. 拒绝 B
  • 假设你已经完成了 B 的“老化”测试,一切都很好
  • 逐步更新DNS 中 B的优先级和权重
  • 从 DNS 中完全删除 A
  • 等待 DNS TTL 到期;A 不应再收到任何请求
  • 拒绝 A

你就完成了。

详细信息、图表和工具

查看这些可以帮助您自动化流程的文章和工具,但总体思路是相同的:

道德

“计算机科学中的所有问题都可以通过另一个层次的间接性来解决,当然,间接性过多的问题除外。” 大卫·惠勒