首页 > 解决方案 > 如何使用 Kubernetes 和 Skaffold 处理数据库迁移

问题描述

问题:

在本地,我使用 Skaffold (Kubernetes) 热重载代码的客户端和服务器端。当我关闭它时,它会删除我的服务器 pod,包括我的 /migrations/ 文件夹,因此与我的数据库 alembic_version 不同步。在生产中,我不会删除我的服务器 pod,但我会在部署时重建 docker 映像,这会导致我的 /migrations/ 文件夹被替换。

问题

如何处理这些迁移,以使我的数据库不会不同步?


应用程序设置

Flask/Python API 并使用 Flask Migrate。对于那些不熟悉的人,它的作用是创建一个带有版本文件的迁移文件夹,例如5a7b1a44a69a_.py. 该文件的内部是def upgrade()downgrade()操作数据库。它还记录了我的 postgres pod 中 alembic_version 表的修订和 down_revision 引用。

Kubernetes 和 Docker 设置

我有一个服务器 pod 和 postgres pod。我登录到服务器 pod 的 shell 以运行迁移命令。它在 docker 容器内创建版本文件并更新数据库。

要显示问题的分步示例:

  1. sh 进入服务器部署 pod 并运行 db init。
  2. 迁移文件夹已创建。
  3. 在创建迁移文件并更新数据库的服务器部署上执行迁移。
  4. postgres pod db 输入 alembic_version 并进行更新。
  5. 使用 skaffold 删除或 ctrl-c skaffold。
  6. server-deployment pod 被删除,但 postgres 没有。迁移文件夹消失。
  7. 开始备份 skaffold 和 sh 到 server-deployment pod 并尝试运行 db migrate。要求您执行 db init。
  8. 如果您尝试从这里降级,它不会做任何事情。现在服务器 pod 和 postgres pod 在 alembic_version 方面不同步。

最后的笔记

我以前做的 pre-docker/kubernetes 是在本地运行它,然后我会将迁移版本文件提交到我的 repo。它在所有环境中同步,因此每个人的 repo 都在同一个 alembic_version 上。我考虑过创建一个单独的、永远在线的“迁移部署”pod,它是烧瓶的另一个实例,因此它永远不会丢失 /migrations/ 文件夹。然而,这似乎是一个非常糟糕的解决方案。


希望有最佳实践或想法!

标签: dockerflaskkubernetesskaffold

解决方案


我想出了一个办法来处理这个问题。在其他人确认这是否是一个好方法之前,我不会将其设置为正确答案。

基本上,我所做的是创建一个持久卷声明。在服务器部署中,我将迁移/文件夹连接到该持久卷。这样,每当 pod 被删除时,migrations/ 文件夹就会保留下来,并在 pod 重新启动时保持不变。

它在服务器部署中看起来像这样。

      containers:
      ..........
        volumeMounts:
          - name: migrationstuff
            mountPath: 'MyServerApplicationDirectory/migrations'
      volumes:
        - name: migrationstuff
          persistentVolumeClaim:
            claimName: migrate-pvc

PVC 看起来像这样:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: migrate-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

对于那些决定采用这种烧瓶迁移方法的人来说,有一个棘手的“先有鸡还是先有蛋”的问题。当您运行 flask db init 时,它会创建带有一些东西的 migrations/ 文件夹。但是,如果有一个 PVC 创建了空的 migrations/ 文件夹,flask migrate 已经认为该文件夹存在。您也不能使用 rmdir 删除该文件夹,因为它有一个工作进程。但是,您需要将 flask migrate init 命令的内容放入空的 migrations/ 文件夹中......

我发现的窍门是:

python flask db init --directory migration
mv migration/* migrations/

这将您需要的所有文件初始化到一个新的“迁移”文件夹中。然后,您将其全部复制到 migrations/ 文件夹中以从那时起持续存在。如果您省略 --directory 标志,Flask migrate 会自动查找该文件夹。

然后删除迁移文件夹rmdir migration(或者等到您的 pod 重新启动,在这种情况下它无论如何都会消失)。

您现在有一个适当的 migrations/ 文件夹,其中包含所有内容。当您关闭烧瓶 pod 并重新启动时,PVC 会将填满的 migrations/ 文件夹注入到 pod 中。我现在可以升级/降级。只是要小心不要删除pvc!


推荐阅读