前言:
现在同学们对“ubuntu快照备份”大体比较着重,大家都想要知道一些“ubuntu快照备份”的相关内容。那么小编也在网摘上网罗了一些有关“ubuntu快照备份””的相关知识,希望看官们能喜欢,兄弟们快快来学习一下吧!本文方案仅供技术参考与娱乐!
前言
数据很重要,所以我们要经常备份。
那么怎么备份呢?假如我们使用云厂商的数据库,里面已经自带了快照和备份功能了,只要你愿意花钱,就能帮你解决大部分技术问题。它们这些数据库往往是部署在单独一/多台主机实例上,不会放在容器里去跑。为什么?俺也不是专业的运维,俺也不知道。这里给个知乎链接作为参考
对于我们个人项目而言,一般不会去购买昂贵的数据库实例,往往 云主机容器部署 + serverless + oss/cdn 就能满足绝大部分开发的需求了。很多时候简单的 docker compose up -d 就够用了,然后再加个开源的BAAS平台:supabase 一起组网,开发爽的不要不要的。
说远了,接下来进入本篇的正题:如何设计一个方案,把 Github Repo 转化为我们数据库备份的对象存储,并利用CI持续化集成呢?
方案设计与拆解
显然,思考如何把大象装进冰箱,我们要把整个过程拆解成以下几个步骤:
链接远程机器
导出数据库文件
下载与上传数据库备份文件
数据库备份的增删管理
这样我们只需要依次实现对应的功能,再把功能串联起来就达到我们的目标了。
本文运行环境:云主机为 华为云,数据库为 postgres
数据库备份方案
备份数据库通常非常简单,主要分为 2 步:
db dump
upload to Amazon S3/Aliyun OSS/Tencent Cloud COS /...
这个很容易理解,写个 shell 脚本,导出数据库,上传到 OSS。然后把它设置成定时任务就行。
然而本文的邪道方案中,我们需要使用 github action 来远程连上云主机,然后执行脚本获取数据库备份,再同步到 git 仓库。
这显然要复杂许多,于是我就学习了一会shell编程,写了一段脚本,具体思考调试过程可以见注释:
#!/bin/shFILENAME=$(date +"%Y%m%d-%H%M%S") # 时间戳文件名BASENAME="${FILENAME}.dump" # +后缀KEY_PATH=./xxx.pem # ssh私钥路径DESTINATION=root@xxx.xxx.xxx.xxx # 云主机登录用户以及ip地址DUMP_FILE_PATH=/path/to/${BASENAME} # 云主机 dump 文件路径CONTAINER_NAME=container-name # 云主机数据库容器名称PG_USER=postgres # 云主机数据库容器登录用户# Permissions 0400 for './*.pem' are too open# 修改私钥权限,避免 Permissions too open 问题chmod 400 $KEY_PATHecho " -> Connecting $DESTINATION and Dumping"# dump datebase from docker container# option StrictHostKeyChecking=accept-new for ssh key prompt# 这里设置 StrictHostKeyChecking=accept-new 来避免初次由于 .ssh/known_hosts 不存在,导致的 prompt 问题# 相当于执行了3个命令,ssh <command> / docker exec <command> / sh -c "db_dump"# 把 dump 出来的数据文件,放到docker的挂载卷中ssh -o StrictHostKeyChecking=accept-new -i $KEY_PATH $DESTINATION "docker exec -u $PG_USER $CONTAINER_NAME sh -c \"pg_dump -Fc postgres > /var/lib/postgresql/data/${BASENAME}\""echo " -> Downloading $DUMP_FILE_PATH"# download dump file to git repo# 把dump文件下载到本地scp -i $KEY_PATH $DESTINATION:$DUMP_FILE_PATH ./${BASENAME}echo " -> Deleting $DUMP_FILE_PATH"# delete dump file# 下载完成后,删除服务器上的 dump 文件ssh -i $KEY_PATH $DESTINATION rm $DUMP_FILE_PATHecho ""echo "...done!"echo ""
其中,使用秘钥和 StrictHostKeyChecking=accept-new 都是为了免 prompt 登录。在执行备份数据库命令时要注意字符串的转义。
另外在调试时,还遇到了一个问题,我们 docker exec -it <c_name>,进入容器中执行 su <user> 是可行的,但是直接 docker exec <c_name> <command> 里面 su,生成出来的 dump 文件所属却是 root! 必须要使用 -u 参数,指定 <user> 才行。这里我并不理解,希望懂的人可以告诉我这个问题的原因。
通过这些步骤,就顺利的把数据库备份文件,给下载到了 git 仓库里了。
删除数据库Blob文件方案
既然我们已经下载到了数据库文件了,我们就要对这些文件进行管理。
比如我们目标是,保存最近 7 次备份的文件,那么显然我们要把比较旧的数据库文件给删除掉,那么怎么做呢?
这里我也做了一个简单设计:
DUMPS=$(ls | grep ".dump$") # 获取当前目录所有的 .dumpCOUNT=$(echo "$DUMPS" | wc -l) # .dump文件个数SORTED_LIST=$(echo "$DUMPS" | sort -k1.1n) # 按照时间排个序KEEP_BLOB_COUNT=7 # 保留数据文件的个数if [ "$COUNT" -gt "${KEEP_BLOB_COUNT}" ]; then DEL_COUNT=$(expr $COUNT - ${KEEP_BLOB_COUNT}) # 删除个数 echo "DELETE COUNT:${DEL_COUNT}" DEL_LIST=$(echo "$SORTED_LIST" | head -n $DEL_COUNT) # 删除文件名列表 for i in $DEL_LIST; do echo "DELETEING ${i}..." rm $i # 删除过时的数据 echo "DELETE ${i} SUCCESSFUL!" donefi
避免Git仓库过大方案
我们知道 git 仓库一直是在增大的,当我们删除一个文件的时候,看似这个文件从我们的工作目录中消失了,实际上这个文件并没有被删除,而是跑到了 git history 里面去,久而久之这个项目就越来越大了,因为之前所以被删除的文件,还是被保存在 .git 文件夹里。
那么怎么避免这个问题呢?
Github给了一个解决方案见 removing-sensitive-data-from-a-repository。文章里,给我们介绍了 2 种工具,分别是 java 写的 BFG Repo-Cleaner 和 python 写的 git-filter-repo。
然而我都不想用...
我回想起了很多年前,看到的一则谣言:程序员枪杀四名同事的新闻。
霎时,想到了一个天怒人怨的命令:git push -f !
我们可以使用这个方式,强制更新我们的 git 仓库,把它当成一个 OSS 来用啊!
那么脚本就很容易设计出来了:
git config --global user.email "your_name@gmail.com"git config --global user.name "icebreaker-bot"git checkout --orphan latest_branch # 创建个纯洁的孤儿分支git add -Agit commit -am "project recreate"git branch -D maingit branch -m maingit push -fu origin main # 嘿嘿
当然,这段脚本只适合在自己把控范围内去使用。切勿在工作中使用,不然就会出现几把机械键盘直接砸到脸上的暴力场景。
Github Action CI
最后,我们接下来把上述这三段脚本,串联起来。然后写一个 yml 文件交给 action 定时执行就大功告成啦!
name: Sync_Datebaseon: schedule: # UTC时间触发 - cron: "0 0 * * *" workflow_dispatch:jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run sync script run: | chmod 755 ./bak.sh chmod 755 ./del.sh chmod 755 ./git-clear.sh ./bak.sh
这样每次执行完这个脚本,整个仓库焕然一新,历史永远就只有一条了。(笑~)
尾言
这种方式去备份数据库,显然是一种邪魔歪道,有点钻牛角尖,不过思考实现的过程却比较有趣,有兴趣的同学可以参照本文实现一下。
还有 Github ssh 下载实际上速度是很快的,但是由于某些zg特色因素,大概率网速会变成小水管。这种情况可以转而使用某些国内代码托管商,来尝试这个方案。
最后方案并不完美,欢迎建议和意见。
标签: #ubuntu快照备份