GitLab CI 示例:利用 CI 同步生产环境数据库到开发环境
发表于 2018-11-21
作者: 灼灼团队
本文字数: 3336
阅读时长 ≈ 11.1 分钟

# 问题

我们通常需要频繁的将生产环境(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。

# 示例代码

# .gitlab-ci.yml
stages:
  - dump
  - upload
  - restore

before_script:
  - if [ $TO = dev ];then export SERVER_HOST=$DEV_SERVER_HOST;fi
  - if [ $TO = stg ];then export SERVER_HOST=$STG_SERVER_HOST;fi
  - if [ $PROJECT = project-a ];then export MONGO_DB=project-a-db;fi
  - if [ $PROJECT = project-b ];then export MONGO_DB=project-b-db;fi
  - if [ $PROJECT = project-c ];then export MONGO_DB=project-c-db;fi
  
cache:
  paths:
    - tmp_data

dump_db:
  image: mongo:latest
  stage: dump
  script:
    - rm -rf tmp_data || true
    - mkdir tmp_data || true
    - >
      mongodump -h $MONGO_HOST --port=$MONGO_PORT -u $MONGO_USER
       -p $MONGO_PASSWORD -d $MONGO_DB --out=tmp_data
    - cd tmp_data/$MONGO_DB && tar -zcvf ./../data.tar.gz ./*
  only:
    variables:
      - $PROJECT
      - $TO

upload_db:
  image: laogen/openssh-client:latest
  stage: upload
  script:
    - eval $(ssh-agent -s)
    - echo "$SERVER_SSH_PRIV_KEY" > deploy.key
    - mkdir -p ~/.ssh
    - chmod 0600 deploy.key
    - ssh-add deploy.key
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - ssh root@$SERVER_HOST "rm -rf /srv/db-data/$PROJECT/_data/ || true"
    - ssh root@$SERVER_HOST "rm -rf /srv/db-data/$PROJECT/data.tar.gz || true"
    - scp tmp_data/data.tar.gz root@$SERVER_HOST:/srv/db-data/$PROJECT/data.tar.gz
    - ssh root@$SERVER_HOST "mkdir -p /srv/db-data/$PROJECT/_data || true"
    - ssh root@$SERVER_HOST "tar zxvf /srv/db-data/$PROJECT/data.tar.gz -C /srv/db-data/$PROJECT/_data"
  only:
    variables:
      - $PROJECT

restore:
  image: laogen/openssh-client:latest
  stage: restore
  script:
    - eval $(ssh-agent -s)
    - echo "$SERVER_SSH_PRIV_KEY" > deploy.key
    - mkdir -p ~/.ssh
    - chmod 0600 deploy.key
    - ssh-add deploy.key
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - scp restore.sh root@$SERVER_HOST:/srv/db-bak/$PROJECT/restore.sh
    - export CONTAINER_ID='$(docker ps -f name='$PROJECT' -f ancestor=bitnami/mongodb -q)'
    - ssh root@$SERVER_HOST "docker exec $CONTAINER_ID sh /bitnami/restore.sh"
  only:
    variables:
      - $TO
      - $PROJECT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

这个 Pipeline 有三个 stages:

- dump 从 prod 数据库中把数据导出为文件
- upload 将数据文件上传到 dev/stg 目标服务器
- restore 通过 ssh 远程连接到目标服务器,将数据文件导入(restore)到 mongo 中

其中涉及的 ssh 等操作前文具体讲过,不了解的话可移步 {% post_link gitlab-ci/example-docker-ssh-deploy GitLab CI 示例:Docker 镜像打包发布 & SSH 部署 %}。

这段 CI 脚本是我在实际工作中使用的,其中 mongodb 是使用 bitnami/mongodb 镜像启动的,所以会有 bitnami 相关的字眼,需要了解的话请查看文末的相关链接。

如果使用其它 mongo 镜像或者其它数据库( mysql 等)需要做相应的调整,这里只是提供一个思路作为参考。

restore.sh 这个文件在 git repo中,它被挂载到数据库容器中执行的:

# restore.sh
mongorestore --drop -u $MONGODB_USERNAME -p $MONGODB_PASSWORD -d $MONGODB_DATABASE /bitnami/_data
1
2

# 触发同步

我们通过 $PROJECT 来控制要同步哪个项目的数据库; 通过 $TO 控制要同步到哪个服务器环境(develop / staging)。

# 同步 project-a 项目的数据库到 dev 环境
curl -X POST -F token=XXXXXXX \
    -F ref=master -F "variables[TO]=dev" \
    -F "variables[PROJECT]=project-a" \
    https://gitlab.com/api/v4/projects/xxxxxx/trigger/pipeline
1
2
3
4
5
# 同步 project-b 项目的数据库到 stg 环境
curl -X POST -F token=XXXXXXX \
    -F ref=master -F "variables[TO]=stg" \
    -F "variables[PROJECT]=project-b" \
    https://gitlab.com/api/v4/projects/xxxxxx/trigger/pipeline
1
2
3
4
5

我们通过 GitLab CI 的 HTTP 触发机制触发 Pipeline 的执行。 其中 tokenurl 在 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
联系我们
联系电话:17681177133
联系邮箱:admin@zhuo-zhuo.com
公司地址:合肥市高新区习友路2666号 (习友路和石莲南路交叉口西北角)二期304室
官网
博客
皖ICP备20009670号-2
合肥灼灼信息技术有限公司 | Copyright © 2020-present zhuo-zhuo.com