Initial LisgloSIPS V2 implementation
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
# 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` active,A 到 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。
|
||||
Reference in New Issue
Block a user