- 知识库已有部署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 业务功能验证
- 登录管理后台,确认用户/群组/Space列表正常
- 发送测试消息(IM + Bot消息各一条)
- 上传测试文件,确认MinIO读写正常
- 创建测试Space并邀请成员,确认权限正常
- 检查历史消息记录是否完整
九、升级/迁移场景备份前置
【✅源码确认】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 |