docker - 如何使用 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 容器内创建版本文件并更新数据库。
要显示问题的分步示例:
- sh 进入服务器部署 pod 并运行 db init。
- 迁移文件夹已创建。
- 在创建迁移文件并更新数据库的服务器部署上执行迁移。
- postgres pod db 输入 alembic_version 并进行更新。
- 使用 skaffold 删除或 ctrl-c skaffold。
- server-deployment pod 被删除,但 postgres 没有。迁移文件夹消失。
- 开始备份 skaffold 和 sh 到 server-deployment pod 并尝试运行 db migrate。要求您执行 db init。
- 如果您尝试从这里降级,它不会做任何事情。现在服务器 pod 和 postgres pod 在 alembic_version 方面不同步。
最后的笔记
我以前做的 pre-docker/kubernetes 是在本地运行它,然后我会将迁移版本文件提交到我的 repo。它在所有环境中同步,因此每个人的 repo 都在同一个 alembic_version 上。我考虑过创建一个单独的、永远在线的“迁移部署”pod,它是烧瓶的另一个实例,因此它永远不会丢失 /migrations/ 文件夹。然而,这似乎是一个非常糟糕的解决方案。
希望有最佳实践或想法!
解决方案
我想出了一个办法来处理这个问题。在其他人确认这是否是一个好方法之前,我不会将其设置为正确答案。
基本上,我所做的是创建一个持久卷声明。在服务器部署中,我将迁移/文件夹连接到该持久卷。这样,每当 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!
推荐阅读
- python - 如何解决在变量中使用类的问题
- python - 多类分类 xgboost python 中 eval_set 的正确设置,错误是“检查失败:preds.size() == info.labels_.size()”
- javascript - Mongo - 基于名称的值总和聚合
- python - 带有 CSV 阅读器和 StringIO 的 Python 3 使用过多的内存
- java - Cannot call setVisibility method when trying to show/unhide my LinearLayout
- python - 使用python读取多个word文档并将结果按重要性排序输出到excel
- python - 计算表示马尔可夫链规则的字典中值的总频率和相对频率
- ios - 将多维数组转换为 Data 对象以进行 TF 推理
- python - 如何在循环中动态创建目标文件名列表?
- android - 如何向我的 JSON 请求添加自定义授权标头?