问题
我们通常需要频繁的将生产环境(production)的数据库同步到 develop 和 staging 环境。
之前我们的做法是写了一个 shell 在服务器上手动运行,这个需要测试人员和开发人员拥有服务器权限,甚至是生产环境的权限,风险较大且 “不够 CI/CD 化”。
后来是想写一个 HTTP 服务来触发这样的数据库同步操作,增加了额外的工作开销,还要为这个服务配相应的 CI/CD,不如直接使用 GitLab CI 来完成这个工作。
GitLab CI Pipeline 不仅可以在用户 push 代码的时候被触发,还可以通过 HTTP 调用的形式主动触发。
目标
开发 & 测试人员将 production 环境的数据库同步到 develop / staging 环境:
- 无需接触服务器环境
- 任意时间可主动进行同步(相对于计划任务而言)
- 可指定同步某个项目相关的数据库
- 可指定同步到某个服务器环境 ( develop / staging )
预设场景:
- 有三个数据库项目:project-a project-b project-c
- 有三个服务器环境:production develop staging
- 通过 GitLab CI Pipeline Triggers 来触发执行(HTTP方式)
- 我们可任意指定同步某一个项目的 production 数据库到 develop 或 staging
首先,我们建了一个新的 GitLab Repo,可以叫作 db-sync
,并开始配置其 CI Pipeline。
示例代码
1 | # .gitlab-ci.yml |
这个 Pipeline 有三个 stages:
- dump 从 prod 数据库中把数据导出为文件
- upload 将数据文件上传到 dev/stg 目标服务器
- restore 通过 ssh 远程连接到目标服务器,将数据文件导入(restore)到 mongo 中
其中涉及的 ssh 等操作前文具体讲过,不了解的话可移步 GitLab CI 示例:Docker 镜像打包发布 & SSH 部署。
这段 CI 脚本是我在实际工作中使用的,其中 mongodb 是使用 bitnami/mongodb
镜像启动的,所以会有 bitnami
相关的字眼,需要了解的话请查看文末的相关链接。
如果使用其它 mongo
镜像或者其它数据库( mysql
等)需要做相应的调整,这里只是提供一个思路作为参考。
restore.sh
这个文件在 git repo中,它被挂载到数据库容器中执行的:1
2# restore.sh
mongorestore --drop -u $MONGODB_USERNAME -p $MONGODB_PASSWORD -d $MONGODB_DATABASE /bitnami/_data
触发同步
我们通过 $PROJECT
来控制要同步哪个项目的数据库;
通过 $TO
控制要同步到哪个服务器环境(develop / staging)。
1 | # 同步 project-a 项目的数据库到 dev 环境 |
1 | # 同步 project-b 项目的数据库到 stg 环境 |
我们通过 GitLab CI 的 HTTP 触发机制触发 Pipeline 的执行。
其中 token
和 url
在 GitLab 仓库的设置页面获取 Settings > CI/CD > Pipeline triggers > Add trigger
,该页面中有详情的使用说明。
小结
上面触发的例子是通过 curl
发送请求完成的,也可以使用 Webhook 的方式,这样可以把请求链接加入到浏览器的书签中,需要同步数据库的时候,直接打开相应的书签即可快捷完成。
这种方式不仅可以用来同步数据库,还可以用来同步其它生产环境的数据,比如文件资源等。
同时,除去用来同步数据,也可用于备份数据等工作。
相关链接
- bitnami/mongodb: https://github.com/bitnami/bitnami-docker-mongodb
- MongoDB 备份(mongodump)与恢复(mongorestore)
http://www.runoob.com/mongodb/mongodb-mongodump-mongorestore.html