5.5 KiB
5.5 KiB
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 调整前执行:
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
另外备份:
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 只恢复到隔离临时库:
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 只启动隔离临时实例:
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. 发布顺序
- 记录当前 release、数据库迁移版本、Redis
cfg:active_version、A OpenSIPS 配置 SHA-256。 - 执行 S30 备份与恢复演练。
- 上传新 release 到
/opt/lisglosips/releases/<release-id>,校验package.json、pnpm-lock.yaml和构建产物。 - 执行向前兼容数据库迁移,禁止同窗口不可逆删列。
- 原子切换
/opt/lisglosips/current。 - 重启
lisglosips@api、lisglosips@cdr-worker、lisglosips@recording-worker。 nginx -t后 reload Nginx。- 执行
infra/server-b/s30/lisglosips-release-preflight.sh。 - 发布 Redis 配置快照并确认 A 使用新版本。
- T 发起测试呼叫,按 Call-ID 核对 SIP、CDR、计费、录音、HOMER。
- 开始灰度。
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 应用回滚
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 回滚
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:
- 确认 B
redis-serveractive,A 到 B Redis 端口可达。 - 重启 A
lisglosips-redis-auth-proxy。 - 若仍失败,维护窗口内重启 A
opensips。 - 记录 Call-ID、A 日志、Redis proxy 日志,作为后续根因修复输入。
8. 阿里云迁移前阻断项
- 正式 DNS/TLS 未完成;
- A/B 未位于同 VPC 低时延私网;
- B 未使用独立数据盘承载 MySQL、Redis、录音和监控;
- 安全组未限制 SSH 管理来源,或禁用了 SSH 密钥登录;
- 未完成新环境备份恢复演练;
- 未完成 T 或外部测试端到端呼叫;
- Redis 恢复后 OpenSIPS 自动恢复风险未纳入告警/Runbook。