# Hifast S3 备份集成 Runbook

本文档记录 `2026-05-13` 已经实际确认和完成的 S3 备份集成状态，以及后续如何把它和当前 `AWS 主生产 + 104 外部备用` 架构结合起来。

## 1. 当前已完成状态

- 已创建 S3 备份桶：`hifast-prod-backups-200810848252-ap-east-1`
- Region: `ap-east-1`
- Public access: blocked
- Versioning: enabled
- 已确认 RDS 主库 `hifast-mysql-prod-v2` 自动备份已启用：
  - retention: `7 days`
  - `2026-05-13` 已有自动快照
- 已确认 `104.238.220.230` MySQL 外部从库健康，可作为逻辑备份源：
  - `Replica_IO_Running: Yes`
  - `Replica_SQL_Running: Yes`
  - `Seconds_Behind_Source: 0`
- 已确认 `104.238.220.230` Redis 从库健康，可作为 RDB 备份源：
  - `role:slave`
  - `master_link_status:up`

## 2. 推荐组合方案

当前最稳的做法不是只依赖一种备份，而是保留两层：

1. `RDS automated backup`
2. `104` 从库导出的逻辑备份上传到 S3

原因：

- RDS 自动备份适合快速恢复整库
- S3 逻辑备份适合独立下载、跨环境恢复、长期归档
- 从 `104` 导出 MySQL / Redis 备份，对 AWS 主生产扰动最小

## 3. 仓库已补充内容

- MySQL 备份脚本：
  - [`deploy/scripts/mysql_backup_to_s3.sh`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/scripts/mysql_backup_to_s3.sh)
- Redis RDB 备份脚本：
  - [`deploy/scripts/redis_rdb_backup_to_s3.sh`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/scripts/redis_rdb_backup_to_s3.sh)
- 环境变量模板：
  - [`deploy/aws/ap-east-1/configs/backup-to-s3.env.example`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/aws/ap-east-1/configs/backup-to-s3.env.example)
- 主从切换环境变量模板：
  - [`deploy/aws/ap-east-1/configs/replica-ops.env.example`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/aws/ap-east-1/configs/replica-ops.env.example)
- 数据迁移交互工具：
  - [`deploy/scripts/hifast_data_sync_tool.sh`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/scripts/hifast_data_sync_tool.sh)
- 主从运维交互工具：
  - 统一入口仍使用 [`deploy/scripts/hifast_data_sync_tool.sh`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/scripts/hifast_data_sync_tool.sh)

## 4. 建议部署位置

### 4.1 MySQL

优先部署在 `104.238.220.230`：

- 直接从本地 MySQL 从库导出
- 不占用 AWS RDS 主库的备份窗口
- 故障时备份和备用节点仍在同一台机器上

### 4.2 Redis

优先部署在 `104.238.220.230`：

- 直接从 Redis 从库导出 `RDB`
- 不影响 AWS Redis 主库对外服务

## 5. 104 当前还缺的东西

截至 `2026-05-13`，`104` 已具备：

- `mysql`
- `mysqldump`
- `gzip`

但仍缺：

- `aws cli`
- 一套最小权限的 S3 上传凭证

## 6. 推荐权限模型

当前最实用的选择有两种：

1. `104` 使用专用 IAM 用户的最小权限 `AK/SK`
2. 未来如果备份转到 AWS EC2，再改为 `EC2 Instance Role`

按现有拓扑，推荐先走第 1 种，因为 MySQL 和 Redis 的备份源都在 `104`。

### 6.1 最小权限策略示例

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListBackupBucket",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::hifast-prod-backups-200810848252-ap-east-1"
    },
    {
      "Sid": "WriteBackupObjects",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:AbortMultipartUpload"
      ],
      "Resource": "arn:aws:s3:::hifast-prod-backups-200810848252-ap-east-1/*"
    }
  ]
}
```

说明：

- 不建议给 `s3:*`
- 不建议把 AK/SK 写进 repo
- 建议只写入 `104` 本机的 `/root/.aws/credentials`

## 7. 104 安装与配置步骤

### 7.1 安装 `aws cli`

```bash
apt-get update
apt-get install -y awscli
```

### 7.2 写入 AWS 凭证

```bash
mkdir -p /root/.aws
chmod 700 /root/.aws
cat >/root/.aws/credentials <<'EOF'
[default]
aws_access_key_id=CHANGE_ME
aws_secret_access_key=CHANGE_ME
EOF
chmod 600 /root/.aws/credentials
```

### 7.3 准备环境变量文件

```bash
cp deploy/aws/ap-east-1/configs/backup-to-s3.env.example /root/backup-to-s3.env
chmod 600 /root/backup-to-s3.env
```

把下面这些值改成真实值：

- `MYSQL_PASSWORD`
- `REDIS_PASSWORD`
- `HOST_TAG`

如果 MySQL 就跑在 `104` 本机，可保持：

- `MYSQL_HOST=127.0.0.1`

如果 Redis 就跑在 `104` 本机，可保持：

- `REDIS_HOST=127.0.0.1`

## 8. 手工执行方式

### 8.1 MySQL 逻辑备份

```bash
set -a
source /root/backup-to-s3.env
set +a

bash deploy/scripts/mysql_backup_to_s3.sh
```

默认产物：

- 本地：`/var/backups/hifast/*.sql.gz`
- S3：`s3://hifast-prod-backups-200810848252-ap-east-1/mysql/<HOST_TAG>/`

### 8.2 Redis RDB 备份

```bash
set -a
source /root/backup-to-s3.env
set +a

S3_PREFIX=redis bash deploy/scripts/redis_rdb_backup_to_s3.sh
```

默认产物：

- 本地：`/var/backups/hifast/*.rdb.gz`
- S3：`s3://hifast-prod-backups-200810848252-ap-east-1/redis/<HOST_TAG>/`

## 9. 定时任务建议

### 9.1 MySQL 每天凌晨执行

```cron
15 3 * * * . /root/backup-to-s3.env && /bin/bash /opt/ppanel/deploy/scripts/mysql_backup_to_s3.sh >>/var/log/hifast-mysql-backup.log 2>&1
```

### 9.2 Redis 每天凌晨执行

```cron
45 3 * * * . /root/backup-to-s3.env && S3_PREFIX=redis /bin/bash /opt/ppanel/deploy/scripts/redis_rdb_backup_to_s3.sh >>/var/log/hifast-redis-backup.log 2>&1
```

说明：

- MySQL 和 Redis 建议错峰执行
- 本地临时文件默认只保留 `3` 天
- 长期保留建议通过 S3 Lifecycle 管理，而不是靠本机 cron 删除

### 9.3 MySQL 每 10 分钟执行一次

如果你要在 `104` 上做高频逻辑备份，仓库里已经补了 `systemd timer` 安装脚本：

- 安装脚本：
  - [`deploy/scripts/install_mysql_backup_timer.sh`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/scripts/install_mysql_backup_timer.sh)
- systemd service：
  - [`deploy/systemd/hifast-mysql-backup.service`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/systemd/hifast-mysql-backup.service)
- systemd timer：
  - [`deploy/systemd/hifast-mysql-backup.timer`](/Users/Apple/code_vpn/vpn/ppanel-server/deploy/systemd/hifast-mysql-backup.timer)

安装方式：

```bash
cp deploy/aws/ap-northeast-1/configs/backup-to-s3.env.example /root/backup-to-s3.env
chmod 600 /root/backup-to-s3.env
vim /root/backup-to-s3.env

bash deploy/scripts/install_mysql_backup_timer.sh /opt/ppanel /root/backup-to-s3.env
```

查看状态：

```bash
systemctl list-timers --all | grep hifast-mysql-backup
systemctl status hifast-mysql-backup.timer --no-pager -l
systemctl status hifast-mysql-backup.service --no-pager -l
journalctl -u hifast-mysql-backup.service -n 50 --no-pager
```

补充说明：

- 定时表达式是 `OnCalendar=*:0/10`，即每 `10` 分钟执行一次
- 备份脚本已加 `flock` 锁，上一轮未结束时，下一轮会自动跳过，不会并发打包
- 高频逻辑备份会持续产生 `mysqldump` 开销，建议只在 `104` 这样的从库或备用库上执行，不要直接打主库

## 10. 恢复思路

### 10.1 MySQL

1. 从 S3 下载目标 `sql.gz`
2. 校验 `.sha256`
3. 解压
4. 导入目标 MySQL

示例：

```bash
aws s3 cp s3://hifast-prod-backups-200810848252-ap-east-1/mysql/104-standby/20260513T120000Z_104-standby_hifast.sql.gz .
aws s3 cp s3://hifast-prod-backups-200810848252-ap-east-1/mysql/104-standby/20260513T120000Z_104-standby_hifast.sql.gz.sha256 .
sha256sum -c 20260513T120000Z_104-standby_hifast.sql.gz.sha256
gunzip -c 20260513T120000Z_104-standby_hifast.sql.gz | mysql -h <target-host> -u <user> -p
```

### 10.2 Redis

1. 从 S3 下载目标 `rdb.gz`
2. 校验 `.sha256`
3. 解压得到 `dump.rdb`
4. 在维护窗口内替换 Redis 数据文件后重启

## 11. 当前推荐落地顺序

1. 保持当前 `RDS automated backup` 不变
2. 在 `104` 安装 `aws cli`
3. 创建最小权限 S3 上传凭证并仅保存到 `104`
4. 先手工执行一轮 MySQL 备份上传
5. 验证 S3 对象、校验文件、恢复可读性
6. 再补 Redis RDB 备份
7. 最后加 cron 和 S3 Lifecycle

## 12. 104 上的交互式运维脚本

为了减少手工敲命令，仓库里现在统一使用一套交互式总入口。

### 12.1 统一入口

```bash
bash deploy/scripts/hifast_data_sync_tool.sh /root/replica-ops.env
```

菜单支持：

- 备份 MySQL 到 S3
- 备份 Redis 到 S3
- 导出 MySQL dump
- 导入 MySQL dump 到 AWS RDS
- 导出后直接导入
- 导出 Redis RDB
- 导入 Redis RDB 到 Docker / 宿主机 Redis
- 查看 MySQL / Redis 当前主从状态
- 强制重拉 MySQL 主从
- 强制重拉 Redis 主从
- 把 MySQL 从库提升为可写主库
- 把 Redis 从库提升为主库
