Files
lisglosips/docs/SERVER_B_DATA_SERVICES_RUNBOOK.md
T

235 lines
6.7 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.
# Server B MySQL 与 Redis Runbook
> 对应任务:S04
> 完成日期:2026-06-20
> 环境:本地开发 Server B
## 1. 版本与状态
| 服务 | 固定版本 | 监听 |
| --- | --- | --- |
| MySQL | 8.0.46-0ubuntu0.24.04.2 | 127.0.0.1:3306、127.0.0.1:33060 |
| Redis | 7.0.15-1ubuntu0.24.04.4 | 127.0.0.1:6379、100.90.90.91:6379 |
固定包:
```bash
apt-mark showhold | grep -E 'mysql|redis'
```
更新前必须先阅读安全公告、备份并执行恢复演练,然后显式 `apt-mark unhold`。不要长期忽略安全更新。
版本清单位于:
- B`/etc/lisglosips/versions.env`
- 仓库:`infra/server-b/s04/versions.env`
## 2. 数据目录
开发服务器没有独立数据盘。实际数据写入:
- `/data/mysql`
- `/data/redis`
为兼容 Ubuntu 包、AppArmor 和 systemd,使用 bind mount 保留标准服务路径:
```fstab
/data/mysql /var/lib/mysql none bind 0 0
/data/redis /var/lib/redis none bind 0 0
```
服务分别依赖 `var-lib-mysql.mount``var-lib-redis.mount`。迁移阿里云时必须改用独立数据盘,不能直接复制本地根盘布局。
## 3. MySQL 基线
配置:`/etc/mysql/mysql.conf.d/99-lisglosips.cnf`
- 仅绑定回环地址;
- 业务库:`lisglosips`utf8mb4
- binlog 已启用,格式 ROW,保留 7 天;
- `sync_binlog=1`
- `innodb_flush_log_at_trx_commit=1`
- 数据库默认时区 UTC
- 禁止 `local_infile` 和 DNS 主机名解析;
- 慢查询阈值 1 秒;
- InnoDB buffer pool 1 GiB,最大连接数 200。
账号:
| 账号 | 来源 | 权限 |
| --- | --- | --- |
| lisglosips_app | 127.0.0.1 | SELECT/INSERT/UPDATE/DELETE/EXECUTE |
| lisglosips_migrate | 127.0.0.1 | `lisglosips.*` 全权限,用于迁移 |
应用账号不能 DDL;S04 已用实际 ALTER 拒绝测试验证。
## 4. Redis 基线
配置:
- `/etc/redis/redis-lisglosips.conf`
- `/etc/redis/users.acl`
关键策略:
- protected mode 开启;
- AOF everysec 与 RDB 快照同时启用;
- 最大内存 1536 MiB
- `maxmemory-policy=noeviction`,业务热数据和 Stream 不静默淘汰;
- 默认用户关闭;
- `lisglosips` 允许业务命令但移除 dangerous 类命令;
- `lisglo-backup` 仅允许 PING、INFO、BGSAVE、LASTSAVE。
Redis 绑定 Tailscale 地址。`lisglosips-tailscale-ready.service` 会先等待 100.90.90.91/32 出现,避免 Redis 开机首次启动竞态。
## 5. 凭据
本地 DPAPI 加密文件:
`.codex-private/SERVICE_CREDENTIALS.clixml`
包含:
- MYSQL_APP
- MYSQL_MIGRATE
- REDIS_APP
- REDIS_BACKUP
B 机:
| 文件 | 权限 |
| --- | --- |
| `/etc/lisglosips/secrets/mysql-app.env` | root:lisglosips 0640 |
| `/etc/lisglosips/secrets/mysql-migrate.env` | root:root 0600 |
| `/etc/lisglosips/secrets/redis.env` | root:lisglosips 0640 |
| `/etc/lisglosips/secrets/redis-backup.env` | root:root 0600 |
| `/etc/redis/users.acl` | root:redis 0640 |
禁止在聊天、日志、状态文件、仓库或命令参数中输出密码。
## 6. 网络安全
- MySQL 不允许远程连接。
- Redis 仅允许 A 的 Tailscale IP 100.90.90.90 通过 B 的 nftables 访问。
- T 对 3306/6379 的连接已验证为超时拒绝。
- A 第一次访问 B 时可能需要先建立 Tailscale direct 路径:
```bash
tailscale ping --c 1 100.90.90.91
```
稳态 direct 后 Redis 认证连接正常。
## 7. 自动备份
脚本:
- `/usr/local/sbin/lisglosips-mysql-backup`
- `/usr/local/sbin/lisglosips-redis-backup`
systemd
- `lisglosips-backup.service`
- `lisglosips-backup.timer`
每天 03:15 执行,随机延迟最多 15 分钟,保留 14 天。
备份目录:
```text
/data/backups/mysql/YYYYMMDDTHHMMSSZ/
all-databases.sql.gz
lisglosips.sql.gz
metadata.tsv
SHA256SUMS
/data/backups/redis/YYYYMMDDTHHMMSSZ/
dump.rdb
redis-check-rdb.txt
metadata.txt
SHA256SUMS
```
首次有效备份:`20260620T120955Z`
检查:
```bash
sudo systemctl start lisglosips-backup.service
sudo systemctl show -p Result lisglosips-backup.service
sudo systemctl list-timers lisglosips-backup.timer
cd /data/backups/mysql/LATEST_DIRECTORY && sudo sha256sum -c SHA256SUMS
cd /data/backups/redis/LATEST_DIRECTORY && sudo sha256sum -c SHA256SUMS
```
MySQL 全库备份包含账号密码哈希,只允许 root 读取。Redis ACL 明文密码不进入自动备份,灾难恢复时从 DPAPI 凭据重新生成。
## 8. 恢复
### MySQL 业务库
先创建空的临时数据库进行验证:
```bash
sudo mysql -e 'CREATE DATABASE lisglosips_restore_test CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;'
gzip -dc /data/backups/mysql/TIMESTAMP/lisglosips.sql.gz | sudo mysql lisglosips_restore_test
sudo mysql -e 'SHOW TABLES FROM lisglosips_restore_test;'
```
确认数据后再安排正式恢复窗口。禁止直接将 `all-databases.sql.gz` 覆盖到运行中的生产实例。
### Redis RDB
将备份 `dump.rdb` 复制到独立临时目录,用 `port 0` 和独立 Unix socket 启动临时 Redis,验证关键 key 后关闭。不要替换运行中实例的 RDB/AOF。
S04 已完成:
- MySQL 备份后删除源表,恢复到临时库并验证 token;
- Redis 备份后删除源 key,恢复到独立实例并验证 token;
- 两类探针和临时实例均已清理。
## 9. 健康检查
```bash
systemctl is-active mysql redis-server lisglosips-backup.timer
mysqladmin --protocol=socket ping
sudo mysql -e 'SELECT @@version, @@log_bin, @@binlog_format, @@time_zone;'
sudo findmnt /var/lib/mysql
sudo findmnt /var/lib/redis
sudo systemctl show redis-server -p Result -p NRestarts
sudo journalctl -b -u mysql -u redis-server -p err
```
验收状态:
- 重启后 MySQL/Redis active
- Redis 首次启动 `NRestarts=0`
- 没有 failed systemd unit
- AOF 写入和 RDB BGSAVE 均正常;
- 重启持久化探针通过并已清理。
## 10. 回滚
S04 前备份:
`/var/backups/lisglosips-s04/20260620195847`
包含配置基线、迁移前 MySQL/Redis 数据目录压缩包、变更后配置、失败演练样本和 SHA-256 清单。
回滚数据目录必须在维护窗口执行:
1. 停止 `lisglosips-backup.timer`、MySQL 和 Redis。
2. 卸载 `/var/lib/mysql``/var/lib/redis`
3. 恢复 S04 前 fstab。
4. 将当前数据目录另行归档,不直接覆盖。
5. 解压 `mysql.pre-s04.tar.gz``redis.pre-s04.tar.gz``/var/lib`
6. 恢复配置后执行语法检查,再逐个启动服务。
不要在没有完整备份与控制台访问的情况下卸载、覆盖或降级数据库包。
## 11. 已知事项
- 早期一次备份使用绝对校验路径,已移至 S04 备份目录下的 `failed-backups` 留档,不参与恢复。
- 本地根盘适合开发,不满足生产数据库与录音故障隔离要求。
- 软件包处于 hold;上线前需建立定期安全更新和预生产验证流程。