简体   繁体   English

如何使用Kubernetes和Skaffold处理数据库迁移

[英]How to handle database migrations with Kubernetes and Skaffold

The issue: 问题:

Locally, I use Skaffold (Kubernetes) to hot reload both the client side and server side of my code. 在本地,我使用Skaffold(Kubernetes)来热重新加载我的代码的客户端和服务器端。 When I shut it down, it deletes my server pod, including my /migrations/ folder and thus gets out of sync with my database alembic_version. 当我关闭它时,它会删除我的服务器pod,包括我的/ migrations /文件夹,因此与我的数据库alembic_version不同步。 On production, I'm not deleting my server pod, but I am rebuilding the docker image when I deploy which results in my /migrations/ folder being replaced. 在生产时,我不是删除我的服务器pod,但是在部署时我正在重建docker镜像,导致我的/ migrations /文件夹被替换。

The question 这个问题

How do I handle these migrations so my database doesn't get out of sync? 如何处理这些迁移,以便我的数据库不会失去同步?


application setup 应用程序设置

Flask/Python API and use Flask Migrate. Flask / Python API并使用Flask Migrate。 For those unfamiliar, what it does is create a migrations folder with version files like 5a7b1a44a69a_.py . 对于那些不熟悉的人,它的作用是创建一个包含5a7b1a44a69a_.py等版本文件的迁移文件夹。 Inside of that file are def upgrade() and downgrade() to manipulate the db. 在该文件内部是def upgrade()downgrade()来操纵数据库。 It also records the revision and down_revision references for the alembic_version table in my postgres pod. 它还记录了postgres pod中alembic_version表的修订版和down_revision引用。

Kubernetes and Docker setup Kubernetes和Docker设置

I have a server pod and postgres pod. 我有一个服务器pod和postgres pod。 I login to the shell of the server pod to run the migrate commands. 我登录到服务器pod的shell以运行migrate命令。 It creates the version files inside of the docker container and updates the db. 它在docker容器内创建版本文件并更新db。

To show a step-by-step example of the problem: 要显示问题的分步示例:

  1. sh into server-deployment pod and run db init. 进入服务器部署pod并运行db init。
  2. Migrations folder is created. 迁移文件夹已创建。
  3. perform migration on server-deployment which creates migration file and updates the db. 在服务器部署上执行迁移,从而创建迁移文件并更新数据库。
  4. postgres pod db gets alembic_version entered and an update. postgres pod db输入alembic_version并进行更新。
  5. use skaffold delete or ctrl-c skaffold. 使用skaffold delete或ctrl-c skaffold。
  6. server-deployment pod gets deleted, but postgres doesn't. 服务器部署pod被删除,但postgres没有。 Migrations folder goes away. 迁移文件夹消失了。
  7. Start back up skaffold and sh into server-deployment pod and try to run db migrate. 开始备份skaffold并进入服务器部署pod并尝试运行db migrate。 Asks you to do an db init. 要求你做一个db init。
  8. If you try to downgrade from here, it doesn't do anything. 如果您尝试从此处降级,则不会执行任何操作。 Now server pod and postgres pod are out of sync in terms of alembic_version. 现在服务器pod和postgres pod在alembic_version方面不同步。

Final Notes 最后的笔记

What I used to do pre-docker/kubernetes was run it locally and I would commit that migrations version file to my repo. 我以前做的pre-docker / kubernetes是在本地运行的,我会将迁移版本文件提交到我的repo。 It was synced across all environments so everyone's repo was on the same alembic_version. 它在所有环境中同步,因此每个人的回购都在同一个alembic_version上。 I've considered created a separate, always-on "migrations-deployment" pod that is another instance of flask so that it never loses the /migrations/ folder. 我已经考虑创建一个单独的,永远在线的“迁移 - 部署”窗格,它是另一个烧瓶实例,因此它永远不会丢失/ migrations /文件夹。 However, that seems like a really poor solution. 然而,这似乎是一个非常糟糕的解决方案。


Hoping for best practices or ideas! 希望获得最佳实践或想法!

I figured out a way to handle this. 我找到了解决这个问题的方法。 I'm not going to set it as the correct answer until someone else confirms if this is a good approach. 在其他人确认这是否是一个好方法之前,我不会将其设置为正确的答案。

Basically, what I did was create a Persistent Volume Claim. 基本上,我所做的是创建一个永久卷声明。 Inside the server-deployment I hook up the migrations/ folder to that Persistent Volume. 在服务器部署中,我将迁移/文件夹连接到该持久卷。 That way, whenever the pod gets deleted, the migrations/ folder remains and gets persisted across pod restarts. 这样,无论何时删除pod,迁移/文件夹都会保留并在pod重新启动后保持不变。

It would look something like this inside the server deployment. 它在服务器部署中看起来像这样。

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

The PVC would look like this: PVC看起来像这样:

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

For those who decide to take this approach with flask migrate, there's a tricky "chicken or the egg" issue. 对于那些决定采用这种方法进行烧瓶迁移的人来说,有一个棘手的“鸡或鸡蛋”问题。 When you run flask db init, it creates the migrations/ folder with some stuff in it. 运行flask db init时,它会创建包含一些内容的迁移/文件夹。 However, if there's a PVC creating the empty migrations/ folder, flask migrate already thinks the folder exists. 但是,如果有一个PVC创建空迁移/文件夹,那么flask migrate已经认为该文件夹存在。 You can't delete the folder either with rmdir because it's got a working process on it. 你不能用rmdir删除文件夹,因为它有一个工作过程。 However, you need to get the contents of the flask migrate init command into the empty migrations/ folder..... 但是,您需要将flask migrate命令的内容放入空迁移/文件夹中.....

The trick I found was: 我找到的诀窍是:

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

This intialized all the files you need into a new "migration" folder. 这会将您需要的所有文件初始化为新的“迁移”文件夹。 You then copy it all into the migrations/ folder to persist from then on. 然后,将其全部复制到迁移/文件夹中,以便从那时起保留。 Flask migrate automatically looks for that folder if you leave out the --directory flag. 如果省略--directory标志,Flask migrate会自动查找该文件夹。

Then delete the migration folder rmdir migration (or just wait until your pod restarts in which case it'll disappear anyways). 然后删除迁移文件夹rmdir migration (或者等到你的pod重新启动,在这种情况下它将会消失)。

You now have a proper migrations/ folder with everything in it. 您现在拥有适当的迁移/文件夹,其中包含所有内容。 When you close your flask pod and restarted, the PVC injects that filled up migrations/ folder back into the pod. 当您关闭烧瓶舱并重新启动时,PVC将填充的迁移/文件夹注入到容器中。 I can now upgrade/downgrade. 我现在可以升级/降级。 Just have to be careful not to delete the pvc! 只是要小心不要删除pvc!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM