Remove unused deployment and observability assets

This commit is contained in:
2026-06-02 21:01:55 -07:00
parent fc6f193479
commit 9ddd8257c5
41 changed files with 9 additions and 7247 deletions
-652
View File
@@ -1,652 +0,0 @@
# 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 连接失败告警
- 定期灾备切换演练
-33
View File
@@ -1,33 +0,0 @@
# Docker Image Version Pins
This file records the infrastructure image versions pinned in `docker-compose.cloud.yml`.
The versions below match the images observed on the test deployment on 2026-05-26.
| Service | Image | Running version source |
| --- | --- | --- |
| grafana | `grafana/grafana:13.0.1` | `grafana version 13.0.1` |
| prometheus | `prom/prometheus:v3.11.3` | `prometheus, version 3.11.3` |
| nginx-exporter | `nginx/nginx-prometheus-exporter:1.5.0` | image label `org.opencontainers.image.version=1.5.0` |
| node-exporter | `prom/node-exporter:v1.11.1` | `node_exporter, version 1.11.1` |
| cadvisor | `gcr.io/cadvisor/cadvisor:v0.55.1` | `cAdvisor version v0.55.1` |
The test deployment in `/root/bindbox/docker-compose.cloud.yml` also contains
live-only exporter services that are not present in this repository's
`docker-compose.cloud.yml`. They were pinned during staging validation:
| Test-only service | Image | Running version source |
| --- | --- | --- |
| mysql-exporter | `prom/mysqld-exporter:v0.19.0` | `mysqld_exporter, version 0.19.0` |
| redis-exporter | `oliver006/redis_exporter:v1.82.0` | image label `org.opencontainers.image.version=v1.82.0` |
`ppanel-server` intentionally remains variable and requires `PPANEL_SERVER_TAG`
from CI/CD so deployments use an immutable application image tag.
## Rollback
Restore the previous compose file from git and redeploy:
```sh
git checkout HEAD~1 -- docker-compose.cloud.yml .env.example ops/docker-image-version-pins.md
docker compose -f docker-compose.cloud.yml up -d
```
-26
View File
@@ -1,26 +0,0 @@
# GitHub Staging Deploy
This repository deploys the `internal` branch to the staging server `154.12.35.103` with GitHub Actions.
## Required GitHub secrets
- `STAGING_SSH_USER`: SSH user for `154.12.35.103`.
- `STAGING_SSH_KEY`: Private SSH key that can log in to the staging server.
- `STAGING_SSH_PORT`: SSH port. Use `22` if the server uses the default port.
- `GHCR_USERNAME`: Optional. Required only if the GHCR package is private and the server needs to log in before pulling.
- `GHCR_TOKEN`: Optional. A GitHub PAT with `read:packages` for private GHCR pulls.
## Server requirements
- Docker and either `docker compose` or `docker-compose` are installed.
- The deployment directory is `/opt/hifast-server`.
- Runtime files already exist beside `docker-compose.cloud.yml`, especially `configs/ppanel.yaml`, `logs/`, `cache/`, `loki/`, `grafana/`, `prometheus/`, and `tempo/`.
## What the workflow does
1. Builds the Docker image for `linux/amd64`.
2. Pushes `ghcr.io/tawcorp/hifast-server:<commit-sha>` and `ghcr.io/tawcorp/hifast-server:staging`.
3. Copies `docker-compose.cloud.yml` to the staging server.
4. Pulls the immutable commit image and restarts `ppanel-server`.
5. Checks `http://127.0.0.1:8080/v1/common/heartbeat`.
6. Attempts rollback to the previous container image if the health check fails.
-116
View File
@@ -1,116 +0,0 @@
# Hifast 东京切换执行清单
本文档用于正式执行香港 `ap-east-1` -> 东京 `ap-northeast-1` 迁移时,逐项勾选和留痕。
## 0. 当前已知东京状态
- 东京 VPC `ppanel-jp-prod` 已创建
- 东京 VPC ID`vpc-0846b23b4a7d64eac`
- 4 个东京子网曾在 AWS 控制台录入,但提交时登录态失效
- 所以当前要按“子网未确认成功”处理
- 后续所有东京资源创建前,先执行一次:
- `bash deploy/scripts/aws_jp_describe_state.sh /root/aws-jp-infra.env`
- 真实状态登记文件:
- `deploy/aws/ap-northeast-1/configs/resource-inventory.current.md`
## 1. 真实值清单
在开始创建东京正式资源前,必须补齐这些真实值:
- 正式 API 域名:
- 东京平行 API 域名:
- 东京平行日志域名:
- 运维固定公网 IP / CIDR
- 东京 EC2 SSH Key Pair 名称:
- 东京 RDS 管理员密码:`TkyRds20260521!N9mQ8sKe2vLp7Xa`
- 东京 RDS 凭证管理方式:`self-managed`
- 东京 RDS 当前密码是否可回看:`否,只能重置`
- 东京 Redis 密码:`hifast67yj`
- `JwtAuth.AccessSecret`
- `Administrator.Email``admin@ppanel.dev`
- `Administrator.Password``PpanelAdmin!20260521Temp`
- `AppSignature.AppSecrets.android-client``uB4G,XxL2{7b`
- `AppSignature.AppSecrets.ios-client``uB4G,XxL2{7b`
- `AppSignature.AppSecrets.web-client``uB4G,XxL2{7b`
- `device.security_secret``uB4G,XxL2{7b`
- 东京备份桶最终名称:
- `104.238.220.230` MySQL 复制密码:`XwWrQGVWtxmXJ3etHmkFvnRSD54MKYer`
- `104.238.220.230` Redis 主从认证密码:`hifast67yj`
## 2. 东京资源创建勾选
- 已切换 AWS 控制台到 `ap-northeast-1`
- 已确认东京区可用
- 已确认 EC2 配额满足 `t4g.large`
- 已确认 RDS 配额满足 `db.r7g.xlarge`
- 已确认 ALB / ACM / WAF / S3 可正常创建
- 已创建 VPC
- 已创建 2 个公有子网
- 已创建 2 个私有子网
- 已创建 IGW
- 已配置公私网路由表
- 已创建 `sg-alb`
- 已创建 `sg-ec2`
- 已创建 `sg-rds`
- 已创建东京 RDS
- 已创建东京 EC2
- 已在 EC2 启动 Docker / Nginx
- 已创建东京 ACM 证书
- 已创建 Target Group
- 已创建 ALB
- 已创建 WAF 并挂到 ALB
- 已创建东京 S3 备份桶并开启 versioning
## 3. 东京应用部署勾选
- 已上传 `docker-compose.cloud.yml`
- 已上传 `configs/ppanel.yaml`
- 已上传 `.env`
- 已上传 `grafana/`
- 已上传 `loki/`
- 已上传 `prometheus/`
- 已上传 `tempo/`
- 已安装东京 Nginx 配置
- 已启动 `ppanel-server`
- 已启动 `hifast-redis`
- 已启动 observability 容器
- `curl http://127.0.0.1:8080/v1/common/heartbeat` 正常
- `curl http://127.0.0.1/v1/common/heartbeat` 正常
- ALB 健康检查正常
## 4. 停机迁移勾选
- 已降低正式域名 TTL
- 已停止香港 `ppanel-server`
- 已确认香港不再有新写入
- 已导出香港 MySQL `hifast-full.sql.gz`
- 已导出香港 Redis `dump.rdb`
- 已导入东京 RDS
- 已导入东京 Redis
- 东京应用已改为连接东京 MySQL / Redis
- 平行域名验收通过
## 5. 104 灾备重挂勾选
- 东京 RDS 已设置 `binlog retention hours`
- 东京 RDS 已创建 `repl@104.238.220.230`
- 已用东京 dump 重建 `104``hifast`
- `104` MySQL 已成功挂东京主库
- `104` MySQL `Replica_IO_Running: Yes`
- `104` MySQL `Replica_SQL_Running: Yes`
- `104` MySQL `Seconds_Behind_Source: 0`
- `104` Redis 已成功挂东京主库
- 东京 Redis `connected_slaves:1`
- `104` Redis `role:slave`
- `104` Redis `master_link_status:up`
## 6. 正式切换与回滚勾选
- 已切正式域名到东京 ALB
- 外网请求正常
- 核心业务接口无 `5xx`
- 应用日志无 MySQL / Redis 连接错误
- WAF 无误伤
- 已验证 DNS 可回切
- 香港环境已保留为只读回滚基线
- 香港环境计划保留 `7` 天观察期
-286
View File
@@ -1,286 +0,0 @@
# Hifast AWS 香港到日本东京迁移 Runbook
本文档用于把当前香港区 `ap-east-1` 主生产,迁移到日本东京 `ap-northeast-1`
适用目标:
- 东京成为新主站
- 架构升级为 `ALB + WAF + EC2 + RDS`
- `104.238.220.230` 继续作为东京主站的 MySQL / Redis 外部灾备
## 0. 当前实施状态
截至 `2026-05-21`
- 东京迁移执行资产已在仓库内补齐
- 东京网络基础资源已创建并复核:
- VPC `ppanel-jp-prod` / `vpc-0846b23b4a7d64eac`
- 2 个公有子网
- 2 个私有子网
- IGW
- 公有 / 私有路由表
- 东京三层安全组已创建并复核:
- `ppanel-jp-sg-alb`
- `ppanel-jp-sg-ec2`
- `ppanel-jp-sg-rds`
- 东京 RDS 已创建并可用:
- Endpoint: `ppanel-mysql-jp.cpo0keikgh80.ap-northeast-1.rds.amazonaws.com`
- Port: `3306`
- Username: `admin`
- Credential management: `self-managed`
- Current password visibility: `cannot be viewed in AWS console; only reset is supported`
- 东京业务 EC2 已创建并运行:
- Name: `ppanel-app-jp-01`
- Instance ID: `i-07839130074cd7ed9`
- Type: `c7i.xlarge`
- Private IP: `10.20.1.168`
- Elastic IP: `3.114.29.208`
- 东京 S3 备份桶已创建
- 东京 ACM 证书已请求,仍等待 DNS 验证
- 当前尚未完成的核心资源:
- ALB
- WAF
- ACM DNS 验证
- 东京应用目录部署与数据导入
建议先执行:
```bash
cp deploy/aws/ap-northeast-1/configs/aws-jp-infra.env.example /root/aws-jp-infra.env
vim /root/aws-jp-infra.env
bash deploy/scripts/aws_jp_create_base_infra.sh /root/aws-jp-infra.env
bash deploy/scripts/aws_jp_describe_state.sh /root/aws-jp-infra.env
```
然后把结果回填到:
- `deploy/aws/ap-northeast-1/configs/resource-inventory.current.md`
- `ops/hifast-aws-jp-cutover-checklist-zh.md`
## 1. 当前基线
迁移前默认当前现网状态为:
- 香港应用 EC2`hifast-hk-app-01`
- 香港 RDS`hifast-mysql-prod-v2.cd6aey40m6ag.ap-east-1.rds.amazonaws.com`
- 香港 Redis 主库:`18.163.33.75:6379`
- 外部灾备:`104.238.220.230`
- 当前应用部署目录:`/opt/ppanel`
- 当前应用配置文件:`/opt/ppanel/configs/ppanel.yaml`
- 当前业务容器:`ppanel-server`
## 2. 迁移前准备
正式迁移前必须完成:
1. 东京基础设施已创建
2. 东京 EC2 已部署应用目录,但暂未导入正式数据
3. 东京 RDS 可连通
- 已验证从东京 EC2 到 `ppanel-mysql-jp.cpo0keikgh80.ap-northeast-1.rds.amazonaws.com:3306` 网络畅通
- 当前若无密码只能得到 `ERROR 1045 ... using password: NO`,这表示链路正常,不表示实例异常
4. 东京 Redis 已启动并可认证
5. 平行域名已准备:
- `api-jp.hifast.biz`
- `logs-jp.hifast.biz`
6. 东京 ALB 健康检查已通过
7. 东京 ACM 证书已签发
8. 东京 WAF 已挂到 ALB
9. 已准备正式回滚入口
10. 已把正式域名 TTL 降低
## 3. 香港停机冻结
在香港主环境执行:
1. 停止业务写入
2.`ppanel-server`
3. 保留 Nginx 维护页或直接下线入口
建议命令:
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml stop ppanel-server
```
冻结后确认:
- `/v1/common/heartbeat` 不再提供正式流量
- 不再有新写入进入香港 MySQL / Redis
## 4. 导出香港数据
### 4.1 MySQL
从香港主库导出:
```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 | gzip > hifast-full.sql.gz
```
### 4.2 Redis
在香港 Redis 主库导出:
```bash
docker exec hifast-redis redis-cli -a '<REDIS_PASSWORD>' BGSAVE
docker cp hifast-redis:/data/dump.rdb ./dump.rdb
```
## 5. 导入东京
### 5.1 MySQL 导入东京 RDS
```bash
gunzip -c hifast-full.sql.gz | mysql -h <TOKYO_RDS_ENDPOINT> -u admin -p hifast
```
导入后确认:
```bash
mysql -h <TOKYO_RDS_ENDPOINT> -u admin -p -e "USE hifast; SHOW TABLES;"
```
### 5.2 Redis 导入东京
1. 停止东京 Redis 容器
2. 替换 `/data/dump.rdb`
3. 启动东京 Redis 容器
导入后确认:
```bash
docker exec hifast-redis redis-cli -a '<TOKYO_REDIS_PASSWORD>' PING
```
## 6. 启动东京应用
更新东京:
- `/opt/ppanel/configs/ppanel.yaml`
- `/opt/ppanel/.env`
关键值:
- `MySQL.Addr=<TOKYO_RDS_ENDPOINT>:3306`
- `MySQL.Username=admin`
- `MySQL.Password=<TOKYO_RDS_PASSWORD>`
- `Redis.Host=127.0.0.1:6379`
- `Redis.Pass=<TOKYO_REDIS_PASSWORD>`
- `Site.Host=api-jp.hifast.biz`
- `.env``AWS_REGION=ap-northeast-1`
注意:
- 东京这台 RDS 当前不是 Secrets Manager 托管密码
- AWS 控制台不能回看旧密码明文
- 如果现有密码遗失,只能在 RDS 修改页重置新密码,再同步写入东京 `ppanel.yaml`
当前东京已实际生效:
- `MySQL.Addr=ppanel-mysql-jp.cpo0keikgh80.ap-northeast-1.rds.amazonaws.com:3306`
- `MySQL.Username=admin`
- `MySQL.Password=TkyRds20260521!N9mQ8sKe2vLp7Xa`
- `Redis.Host=127.0.0.1:6379`
- `Redis.Pass=hifast67yj`
启动:
```bash
cd /opt/ppanel
docker compose -f docker-compose.cloud.yml up -d
```
## 7. 东京平行环境验收
至少执行:
```bash
curl -sf http://127.0.0.1:8080/v1/common/heartbeat
curl -sf http://127.0.0.1/v1/common/heartbeat
docker compose -f /opt/ppanel/docker-compose.cloud.yml ps
docker compose -f /opt/ppanel/docker-compose.cloud.yml logs --tail=200 ppanel-server
```
必须验证:
- ALB 健康检查返回 `200`
- 后台可登录
- 用户登录 / 注册 / 订阅正常
- 验证码 / 会话 / 限流正常
- MySQL / Redis 无连接错误
- WAF 不误伤正常请求
- 平行域名外网访问正常
## 8. 正式域名切换
仅在东京平行环境验收全部通过后执行:
1. 将正式域名切到东京 `ALB`
2. 观察 5xx、延迟、容器日志、RDS、Redis
3. 保持香港不删,只做回滚保留
## 9. 104 灾备重挂
### 9.1 MySQL
在东京 RDS 上:
```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;
SHOW BINARY LOG STATUS;
```
当前东京已准备完成:
- `repl@104.238.220.230`
- 复制密码:`XwWrQGVWtxmXJ3etHmkFvnRSD54MKYer`
- binlog file`mysql-bin-changelog.000189`
- binlog pos`185053`
然后在 `104` 重建并挂从。
### 9.2 Redis
`104` Redis 指向东京 EC2 Redis 主库,确认:
- 东京 `role:master`
- 东京 `connected_slaves:1`
- `104` `role:slave`
- `104` `master_link_status:up`
## 10. 回滚
如果东京验收失败:
- 不切正式域名
- 继续保留香港主环境
如果正式切换后发现严重问题:
1. 立刻把 DNS 切回香港
2. 恢复香港 `ppanel-server`
3. 放弃本次东京接管
## 11. 切换后观察期
切换后至少保留香港环境 `7` 天:
- 香港 RDS 快照
- 香港 Redis RDB
- 香港 EC2 配置
- 香港 `ppanel.yaml` 备份
观察期内不删除香港资源。
-696
View File
@@ -1,696 +0,0 @@
# Hifast AWS 主生产 + 外部备用 完整部署方案与访问架构
本文档整理当前已经实际落地的生产架构、访问链路、数据库与缓存主从关系、网络边界、故障切换方案,以及后续扩展建议。
目标是让团队在一个文档里就能看清:
- 现在生产到底部署成了什么样
- 请求是怎么进来的,数据是怎么流转的
- AWS 与外部备用服务器分别承担什么角色
- 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 区域
- Region: `ap-east-1`
- 说明:香港区
### 1.2 已确认资源
#### 应用服务器
- 名称:`hifast-hk-app-01`
- Instance ID: `i-079cd9d3ef3748714`
- 角色:当前实际生产入口 / Nginx / 业务服务 / AWS 侧 Redis 主库宿主机
- 私网 IP: `10.0.1.201`
- 公网 IP: `18.163.33.75`
- 业务服务运行方式:`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-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 主库
- 部署位置:`AWS EC2 hifast-hk-app-01`
- 部署方式:`Docker`
- 容器名:`hifast-redis`
- 版本:`redis:8.2.1`
- 访问端口:`6379`
- 主库出口地址:`18.163.33.75:6379`
- 应用当前实际连接:`127.0.0.1:6379`
- 认证方式:已启用密码认证
#### 外部备用服务器
- IP: `104.238.220.230`
- 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
flowchart TB
USER["用户 / 客户端"] --> DNS["域名 / DNS / 入口层"]
DNS --> APP["AWS EC2\nhifast-hk-app-01\n18.163.33.75\n10.0.1.201"]
APP --> RDS["AWS RDS MySQL\nhifast-mysql-prod-v2\n主库"]
APP --> REDISM["AWS Redis 主库\nDocker redis:8.2.1\n18.163.33.75:6379"]
RDS -. MySQL 备用 / 同步 .-> MYSQLS["104.238.220.230\nMySQL 备用库"]
REDISM -. Redis 主从复制 .-> REDISS["104.238.220.230\n原生 Redis 8.6.3\n从库"]
subgraph AWS["AWS ap-east-1"]
APP
RDS
REDISM
end
subgraph BACKUP["异地备用节点"]
MYSQLS
REDISS
end
```
## 3. 访问链路
### 3.1 用户访问链路
当前生产访问链路可以概括为:
`用户 -> 域名 / DNS -> AWS EC2 应用机 -> MySQL / Redis`
说明:
- 当前主应用入口实际在 `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 提供。
### 3.2 应用访问数据链路
应用侧内部依赖关系如下:
```text
App / Nginx
-> RDS MySQL 主库
-> AWS EC2 Redis 主库
```
### 3.3 备用链路
备用服务器 `104.238.220.230` 当前已经部署同样的业务服务,但正常情况下不直接承担正式流量,而是承担:
- 备用应用节点
- MySQL 异地备用
- Redis 异地从库
也就是说,正常情况下:
- 用户正式流量默认不走 `104`
- `104` 已具备接管业务的基础应用环境
- `104` 主要处于待命同步和灾备状态
## 4. 网络与安全边界
### 4.1 当前安全组
截至 `2026-05-13`VPC `vpc-09fc384522517debc` 内仅保留 4 个安全组:
- `default`
- `hifast-hk-app-core-sg`
- `hifast-hk-rds-core-sg`
- `hifast-hk-web-sg`
其中绑定关系已经收敛为:
- `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`
旧组:
- `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["hifast-hk-app-core-sg"] --> REDIS["AWS Redis 主库\n18.163.33.75:6379"]
STANDBY["104.238.220.230/32"] --> SG
```
### 4.4 RDS 访问原则
RDS 当前状态已经比之前干净很多:
- 当前只对白名单和应用安全组开放 `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 主库:
- 目标地址:`18.163.33.75:6379`
- 连接方式:`TCP`
- 认证方式:`Redis 密码`
- 网络前提:AWS EC2 安全组已放行 `104.238.220.230/32 -> 6379`
也就是说:
```text
104 Redis 从库 -> 直连 AWS Redis 主库公网地址 -> 密码认证 -> 建立复制
```
示意命令:
```bash
redis-cli -h 18.163.33.75 -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 主库
- 部署方式:Docker
- 版本:`8.2.1`
- 主库地址:`18.163.33.75:6379`
- 运行容器:`hifast-redis`
### 5.2 104 Redis 从库
- 部署方式:宿主机原生安装
- 版本:`8.6.3`
- 角色:`replica / slave`
### 5.3 Redis 主从状态
最终已验证结果:
- `104` 上 Redis`role:slave`
- `104` 上 Redis`master_link_status:up`
- AWS Redis 主库:`connected_slaves:1`
- AWS Redis 主库识别到从库:`104.238.220.230:6379`
### 5.4 Redis 验证结果
已做过的验证:
-`104` 连接 AWS Redis 主库,认证成功
- AWS 主库写入测试键
- `104` 从库成功读取测试键
- `2026-05-13` 已确认应用机本地 `ppanel-server -> 127.0.0.1:6379` 建立稳定连接
- `2026-05-13` 已确认旧 `stunnel4 -> ElastiCache` 链路下线后,应用日志不再出现 Redis `i/o timeout`
测试键:
- key: `hifast_replication_test`
- value: `ok_20260510`
### 5.5 Redis 主从拓扑
```mermaid
flowchart LR
REDISMASTER["AWS Redis 主库\n18.163.33.75:6379\nDocker redis:8.2.1"]
REDISSLAVE["104.238.220.230\n原生 Redis 8.6.3\nrole: slave"]
REDISMASTER --> REDISSLAVE
```
## 6. MySQL 部署与备用关系
### 6.1 主库角色
- 主库在 `AWS RDS MySQL`
- 实例:`hifast-mysql-prod-v2`
### 6.2 外部备用角色
- `104.238.220.230` 上存在 MySQL 备用用途
- 目标是让 `104` 尽量实时同步 AWS 数据
### 6.3 当前文档说明
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)
## 7. 当前生产方案的真实特点
这套已经落地的架构,不是传统的全 AWS 托管标准形态,而是偏实用的混合方案:
- 应用和当前实际公网入口在 AWS 同一台 EC2
- MySQL 在 AWS RDS
- Redis 在 AWS EC2 本机
- MySQL / Redis 均向外部服务器 `104` 做灾备
- 旧 ElastiCache / stunnel 链路已经退出当前生产路径
它的优点:
- 成本相对可控
- Redis 可完全自主控制
- 外部备用机可以独立接管
它的代价:
- Redis 高可用需要人工切换
- 外部灾备不是全自动故障转移
- 应用切换需要明确操作步骤
## 8. 故障切换方案
### 8.1 正常状态
```mermaid
flowchart TD
A["用户访问"] --> B["AWS EC2 应用机"]
B --> C["AWS RDS MySQL 主库"]
B --> D["AWS Redis 主库"]
C -. 同步 .-> E["104 MySQL 备用"]
D -. 复制 .-> F["104 Redis 从库"]
```
### 8.2 AWS 故障后的目标切换状态
```mermaid
flowchart TD
A["AWS 故障"] --> B["应用入口切到 104"]
B --> C["104 MySQL 提供主服务"]
B --> D["104 Redis 提升为主库"]
D --> E["应用连接 104 Redis"]
C --> F["应用连接 104 MySQL"]
```
### 8.2.1 Nginx 是否可以直接切到 104
可以,但前提不是“只切 Nginx 就完成故障切换”。
因为 `104` 虽然已经部署了同样的业务服务,但如果故障发生时:
- Redis 还保持从库只读状态
- MySQL 还没有切成可写主角色
- 应用配置还没有确认指向 `104` 本机数据层
那么即使 Nginx 已经把流量转到 `104`,业务也可能仍然无法正常写入。
所以更准确的原则是:
`104` 已具备应用接管能力,Nginx 切换可以作为最后一步对外放流量动作,但不能作为唯一动作。
### 8.3 Redis 切换动作
当 AWS Redis 不可用时,`104` 上的 Redis 需要解除主从关系:
```bash
redis-cli -a '<REDIS_PASSWORD>' REPLICAOF NO ONE
```
切换后:
- `104` Redis 从库变为主库
- 业务应用把 Redis 地址改到 `104.238.220.230:6379`
### 8.4 MySQL 切换动作
当 AWS RDS 不可用时,需要让 `104` MySQL 接管写流量。
这部分是否能立即切,需要依赖:
- 当前 `104` MySQL 是否是健康从库
- 是否已经取消只读
- 应用数据库配置是否能快速切换到 `104`
### 8.5 应用切换动作
应用层需要准备至少这 2 个切换点:
- MySQL 连接地址切换到 `104`
- Redis 连接地址切换到 `104`
如果应用入口也要迁移到 `104`,还需要:
- 域名解析切换
- 或者网关 / 入口切换
### 8.6 推荐的实际切换顺序
因为 `104` 已经部署同样的应用服务,所以 AWS 故障时推荐按下面顺序操作:
1. 确认 `104` 上业务服务和 Nginx 进程正常。
2.`104` 上 Redis 从库提升为主库。
3.`104` 上 MySQL 从库切换为可写主库。
4. 确认 `104` 上应用配置已指向本机 MySQL / Redis。
5. 最后再把 Nginx 上游或域名流量切到 `104`
可以把它理解成:
`先数据接管 -> 再应用确认 -> 最后入口切流量`
## 9. 建议的运维操作顺序
### 9.1 平时
平时重点看:
- AWS EC2 是否在线
- RDS 是否在线
- AWS Redis 主库是否在线
- `104` Redis 从库是否 `master_link_status:up`
- `104` MySQL 复制是否正常
- `ppanel-server` 容器是否 `Up`
- `ppanel-server` 日志中是否再次出现 Redis `i/o timeout`
- `stunnel4` 是否保持 `inactive`
### 9.2 Redis 故障时
1. 确认 AWS Redis 主库不可恢复。
2.`104` 执行 `REPLICAOF NO ONE`
3. 修改应用 Redis 地址到 `104.238.220.230:6379`
4. 验证应用读写 Redis 正常。
### 9.3 MySQL 故障时
1. 确认 RDS 故障。
2. 确认 `104` MySQL 数据已同步到最新可用点。
3. 去掉 `104` MySQL 只读限制。
4. 修改应用 MySQL 地址到 `104`
5. 验证应用读写数据库正常。
### 9.4 整体 AWS 故障时
1. 把 Redis 主角色切到 `104`
2. 把 MySQL 主角色切到 `104`
3. 确认 `104` 上同版本应用服务正常。
4. 把应用入口切到备用应用节点。
5. 更新 DNS 或 Nginx 上游流量入口。
6. 验证用户访问链路。
## 10. 当前方案与理想方案的差异
### 10.1 当前实际方案
`DNS -> hifast-hk-app-01(Nginx + App + Redis) -> RDS MySQL -> 104 灾备`
### 10.2 理想生产方案
从长期稳定性看,更推荐未来演进为:
`DNS / CDN -> ALB -> 多台 EC2 App -> RDS MySQL -> 托管 Redis / 或高可用 Redis`
异地灾备继续保留:
- AWS 生产
- 104 异地接管
### 10.3 当前最值得继续补的项
建议按优先级补齐:
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. 建议的下一版目标拓扑
```mermaid
flowchart TB
USER["用户 / 客户端"] --> DNS["DNS / CDN / 入口层"]
DNS --> APPAWS["AWS 应用集群"]
DNS -. 故障时切换 .-> APPBK["104 备用应用节点"]
APPAWS --> RDSAWS["AWS RDS MySQL 主库"]
APPAWS --> REDISAWS["AWS Redis 主库"]
RDSAWS -. 同步 .-> MYSQLBK["104 MySQL 备用"]
REDISAWS -. 复制 .-> REDISBK["104 Redis 备用"]
APPBK --> MYSQLBK
APPBK --> REDISBK
```
## 12. 本文档结论
截至当前,已经可以确认的生产与灾备状态是:
- AWS 是主生产环境
- 应用当前跑在 `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` 链路已经退出生产路径
如果后续要继续完善这份方案,优先补充:
- RDS 子网与公网访问模型收敛
- 入口域名 / DNS 切换细则
- 应用层在 `104` 的接管与回切执行清单
- 待资源到位后的独立 `nginx` 迁移清单
-246
View File
@@ -1,246 +0,0 @@
# Hifast 当前架构文档(东京主站版)
最后更新:`2026-05-21`
这份文档只描述**当前真实生效**的架构,不描述理想目标,不混入已经下线或待迁移的香港旧链路。
如果后续东京 `ALB / WAF / 正式域名` 上线,应继续更新这份文档,而不是回头参考旧香港架构文档。
## 1. 当前结论
当前已经实际跑起来的是:
`用户 / 运维 -> 东京 EC2 -> ppanel-server + Redis + observability -> 东京 RDS MySQL`
当前还**没有**实际生效的组件:
- `ALB`
- `WAF`
- 正式域名切流
- `104.238.220.230` 重挂东京 MySQL / Redis 从库
也就是说,东京环境目前是:
- 一台业务 EC2 已可用
- 一台东京 RDS 已可用
- 本机 Redis 已可用
- `ppanel-server` 已成功启动并连通 MySQL / Redis
- 灾备链路参数已准备好,但 `104` 还没最终挂上去
## 2. 当前真实拓扑
```mermaid
flowchart TB
USER["用户 / 运维"] --> EIP["东京 EC2 公网入口\n3.114.29.208"]
EIP --> NGINX["Nginx\nEC2 本机"]
NGINX --> APP["ppanel-server\nhost network\n127.0.0.1:8080"]
APP --> REDIS["Redis Docker\n127.0.0.1:6379"]
APP --> RDS["Tokyo RDS MySQL\nppanel-mysql-jp"]
APP --> OBS["Grafana / Loki / Tempo / Prometheus"]
RDS -. 预留复制 .-> DRMYSQL["104.238.220.230\nMySQL DR\n未最终接入"]
REDIS -. 预留复制 .-> DRREDIS["104.238.220.230\nRedis DR\n未最终接入"]
```
## 3. 云资源清单
### 3.1 Region
- AWS account: `hifastvpn (200810848252)`
- Region: `ap-northeast-1`
### 3.2 网络
- VPC: `ppanel-jp-prod`
- VPC ID: `vpc-0846b23b4a7d64eac`
- CIDR: `10.20.0.0/16`
公有子网:
- `ppanel-jp-public-a` / `subnet-091232bdb53e71490` / `10.20.0.0/24`
- `ppanel-jp-public-c` / `subnet-01ba0975c525ce8cf` / `10.20.1.0/24`
私有子网:
- `ppanel-jp-private-a` / `subnet-0bd13111c02f0edbe` / `10.20.10.0/24`
- `ppanel-jp-private-c` / `subnet-0d86c5c756dbc84b2` / `10.20.11.0/24`
### 3.3 安全组
- `ppanel-jp-sg-alb`
- `80/tcp <- 0.0.0.0/0`
- `443/tcp <- 0.0.0.0/0`
- `ppanel-jp-sg-ec2`
- `80/tcp <- sg-0b3a23c31041a5a5a`
- `22/tcp <- 64.118.144.142/32`
- `6379/tcp <- 104.238.220.230/32`
- `ppanel-jp-sg-rds`
- `3306/tcp <- sg-01f2a5a81e7505c91`
- `3306/tcp <- 104.238.220.230/32`
## 4. 计算与数据库
### 4.1 业务 EC2
- Name: `ppanel-app-jp-01`
- Instance ID: `i-07839130074cd7ed9`
- Type: `c7i.xlarge`
- AZ: `ap-northeast-1c`
- Private IP: `10.20.1.168`
- Public IP / Elastic IP: `3.114.29.208`
- Public DNS: `ec2-3-114-29-208.ap-northeast-1.compute.amazonaws.com`
- Root volume: `gp3 100GiB`
- Status: `running`
说明:
- 当前公网入口是这台 EC2 自己
- 这里绑定的是 `EIP`,不是依赖实例自动分配的临时公网 IP
- 绑定 EIP 的目的,是保证以后 Redis 主从、白名单、DNS、文档里的公网地址不因为实例变更而漂移
### 4.2 Tokyo RDS
- Identifier: `ppanel-mysql-jp`
- Engine: `MySQL Community 8.4.8`
- Class: `db.r7g.xlarge`
- Storage: `gp3 100GiB`
- Master user: `admin`
- Endpoint: `ppanel-mysql-jp.cpo0keikgh80.ap-northeast-1.rds.amazonaws.com`
- Public access: `enabled`
- Credential management: `self-managed`
- Current status: `available`
当前实际连接值:
- Host: `ppanel-mysql-jp.cpo0keikgh80.ap-northeast-1.rds.amazonaws.com`
- Port: `3306`
- User: `admin`
### 4.3 Redis
- 部署位置:东京 EC2 本机
- 部署方式:Docker
- 容器名:`ppanel-redis`
- 当前角色:`master`
- 当前监听:`127.0.0.1:6379`(应用本机访问)
- 当前对灾备开放:`3.114.29.208:6379`
### 4.4 应用与可观测
业务容器:
- `ppanel-server`
可观测容器:
- `ppanel-grafana`
- `ppanel-loki`
- `ppanel-promtail`
- `ppanel-prometheus`
- `ppanel-tempo`
- `ppanel-cadvisor`
- `ppanel-node-exporter`
- `ppanel-nginx-exporter`
## 5. 当前部署方式
部署目录:
- `/opt/ppanel`
关键文件:
- `/opt/ppanel/docker-compose.cloud.yml`
- `/opt/ppanel/configs/ppanel.yaml`
- `/opt/ppanel/.env`
业务启动方式:
- `ppanel-server` 使用 `docker compose`
- `network_mode: host`
当前配置指向:
- MySQL -> 东京 RDS
- Redis -> 本机 Docker Redis
- Trace -> `127.0.0.1:4317`
## 6. 当前已验证状态
截至 `2026-05-21` 已确认:
- `docker exec ppanel-redis redis-cli -a 'hifast67yj' PING` 返回 `PONG`
- `MYSQL_PWD=... mysql -h ppanel-mysql-jp.cpo0keikgh80.ap-northeast-1.rds.amazonaws.com -u admin -e "select 1"` 返回正常
- `docker compose -f /opt/ppanel/docker-compose.cloud.yml up -d ppanel-server` 已成功
- `docker logs ppanel-server` 无 MySQL / Redis 连接报错
- `curl http://127.0.0.1:8080/v1/common/heartbeat` 返回成功
可以认为当前东京单站已经具备:
- 服务启动能力
- 数据库连接能力
- Redis 连接能力
- 基础可观测能力
## 7. 当前未落地项
下面这些还属于“目标方案”,不是“当前实际架构”:
- `ALB`
- `WAF`
- ACM 证书完成 DNS 验证
- 正式域名切换到东京
- `104.238.220.230` 完整接成东京 DR
所以现在请不要把当前架构理解成:
`DNS -> ALB -> WAF -> EC2 -> RDS`
当前真实架构更准确地说是:
`EIP -> EC2(Nginx + ppanel-server + Redis + observability) -> RDS`
## 8. 灾备准备状态
### 8.1 MySQL DR
已准备好:
- DR host: `104.238.220.230`
- 复制账号:`repl@104.238.220.230`
- binlog retention hours: `24`
- current binlog file: `mysql-bin-changelog.000189`
- current binlog position: `185053`
当前状态:
- 东京侧已准备完成
-`104` 侧还没有最终执行挂从
### 8.2 Redis DR
已准备好:
- 东京 Redis 主地址:`3.114.29.208:6379`
- 东京 Redis 当前角色:`role:master`
- 东京 Redis 当前状态:`connected_slaves:0`
当前状态:
- 东京侧已可作为主库提供同步
-`104` 侧还没有最终执行 `REPLICAOF`
## 9. 权威文档入口
与当前东京架构直接相关的文档,以这些为准:
- [当前架构文档](./hifast-current-architecture-zh.md)
- [东京资源清单](../deploy/aws/ap-northeast-1/configs/resource-inventory.current.md)
- [东京迁移 Runbook](./hifast-aws-jp-migration-runbook-zh.md)
- [东京切换清单](./hifast-aws-jp-cutover-checklist-zh.md)
下面这些旧文档可以继续保留,但不要作为“当前实际架构”依据:
- 香港旧主站相关文档
- 仍以 `ap-east-1` 为主语的历史架构说明
-286
View File
@@ -1,286 +0,0 @@
# 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 待后续下线
-311
View File
@@ -1,311 +0,0 @@
# 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 从库提升为主库