Files
lisglosips/docs/S30_RELEASE_BACKUP_RUNBOOK.md
T

143 lines
5.5 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.
# S30 备份、Runbook、灰度与上线
## 1. 范围
当前 S30 面向本地 KVM 开发环境的 V2 闭环冻结与上线演练,不执行真实阿里云切流。阿里云迁移必须在新 VPC、正式 DNS/TLS、独立数据盘和安全组完成后,按本文重新演练。
## 2. 冻结清单
| 项 | 当前值 |
| --- | --- |
| B release | `/opt/lisglosips/releases/s28-v2-20260621220924` |
| B current | `/opt/lisglosips/current` 指向当前 release |
| A OpenSIPS | `/etc/opensips/opensips.cfg` |
| T 测试脚本 | `/opt/lisglosips-s28/lisglosips-s28-sip.py` |
| 数据库迁移 | 以 `prisma/migrations/` 和 B 当前库为准 |
| Redis 配置版本 | 以 `cfg:active_version` 为准 |
冻结后只允许以下变更进入上线窗口:
- 修复已确认阻塞缺陷;
- 更新正式域名/TLS/安全组等环境参数;
- 文档化灰度和回滚记录。
## 3. 上线前备份
在任何 release 切换、数据库迁移、OpenSIPS 配置替换、Nginx/TLS 调整前执行:
```bash
sudo systemctl start lisglosips-backup.service
sudo find /data/backups/mysql -mindepth 1 -maxdepth 1 -type d | sort | tail -1
sudo find /data/backups/redis -mindepth 1 -maxdepth 1 -type d | sort | tail -1
sudo sha256sum -c /data/backups/mysql/<stamp>/SHA256SUMS
sudo sha256sum -c /data/backups/redis/<stamp>/SHA256SUMS
```
另外备份:
```bash
sudo install -d -m 0700 /var/backups/lisglosips-s30/<stamp>
sudo cp -a /etc/lisglosips /etc/nginx /etc/systemd/system/lisglosips@.service /var/backups/lisglosips-s30/<stamp>/
sudo cp -a /etc/opensips/opensips.cfg /var/backups/lisglosips-s30/<stamp>/opensips.cfg
```
备份目录只允许 root 读取,不复制明文 secret 到仓库或聊天记录。
## 4. 恢复演练
MySQL 只恢复到隔离临时库:
```bash
sudo mysql -e 'DROP DATABASE IF EXISTS lisglosips_s30_restore; CREATE DATABASE lisglosips_s30_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;'
gzip -dc /data/backups/mysql/<stamp>/lisglosips.sql.gz | sudo mysql lisglosips_s30_restore
sudo mysql -e 'SELECT COUNT(*) FROM lisglosips_s30_restore.raw_cdrs;'
sudo mysql -e 'DROP DATABASE lisglosips_s30_restore;'
```
Redis 只启动隔离临时实例:
```bash
sudo install -d -m 0700 /tmp/lisglosips-s30-redis-restore
sudo cp /data/backups/redis/<stamp>/dump.rdb /tmp/lisglosips-s30-redis-restore/dump.rdb
sudo redis-server --dir /tmp/lisglosips-s30-redis-restore --dbfilename dump.rdb --port 0 --unixsocket /tmp/lisglosips-s30-redis.sock --daemonize yes
sudo redis-cli -s /tmp/lisglosips-s30-redis.sock DBSIZE
sudo redis-cli -s /tmp/lisglosips-s30-redis.sock SHUTDOWN NOSAVE
```
禁止把备份直接覆盖运行中 `/var/lib/mysql``/var/lib/redis`
## 5. 发布顺序
1. 记录当前 release、数据库迁移版本、Redis `cfg:active_version`、A OpenSIPS 配置 SHA-256。
2. 执行 S30 备份与恢复演练。
3. 上传新 release 到 `/opt/lisglosips/releases/<release-id>`,校验 `package.json``pnpm-lock.yaml` 和构建产物。
4. 执行向前兼容数据库迁移,禁止同窗口不可逆删列。
5. 原子切换 `/opt/lisglosips/current`
6. 重启 `lisglosips@api``lisglosips@cdr-worker``lisglosips@recording-worker`
7. `nginx -t` 后 reload Nginx。
8. 执行 `infra/server-b/s30/lisglosips-release-preflight.sh`
9. 发布 Redis 配置快照并确认 A 使用新版本。
10. T 发起测试呼叫,按 Call-ID 核对 SIP、CDR、计费、录音、HOMER。
11. 开始灰度。
## 6. 灰度策略
本地环境使用 `cus_s28_t` 和 T 专用 UAS 作为灰度对象;生产环境选择一个低风险客户或一条低风险线路。
灰度观察项:
- SIP 2xx/4xx/5xx 分布;
- Redis Stream lag 和 pending
- CDR 入库与重复扣费;
- 余额变化和充值幂等;
- 录音 READY 比例、A tmpfs 使用率;
- API 5xx、P95/P99
- HOMER 是否可按 Call-ID 查询。
扩大条件:连续观察 24-72 小时无 P1/P2 缺陷、无 CDR/余额异常、录音搬运无持续积压。
## 7. 回滚
### B 应用回滚
```bash
sudo infra/server-b/s30/lisglosips-release-rollback.sh /opt/lisglosips/releases/<previous-release>
```
脚本会切换 `current`、重启 API/CDR/Recording Worker、校验 Nginx 并检查 API ready。
### Redis 配置回滚
切回上一个 `cfg:active_version`,不删除 Stream 或 deadletter。回滚后用 T 呼叫验证 A 已读取旧版本。
### OpenSIPS 回滚
```bash
sudo infra/server-a/s30/lisglosips-opensips-config-restore.sh /var/backups/<path>/opensips.cfg
```
脚本会先备份当前配置、执行 `opensips -C`,通过后替换并重启 OpenSIPS。重启会影响现有通话,生产必须放在维护窗口或确认可接受。
### 数据库回滚
优先发布向前修复迁移;只有在确认不可用且有完整备份时,才进入维护窗口做数据恢复。充值、CDR、审计、录音记录不直接物理删除。
### S29 Redis 恢复遗留风险
若 B Redis 故障恢复后 A 继续返回 `503 Redis Unavailable`
1. 确认 B `redis-server` activeA 到 B Redis 端口可达。
2. 重启 A `lisglosips-redis-auth-proxy`
3. 若仍失败,维护窗口内重启 A `opensips`
4. 记录 Call-ID、A 日志、Redis proxy 日志,作为后续根因修复输入。
## 8. 阿里云迁移前阻断项
- 正式 DNS/TLS 未完成;
- A/B 未位于同 VPC 低时延私网;
- B 未使用独立数据盘承载 MySQL、Redis、录音和监控;
- 安全组未限制 SSH 管理来源,或禁用了 SSH 密钥登录;
- 未完成新环境备份恢复演练;
- 未完成 T 或外部测试端到端呼叫;
- Redis 恢复后 OpenSIPS 自动恢复风险未纳入告警/Runbook。