chore: snapshot current aws standby and backup tooling work

This commit is contained in:
2026-05-13 10:59:03 -07:00
parent c4b2ebf7e1
commit f6911965dc
31 changed files with 1626 additions and 12482 deletions
+596 -88
View File
@@ -1,99 +1,396 @@
# AWS RDS to External Replica Runbook
# AWS RDS + EC2 Redis 到外部备用服务器 Runbook
目标:让外部服务器 `104.238.220.230` 上的 MySQL/Redis 尽量实时同步 AWS 侧数据,作为备用数据节点。
目标:让 `104.238.220.230` 持续作为 AWS 主生产环境的异地备用节点,承接:
## 已知资源
- MySQL 外部只读从库
- Redis 外部从库
- 故障时的快速提升与业务切换
- AWS region: `ap-east-1`
- RDS endpoint: `hifast-mysql-prod.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- RDS username: `admin`
- RDS password: `VIbW2nNoh0LXq2!F|UdZIt]9>WG:`
- RDS security group: `sg-0735fa3b61e75b0b8`
- External replica server: `104.238.220.230`
- External OS: Ubuntu 24.04 LTS
- External MySQL: 8.0.45
- External Redis: 7.0.15
本文档以 `2026-05-13` 的真实现网状态为准,覆盖:
## AWS Console 必须完成
- 当前已经落地的主从架构
- 日常验收命令
- 主从故障排查
- 全量重建从库
- “新建规范 RDS 再切换”的生产级收敛路线
- 故障切换与回滚
1. RDS `hifast-mysql-prod` 修改为 `Publicly accessible = Yes`
2. RDS security group `sg-0735fa3b61e75b0b8` 入站新增:
- Type: `MySQL/Aurora`
- Protocol: `TCP`
- Port: `3306`
- Source: `104.238.220.230/32`
- Description: `external mysql replica`
## 1. 当前已确认资源
不要开放 `0.0.0.0/0` 到 RDS 3306。
### 1.1 AWS 主生产
## RDS 上执行 SQL
- Region: `ap-east-1`
- AWS app EC2:
- Name: `hifast-hk-app-01`
- Public IP: `43.198.248.161`
- Private IP: `10.0.1.201`
- AWS MySQL:
- Type: `RDS MySQL`
- Instance: `hifast-mysql-prod-v2`
- Endpoint: `hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- Version: `8.4.8`
- DB Name: `hifast`
- Admin user: `admin`
- Admin password: keep it in a secret store, do not write plaintext into repo docs
- Replication user: `repl`
- Replication password: keep it in a secret store, do not write plaintext into repo docs
- AWS Redis:
- Location: `hifast-hk-app-01`
- Deployment: `Docker`
- Container: `hifast-redis`
- Version: `redis:8.2.1`
- Listen: `0.0.0.0:6379`
- Password: keep it in a secret store, do not write plaintext into repo docs
先连接:
### 1.2 外部备用服务器
- Host: `104.238.220.230`
- OS: `Ubuntu 24.04 LTS`
- SSH user: `root`
- MySQL version: `8.4.9`
- Redis version: `8.6.3`
- 当前角色:
- MySQL external replica
- Redis replica
- 备用应用节点
### 1.3 当前应用真实运行方式
AWS 应用机上的 `ppanel-server` 当前不是 systemd 托管,而是 Docker Compose 服务:
- Compose file: `/opt/ppanel/docker-compose.cloud.yml`
- Config file: `/opt/ppanel/configs/ppanel.yaml`
- Container name: `ppanel-server`
- Current MySQL target: `hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com:3306`
- Current Redis target: `127.0.0.1:6379`
也就是说,后续所有应用侧切换步骤,都应该以修改:
- `/opt/ppanel/configs/ppanel.yaml`
并执行:
```bash
mysql -h hifast-mysql-prod.cd6aey40m6ag.ap-east-1.rds.amazonaws.com -u admin -p
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml up -d ppanel-server
```
然后执行:
作为准。
## 2. 当前健康基线
截至 `2026-05-13`,已确认以下状态成立:
- `104` MySQL:
- `Source_Host = hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source: 0`
- `read_only = ON`
- `super_read_only = ON`
- AWS Redis 主库:
- `role:master`
- `connected_slaves:1`
- `104` Redis:
- `role:slave`
- `master_link_status:up`
- AWS 应用:
- `curl http://127.0.0.1:8080/v1/common/heartbeat` 返回 `code=200`
这说明当前状态已经达到:
- 主生产可用
- 外部备用持续同步
- Redis 已回到真实本机链路
## 3. 当前网络前提
### 3.1 安全组
当前实际生效的安全组如下:
- `hifast-hk-app-core-sg`
- `22/tcp <- 0.0.0.0/0`
- `6379/tcp <- 104.238.220.230/32`
- `8080/tcp <- hifast-hk-web-sg`
- `hifast-hk-rds-core-sg`
- `3306/tcp <- 104.238.220.230/32`
- `3306/tcp <- hifast-hk-app-core-sg`
- `hifast-hk-web-sg`
- `22/80/443 <- 0.0.0.0/0`
### 3.2 当前结构性限制
当前 `104 -> RDS` 公网复制链路虽然可用,但依赖的是:
- `hifast-mysql-prod-v2``Publicly accessible = Yes`
- RDS ENI 仍位于 `hifast-hk-private-1b`
- `private-1b` 被临时挂到了公网路由表
这不是最终规范的生产形态。
当前这条路线已经完成,后续更推荐的动作是:
1. 持续确认应用主库目标保持在 `hifast-mysql-prod-v2`
2. 持续确认 `104` 复制目标保持在 `hifast-mysql-prod-v2`
3. 根据回收窗口安排旧 RDS 下线
4. 按网络收敛计划处理 `private-1b` 路由语义
## 4. 日常验收命令
### 4.1 验收 MySQL 主从
`104` 执行:
```bash
mysql -e "SHOW REPLICA STATUS\G"
```
重点看:
- `Source_Host`
- `Replica_IO_Running`
- `Replica_SQL_Running`
- `Seconds_Behind_Source`
- `Last_IO_Error`
- `Last_SQL_Error`
成功标准:
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source: 0` 或较小
### 4.2 验收 Redis 主从
在 AWS app EC2 执行:
```bash
docker exec hifast-redis redis-cli -a '0BVz9XOHf7KUfEuoFJRK-dURdKUGFiZ8QeaHpysHnKeKhLskZb55HPK121lFsKtr' INFO replication
```
重点看:
- `role:master`
- `connected_slaves:1`
`104` 执行:
```bash
redis-cli INFO replication
```
重点看:
- `role:slave`
- `master_host:43.198.248.161`
- `master_port:6379`
- `master_link_status:up`
### 4.3 验收应用
在 AWS app EC2 执行:
```bash
curl -sf http://127.0.0.1:8080/v1/common/heartbeat
```
期望返回:
- `{"code":200,...}`
查看容器:
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml ps
```
期望:
- `ppanel-server``Up`
- `hifast-redis``Up`
## 5. MySQL 复制故障排查
### 5.1 先看复制状态
```bash
mysql -e "SHOW REPLICA STATUS\G"
```
重点判断:
- `Replica_IO_Running = No`
- `Replica_SQL_Running = No`
- `Last_IO_Error`
- `Last_SQL_Error`
### 5.2 常见场景
#### 场景 A:网络或白名单断开
表现:
- `Replica_IO_Running: No`
- `Last_IO_Error` 出现连接失败、超时、拒绝访问
排查:
```bash
mysql -h hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com -u repl -p -e "SELECT 1;"
```
处理:
- 检查 RDS SG 是否仍保留 `104.238.220.230/32 -> 3306`
- 检查 RDS 是否仍为 `Publicly accessible = Yes`
- 如果后续已迁到新规范 RDS,则检查新实例的 SG 和公网可达性
#### 场景 B:主库 binlog 位点丢失
表现:
- `Last_IO_Error``Last_SQL_Error` 指向缺失 binlog
处理:
- 不要硬跳过
- 直接执行全量重建从库
#### 场景 CSQL 执行报错
表现:
- `Replica_SQL_Running: No`
- `Last_SQL_Error` 有实际 SQL 冲突信息
处理建议:
- 如果只是临时演练环境,可重建从库
- 如果已经进入生产切换阶段,不建议盲目 `sql_slave_skip_counter`
- 优先保守做法仍是重新全量初始化
## 6. Redis 复制故障排查
### 6.1 看 `104` 从库状态
```bash
redis-cli INFO replication
```
重点:
- `role`
- `master_host`
- `master_link_status`
### 6.2 看 AWS 主库状态
```bash
docker exec hifast-redis redis-cli -a '0BVz9XOHf7KUfEuoFJRK-dURdKUGFiZ8QeaHpysHnKeKhLskZb55HPK121lFsKtr' INFO replication
```
重点:
- `role:master`
- `connected_slaves`
### 6.3 常见问题
#### 场景 A:安全组断开
表现:
- `master_link_status:down`
处理:
- 确认 `hifast-hk-app-core-sg` 仍保留:
- `6379/tcp <- 104.238.220.230/32`
#### 场景 B:主库密码漂移
表现:
- 从库重连失败
- 日志出现 `NOAUTH`
处理:
- 统一更新 `/etc/redis/redis.conf` 中的:
- `masterauth`
- 然后:
```bash
systemctl restart redis-server
redis-cli INFO replication
```
## 7. 全量重建 MySQL 从库
适用场景:
- 主从中断且无法安全追平
- `6666@qq.com` 这类写入在主库存在、从库未同步
- binlog 不连续
- 需要回到最稳妥状态
### 7.1 在主库导出
在一台可连 RDS 的机器上执行:
```bash
mysqldump \
-h hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com \
-u admin \
-p \
--single-transaction \
--routines \
--triggers \
--events \
--set-gtid-purged=OFF \
hifast > hifast-full.sql
```
如果需要同步账号权限,也可以额外单独导出授权对象;但当前业务库恢复重点是 `hifast` 数据库本身。
### 7.2 清理 `104` 当前复制
`104` 执行:
```sql
CALL mysql.rds_set_configuration('binlog retention hours', 24);
STOP REPLICA;
RESET REPLICA ALL;
```
CREATE USER IF NOT EXISTS 'repl'@'104.238.220.230' IDENTIFIED BY 'THcPeHaerV4PwyE9qtF6PHZd';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'104.238.220.230';
FLUSH PRIVILEGES;
### 7.3 重新导入业务库
SHOW VARIABLES LIKE 'gtid_mode';
`104` 执行:
```bash
mysql -e "DROP DATABASE IF EXISTS hifast; CREATE DATABASE hifast CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;"
mysql hifast < hifast-full.sql
```
### 7.4 重新挂复制
当前现网是非 GTID 自动定位,使用 file/position 模式。
先在主库取位点:
```sql
SHOW MASTER STATUS;
```
记录 `SHOW MASTER STATUS` 输出的 `File``Position`。如果 `gtid_mode = ON`,外部从库可用 auto-position;否则使用 file/position。
## 外部服务器基础配置
`104.238.220.230` root shell 执行:
```bash
cat >/etc/mysql/mysql.conf.d/99-replica.cnf <<'EOF'
[mysqld]
server-id=230
read_only=ON
super_read_only=ON
relay_log=relay-bin
log_bin=mysql-bin
binlog_format=ROW
EOF
systemctl restart mysql
mysql -e "SHOW VARIABLES WHERE Variable_name IN ('server_id','read_only','super_read_only','log_bin','binlog_format');"
```
如果 RDS `gtid_mode = ON`
然后在 `104` 执行:
```sql
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='hifast-mysql-prod.cd6aey40m6ag.ap-east-1.rds.amazonaws.com',
SOURCE_HOST='hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com',
SOURCE_PORT=3306,
SOURCE_USER='repl',
SOURCE_PASSWORD='THcPeHaerV4PwyE9qtF6PHZd',
SOURCE_AUTO_POSITION=1,
SOURCE_SSL=1;
START REPLICA;
SHOW REPLICA STATUS\G
```
如果 RDS `gtid_mode != ON`,把 `<MASTER_LOG_FILE>``<MASTER_LOG_POS>` 替换成 `SHOW MASTER STATUS` 里的值:
```sql
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='hifast-mysql-prod.cd6aey40m6ag.ap-east-1.rds.amazonaws.com',
SOURCE_PORT=3306,
SOURCE_USER='repl',
SOURCE_PASSWORD='THcPeHaerV4PwyE9qtF6PHZd',
SOURCE_PASSWORD='<REPL_PASSWORD>',
SOURCE_LOG_FILE='<MASTER_LOG_FILE>',
SOURCE_LOG_POS=<MASTER_LOG_POS>,
SOURCE_SSL=1;
@@ -101,37 +398,36 @@ START REPLICA;
SHOW REPLICA STATUS\G
```
成功标准:
### 7.5 验收
确认:
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source``0` 或较小数值
- `Seconds_Behind_Source: 0`
- `read_only = ON`
- `super_read_only = ON`
## Redis 复制
## 8. 重新配置 Redis 从库
Redis 源端还未确认。之前方案是 Redis 放在 AWS app EC2 上,与服务端同机。需要先登录 AWS app EC2,确认 Redis 是否存在、端口、密码、监听地址
当前 `104` Redis 为原生安装,不使用 Docker
外部 Redis 从库命令模板:
### 8.1 临时切回从库
```bash
redis-cli CONFIG SET masterauth '0BVz9XOHf7KUfEuoFJRK-dURdKUGFiZ8QeaHpysHnKeKhLskZb55HPK121lFsKtr'
redis-cli REPLICAOF 43.198.248.161 6379
redis-cli CONFIG SET replica-read-only yes
redis-cli REPLICAOF <AWS_REDIS_PRIVATE_OR_PUBLIC_IP> 6379
redis-cli INFO replication
```
如果源端有密码:
### 8.2 持久化配置
```bash
redis-cli CONFIG SET masterauth '<REDIS_PASSWORD>'
redis-cli REPLICAOF <AWS_REDIS_PRIVATE_OR_PUBLIC_IP> 6379
redis-cli INFO replication
```
持久化写入 `/etc/redis/redis.conf`
检查 `/etc/redis/redis.conf` 至少包含:
```conf
replicaof <AWS_REDIS_PRIVATE_OR_PUBLIC_IP> 6379
masterauth <REDIS_PASSWORD>
replicaof 43.198.248.161 6379
masterauth 0BVz9XOHf7KUfEuoFJRK-dURdKUGFiZ8QeaHpysHnKeKhLskZb55HPK121lFsKtr
replica-read-only yes
```
@@ -142,3 +438,215 @@ systemctl restart redis-server
redis-cli INFO replication
```
## 9. 生产级收敛路线:新建规范 RDS 再切换
这条路线已经完成,当前现网主库已经切到 `hifast-mysql-prod-v2`。下面内容保留为迁移归档参考,不再表示待执行。
### 9.1 目标
把当前临时方案:
- `private-1b` 挂公网路由
收敛成:
- RDS 使用纯公网 DB subnet group
- 安全组仍只对白名单和应用组开放
### 9.2 已准备好的资源
- 已建 DB subnet group:
- `hifast-hk-rds-public-only-sgprep`
- 子网:
- `hifast-hk-public-1a`
- `hifast-hk-public-1b`
### 9.3 新 RDS 建议参数
新实例建议名:
- `hifast-mysql-prod-v2`
建议保持与旧主库一致:
- Engine: `mysql`
- Version: `8.4.8`
- Class: `db.r7g.xlarge`
- Storage: `gp3`
- Size: `200 GB`
- IOPS: `3000`
- Throughput: `125`
- Publicly accessible: `Yes`
- Multi-AZ: `No` 或按预算单独评估
- Deletion protection: `On`
- Performance Insights: `On`
- Backup retention: `7`
- DB subnet group: `hifast-hk-rds-public-only-sgprep`
- VPC SG: `hifast-hk-rds-core-sg`
### 9.4 迁移步骤
1. 已创建新 RDS `hifast-mysql-prod-v2`
2. 在旧主库导出 `hifast`
3. 导入新库
4. 在新库创建 `repl` 用户并配置 binlog retention
5. 修改 AWS app EC2 上 `/opt/ppanel/configs/ppanel.yaml``MySQL.Addr`
6. 重启 `ppanel-server` 容器
7.`104``STOP REPLICA; RESET REPLICA ALL;`
8. 指向新 RDS endpoint 重新挂复制
9. 验收应用与主从
10. 验收通过后,安排旧 RDS 下线,并推进 `private-1b` 恢复私网路由
### 9.5 应用切换命令
在 AWS app EC2
1. 备份配置
```bash
cp /opt/ppanel/configs/ppanel.yaml /opt/ppanel/configs/ppanel.yaml.bak.$(date +%Y%m%d%H%M%S)
```
2. 编辑:
- `/opt/ppanel/configs/ppanel.yaml`
把:
```yaml
MySQL:
Addr: hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com:3306
```
改成:
```yaml
MySQL:
Addr: hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com:3306
```
3. 重启应用容器:
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml up -d ppanel-server
```
4. 验证:
```bash
curl -sf http://127.0.0.1:8080/v1/common/heartbeat
docker compose -f docker-compose.cloud.yml logs --tail=100 ppanel-server
```
### 9.6 `104` 改挂新 RDS
```sql
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='<NEW_RDS_ENDPOINT>',
SOURCE_PORT=3306,
SOURCE_USER='repl',
SOURCE_PASSWORD='<REPL_PASSWORD>',
SOURCE_LOG_FILE='<MASTER_LOG_FILE>',
SOURCE_LOG_POS=<MASTER_LOG_POS>,
SOURCE_SSL=1;
START REPLICA;
SHOW REPLICA STATUS\G
```
### 9.7 切换验收
至少确认:
- AWS 应用心跳正常
- 新 RDS 可正常读写
- `104` 复制恢复为 `Yes/Yes`
- `Seconds_Behind_Source` 追到 `0`
- Navicat 可从允许的白名单来源连接新 RDS
### 9.8 回滚
如果新 RDS 切换后应用异常:
1. 立即把 `/opt/ppanel/configs/ppanel.yaml``MySQL.Addr` 改回旧 endpoint
2. 重启 `ppanel-server`
3. 暂不处理 `104`,先恢复主生产
4. 复盘新库数据、权限、参数、网络
## 10. AWS 故障时的备用接管
### 10.1 Redis 提升为主库
`104`
```bash
redis-cli REPLICAOF NO ONE
redis-cli INFO replication
```
期望:
- `role:master`
### 10.2 MySQL 提升为可写主库
`104`
```sql
STOP REPLICA;
RESET REPLICA ALL;
SET GLOBAL super_read_only=OFF;
SET GLOBAL read_only=OFF;
```
再确认:
```sql
SHOW VARIABLES LIKE 'read_only';
SHOW VARIABLES LIKE 'super_read_only';
```
期望:
- `OFF`
- `OFF`
### 10.3 应用切到 `104` 本机数据层
如果 `104` 上也部署同样的 PPanel 服务,则应用配置应改为:
- MySQL 指向 `127.0.0.1:3306` 或本机 socket
- Redis 指向 `127.0.0.1:6379`
### 10.4 最后切入口
数据层和应用层都确认可写后,再做:
- DNS 切换
- 或 Nginx / 上游切流量
原则:
- 先数据接管
- 再应用确认
- 最后入口切换
## 11. 日常巡检建议
建议至少每天巡检一次:
1. `104` MySQL `SHOW REPLICA STATUS\G`
2. `104` Redis `INFO replication`
3. AWS Redis 主库 `INFO replication`
4. AWS app 心跳 `/v1/common/heartbeat`
5. `docker compose -f /opt/ppanel/docker-compose.cloud.yml ps`
如果后续要做真正的生产级自动化,再补:
- MySQL 复制延迟告警
- Redis 主从断链告警
- 应用心跳失败告警
- RDS 连接失败告警
- 定期灾备切换演练
+297 -39
View File
@@ -10,6 +10,47 @@
- MySQL / Redis 的同步关系是什么
- 故障时应该如何切换
## 0. 2026-05-13 验收摘要
- 已确认 `104.238.220.230 -> AWS RDS MySQL` 连通,MySQL 外部从库健康:
- 当前复制上游:`hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source: 0`
- 已确认 `104.238.220.230 -> AWS EC2 Redis` 主从健康:
- `104``role:slave`
- `master_link_status:up`
- AWS Redis 主库 `connected_slaves:1`
- 已修复应用侧 Redis 配置漂移:
- 旧链路:`127.0.0.1:6380 -> stunnel4 -> 旧 ElastiCache`
- 新链路:`127.0.0.1:6379 -> 本机 Docker Redis`
-`stunnel4` 已停用并禁用自启,`ppanel-server` 日志里的 Redis `i/o timeout` 已停止出现。
- 已确认 `ppanel-server` 当前运行方式为 Docker Compose 容器,而不是 systemd 服务:
- Compose 文件:`/opt/ppanel/docker-compose.cloud.yml`
- 配置文件:`/opt/ppanel/configs/ppanel.yaml`
- 容器名:`ppanel-server`
- 健康检查:`curl http://127.0.0.1:8080/v1/common/heartbeat` 返回正常
- 旧自建安全组 `hifast-hk-app-sg``hifast-hk-nginx-sg` 已删除;当前 VPC 内仅保留:
- `hifast-hk-app-core-sg`
- `hifast-hk-rds-core-sg`
- `hifast-hk-web-sg`
- `default`
- 目前已经达到“可用且关键链路已恢复”的状态。
- 当前入口层属于已确认的过渡方案:
- 现阶段公网入口仍在 `hifast-hk-app-01`
- 独立 `nginx` 服务器已预留,待 AWS 后续资源到位后再迁移承接
- 当前仍需要继续收敛的核心生产项只剩 1 个:
- RDS 为了让 `104` 走公网白名单复制,当前仍依赖 `hifast-hk-private-1b` 子网临时挂到公网路由表,这不是最终规范形态。
- 已完成的下一步准备:
- 已创建纯公网子网专用的 `DB subnet group``hifast-hk-rds-public-only-sgprep`
- 子网包含:
- `subnet-070e3f264a9c79f32` `hifast-hk-public-1a`
- `subnet-00cb5add705c447c8` `hifast-hk-public-1b`
- 已创建专用 S3 备份桶:
- `hifast-prod-backups-200810848252-ap-east-1`
- 当前状态:private
- 当前状态:versioning enabled
## 1. 当前实际环境
### 1.1 AWS 区域
@@ -23,15 +64,37 @@
- 名称:`hifast-hk-app-01`
- Instance ID: `i-079cd9d3ef3748714`
- 角色:应用机 / Nginx / 业务服务 / AWS 侧 Redis 主库宿主机
- 角色:当前实际生产入口 / Nginx / 业务服务 / AWS 侧 Redis 主库宿主机
- 私网 IP: `10.0.1.201`
- 公网 IP: `43.198.248.161`
- 业务服务运行方式:`Docker Compose`
- 业务容器:`ppanel-server`
- 部署目录:`/opt/ppanel`
- 实际配置文件:`/opt/ppanel/configs/ppanel.yaml`
#### 独立 Nginx 服务器
- 名称:`hifast-hk-nginx-01`
- Instance ID: `i-0701d54bf2c6bf594`
- 角色:计划中的独立入口机
- 私网 IP: `10.0.1.175`
- 当前状态:`stopped`
- 当前说明:已经只绑定 `hifast-hk-web-sg`,但目前并未承接正式流量
#### MySQL 主库
- 类型:`AWS RDS MySQL`
- 实例名:`hifast-mysql-prod`
- 实例名:`hifast-mysql-prod-v2`
- Endpoint: `hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- 角色:生产主库
- Engine: `MySQL 8.4.8`
- Publicly accessible: `Yes`
- Multi-AZ: `No`
- Backup retention: `7 days`
- Deletion protection: `On`
- 当前数据库实际体量:约 `187.41 MB`
- 当前表数量:`37`
- 当前 `user` 表记录数:`45076`
#### Redis 主库
@@ -41,6 +104,8 @@
- 版本:`redis:8.2.1`
- 访问端口:`6379`
- 主库出口地址:`43.198.248.161:6379`
- 应用当前实际连接:`127.0.0.1:6379`
- 认证方式:已启用密码认证
#### 外部备用服务器
@@ -48,10 +113,18 @@
- OS: `Ubuntu 24.04 LTS`
- 角色:异地备用节点
- 当前状态:已部署与 AWS 相同的业务服务
- 当前 MySQL 状态:外部只读从库
- 当前 Redis 部署方式:`宿主机原生安装`
- 当前 Redis 版本:`8.6.3`
- 当前 Redis 角色:`AWS Redis 主库的从库`
#### S3 备份桶
- Bucket: `hifast-prod-backups-200810848252-ap-east-1`
- Region: `ap-east-1`
- Public access: blocked
- Versioning: enabled
## 2. 架构总览
```mermaid
@@ -59,7 +132,7 @@ flowchart TB
USER["用户 / 客户端"] --> DNS["域名 / DNS / 入口层"]
DNS --> APP["AWS EC2\nhifast-hk-app-01\n43.198.248.161\n10.0.1.201"]
APP --> RDS["AWS RDS MySQL\nhifast-mysql-prod\n主库"]
APP --> RDS["AWS RDS MySQL\nhifast-mysql-prod-v2\n主库"]
APP --> REDISM["AWS Redis 主库\nDocker redis:8.2.1\n43.198.248.161:6379"]
RDS -. MySQL 备用 / 同步 .-> MYSQLS["104.238.220.230\nMySQL 备用库"]
@@ -87,8 +160,10 @@ flowchart TB
说明:
- 当前主应用入口在 AWS EC2
- EC2 同时承担业务服务入口
- 当前主应用入口实际在 `hifast-hk-app-01`
- `hifast-hk-app-01` 同时承担 Nginx、业务服务、Redis 主库
- 当前业务服务不是 systemd 单进程部署,而是由 `/opt/ppanel/docker-compose.cloud.yml` 管理的 `ppanel-server` 容器提供 `8080`
- 独立入口机 `hifast-hk-nginx-01` 已存在,但当前仅作为后续资源开通后的迁移目标。
- MySQL 在 AWS RDS。
- Redis 不在 ElastiCache,而是在 EC2 本机通过 Docker 提供。
@@ -118,43 +193,187 @@ App / Nginx
## 4. 网络与安全边界
### 4.1 EC2 安全组
### 4.1 当前安全组
- 安全组名称:`hifast-hk-app-sg`
- 安全组 ID: `sg-09266fb27bde15714`
截至 `2026-05-13`VPC `vpc-09fc384522517debc` 内仅保留 4 个安全组:
已确认规则:
- `default`
- `hifast-hk-app-core-sg`
- `hifast-hk-rds-core-sg`
- `hifast-hk-web-sg`
- Redis `6379/tcp`
- 来源:`104.238.220.230/32`
其中绑定关系已经收敛为:
这条规则的作用是:
- `hifast-hk-app-01` -> `hifast-hk-app-core-sg`
- `hifast-hk-nginx-01` -> `hifast-hk-web-sg`
- `hifast-mysql-prod-v2` -> `hifast-hk-rds-core-sg`
- 允许外部备用服务器 `104.238.220.230` 连到 AWS Redis 主库
- 避免 Redis 对全网开放
旧组:
### 4.2 Redis 网络关系
- `hifast-hk-app-sg`
- `hifast-hk-nginx-sg`
已经删除,不再使用。
### 4.2 当前入站规则
#### `hifast-hk-app-core-sg`
- `22/tcp <- 0.0.0.0/0`
- `6379/tcp <- 104.238.220.230/32`
- `8080/tcp <- hifast-hk-web-sg`
#### `hifast-hk-rds-core-sg`
- `3306/tcp <- 104.238.220.230/32`
- `3306/tcp <- hifast-hk-app-core-sg`
#### `hifast-hk-web-sg`
- `22/tcp <- 0.0.0.0/0`
- `80/tcp <- 0.0.0.0/0`
- `443/tcp <- 0.0.0.0/0`
### 4.3 Redis 网络关系
```mermaid
flowchart LR
SG["EC2 Security Group\nsg-09266fb27bde15714"] --> REDIS["AWS Redis 主库\n43.198.248.161:6379"]
SG["hifast-hk-app-core-sg"] --> REDIS["AWS Redis 主库\n43.198.248.161:6379"]
STANDBY["104.238.220.230/32"] --> SG
```
### 4.3 RDS 访问原则
### 4.4 RDS 访问原则
RDS 不应该对公网全开放。
RDS 当前状态已经比之前干净很多:
推荐且已执行过的方向是:
- 只对白名单源 IP 开放 `3306`
- 如果 `104.238.220.230` 需要做外部从库,则只放行这个 IP
- 当前只对白名单和应用安全组开放 `3306`
- 已移除 `3306 <- 0.0.0.0/0`
- 当前 RDS 仅绑定 `hifast-hk-rds-core-sg`
建议原则:
- 不开放 `0.0.0.0/0` 到 MySQL `3306`
- 不开放 `0.0.0.0/0` 到 Redis `6379`
### 4.5 当前仍需继续收敛的网络点
#### 4.5.1 入口层当前属于过渡方案,不作为本阶段阻塞项
当前运行形态是:
- `hifast-hk-app-01` 本机 `nginx` 正在监听 `80/443`
- `hifast-hk-nginx-01` 当前停止
但当前安全组设计是按“独立 nginx 机”拆的:
- `hifast-hk-web-sg``hifast-hk-nginx-01`
- `hifast-hk-app-core-sg``hifast-hk-app-01`
这意味着当前真实入口和安全组角色划分还没有完全一致。
但这一点已经被确认为过渡设计,不作为当前阶段必须整改的问题。后续待 AWS 新资源到位后,再把公网入口迁到独立 `nginx` 服务器即可。
#### 4.5.2 RDS 公网复制链路仍是当前唯一核心结构性问题
为了让 `104.238.220.230` 通过公网白名单访问 RDS,当前实际依赖的是:
- RDS `PubliclyAccessible = true`
- RDS ENI 仍在 `subnet-0dcf46db665b6d8a7`
- 该子网名称是 `hifast-hk-private-1b`
- 但这个子网当前被临时关联到了公网路由表
这能用,但不属于最终规范的“纯公网子网组”设计。
本轮已经额外完成的准备动作:
- 已新建纯公网 `DB subnet group``hifast-hk-rds-public-only-sgprep`
- 该组状态:`Complete`
- 该组仅包含两条公网子网:
- `hifast-hk-public-1a`
- `hifast-hk-public-1b`
当前结论:
- 不建议继续在现有生产 RDS 上反复试在线切子网组。
- 更稳的收敛方案是:新建一台使用规范公网子网组的生产 RDS,再做一次短切换。
- 由于当前库体量只有约 `187 MB`,这条路线的执行成本并不高,风险也比在现网主库上硬改更可控。
## 4.6 104 如何连接 AWS
这里要特别区分:
- `104` 连接 AWS 数据层
- 本地电脑登录 AWS EC2
这不是同一件事。
### 4.6.1 104 连接 AWS Redis 的方式
`104.238.220.230` 连接 AWS Redis,不是通过 PEM 证书,也不是通过 SSH 登录 AWS 机器,而是直接作为 Redis 从库去访问 AWS Redis 主库:
- 目标地址:`43.198.248.161:6379`
- 连接方式:`TCP`
- 认证方式:`Redis 密码`
- 网络前提:AWS EC2 安全组已放行 `104.238.220.230/32 -> 6379`
也就是说:
```text
104 Redis 从库 -> 直连 AWS Redis 主库公网地址 -> 密码认证 -> 建立复制
```
示意命令:
```bash
redis-cli -h 43.198.248.161 -p 6379 -a '<REDIS_PASSWORD>'
```
### 4.6.2 104 连接 AWS MySQL RDS 的方式
`104.238.220.230` 连接 AWS RDS,也不是通过 PEM 证书,而是通过数据库连接:
- 目标地址:`hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com:3306`
- 连接方式:`MySQL TCP`
- 认证方式:`MySQL 用户名 + 密码`
- 网络前提:RDS 白名单或安全组放行 `104.238.220.230`
也就是说:
```text
104 MySQL 从库 -> 直连 AWS RDS endpoint -> 账号密码认证 -> 建立复制
```
示意命令:
```bash
mysql -h hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com -u admin -p
```
### 4.6.3 本地电脑登录 AWS EC2 的方式
本地电脑这边之前进入 AWS EC2,用的不是 `hifast-hk-app-01-key.pem`,而是:
- `AWS Console`
- `EC2 Instance Connect`
- 浏览器里的 Web SSH 终端
所以当前要理解成 3 条不同链路:
1. 本地电脑 -> AWS 控制台 -> EC2 Instance Connect -> AWS EC2
2. `104` -> AWS Redis 主库公网地址 -> Redis 密码认证
3. `104` -> AWS RDS endpoint -> MySQL 用户密码认证
### 4.6.4 关键结论
当前灾备链路里,`104` 与 AWS 数据同步不依赖 `.pem` 证书文件。
真正依赖的是:
- Redis 安全组放行
- RDS 白名单 / 安全组放行
- 正确的 Redis 密码
- 正确的 MySQL 账号密码
## 5. Redis 实际部署与同步状态
### 5.1 AWS Redis 主库
@@ -186,6 +405,8 @@ RDS 不应该对公网全开放。
-`104` 连接 AWS Redis 主库,认证成功
- AWS 主库写入测试键
- `104` 从库成功读取测试键
- `2026-05-13` 已确认应用机本地 `ppanel-server -> 127.0.0.1:6379` 建立稳定连接
- `2026-05-13` 已确认旧 `stunnel4 -> ElastiCache` 链路下线后,应用日志不再出现 Redis `i/o timeout`
测试键:
@@ -206,7 +427,7 @@ flowchart LR
### 6.1 主库角色
- 主库在 `AWS RDS MySQL`
- 实例:`hifast-mysql-prod`
- 实例:`hifast-mysql-prod-v2`
### 6.2 外部备用角色
@@ -215,26 +436,32 @@ flowchart LR
### 6.3 当前文档说明
Redis 的主从状态已经在本次执行中完成并验证
MySQL 当前已经完成实际验收,不再只是“待确认”状态
`2026-05-13` 验收结果:
- `Source_Host = hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- `Replica_IO_Running = Yes`
- `Replica_SQL_Running = Yes`
- `Seconds_Behind_Source = 0`
- `read_only = ON`
- `super_read_only = ON`
这表示 `104` 当前是健康的只读外部备用库。
MySQL 这部分在此前已经有专门 runbook:
- [ops/aws-rds-external-replica-runbook.md](/Users/Apple/code_vpn/vpn/ppanel-server/ops/aws-rds-external-replica-runbook.md)
如果要把 MySQL 也完全纳入同一灾备演练,需要继续确认:
- `104` 当前 MySQL 的同步线程状态
- `SHOW REPLICA STATUS\G` 是否仍然正常
- RDS 到 `104` 的白名单是否仍然保留
## 7. 当前生产方案的真实特点
这套已经落地的架构,不是传统的全 AWS 托管标准形态,而是偏实用的混合方案:
- 应用在 AWS EC2
- 应用和当前实际公网入口在 AWS 同一台 EC2
- MySQL 在 AWS RDS
- Redis 在 AWS EC2 本机
- MySQL / Redis 均向外部服务器 `104` 做灾备
- 旧 ElastiCache / stunnel 链路已经退出当前生产路径
它的优点:
@@ -348,6 +575,9 @@ redis-cli -a '<REDIS_PASSWORD>' REPLICAOF NO ONE
- AWS Redis 主库是否在线
- `104` Redis 从库是否 `master_link_status:up`
- `104` MySQL 复制是否正常
- `ppanel-server` 容器是否 `Up`
- `ppanel-server` 日志中是否再次出现 Redis `i/o timeout`
- `stunnel4` 是否保持 `inactive`
### 9.2 Redis 故障时
@@ -377,7 +607,7 @@ redis-cli -a '<REDIS_PASSWORD>' REPLICAOF NO ONE
### 10.1 当前实际方案
`DNS -> AWS EC2(App + Nginx) -> RDS MySQL + EC2 Redis -> 104 灾备`
`DNS -> hifast-hk-app-01(Nginx + App + Redis) -> RDS MySQL -> 104 灾备`
### 10.2 理想生产方案
@@ -394,11 +624,35 @@ redis-cli -a '<REDIS_PASSWORD>' REPLICAOF NO ONE
建议按优先级补齐:
1. 明确 `104` 应用接管脚本与启动检查项
2. 明确 MySQL 故障切换脚本
3. 明确 Redis 故障切换脚本
4. 明确域名 / DNS 切换方式
5. 做一次完整灾备演练
1. 把 RDS 从“private 子网挂公网路由”的临时方案,收敛成真正的公网 DB subnet group,或改成私网复制方案
2. 明确 `104` 应用接管脚本与启动检查项
3. 明确 MySQL 故障切换脚本
4. 明确 Redis 故障切换脚本
5. 明确域名 / DNS 切换方式
6. 做一次完整灾备演练
7. 待 AWS 新资源到位后,再把公网入口迁到独立 `nginx` 服务器
### 10.4 RDS 推荐收敛路线
当前原先规划的“新建规范 RDS 再切换”路线已经完成,现网主库已经是 `hifast-mysql-prod-v2`
后续更推荐的正式路线是:
1. 继续以 `hifast-mysql-prod-v2` 作为当前生产主库
2. 确认其持续使用 `hifast-hk-rds-public-only-sgprep`
3. 安全组持续只放:
- `104.238.220.230/32 -> 3306`
- `hifast-hk-app-core-sg -> 3306`
4. 持续确认应用连接目标为 `hifast-mysql-prod-v2`
5. 持续确认 `104` 的外部复制目标为 `hifast-mysql-prod-v2`
6. 验证通过后,再安排旧 RDS 下线
这条路线的优点:
- 最终拓扑规范清晰
- 不需要继续保留“private 子网挂公网路由”的临时设计
- 对当前现网主库的扰动最小
- 当前数据库体量较小,迁移成本可控
## 11. 建议的下一版目标拓扑
@@ -423,16 +677,20 @@ flowchart TB
截至当前,已经可以确认的生产与灾备状态是:
- AWS 是主生产环境
- 应用跑在 `hifast-hk-app-01`
- 应用当前跑在 `hifast-hk-app-01`
- MySQL 主库在 AWS RDS
- Redis 主库在 AWS EC2 Docker
- `104.238.220.230` 是异地备用节点
- `104` 已部署与 AWS 相同的业务服务
- `104` 上 Redis 已切为宿主机原生安装
- `104` Redis 已成功作为 AWS Redis 主库的从库在线同步
- `104` MySQL 已恢复并保持健康复制
- 应用已经切回当前真实可用的本机 Redis 主库
-`stunnel4 -> ElastiCache` 链路已经退出生产路径
如果后续要继续完善这份方案,优先补充:
- MySQL 最终同步状态复核
- RDS 子网与公网访问模型收敛
- 入口域名 / DNS 切换细则
- 应用层在 `104` 的接管与回切执行清单
- 待资源到位后的独立 `nginx` 迁移清单
+286
View File
@@ -0,0 +1,286 @@
# Hifast 新 RDS 生产切换清单(已完成归档)
本文档记录已完成的 `hifast-mysql-prod -> hifast-mysql-prod-v2` 生产切换过程,作为归档和回溯参考。
本次切换已经完成,当时的目标是避免继续在线硬改现有生产 RDS,而是:
1. 新建一台规范公网子网组的新 RDS
2. 导入现有 `hifast` 数据
3. 将 AWS 应用切到新 RDS
4.`104.238.220.230` 的外部从库改挂新 RDS
5. 验收通过后再下线旧 RDS
## 1. 适用背景
当前现网已经可用,但还存在 1 个结构性问题:
- 为了让 `104` 通过公网白名单做 MySQL 复制,当时的 `hifast-mysql-prod` 仍依赖 `hifast-hk-private-1b` 临时挂公网路由
当前已准备好的收敛资源:
- 纯公网 DB subnet group:
- `hifast-hk-rds-public-only-sgprep`
- 安全组:
- `hifast-hk-rds-core-sg`
## 2. 目标实例参数
建议新实例名称:
- `hifast-mysql-prod-v2`
建议参数如下:
- Region: `ap-east-1`
- Engine: `MySQL`
- Engine version: `8.4.8`
- Templates: `Production`
- DB instance class: `db.r7g.xlarge`
- Storage type: `gp3`
- Allocated storage: `200 GiB`
- Provisioned IOPS: `3000`
- Storage throughput: `125`
- Multi-AZ: `No`
- Publicly accessible: `Yes`
- VPC: `vpc-09fc384522517debc`
- DB subnet group: `hifast-hk-rds-public-only-sgprep`
- VPC security group: `hifast-hk-rds-core-sg`
- DB name: `hifast`
- Master username: `admin`
- Master password: 与现网保持一致
- Backup retention: `7 days`
- Performance Insights: `On`
- Storage encryption: `On`
- Deletion protection: `On`
- Auto minor version upgrade: 建议保持与现网一致
- Maintenance window: 可与现网同策略,建议维护窗口内切换
## 3. 切换前确认
切换前必须满足:
1. `104` 当前主从正常:
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source: 0`
2. AWS 应用机心跳正常:
- `curl http://127.0.0.1:8080/v1/common/heartbeat`
3. AWS Redis 主从正常:
- AWS 主 `connected_slaves:1`
- `104``master_link_status:up`
4. 已确认当前应用真实配置文件:
- `/opt/ppanel/configs/ppanel.yaml`
5. 已确认当前应用重启方式:
- `cd /opt/ppanel && docker compose -f docker-compose.cloud.yml up -d ppanel-server`
## 4. 创建新 RDS
已在 AWS 控制台创建 `hifast-mysql-prod-v2`,未对原 `hifast-mysql-prod` 做高风险在线子网调整。
创建完成后先确认:
1. 新 endpoint 已分配
2. `Publicly accessible = Yes`
3. SG 为 `hifast-hk-rds-core-sg`
4. DB subnet group 为 `hifast-hk-rds-public-only-sgprep`
5.`104` 可以 TCP 连通 `3306`
连通性验证:
```bash
nc -zv <NEW_RDS_ENDPOINT> 3306
```
## 5. 导出旧主库
在一台可连旧 RDS 的机器执行:
```bash
mysqldump \
-h hifast-mysql-prod.cd6aey40m6ag.ap-east-1.rds.amazonaws.com \
-u admin \
-p \
--single-transaction \
--routines \
--triggers \
--events \
--set-gtid-purged=OFF \
hifast > hifast-full.sql
```
说明:
- 当前业务库体量约 `187 MB`
- 这条路线的成本低,且比现网主库在线改子网更稳
## 6. 初始化新 RDS
先连接新 RDS
```bash
mysql -h <NEW_RDS_ENDPOINT> -u admin -p
```
建议先执行:
```sql
CALL mysql.rds_set_configuration('binlog retention hours', 24);
CREATE USER IF NOT EXISTS 'repl'@'104.238.220.230' IDENTIFIED BY '<REPL_PASSWORD>';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'104.238.220.230';
FLUSH PRIVILEGES;
```
如果库是空的,再导入:
```bash
mysql -h <NEW_RDS_ENDPOINT> -u admin -p hifast < hifast-full.sql
```
导入完成后确认:
```bash
mysql -h <NEW_RDS_ENDPOINT> -u admin -p -e "USE hifast; SHOW TABLES;"
```
## 7. 切换 AWS 应用到新 RDS
### 7.1 备份当前配置
在 AWS app EC2
```bash
cp /opt/ppanel/configs/ppanel.yaml /opt/ppanel/configs/ppanel.yaml.bak.$(date +%Y%m%d%H%M%S)
```
### 7.2 修改数据库地址
编辑:
- `/opt/ppanel/configs/ppanel.yaml`
把:
```yaml
MySQL:
Addr: hifast-mysql-prod.cd6aey40m6ag.ap-east-1.rds.amazonaws.com:3306
```
改成:
```yaml
MySQL:
Addr: hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com:3306
```
### 7.3 重启业务容器
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml up -d ppanel-server
```
### 7.4 应用验收
```bash
curl -sf http://127.0.0.1:8080/v1/common/heartbeat
docker compose -f /opt/ppanel/docker-compose.cloud.yml logs --tail=100 ppanel-server
```
重点确认:
- 心跳返回 `200`
- 日志中无 MySQL 连接异常
## 8. 改挂 `104` 从库到新 RDS
先在新 RDS 获取位点:
```sql
SHOW MASTER STATUS;
```
然后在 `104` 执行:
```sql
STOP REPLICA;
RESET REPLICA ALL;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com',
SOURCE_PORT=3306,
SOURCE_USER='repl',
SOURCE_PASSWORD='<REPL_PASSWORD>',
SOURCE_LOG_FILE='<MASTER_LOG_FILE>',
SOURCE_LOG_POS=<MASTER_LOG_POS>,
SOURCE_SSL=1;
START REPLICA;
SHOW REPLICA STATUS\G
```
验收标准:
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source: 0`
## 9. 切换后验收
至少做下面这些检查:
1. AWS 应用心跳正常
2. 管理后台可登录
3. 新建一条测试数据后,主库可见
4. `104` 从库能同步到该测试数据
5. Navicat 可从白名单来源连接新 RDS
6. Redis 主从仍正常,不受本次 MySQL 切换影响
推荐额外核对:
```bash
docker compose -f /opt/ppanel/docker-compose.cloud.yml ps
docker exec hifast-redis redis-cli -a '<REDIS_PASSWORD>' INFO replication
```
## 10. 回滚方案
如果切换后 AWS 应用异常:
1. 立刻把 `/opt/ppanel/configs/ppanel.yaml``MySQL.Addr` 改回旧 endpoint
2. 重启 `ppanel-server`
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml up -d ppanel-server
```
3. 优先恢复主生产可用
4. `104` 是否回切旧 RDS 复制,视恢复窗口决定
如果只是 `104` 复制改挂失败,但 AWS 应用已正常使用新 RDS:
- 不必立刻回滚应用
- 先修好 `104 -> 新 RDS` 的白名单、位点、用户或网络
## 11. 切换完成后的收尾
全部验收通过后再做:
1. 已将新 endpoint 记录到正式运维文档
2. 仍需根据回收窗口安排旧 RDS 下线
3. 仍需按网络收敛计划处理 `private-1b` 路由语义
4. 已更新外部复制 runbook 中的主库 endpoint
## 12. 当前建议的执行顺序
本次切换当时按以下顺序执行:
1. 创建 `hifast-mysql-prod-v2`
2. 验证新 RDS 网络与参数
3. 导出旧库
4. 导入新库
5. 创建 / 确认 `repl` 用户
6. 切 AWS 应用到新 RDS
7. 验证应用
8. 改挂 `104` 到新 RDS
9. 验证从库
10. 收尾,并保留旧 RDS 待后续下线
+275
View File
@@ -0,0 +1,275 @@
# 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 删除
## 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 从库提升为主库