Kubernetes 滚动部署和数据库迁移

Posted

技术标签:

【中文标题】Kubernetes 滚动部署和数据库迁移【英文标题】:Kubernetes rolling deployments and database migrations 【发布时间】:2018-07-30 08:07:16 【问题描述】:

在处理带有数据库迁移的滚动更新时,kubernetes 如何处理这个问题?

例如 - 我有一个从 app-v1 更新到 app-v2 的应用程序,其中包括更改现有表的迁移步骤。所以这意味着它需要我在部署后为 Rails 应用程序运行类似 db:migrate 的东西。

当滚动部署发生在 3 个副本集上时。它将从一个吊舱部署到另一个吊舱。可能允许没有新版本应用程序的 POD 中断。

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

【问题讨论】:

【参考方案1】:

防止旧版本中断的一种方法是将迁移拆分为多个步骤。

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

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

不幸的是,这很麻烦,但可以防止在维护页面打开时出现停机。

【讨论】:

这是一篇很好的文章,解释了这个想法:spring.io/blog/2016/05/31/…【参考方案2】:

Kubernetes 本身并不通过数据库迁移处理滚动更新。这是特定于应用程序的,因此应用程序开发人员必须处理它。您可能必须做与非 k8s 设置中相同的事情。

无论如何,我会这样做:

将您的副本扩展到 1 个。 更新图片。 将您的副本扩展到 3 个。

这不是万无一失的,但不涉及代码更改。在 db:migrate 步骤和实际服务器监听之间有一个小窗口,请求将转到旧副本(一旦新副本准备好,它将终止)。该请求可能会失败,也可能不会失败,具体取决于代码块是否与架构更改直接相关。

如果我不太关心停机时间,那么我会使用重新创建策略。

【讨论】:

【参考方案3】:

我最近正在解决这个问题,这是我的方法:

使用deployment annotations 存储您通常需要在部署之前或之后运行的命令。 创建一个能够按名称读取您的部署的脚本,然后创建一个作业来运行部署注释中指定的命令。 将图像推送到 docker 注册表时,添加一个 webhook,它将调用您在上一点中指定的脚本。 为避免与不兼容的数据库结构相关的问题: 不要以向后不兼容的方式修改 db 列。 不要立即删除迁移中未使用的列。您可以在下一个版本中执行此操作。这样你就只有一个 您将在部署之前运行的迁移脚本。

附:为了能够在您的脚本中使用 Kubernetes,您可能需要熟悉以下链接:Kubernetes API、Kubernetes API Overview、Access Clusters Using the Kubernetes API、Client Libraries。

【讨论】:

这听起来很有希望,但我不确定我是否理解第 3 点。您能否举例说明这将如何工作? @GregFerreri 不幸的是,我为此编写的应用程序不是开源的,但我用 golang 编写了它,在 Kubernetes(读/写部署和作业)中提供了访问权限,它作为 http 守护进程进行侦听并执行描述的东西。

以上是关于Kubernetes 滚动部署和数据库迁移的主要内容,如果未能解决你的问题,请参考以下文章

Oracle数据库部分迁至闪存存储方案

Elasticsearch数据迁移与集群容灾

Redis数据库备份、迁移、恢复实践

在自动缩放条件下重新部署时,Kubernetes 滚动更新不遵守“maxUnavailable”副本

使用 EF 4.1 部署数据库更改

使用容器编排处理 EF Core 迁移