Kubernetes滚动部署和数据库迁移

45

在进行带有数据库迁移的滚动更新时,Kubernetes如何处理?

举个例子,我有一个应用程序从app-v1升级到app-v2,其中包括修改现有表的迁移步骤。这意味着我需要在部署后运行类似于db:migrate的命令来完成Rails应用程序的迁移。

当针对3个副本集进行滚动部署时,它将从一个Pod部署到另一个Pod,可能会导致没有新版本应用程序的POD出现故障。

虽然这种情况并不经常发生,但很可能会发生。我想了解这种情况的最佳/推荐方法。

3个回答

30

防止旧版本出现问题的一种方法是将迁移分成多个步骤。

例如,您想在数据库中重命名一个列。直接重命名该列会破坏应用程序的旧版本。可以将其拆分为多个步骤:

  • 添加一个数据库迁移,插入新列
  • 更改应用程序,使所有写入都到旧列和新列
  • 运行任务将所有值从旧列复制到新列
  • 更改应用程序以从新列读取
  • 添加一个迁移,删除旧列

这很麻烦,但避免了维护页面停机时间。


2
这是一篇很好的文章,解释了这个想法:https://spring.io/blog/2016/05/31/zero-downtime-deployment-with-a-database - tsauerwein

9
Kubernetes不支持包含数据库迁移的滚动更新。这是应用程序特定的,所以应用程序开发人员需要处理它。您可能需要执行与非k8s环境相同的操作。
无论如何,我会这样做:
1. 将副本数缩小到1。 2. 更新镜像。 3. 将副本数扩大到3。
这并不是完美的解决方案,但不需要更改代码。在db:migrate步骤和实际服务器监听之间存在一个小窗口,在这个窗口期内,请求将发送到旧副本(一旦新副本准备好,旧副本就会终止)。该请求可能会成功或失败,具体取决于代码块是否直接涉及模式更改。
如果我不太关心停机时间,那么我会使用重新创建策略。

5
我最近解决了这个问题,以下是我的方式:
  • 使用 部署注释 存储您通常需要在部署之前或之后运行的命令。
  • 创建一个脚本,可以根据名称读取您的部署,然后创建一个作业以运行部署注释中指定的命令。
  • 将镜像推送到Docker注册表时添加一个Webhook,该Webhook将调用先前指定的脚本。
  • 为避免与不兼容的数据库结构出现问题:
    • 不要以向后不兼容的方式修改数据库列。
    • 不要立即在迁移中删除未使用的列。您可以在下一个版本中进行操作。这样,您将只有一个迁移脚本,在部署之前运行它。

P.S. 如果你想在脚本中使用Kubernetes,可能需要熟悉以下链接:Kubernetes API, Kubernetes API概述, 使用Kubernetes API访问集群, 客户端库


这听起来很有前途,但我不确定我理解第三点。你能提供一个例子说明一下吗? - Greg Ferreri
很遗憾,我为此编写的应用程序不是开源的,但我用golang编写了它,在Kubernetes中授予了访问权限(读/写部署和作业),它作为http守护进程监听并执行所描述的操作。 - Denis V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接