09 — 备份恢复与灾难恢复

9.1 需要备份什么?

FreeIPA 的所有数据都在 Docker 宿主机的一个目录中:

/data/docker-space/ipa-data/

这个目录包含了:

ipa-data/
├── var/lib/dirsrv/       ← LDAP 数据库
├── var/lib/ipa/          ← IPA 配置、证书
├── var/lib/krb5kdc/      ← Kerberos 数据库(最关键!)
├── var/lib/pki/          ← CA 证书和密钥
├── etc/dirsrv/           ← LDAP 配置
├── etc/ipa/              ← IPA 配置
└── etc/pki/              ← PKI 配置

备份这个目录 = 备份整个 FreeIPA 系统。

9.2 备份方案

方案一:全量目录备份(最简单、最可靠)

#!/bin/bash
# backup-freeipa-full.sh — 全量备份
 
BACKUP_DIR="/backup/freeipa"
DATA_DIR="/data/docker-space/ipa-data"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/freeipa_full_${TIMESTAMP}.tar.gz"
 
mkdir -p "$BACKUP_DIR"
 
echo "=== 开始全量备份 FreeIPA ==="
echo "备份时间: $(date)"
 
# 1. 停止容器(确保数据一致性)
docker stop freeipa-server
echo "容器已停止"
 
# 2. 打包数据目录
tar -czf "$BACKUP_FILE" -C "$(dirname "$DATA_DIR")" "$(basename "$DATA_DIR")"
echo "数据已打包: $BACKUP_FILE"
 
# 3. 启动容器
docker start freeipa-server
echo "容器已启动"
 
# 4. 检查备份文件
ls -lh "$BACKUP_FILE"
 
# 5. 保留最近 7 天的备份(可根据需要调整)
find "$BACKUP_DIR" -name "freeipa_full_*.tar.gz" -mtime +7 -delete
 
echo "=== 备份完成 ==="

方案二:在线备份(不停机)

#!/bin/bash
# backup-freeipa-online.sh — 在线备份(适合生产环境)
 
BACKUP_DIR="/backup/freeipa"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
 
mkdir -p "$BACKUP_DIR"
 
echo "=== 开始在线备份 FreeIPA ==="
 
# 进入容器执行在线备份
docker exec freeipa-server bash -c "
  echo 'YourAdminPassword' | kinit admin
  
  # 创建备份目录
  BACKUP_DIR=\"/data/backup_${TIMESTAMP}\"
  mkdir -p \$BACKUP_DIR
  
  # 1. LDAP 数据库备份
  db2ldif -Z \$(hostname) -n userRoot -a \$BACKUP_DIR/userRoot.ldif
  
  # 2. IPA 配置备份
  ipa-backup --data --online --logs
  
  # 3. 证书备份
  cp -r /etc/pki \$BACKUP_DIR/
  cp -r /var/lib/pki \$BACKUP_DIR/
  
  echo '备份完成'
  ls -lh \$BACKUP_DIR/
"
 
# 从容器中拷贝备份到宿主机
docker cp freeipa-server:/data/backup_${TIMESTAMP} "$BACKUP_DIR/backup_${TIMESTAMP}"
 
# 从容器中拷贝 ipa-backup 生成的文件
# ipa-backup 默认输出到 /var/lib/ipa/backup/
docker cp freeipa-server:/var/lib/ipa/backup "$BACKUP_DIR/ipa-backup"
 
echo "=== 在线备份完成 ==="

方案三:自动化定时备份

# 添加到 crontab(每天凌晨 2 点备份)
# crontab -e
# 0 2 * * * /opt/scripts/backup-freeipa-full.sh >> /var/log/freeipa-backup.log 2>&1

9.3 恢复方案

场景一:数据目录损坏/丢失(从全量备份恢复)

#!/bin/bash
# restore-freeipa-from-full.sh — 从全量备份恢复
 
BACKUP_FILE=$1  # 备份文件路径
DATA_DIR="/data/docker-space/ipa-data"
 
if [ -z "$BACKUP_FILE" ]; then
  echo "用法: $0 <备份文件.tar.gz>"
  exit 1
fi
 
echo "=== 开始恢复 FreeIPA ==="
 
# 1. 停止并删除容器
docker stop freeipa-server 2>/dev/null
docker rm freeipa-server 2>/dev/null
echo "容器已删除"
 
# 2. 清空数据目录
rm -rf "${DATA_DIR:?}"/*
echo "数据目录已清空"
 
# 3. 解压备份
tar -xzf "$BACKUP_FILE" -C "$(dirname "$DATA_DIR")"
echo "备份已解压"
 
# 4. 重新启动容器
# (使用与原始部署相同的 docker run 命令)
docker run -d \
  --privileged \
  --cgroupns=host \
  -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
  -v /proc/meminfo:/proc/meminfo:ro \
  --name freeipa-server \
  --hostname ipa-local.thinkmeta.site \
  --restart unless-stopped \
  --sysctl net.ipv6.conf.all.disable_ipv6=0 \
  --add-host ipa-local.thinkmeta.site:192.168.3.90 \
  -e IPA_SERVER_IP=192.168.3.90 \
  -v /data/docker-space/ipa-data:/data \
  -p 192.168.3.90:53:53/tcp \
  -p 192.168.3.90:53:53/udp \
  -p 80:80/tcp \
  -p 443:443/tcp \
  -p 389:389/tcp \
  -p 636:636/tcp \
  -p 88:88/tcp \
  -p 88:88/udp \
  -p 464:464/tcp \
  -p 464:464/udp \
  -p 123:123/udp \
  -e PASSWORD="YourAdminPassword" \
  freeipa/freeipa-server:almalinux-10-4.13.1
 
echo "等待容器启动(60秒)..."
sleep 60
 
# 5. 验证
echo "检查容器状态:"
docker ps | grep freeipa
echo "检查 FreeIPA 服务状态:"
docker exec freeipa-server ipactl status
 
echo "=== 恢复完成 ==="

场景二:服务器迁移(换一台机器运行 FreeIPA)

#!/bin/bash
# migrate-freeipa.sh — FreeIPA 迁移脚本
 
# 前提条件:
# 1. 新服务器 IP 地址相同(或准备修改所有客户端配置)
# 2. 备份文件已拷贝到新服务器
 
# 在新服务器上执行与"场景一"相同的恢复步骤
# 如果 IP 地址发生变化,还需要:
 
# 1. 修改 FreeIPA 的 DNS 记录(新 IP)
# 2. 修改所有客户端的 /etc/resolv.conf 指向新 IP
# 3. 修改所有客户端的 /etc/hosts
# 4. 在客户端重新注册:
#    sudo ipa-client-install --uninstall
#    sudo ipa-client-install --domain=... --server=... --realm=... --mkhomedir

场景三:仅恢复部分数据

# 仅恢复 LDAP 数据
docker exec freeipa-server bash -c "
  echo 'YourAdminPassword' | kinit admin
  # 停止目录服务
  ipactl stop
  # 导入 LDIF
  ldif2db -Z \$(hostname) -n userRoot -i /path/to/userRoot.ldif
  # 启动服务
  ipactl start
"

9.4 灾难预防

预防措施清单

□ 每日自动备份到本地磁盘
□ 每周备份同步到远程服务器(rsync/scp)
□ 每月备份离线存储(U盘/移动硬盘)
□ 备份脚本加入健康检查(备份完验证文件大小 > 0)
□ 定期演练恢复流程(每季度一次)
□ 记录 admin 密码并离线安全保存
□ 记录部署参数(Docker run 命令)
□ 记录所有客户端列表

备份脚本带健康检查

#!/bin/bash
# backup-with-health-check.sh
 
HEALTHY=0
 
# 备份
./backup-freeipa-full.sh
BACKUP_FILE=$(ls -t /backup/freeipa/freeipa_full_*.tar.gz | head -1)
 
# 检查 1:文件大小 > 1MB
SIZE=$(stat -c%s "$BACKUP_FILE" 2>/dev/null)
if [ "$SIZE" -gt 1048576 ]; then
  echo "✓ 备份文件大小正常: $(($SIZE/1048576))MB"
  HEALTHY=$((HEALTHY+1))
else
  echo "✗ 备份文件异常(太小)!"
fi
 
# 检查 2:容器已重新启动
if docker ps | grep -q freeipa-server; then
  echo "✓ 容器运行正常"
  HEALTHY=$((HEALTHY+1))
else
  echo "✗ 容器未运行!"
fi
 
# 检查 3:Kerberos 认证正常
if docker exec freeipa-server bash -c "echo 'YourAdminPassword' | kinit admin 2>/dev/null"; then
  echo "✓ Kerberos 认证正常"
  HEALTHY=$((HEALTHY+1))
else
  echo "✗ Kerberos 认证失败!"
fi
 
if [ $HEALTHY -eq 3 ]; then
  echo "=== 备份健康检查通过 ==="
else
  echo "=== 备份健康检查失败!请立即排查 ==="
  # 可在此处发送告警通知
fi

9.5 备份恢复测试流程

建议每季度执行一次恢复演练:

#!/bin/bash
# disaster-recovery-drill.sh — 灾难恢复演练
 
echo "=== 灾难恢复演练 ==="
echo "目标:在隔离环境中验证备份可用性"
echo ""
 
# 1. 创建测试目录
TEST_DIR="/tmp/freeipa-recovery-test"
mkdir -p "$TEST_DIR"
 
# 2. 解压备份到测试目录
BACKUP_FILE=$(ls -t /backup/freeipa/freeipa_full_*.tar.gz | head -1)
tar -xzf "$BACKUP_FILE" -C "$TEST_DIR"
 
# 3. 验证关键文件
REQUIRED_FILES=(
  "ipa-data/var/lib/dirsrv"
  "ipa-data/var/lib/krb5kdc"
  "ipa-data/var/lib/ipa"
  "ipa-data/var/lib/pki"
)
 
ALL_OK=true
for file in "${REQUIRED_FILES[@]}"; do
  if [ -e "$TEST_DIR/$file" ]; then
    echo "✓ $file 存在"
  else
    echo "✗ $file 缺失!"
    ALL_OK=false
  fi
done
 
if $ALL_OK; then
  echo ""
  echo "=== 备份验证通过,可用于恢复 ==="
else
  echo ""
  echo "=== 备份验证失败!需要重新备份 ==="
fi
 
# 清理
rm -rf "$TEST_DIR"

9.6 你的环境特别提醒

你的环境是 Exsi 个人服务器,可能长期关机。以下是针对你的场景的建议:

关机前的正确步骤

# 1. 执行完整备份
./backup-freeipa-full.sh
 
# 2. 将备份拷贝到安全位置(不要和服务器放在同一块盘)
scp /backup/freeipa/freeipa_full_*.tar.gz user@nas-server:/backup/
 
# 3. 停止容器
docker stop freeipa-server
 
# 4. 关机
sudo shutdown -h now

开机后的验证步骤

# 1. 启动 Docker(应自动启动 freeipa-server)
docker ps | grep freeipa
 
# 2. 如果容器没启动,手动启动
docker start freeipa-server
sleep 60
 
# 3. 验证服务
docker exec freeipa-server ipactl status
# 所有服务应为 RUNNING
 
# 4. 测试 Kerberos
docker exec freeipa-server bash -c "echo 'YourAdminPassword' | kinit admin"
docker exec freeipa-server klist
 
# 5. 测试客户端
ssh [email protected]

Kerberos 大时效问题

长期关机不会导致认证失效,只需要注意:

  • Kerberos TGT 会在首次 kinit 后重新生成
  • 证书有效期 2 年,长期不开机要留意到期时间
  • 密码策略中的过期计时基于”上次修改密码的时间”,不受关机影响