首页 产品 为什么选 OCTO 解决方案 文档 关于
文档中心 / 部署运维 / 备份与恢复指南
← 返回文档中心

备份与恢复指南

OCTO 文档中心 · 部署运维

  • 知识库已有部署SOP文档整理
  • Octo产品管家Q12源码级确认(2026-09-22)
  • 通用数据库/对象存储备份最佳实践

备份与恢复指南 v1.0

⚠️ 重要前置说明:octo-server 代码本身不含备份策略(属 deployment/运维层),docker-compose/Helm 全栈编排已迁到独立部署仓 `Mininglamp-OSS/octo-deployment`。本文档为基于组件架构整理的运维最佳实践建议,官方备份方案待 octo-deployment 仓 Owner 补充确认。

【✅源码确认】OCTO有状态服务 = MySQL(业务数据)+ 对象存储(MinIO/COS,文件)+ Redis(session态)。无Kafka/OpenSearch依赖(私有化最小化部署)。


一、备份范围全景

1.1 核心数据组件(必须备份)

组件 数据类型 重要性 备份方式 恢复优先级
MySQL 8 业务核心数据(用户/群组/消息索引/配置/权限等) 🔴极高 mysqldump/物理备份 P0
MinIO(或COS/S3) 文件附件/图片/文档/语音等二进制文件 🔴极高 mc mirror/对象存储同步 P0
Redis 7 Session状态/缓存/限流计数器 🟡中 RDB/AOF持久化文件 P1(可部分重建)
WuKongIM 消息通道配置/离线消息 🔴极高 数据目录备份 P0

1.2 配置文件(必须备份)

文件类型 Docker Compose路径 K8s Helm路径
环境变量配置 .env 文件 values.yaml + helm get values
应用配置 configs/tsdd.yaml ConfigMap(kubectl get cm)
Nginx配置 nginx/conf.d/ 目录 Ingress资源定义
TLS证书 证书文件目录 K8s TLS Secret
Docker编排 docker-compose.yml Helm chart自定义values
MinIO初始化 minio-init脚本 minio-init Job配置

1.3 可选/可重建组件

组件 说明
Kafka(如启用) 消息队列,数据可通过MySQL/MinIO重建,如需严格消息顺序则需备份
OpenSearch(如启用) 全文搜索索引,可从MySQL重建,备份可选但重建耗时
Prometheus/Grafana 监控数据,一般不需要长期备份
容器镜像 建议保留对应版本镜像tar包,避免仓库不可用时无法回滚

二、备份前置检查

2.1 确认服务健康状态

# Docker Compose环境
curl -s http://localhost:8080/v1/ping
# 期望返回: {"status":"ok"}

# K8s环境
kubectl exec -n octo  -- curl -s http://localhost:8080/v1/ping
# Docker
docker compose ps
# K8s
kubectl get pods -n octo

2.2 确认磁盘空间

# 查看MySQL数据量
du -sh /data/mysql/  # Docker或宿主机路径视实际情况
# 查看MinIO数据量
du -sh /data/minio/
# 查看Redis数据量
du -sh /data/redis/
# 查看WuKongIM数据量
du -sh /data/wukongim/

三、Docker Compose 部署备份步骤

3.1 MySQL全量备份

#!/bin/bash
# backup-mysql.sh
# 用法: bash backup-mysql.sh [备份目录]

BACKUP_DIR=${1:-/data/backups/mysql}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# 从.env读取MySQL连接信息
source .env

# 逻辑备份(推荐,跨版本兼容性好)
docker exec octo-mysql mysqldump \
  -h 127.0.0.1 \
  -u"${MYSQL_USER:-root}" \
  -p"${MYSQL_PASSWORD}" \
  --single-transaction \
  --routines \
  --triggers \
  --databases "${MYSQL_DATABASE:-octo}" \
  --set-gtid-purged=OFF \
  > "${BACKUP_DIR}/octo_mysql_${DATE}.sql"

# 压缩
gzip "${BACKUP_DIR}/octo_mysql_${DATE}.sql"

# 清理30天前备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete

echo "MySQL备份完成: ${BACKUP_DIR}/octo_mysql_${DATE}.sql.gz"
ls -lh "${BACKUP_DIR}/octo_mysql_${DATE}.sql.gz"

⚠️ 注意:OCTO启动时会自动执行数据库迁移(migrate)【✅源码确认 `pkg/db/mysql.go` 用 sql-migrate】,迁移失败会panic导致容器起不来。因此升级前必须做MySQL全量备份。

3.2 MinIO对象存储备份

#!/bin/bash
# backup-minio.sh

BACKUP_DIR=${1:-/data/backups/minio}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

source .env

# 方式一:使用mc客户端mirror(推荐)
# 先配置mc别名(首次执行)
docker exec octo-minio mc alias set octo-local \
  http://127.0.0.1:9000 \
  "${MINIO_ROOT_USER}" \
  "${MINIO_ROOT_PASSWORD}" 2>/dev/null

# mirror同步所有bucket
docker exec octo-minio mc mirror --overwrite octo-local/ "${BACKUP_DIR}/minio_full_${DATE}/"

# 方式二:直接打包数据卷(更快速但需停MinIO)
# docker compose stop minio
# tar -czf "${BACKUP_DIR}/minio_data_${DATE}.tar.gz" /data/minio/
# docker compose start minio

echo "MinIO备份完成: ${BACKUP_DIR}/"
du -sh "${BACKUP_DIR}/minio_full_${DATE}/"

3.3 Redis备份

#!/bin/bash
# backup-redis.sh

BACKUP_DIR=${1:-/data/backups/redis}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

source .env

# 触发RDB快照
docker exec octo-redis redis-cli -a "${REDIS_PASSWORD}" --no-auth-warning BGSAVE

# 等待RDB完成(检查lastsave时间戳变化)
sleep 5

# 复制dump.rdb
docker cp octo-redis:/data/dump.rdb "${BACKUP_DIR}/dump_${DATE}.rdb"

# 如启用AOF,也备份
docker cp octo-redis:/data/appendonly.aof "${BACKUP_DIR}/appendonly_${DATE}.aof" 2>/dev/null

gzip "${BACKUP_DIR}/dump_${DATE}.rdb"
[ -f "${BACKUP_DIR}/appendonly_${DATE}.aof" ] && gzip "${BACKUP_DIR}/appendonly_${DATE}.aof"

# 清理14天前
find $BACKUP_DIR -name "*.gz" -mtime +14 -delete

echo "Redis备份完成"

💡 Redis主要存Session和缓存,数据可部分丢失。RDB备份足以满足大多数场景。

3.4 WuKongIM备份

#!/bin/bash
# backup-wukongim.sh

BACKUP_DIR=${1:-/data/backups/wukongim}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# 打包WuKongIM数据目录(含消息、配置等)
docker compose stop wukongim  # 一致性需要
tar -czf "${BACKUP_DIR}/wukongim_${DATE}.tar.gz" /data/wukongim/
docker compose start wukongim

echo "WuKongIM备份完成: ${BACKUP_DIR}/wukongim_${DATE}.tar.gz"

3.5 配置文件备份

#!/bin/bash
# backup-config.sh

BACKUP_DIR=${1:-/data/backups/config}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# 打包所有配置文件
tar -czf "${BACKUP_DIR}/config_${DATE}.tar.gz" \
  .env \
  docker-compose.yml \
  configs/ \
  nginx/ \
  scripts/

echo "配置备份完成: ${BACKUP_DIR}/config_${DATE}.tar.gz"

四、Kubernetes Helm 部署备份步骤

4.1 MySQL备份

#!/bin/bash
# k8s-backup-mysql.sh
NAMESPACE=${1:-octo}
BACKUP_DIR=${2:-/data/backups/mysql}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

MYSQL_POD=$(kubectl get pod -n $NAMESPACE -l app=mysql -o jsonpath='{.items[0].metadata.name}')

# 从Secret读取密码
MYSQL_PWD=$(kubectl get secret -n $NAMESPACE octo-mysql -o jsonpath='{.data.mysql-root-password}' | base64 -d)

# mysqldump
kubectl exec -n $NAMESPACE $MYSQL_POD -- mysqldump \
  -u root -p"$MYSQL_PWD" \
  --single-transaction \
  --routines \
  --triggers \
  --all-databases \
  | gzip > "${BACKUP_DIR}/octo_mysql_k8s_${DATE}.sql.gz"

echo "MySQL(K8s)备份完成"

4.2 MinIO备份(K8s)

#!/bin/bash
NAMESPACE=${1:-octo}
BACKUP_DIR=${2:-/data/backups/minio}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

MINIO_POD=$(kubectl get pod -n $NAMESPACE -l app=minio -o jsonpath='{.items[0].metadata.name}')

# 使用mc mirror
kubectl exec -n $NAMESPACE $MINIO_POD -- mc alias set octo-local http://localhost:9000  
kubectl exec -n $NAMESPACE $MINIO_POD -- mc mirror --overwrite octo-local/ /tmp/minio-backup/
kubectl cp $NAMESPACE/$MINIO_POD:/tmp/minio-backup/ "${BACKUP_DIR}/minio_k8s_${DATE}/"

# 或使用PVC快照(如果StorageClass支持)
# kubectl get pvc -n octo
# 云厂商可使用CSI快照功能

echo "MinIO(K8s)备份完成"

4.3 Helm Values与资源备份

#!/bin/bash
NAMESPACE=${1:-octo}
RELEASE=${2:-octo}
BACKUP_DIR=${3:-/data/backups/k8s-config}
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# 备份Helm values
helm get values $RELEASE -n $NAMESPACE > "${BACKUP_DIR}/values_${DATE}.yaml"

# 备份所有ConfigMap
kubectl get cm -n $NAMESPACE -o yaml > "${BACKUP_DIR}/configmaps_${DATE}.yaml"

# 备份所有Secret(加密存储!)
kubectl get secret -n $NAMESPACE -o yaml > "${BACKUP_DIR}/secrets_${DATE}.yaml"

# 备份Ingress配置
kubectl get ingress -n $NAMESPACE -o yaml > "${BACKUP_DIR}/ingress_${DATE}.yaml"

# 备份PVC信息
kubectl get pvc -n $NAMESPACE -o yaml > "${BACKUP_DIR}/pvc_${DATE}.yaml"

echo "K8s配置备份完成"

⚠️ Secret备份文件包含敏感信息,必须加密存储!


五、备份策略建议

5.1 按部署形态建议

部署形态 MySQL MinIO Redis 配置 建议保留周期
PoC/测试 每日一次 每日一次 每周一次 变更时备份 7天
生产(单机) 每日全量+binlog增量 每日增量+每周全量 每日RDB 变更时备份 30天
生产(高可用) 每日全量+实时binlog 实时跨区域复制 主从复制 版本化管理 90天+异地

5.2 全量 vs 增量

类型 频率 工具 适用场景
全量备份 每日/每周 mysqldump、mc mirror 基线备份,恢复简单
增量备份 实时/每小时 MySQL binlog、MinIO版本控制 减少RPO,配合全量恢复

5.3 MySQL增量备份(binlog)

# 确认binlog已开启
docker exec octo-mysql mysql -uroot -p -e "SHOW VARIABLES LIKE 'log_bin';"

# 定期flush并备份binlog
# 可在my.cnf配置expire_logs_days自动清理

六、备份存储建议

6.1 存储位置

方式 适用场景 注意事项
本地磁盘 PoC/单机 磁盘故障会同时丢数据和备份
NFS/网络存储 K8s/多节点 注意权限和性能
对象存储(S3/OSS/COS) 生产/异地 推荐,成本低可靠性高
异地备份 生产 建议跨区域/跨可用区

6.2 保留周期建议

数据类型 保留周期 合规要求
日常备份 30天 -
月度备份 12个月 -
年度备份 永久/按客户要求 金融/医疗可能有合规要求
升级前备份 保留至新版本稳定运行≥7天 -

6.3 加密

  • 备份文件建议使用GPG或openssl AES-256加密
  • K8s Secret备份必须加密
  • 异地传输使用TLS/加密通道
  • 备份存储目录权限设置为600

七、恢复步骤

7.1 MySQL恢复

#!/bin/bash
# restore-mysql.sh
# 用法: bash restore-mysql.sh <备份文件.sql.gz>

BACKUP_FILE=$1
if [ -z "$BACKUP_FILE" ] || [ ! -f "$BACKUP_FILE" ]; then
  echo "用法: bash restore-mysql.sh <备份文件.sql.gz>"
  exit 1
fi

source .env

echo "⚠️ 警告:即将覆盖MySQL数据,请确认!"
echo "备份文件: $BACKUP_FILE"
read -p "输入YES继续: " CONFIRM
if [ "$CONFIRM" != "YES" ]; then echo "取消"; exit 1; fi

# 停止应用服务(避免恢复期间写入)
docker compose stop octo-server

# 解压并导入
gunzip < "$BACKUP_FILE" | docker exec -i octo-mysql mysql \
  -u"${MYSQL_USER:-root}" \
  -p"${MYSQL_PASSWORD}"

echo "MySQL恢复完成,请验证后重启服务"
# docker compose start octo-server

⚠️ 恢复后启动octo-server时注意:如果版本不同会触发自动migrate【✅源码确认】。如果migrate失败会panic,此时需回到原版本镜像,确认DB状态后再处理。

7.2 MinIO恢复

#!/bin/bash
# restore-minio.sh
BACKUP_DIR=$1
source .env

# 停止MinIO(可选,如果用mc mirror可以在线恢复)
# docker compose stop minio

# 方式一:mc mirror恢复
docker exec octo-minio mc mirror --overwrite "${BACKUP_DIR}/" octo-local/

# 方式二:解压数据卷备份
# tar -xzf minio_data_backup.tar.gz -C /data/minio/
# docker compose start minio

echo "MinIO恢复完成"

7.3 Redis恢复

#!/bin/bash
# restore-redis.sh
BACKUP_FILE=$1  # dump_YYYYMMDD_HHMMSS.rdb.gz

docker compose stop redis
gunzip < "$BACKUP_FILE" > /data/redis/dump.rdb
docker compose start redis

# 验证
docker exec octo-redis redis-cli PING

7.4 K8s环境MySQL恢复

#!/bin/bash
NAMESPACE=${1:-octo}
BACKUP_FILE=$2

MYSQL_POD=$(kubectl get pod -n $NAMESPACE -l app=mysql -o jsonpath='{.items[0].metadata.name}')
MYSQL_PWD=$(kubectl get secret -n $NAMESPACE octo-mysql -o jsonpath='{.data.mysql-root-password}' | base64 -d)

# 先暂停应用
kubectl scale deployment octo-server -n $NAMESPACE --replicas=0

# 恢复数据
gunzip < "$BACKUP_FILE" | kubectl exec -i -n $NAMESPACE $MYSQL_POD -- mysql -u root -p"$MYSQL_PWD"

# 恢复应用
kubectl scale deployment octo-server -n $NAMESPACE --replicas=<原始副本数>

echo "MySQL(K8s)恢复完成"

八、恢复验证SOP

8.1 基础设施验证

# 1. 检查所有容器/Pod状态
docker compose ps
# 或
kubectl get pods -n octo

# 2. MySQL连接验证
docker exec octo-mysql mysql -uroot -p -e "SELECT COUNT(*) FROM information_schema.tables;"

# 3. Redis连接验证
docker exec octo-redis redis-cli PING

# 4. MinIO桶验证
docker exec octo-minio mc ls octo-local/

# 5. WuKongIM验证(使用自带健康检查脚本)
bash scripts/healthcheck-api.sh  # 注意:这个脚本探的是WuKongIM的/route

8.2 应用验证

# 1. 健康检查【✅源码确认:GET /v1/ping → {"status":"ok"}】
curl -s http://<服务器地址>:8080/v1/ping
# 期望: {"status":"ok"}

# 2. 检查日志无ERROR【✅源码确认:zap日志,关键词搜索panic/ERROR】
docker compose logs --tail=100 octo-server | grep -iE "panic|error|failed"
# 重点关注:failed to ping MySQL、migration失败panic

# 3. 日志级别确认
# logger.level: 1debug/2info/3warn/4error

8.3 业务功能验证

  1. 登录管理后台,确认用户/群组/Space列表正常
  2. 发送测试消息(IM + Bot消息各一条)
  3. 上传测试文件,确认MinIO读写正常
  4. 创建测试Space并邀请成员,确认权限正常
  5. 检查历史消息记录是否完整

九、升级/迁移场景备份前置

【✅源码确认】OCTO启动时自动执行数据库迁移(sql-migrate),迁移失败→panic→容器起不来。

9.1 升级前备份检查清单

  • [ ] MySQL全量备份完成,备份文件已验证可解压
  • [ ] MinIO数据已备份
  • [ ] 当前版本配置文件已备份
  • [ ] 当前镜像版本记录(docker images / helm list)
  • [ ] Helm values已导出(K8s环境)
  • [ ] 已通知用户维护窗口
  • [ ] 回滚方案已准备(原版本镜像/镜像包)

9.2 迁移失败回滚流程

# 1. 停止新版本
docker compose stop octo-server
# 或 K8s: kubectl scale deployment octo-server -n octo --replicas=0

# 2. 恢复MySQL到升级前备份
bash restore-mysql.sh <升级前的备份.sql.gz>

# 3. 切回原版本镜像
# 修改docker-compose.yml中的image tag或helm回滚
# docker compose: 编辑image字段
# K8s: helm rollback octo  -n octo

# 4. 启动服务验证
docker compose up -d
curl -s http://localhost:8080/v1/ping

# 5. 检查日志
docker compose logs -f octo-server

十、全量备份一键脚本(Docker Compose)

#!/bin/bash
# full-backup.sh
# OCTO Docker Compose全量备份脚本
# 用法: bash full-backup.sh [备份根目录]

set -e

BACKUP_ROOT=${1:-/data/backups/octo}
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${BACKUP_ROOT}/${DATE}"
mkdir -p "$BACKUP_DIR"/{mysql,minio,redis,wukongim,config}

echo "===== OCTO全量备份开始: $(date) ====="
echo "备份目录: $BACKUP_DIR"

# 1. 健康检查
echo "[1/5] 健康检查..."
HEALTH=$(curl -s http://localhost:8080/v1/ping 2>/dev/null || echo "failed")
if [[ "$HEALTH" != *"ok"* ]]; then
  echo "⚠️ 警告: 健康检查未通过,继续备份但请注意"
fi

# 2. MySQL
echo "[2/5] MySQL备份..."
bash backup-mysql.sh "${BACKUP_DIR}/mysql"

# 3. MinIO
echo "[3/5] MinIO备份..."
bash backup-minio.sh "${BACKUP_DIR}/minio"

# 4. Redis
echo "[4/5] Redis备份..."
bash backup-redis.sh "${BACKUP_DIR}/redis"

# 5. 配置
echo "[5/5] 配置备份..."
bash backup-config.sh "${BACKUP_DIR}/config"

# WuKongIM(需要短暂停机,默认注释,按需执行)
# echo "[额外] WuKongIM备份..."
# bash backup-wukongim.sh "${BACKUP_DIR}/wukongim"

# 打包整个备份目录
echo "===== 打包备份 ====="
cd "$BACKUP_ROOT"
tar -czf "${DATE}.tar.gz" "$DATE"
rm -rf "$DATE"

# 校验
echo "===== 备份校验 ====="
ls -lh "${BACKUP_ROOT}/${DATE}.tar.gz"
echo "MD5: $(md5sum "${BACKUP_ROOT}/${DATE}.tar.gz" | awk '{print $1}')"

echo ""
echo "===== OCTO全量备份完成: $(date) ====="
echo "备份文件: ${BACKUP_ROOT}/${DATE}.tar.gz"

Crontab定时备份建议

# /etc/cron.d/octo-backup
# 每天凌晨2点全量备份
0 2 * * * root /bin/bash /opt/octo/scripts/full-backup.sh /data/backups/octo >> /var/log/octo-backup.log 2>&1

# 每周日凌晨3点做一次MinIO全量mirror
0 3 * * 0 root /bin/bash /opt/octo/scripts/backup-minio.sh /data/backups/minio-weekly >> /var/log/octo-backup.log 2>&1

十一、常见备份恢复问题

Q: mysqldump报错"Table doesn't exist"

Q: MinIO数据量太大,全量备份太慢

Q: 恢复后服务一直重启

Q: 备份文件在哪里最安全

Q: 如何验证备份文件可用


十二、待Owner补充确认项

项目 状态 说明
octo-deployment仓官方备份脚本 ⚠️待补充 octo-server代码不含备份策略
官方推荐的备份频率/保留周期 ⚠️待补充 本文为最佳实践建议
WuKongIM官方备份恢复流程 ⚠️待补充 本文基于通用方案
OpenSearch索引备份方案(如启用) ⚠️待补充 如部署含search模块
Kafka消息备份方案(如启用) ⚠️待补充 如部署含Kafka
跨版本升级DB兼容性矩阵 ⚠️待补充 migrate向前兼容性case-by-case
/health /ready独立探针 ⚠️待补充 代码仅见/v1/ping