












我需要备份 gitlab、禅道 数据,到一个新的机器上,新的机器主要用于存储上述服务的数据,请问改用 ftp、nfs、nas、minio,或是其他?是否有更好的选择?请给我一些较好的方案策略
场景说明:现有业务机器运行GitLab、禅道;新增一台独立机器专门存放备份数据,不运行业务,只做备份归档,需要对比 FTP / NFS / NAS / MinIO,给出多套可落地方案,包含优缺点、适用场景、完整备份策略。
GitLab官方备份支持两种:
gitlab-backup全量备份包 + 单独备份/etc/gitlab配置
zentaopms/www/data)两类业务都包含:数据库(逻辑备份) + 大量小文件(附件、代码仓库)。备份特点:既有数据库dump,又有海量小文件;需要可靠存储、支持版本留存、防误删。
| 方案 | 实现方式 | 优点 | 缺点 | 是否适合本场景 |
|---|---|---|---|---|
| FTP | 备份服务器搭建vsftpd,业务机ftp上传备份包 | 部署简单;跨网络可用 | 无锁、无版本;小文件性能差;无校验;容易断传;没有快照,不推荐生产备份 | ❌不建议作为主备份,仅可做临时中转 |
| NFS | 备份机器开启NFS服务,业务机挂载远程目录到本地,备份直接写挂载点 | Linux原生,配置简单;读写性能好;直接本地路径写入,脚本好写;适合大量小文件 | 网络故障会导致业务机挂载卡死风险;本身不提供版本、快照、防误删,需要额外做快照;无Web管理;仅内网使用 | ✅适合内网,作为基础存储层,需要叠加备份轮转脚本 |
| NAS设备 | 成品NAS(群晖/威联通),支持NFS/SMB/S3 | 自带快照、RAID、硬盘故障容错、WebUI;权限管理;开箱即用 | 硬件成本高;自定义脚本灵活性弱;如果是x86 NAS也可以跑额外服务 | ✅企业首选,硬件一体化备份存储 |
| MinIO(S3兼容对象存储) | 在新备份机器部署MinIO服务,提供S3 API | 支持对象版本、对象锁、生命周期(自动清理旧备份);GitLab原生直接支持S3备份;支持校验、断点续传;支持内网/外网访问;可配套rsync做本地副本;方便对接velero等工具 | 需要维护MinIO服务;小文件会有少量开销;需要做磁盘RAID保证底层磁盘可靠性 | ⭐⭐⭐强烈推荐,软件方案最优 |
补充备选:
- Rsync + SSH(SCP):不单独部署存储服务,业务机通过rsync over ssh推送到备份机器目录。简单可靠,适合文件同步,但缺少版本管理。
- Restic / BorgBackup:备份工具,后端可以对接:本地目录/NFS/S3‑MinIO,支持去重、加密、快照版本,非常适合这两个系统。
新备份机器部署MinIO,底层磁盘建议配置RAID1/RAID5(防止单盘损坏丢失备份)。
mc(minio客户端)上传到MinIO桶。gitlab‑backup、zentao‑backup;开启版本、对象锁。gitlab.rb开启S3备份,直接把备份写入minio。缺点:需要维护MinIO服务;海量KB级小文件会消耗元数据,可适当打包再上传。
备份服务器配置NFS服务,业务机器挂载NFS目录;使用restic备份工具把GitLab、禅道数据备份到NFS存储。
不建议直接裸写文件到NFS,搭配restic实现:快照、去重、加密、版本管理。
部署简单,没有额外对象存储组件;restic自动去重,节省磁盘空间;支持加密。
soft,retry=2,避免备份服务器宕机导致业务机进程卡死。适用场景:机器配置比较弱,不想维护MinIO,纯内网环境。
采购一台NAS(群晖/威联通),开启NFS + S3兼容接口。
优点:不用维护应用服务,磁盘故障告警,快照一键配置。
缺点:硬件成本高。
FTP只适合临时中转。没有完整性校验,传输中断容易产生损坏备份,没有版本保护。
gitlab‑backup‑create,不要直接拷贝数据库文件。mysqldump导出,不要直接拷贝data目录。条件允许,重要数据建议:一份存本方案独立备份机;另外一份异地离线备份。
gitlab‑backup‑restore 恢复。禅道 + GitLab 对接 MinIO 的 shell 备份脚本模板 参考如下:
环境说明
- 备份机器部署 MinIO,业务机器安装
mcminio客户端,业务机可以访问 MinIO服务- GitLab 使用官方 omnibus 安装;禅道使用 MySQL,部署在同一台业务主机
- 预先在MinIO创建2个桶:
gitlab-backup、zentao-backup,建议开启对象版本、对象锁防止误删- mc 已经完成配置:
mc alias set minio http://minio-ip:9000 ACCESS_KEY SECRET_KEY- 脚本执行用户具备 gitlab、mysql、tar 相关权限;建议放入crontab定时执行
- 脚本会生成本地临时备份,上传MinIO之后自动清理本地临时文件;增加简单日志、错误告警预留位
#!/bin/bash
set -euo pipefail
##############################################################################
# 配置项,请根据实际环境修改
##############################################################################
# MinIO mc别名
MINIO_ALIAS="minio"
GITLAB_BUCKET="gitlab-backup"
ZENTAO_BUCKET="zentao-backup"
# GitLab配置 omnibus版本
GITLAB_BACKUP_DIR="/var/opt/gitlab/backups"
GITLAB_CONFIG_DIR="/etc/gitlab"
GITLAB_BACKUP_RETENTION_LOCAL=0 # 本地不保留gitlab备份,上传minio后删除
# 禅道配置
ZENTAO_PATH="/opt/zentaopms" # 禅道程序根目录
ZENTAO_MYSQL_HOST="127.0.0.1"
ZENTAO_MYSQL_PORT="3306"
ZENTAO_MYSQL_USER="root"
ZENTAO_MYSQL_PASS="YourMysqlPasswd"
ZENTAO_MYSQL_DB="zentao"
# 本地临时目录
TMP_BACKUP_DIR="/data/tmp_backup"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/gitlab_zentao_backup.log"
# 告警通知(这里预留,可替换为钉钉/企业微信webhook)
ALERT_WEBHOOK=""
##############################################################################
# 日志函数
##############################################################################
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
}
alert_fail() {
local msg="$1"
log "ERROR: ${msg}"
if [[ -n "${ALERT_WEBHOOK}" ]];then
curl -s -X POST "${ALERT_WEBHOOK}" -d "{\"msg\":\"备份失败:${msg}\"}" >/dev/null 2>&1
fi
}
##############################################################################
# 初始化临时目录
##############################################################################
mkdir -p "${TMP_BACKUP_DIR}"
clean_tmp(){
log "清理临时目录 ${TMP_BACKUP_DIR}"
rm -rf "${TMP_BACKUP_DIR:?}"/*
}
##############################################################################
# 1.GitLab备份:官方备份 + 配置文件,上传MinIO
##############################################################################
backup_gitlab(){
log "===== 开始执行 GitLab 备份 ====="
clean_tmp
# 1.执行gitlab官方备份 omnibus
gitlab-backup create BACKUP="${DATE}" CRON=1
if [ $? -ne 0 ];then
alert_fail "GitLab gitlab-backup create执行失败"
exit 1
fi
# 2.备份gitlab配置文件 gitlab-secrets.json gitlab.rb
GITLAB_CONFIG_TMP="${TMP_BACKUP_DIR}/gitlab-config-${DATE}.tar.gz"
tar -czf "${GITLAB_CONFIG_TMP}" \
"${GITLAB_CONFIG_DIR}/gitlab.rb" \
"${GITLAB_CONFIG_DIR}/gitlab-secrets.json"
# 3.获取生成的备份包
GITLAB_BACKUP_FILE=$(ls -1 ${GITLAB_BACKUP_DIR}/${DATE}_gitlab_backup.tar)
# 4.上传备份包到minio
log "上传GitLab业务备份包 ${GITLAB_BACKUP_FILE} 到 ${MINIO_ALIAS}/${GITLAB_BUCKET}"
mc cp "${GITLAB_BACKUP_FILE}" "${MINIO_ALIAS}/${GITLAB_BUCKET}/gitlab-backup/"
log "上传GitLab配置文件 ${GITLAB_CONFIG_TMP}"
mc cp "${GITLAB_CONFIG_TMP}" "${MINIO_ALIAS}/${GITLAB_BUCKET}/gitlab-config/"
# 清理本地gitlab备份
rm -f "${GITLAB_BACKUP_FILE}"
log "===== GitLab备份完成 ====="
}
##############################################################################
# 2.禅道备份:mysql dump + 附件data目录打包,上传MinIO
##############################################################################
backup_zentao(){
log "===== 开始执行禅道备份 ====="
clean_tmp
ZENTAO_DUMP="${TMP_BACKUP_DIR}/zentao_db_${DATE}.sql"
ZENTAO_ARCHIVE="${TMP_BACKUP_DIR}/zentao_full_${DATE}.tar.gz"
# 1.mysql逻辑备份
log "导出禅道MySQL数据库"
mysqldump -h${ZENTAO_MYSQL_HOST} -P${ZENTAO_MYSQL_PORT} -u${ZENTAO_MYSQL_USER} -p${ZENTAO_MYSQL_PASS} \
--single-transaction --routines --triggers ${ZENTAO_MYSQL_DB} > "${ZENTAO_DUMP}"
if [ $? -ne 0 ];then
alert_fail "禅道mysqldump数据库导出失败"
exit 1
fi
# 2.打包数据库+禅道data附件目录(www/data是附件、截图、上传文件)
log "打包禅道数据库与附件目录"
tar -czf "${ZENTAO_ARCHIVE}" \
-C "${TMP_BACKUP_DIR}" "$(basename ${ZENTAO_DUMP})" \
-C "${ZENTAO_PATH}" www/data
# 3.上传到minio
log "上传禅道完整备份包 ${ZENTAO_ARCHIVE} 到 ${MINIO_ALIAS}/${ZENTAO_BUCKET}"
mc cp "${ZENTAO_ARCHIVE}" "${MINIO_ALIAS}/${ZENTAO_BUCKET}/"
log "===== 禅道备份完成 ====="
}
##############################################################################
# 主流程
##############################################################################
main(){
log ">>>>>>>>>> 启动GitLab+禅道联合备份任务 <<<<<<<<<<"
backup_gitlab
backup_zentao
clean_tmp
log ">>>>>>>>>> 全部备份任务执行完成 <<<<<<<<<<"
}
# 捕获异常
trap 'alert_fail "脚本异常中断";exit 1' ERR
main
gitlab_zentao_backup.shchmod +x gitlab_zentao_backup.sh
./gitlab_zentao_backup.sh
0 2 * * * /opt/scripts/gitlab_zentao_backup.sh >> /var/log/gitlab_zentao_backup_cron.log 2>&1
不要写shell脚本删除旧备份,使用MinIO桶生命周期策略,更安全。
mc命令示例设置生命周期,你可以替换时间:
# 示例:30天过期删除,根据实际业务调整
mc ilm rule add minio/gitlab-backup --expire-days 30
mc ilm rule add minio/zentao-backup --expire-days 30
/var/opt/gitlab/backupsgitlab-backup restore BACKUP=时间戳.my.cnf 免密配置,避免明文密码。set -euo pipefail遇到错误直接退出,防止生成损坏备份上传MinIO。补充一份免明文mysql密码的优化版本,以及MinIO桶完整生命周期mc配置命令。
业务场景:
gitlab‑backup、zentao‑backup两个备份桶- 日常自动备份:保留30天自动删除
- 每月1号月度归档备份:永久保存,不会被生命周期删除(通过标签过滤)
- 同时包含:版本删除、过期清理、非当前版本过期(开启对象版本场景)
前提:已经配置好mc别名,别名叫minio;桶预先开启 版本控制 + 对象锁。
# 开启版本控制
mc version enable minio/gitlab-backup
mc version enable minio/zentao-backup
# 开启对象锁(合规锁,防止误删备份),开启后桶无法关闭
mc retention set minio/gitlab-backup --mode COMPLIANCE --default 0d
mc retention set minio/zentao-backup --mode COMPLIANCE --default 0d
对象锁COMPLIANCE模式:被打上保留的对象,任何账号(包括admin)都不能删除覆盖,适合备份防勒索。
当你每月1号执行备份之后,给该批备份打上标签
backup_type=monthly,生命周期会跳过带此标签的对象,不会自动删除。
#示例,给月度gitlab备份打标签
mc tag set minio/gitlab-backup/gitlab-backup/20260801_020000_gitlab_backup.tar "backup_type=monthly"
mc tag set minio/gitlab-backup/gitlab-config/gitlab-config-20260801_020000.tar.gz "backup_type=monthly"
#禅道月度备份打标签示例
mc tag set minio/zentao-backup/zentao_full_20260801_020000.tar.gz "backup_type=monthly"
脚本改造提示:每月1号备份完成,自动执行上面打标签命令,其余日期不打标签。
规则逻辑:
# 删除已存在全部旧生命周期规则
mc ilm rule rm --all minio/gitlab-backup
# 规则1:非月度标记对象,30天自动过期删除
mc ilm rule add minio/gitlab-backup \
--tag "backup_type!=monthly" \
--expire-days 30
# 规则2:旧版本对象30天后删除(版本控制场景)
mc ilm rule add minio/gitlab-backup \
--noncurrent-expire-days 30
# 规则3:清理残留的删除标记
mc ilm rule add minio/gitlab-backup \
--expire-delete-marker true
mc ilm rule rm --all minio/zentao-backup
mc ilm rule add minio/zentao-backup \
--tag "backup_type!=monthly" \
--expire-days 30
mc ilm rule add minio/zentao-backup \
--noncurrent-expire-days 30
mc ilm rule add minio/zentao-backup \
--expire-delete-marker true
#查看桶全部生命周期规则
mc ilm list minio/gitlab-backup
mc ilm list minio/zentao-backup
#查看桶版本、锁状态
mc version info minio/gitlab-backup
mc retention info minio/gitlab-backup
# 仅测试环境执行,生产不要执行
mc rm --recursive --dangerous minio/gitlab-backup/
mc tag list minio/gitlab-backup/gitlab-backup/xxx.tar
把下面片段追加到备份脚本末尾,实现每月1号自动给备份打monthly标签
# 判断如果是每月1号,打上永久归档标签
DAY_OF_MONTH=$(date +%d)
if [ "${DAY_OF_MONTH}" = "01" ];then
log "本月1号,该备份标记为月度归档永久保存"
mc tag set "${MINIO_ALIAS}/${GITLAB_BUCKET}/gitlab-backup/${DATE}_gitlab_backup.tar" "backup_type=monthly"
mc tag set "${MINIO_ALIAS}/${GITLAB_BUCKET}/gitlab-config/gitlab-config-${DATE}.tar.gz" "backup_type=monthly"
mc tag set "${MINIO_ALIAS}/${ZENTAO_BUCKET}/zentao_full_${DATE}.tar.gz" "backup_type=monthly"
fi
--tag "backup_type!=monthly" 条件:只有不包含该标签的对象才会30天过期;打上monthly标签的对象完全不受这条规则约束,永久保留。--expire‑days 30全部30天过期。如果不需要月度归档,直接执行这个,不需要打标签
mc ilm rule rm --all minio/gitlab-backup
mc ilm rule add minio/gitlab-backup --expire-days 30 --noncurrent-expire-days 30 --expire-delete-marker true
mc ilm rule rm --all minio/zentao-backup
mc ilm rule add minio/zentao-backup --expire-days 30 --noncurrent-expire-days 30 --expire-delete-marker true
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。