653 lines
13 KiB
Markdown
653 lines
13 KiB
Markdown
# 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
|
||
|
||
处理:
|
||
|
||
- 不要硬跳过
|
||
- 直接执行全量重建从库
|
||
|
||
#### 场景 C:SQL 执行报错
|
||
|
||
表现:
|
||
|
||
- `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 连接失败告警
|
||
- 定期灾备切换演练
|