Files
hi-server/ops/aws-rds-external-replica-runbook.md
T
shanshanzhong147 fd522b6c71
Build docker and publish / build (20.15.1) (push) Successful in 8m56s
path
2026-05-19 19:35:44 -07:00

653 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AWS RDS + EC2 Redis 到外部备用服务器 Runbook
目标:让 `104.238.220.230` 持续作为 AWS 主生产环境的异地备用节点,承接:
- MySQL 外部只读从库
- Redis 外部从库
- 故障时的快速提升与业务切换
本文档以 `2026-05-13` 的真实现网状态为准,覆盖:
- 当前已经落地的主从架构
- 日常验收命令
- 主从故障排查
- 全量重建从库
- “新建规范 RDS 再切换”的生产级收敛路线
- 故障切换与回滚
## 1. 当前已确认资源
### 1.1 AWS 主生产
- Region: `ap-east-1`
- AWS app EC2:
- Name: `hifast-hk-app-01`
- Public IP: `18.163.33.75`
- 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
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:18.163.33.75`
- `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
STOP REPLICA;
RESET REPLICA ALL;
```
### 7.3 重新导入业务库
`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;
```
然后在 `104` 执行:
```sql
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
```
### 7.5 验收
确认:
- `Replica_IO_Running: Yes`
- `Replica_SQL_Running: Yes`
- `Seconds_Behind_Source: 0`
- `read_only = ON`
- `super_read_only = ON`
## 8. 重新配置 Redis 从库
当前 `104` Redis 为原生安装,不使用 Docker。
### 8.1 临时切回从库
```bash
redis-cli CONFIG SET masterauth '0BVz9XOHf7KUfEuoFJRK-dURdKUGFiZ8QeaHpysHnKeKhLskZb55HPK121lFsKtr'
redis-cli REPLICAOF 18.163.33.75 6379
redis-cli CONFIG SET replica-read-only yes
redis-cli INFO replication
```
### 8.2 持久化配置
检查 `/etc/redis/redis.conf` 至少包含:
```conf
replicaof 18.163.33.75 6379
masterauth 0BVz9XOHf7KUfEuoFJRK-dURdKUGFiZ8QeaHpysHnKeKhLskZb55HPK121lFsKtr
replica-read-only yes
```
然后:
```bash
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 连接失败告警
- 定期灾备切换演练