GitLab 备份与 NFS 异地存储实施笔记

GitLab 备份与 NFS 异地存储实施笔记

前言

  • 当前环境:GitLab 部署在 Docker 容器中,宿主机磁盘空间紧张(/dev/sda2 仅剩 40GB)。
  • 目标:将所有 GitLab 备份文件自动存储到 98TB 的 NFS 异地存储中,实现数据与系统分离。
  • 存储位置192.168.111.1:/volume1/git14 挂载至宿主机 /gitlab_bak/

存储基础设施配置

NFS 挂载

在宿主机执行挂载,并配置开机自动挂载:

# 创建本地挂载点
mkdir -p /gitlab_bak/

# 临时挂载
mount 192.168.111.1:/volume1/git14 /gitlab_bak/

# 配置持久化挂载 (编辑 /etc/fstab)
echo "192.168.111.1:/volume1/git14 /gitlab_bak/ nfs defaults,nfsvers=3 0 0" >> /etc/fstab

目录与权限初始化

注意:必须确保 NFS 目录对容器内的 git 用户(UID 998)有写入权限。

# 创建备份子目录
mkdir -p /gitlab_bak/backups
mkdir -p /gitlab_bak/config_bak

# 修正权限 (998 是 GitLab 容器内 git 用户的默认 UID)
chown -R 998:998 /gitlab_bak/backups
chmod 755 /gitlab_bak/backups

GitLab 容器部署与配置

容器启动命令

关键点:使用 -v 直接挂载 NFS 路径到容器内部,替代不可靠的宿主机软链接方案。

docker run -d -p 443:443 -p 9980:80 -p 9922:22 \
  --name gitlab_new --restart always \
  -e TZ=Asia/Shanghai \
  -v /etc/localtime:/etc/localtime:ro \
  -v /home/gzeport/gitlab/config:/etc/gitlab \
  -v /home/gzeport/gitlab/logs:/var/log/gitlab \
  -v /home/gzeport/gitlab/data:/var/opt/gitlab \
  -v /gitlab_bak/backups:/var/opt/gitlab/backups \
  docker.ajunyunwei.xyz/gitlab/gitlab-ce:18.2.1-ce.0

规避 NFS 权限报错 (Errno::EPERM)

若 GitLab 在 reconfigure 时尝试 chown NFS 目录会报错,需在 gitlab.rb 中禁用该行为:

# 编辑配置文件
vim /home/gzeport/gitlab/config/gitlab.rb

# 添加以下配置
gitlab_rails['manage_backup_path'] = false
gitlab_rails['backup_keep_time'] = 604800  # 自动清理 7 天前的数据备份

保存后,重启容器应用配置:docker restart gitlab_new

自动化备份实施

核心备份脚本

/home/gzeport/scripts/gitlab_backup.sh 创建以下脚本。

#!/bin/bash
# GitLab 自动备份脚本
# Crontab: 0 2 * * * /bin/bash /home/gzeport/scripts/gitlab_backup.sh > /var/log/gitlab_bak.log 2>&1

set -e  # 遇到错误立即退出

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

log "========== GitLab 备份开始 =========="

# 1. 检查 NFS 挂载状态
if ! mountpoint -q /gitlab_bak; then
    log "错误: /gitlab_bak 未挂载,尝试挂载..."
    mount 192.168.111.1:/volume1/git14 /gitlab_bak || {
        log "错误: NFS 挂载失败,备份终止"
        exit 1
    }
    log "NFS 挂载成功"
fi

# 2. 检查容器运行状态
if ! docker ps | grep -q gitlab_new; then
    log "错误: gitlab_new 容器未运行"
    exit 1
fi

# 3. 执行 GitLab 内部备份程序
log "开始执行 GitLab 数据备份..."
if docker exec gitlab_new gitlab-backup create; then
    log "GitLab 数据备份成功"
else
    log "错误: GitLab 数据备份失败"
    exit 1
fi

# 4. 【非常重要】手动备份配置文件和密钥(这些不在 tar 包里,但恢复必须有它们)
BACKUP_DATE=$(date +%Y%m%d)
CONFIG_BACKUP_DIR="/gitlab_bak/config_bak/$BACKUP_DATE"

log "开始备份配置文件到 $CONFIG_BACKUP_DIR"
mkdir -p "$CONFIG_BACKUP_DIR"

# 备份配置文件
if [ -f /home/gzeport/gitlab/config/gitlab.rb ]; then
    cp /home/gzeport/gitlab/config/gitlab.rb "$CONFIG_BACKUP_DIR/"
    log "gitlab.rb 备份成功"
else
    log "警告: gitlab.rb 文件不存在"
fi

if [ -f /home/gzeport/gitlab/config/gitlab-secrets.json ]; then
    cp /home/gzeport/gitlab/config/gitlab-secrets.json "$CONFIG_BACKUP_DIR/"
    log "gitlab-secrets.json 备份成功"
else
    log "警告: gitlab-secrets.json 文件不存在"
fi

# 5. 删除 30 天前的旧配置备份(与 GitLab 数据备份保留策略一致)
log "清理 30 天前的旧配置备份..."
find /gitlab_bak/config_bak/ -maxdepth 1 -type d -mtime +30 ! -path /gitlab_bak/config_bak/ -exec rm -rf {} \;
log "旧配置备份清理完成"

# GitLab 数据备份(.tar)由 GitLab 自动清理(配置: backup_keep_time = 604800 即 7 天)

# 6. 显示备份统计信息
BACKUP_COUNT=$(ls -1 /gitlab_bak/backups/*.tar 2>/dev/null | wc -l)
CONFIG_COUNT=$(ls -1d /gitlab_bak/config_bak/*/ 2>/dev/null | wc -l)
log "当前保留备份: 数据备份 $BACKUP_COUNT 个, 配置备份 $CONFIG_COUNT 个"

log "========== GitLab 备份完成 =========="

image-20260311211437559

设置定时任务

# 每天凌晨 2:00 执行
crontab -e

0 2 * * * /bin/bash /home/gzeport/scripts/gitlab_backup.sh > /var/log/gitlab_bak.log 2>&1

运维避坑指南

  • 为什么不能用软链接?

    Docker 挂载的是宿主机路径,无法识别指向宿主机其他位置的软链接。必须使用 -v 直接挂载真实路径

  • 为什么一定要备份 gitlab-secrets.json

    .tar 数据包中不包含密钥。如果密钥丢失,备份中的数据库即便恢复,也无法解密用户密码、CI/CD 变量等,整个 GitLab 将处于损坏状态。

  • 权限问题排查: 如果备份报错 Permission Denied,第一时间在宿主机检查 chown -R 998:998 /gitlab_bak/backups

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇