Kubernetes 中使用 Flyway 进行数据库迁移

手工迁移数据库时代

在数据库版本管理概念还没有流行起来的时候,或者是系统规模还不大,只需要维护一个数据库时,数据库管理员常采用直接在数据库中执行sql语句,或者用脚本的方式来导入sql文件来迁移数据库,而在某个git仓库中保存初始化数据的全量脚本,或者是每次更新时再记录下增量脚本。

手工的方式在只需要维护单个数据库还是可以胜任的,但是现实场景中,往往需要维护多个环境的数据库且迁移较频繁,这就导致了如下问题:

  1. 如何确认各环节数据库的迁移变更是否一致
  2. 当前环境的数据库迁移到哪个步骤了

《持续交付》中的数据管理建议

由于手工方式迁移数据库存在以上的弊端,在《持续交付:发布可靠软件的系统方法》中数据管理方面有如下原则于实践:

  1. 像代码版本控制那样,管理初始化数据的版本
  2. 通过自动化脚本来应用数据库变更
  3. 每个修改都要可以执行回滚
  4. 新的数据版本最好保证向后兼容性
  5. 测试数据可以分不同环境来维护,尽量用程序API的方式导入测试数据,而不是直接写入数据库中
  6. 数据版本应与应用程序版本解耦

在 K8s 环境中应用 Flyway 的演示

Flyway是一种 Java 编写的数据库管理工具,可以通过命令行工具、Java API 、Maven插件等形式使用,支持 Mysql 、Postgres等关系型数据库。

Flyway基于原生的sql语句来实现数据库迁移,并在sql文件名的样式要求上体现版本管理,并且通过创建迁移历史记录表来描述某个数据库的迁移状态,通过sql文件和历史记录表的对比保证数据变更的幂等性,可以满足基本的数据管理要求。关于Flyway的更多信息可以参考官方文档。

在 K8s 环境中应用 Flyway 的演示主要参考这个博客:https://developers.redhat.com/blog/2018/01/10/flyway-containerized-db-changes/

步骤1:创建演示数据库,以 Postgres 为例
先创建个 namespace 用于演示

kubectl create namespace flyway

创建 Postgres 数据库,里面已经包含一些数据了

kubectl -n flyway run pgsql --image=jbossdevguidebook/beosbank_posgres_db_europa:latest

查看数据库信息

psql -U postgres        # 进入数据库
\l                                 # 列出数据库信息
\connect  beosbank-europa   #  切换到 beosbank-europa
\d                                # 列出数据表信息
select * from eu_customer;    # 列出数据表 eu_customer 的内容

步骤2: 构建 Flyway 镜像
下载参考博客中的github仓库

git clone https://github.com/nelvadas/ocp-flyway-db-migration.git
ocp-flyway-db-migration

构建 Flyway 镜像,也可以直接用 Flyway 的官方镜像,但是要注意 sql 文件的存放路径

docker build -t jbossdevguidebook/flyway:v1.0.4-rhdblog .

步骤3:创建 ConfigMap 及 Job
Flyway镜像要封装到 K8s workload 中运行,参考博客中推荐的有 Deployment,Job,CronJob,InitContainer 还有边车容器的形式,由于 flyway 的迁移命令本身就是执行一次就推出的,而且也为了演示方便,这里选择 Job 来封装 Flyway。

# beosbank-flyway-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: beosbank-dbupdater-job
spec:
  template:
    metadata:
      name: beosbank-dbupdater
    spec:
      containers:
        - name: db-updater
          image: jbossdevguidebook/flyway:v1.0.4-rhdblog
          volumeMounts:
            - name: sql-configmap-volume
              mountPath: /var/flyway/data/
          env:
          - name: DB_USER
            value: root
          - name: DB_PASSWORD
            value: Europa01#
          - name: DB_URL
            value: "jdbc:postgresql://beosbank-posgres-db-europa/beosbank-europa"
      restartPolicy: Never

      volumes:
      - name: sql-configmap-volume
        configMap:
          name: sql-configmap

从yaml文件中可以看到,Flyway迁移使用的sql文件是放在 /var/flyway/data/ 这个目录下的,为了使后续可以更改,我们将sql文件内容保存在 ConfigMap 中,然后挂载到容器里。

创建包含迁移文件的 ConfigMap

kubectl -n flyway create cm sql-configmap --from-file=./sql

创建 Job

kubectl -n flyway create -f beosbank-flyway-job.yaml

步骤4:查看迁移结果

kubectl -n flyway logs job/beosbank-dbupdater

可以看到每个迁移文件对应的版本和描述,它们会按照版本大小顺序执行。
此时登录数据库也可以看到变更后的数据库以及迁移历史记录表

在实际应用中的优化设想

任何一项工具和技术在实际使用中,还要考虑多部门的分工协作以及融入现有流程等问题。

这里设想下以 Flyway 为工具的数据管理在实际使用中的流程,希望不久后能用上:
1.数据库初始化数据与应用程序息息相关,因此应该由开发人员主要维护 迁移sql文件,这样也比较好命名。

2.在本地开发环境,以及前期的非 K8s 测试环境中,数据迁移可以通过 Flyway 的 Java API来实现,在每次程序启动后正常连接数据库时执行,sql 文件应该以一个独立的 git 仓库存放,并通过 git submodule 同步到应用程序所在的仓库中,这样每次迁移时就可以从程序的某个路径下读取迁移文件;独立 git 仓库的形式,又有利于后续上生产环境后,数据版本可以独立于应用程序的版本升级,实现解耦。

3.在生产环境 K8s 集群中,可以关闭 Flyway Java API,把 Flyway 作为边车容器和应用程序部署到一个 Pod 中,在数据库实例启动后,应用容器启动前完成初始化操作。

此时 Flyway 应该被脚本包装成一个不停监听 sql 文件路径的后台进程,并在有新的sql文件加入时执行一次迁移命令。

为了实现用于迁移的 sql 文件的动态加载,以及版本管理的需求,可以给 Flyway 边车容器设置一个 InitContainer ,初始化容器的镜像就是之前的 sql 文件 git 仓库打包而来,并以最新的sql文件版本作为镜像 tag ,它的主要功能就是把最新的迁移文件拷贝的 Flyway 监听的 sql 文件路径下,这样每当初始化容器的版本变动时,Flyway都会重新执行一次迁移命令,优雅地实现数据版本迭代。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wonain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值