75 lines
5.6 KiB
Markdown
75 lines
5.6 KiB
Markdown
# 续期维护窗口演练记录
|
||
|
||
## 授权与范围
|
||
|
||
2026-09-17 用户明确允许测试期间暂停其他服务、测试后恢复。本轮仅临时暂停共享的 Nginx;Smail 邮件服务、Scert 后端、MySQL 和 PostgreSQL 没有停止。该授权适用于本次测试,不自动代表接受今后自动续期的常规中断窗口。
|
||
|
||
- 基线提交:`2287001`,测试前已推送。
|
||
- 测试服务器:47.108.78.12,所有语法检查、测试脚本和应用探测均在远程执行。
|
||
- 新增工具:`test/deployment/renewal_drill.py`。加载线上续期脚本,将测试目录和临近到期判断替换为隔离输入,真实调用 lego 与 ACME 测试环境。
|
||
- 未修改线上续期源码、应用双程序、正式证书、Nginx 配置或业务数据库;未清库、未执行首次安装。
|
||
- 测试环境目录从原有 staging 状态复制至独立 0700 目录,未复制正式 ACME 账号或密钥。未下载测试账号和私钥,也未删除原始数据。
|
||
|
||
## 恢复保护
|
||
|
||
执行前记录服务状态及正式文件摘要,检查 Nginx 配置和两个项目 HTTPS 入口。仅在 Nginx 已运行的情况下开始演练。
|
||
|
||
1. 原续期脚本在正常异常路径中执行 `finally` 恢复 Nginx。
|
||
2. 临时 systemd 单元设置 `ExecStopPost=/usr/bin/systemctl start nginx.service`,覆盖测试进程被终止的情况。
|
||
3. 每轮开始前创建并确认独立延时恢复定时器处于 active,作为外层兜底。确认服务恢复后停止定时器,避免稍后意外启动服务。本次未实际触发此第三层兜底。
|
||
|
||
两轮使用 MemoryHigh 96 MiB、MemoryMax 128 MiB、MemorySwapMax 0、CPUQuota 100%、TasksMax 64、GOMEMLIMIT 64 MiB,并保留 PrivateTmp、ProtectHome、NoNewPrivileges。正式应用、正式 ACME 目录和 Nginx 配置目录只读挂载,测试证书部署钩子被阻止,不能进入正式证书路径。
|
||
|
||
## 真实续期
|
||
|
||
证据目录:`/var/tmp/smail-renewal-drill-20260917-234758`。
|
||
|
||
隔离 ACME 目录:`/var/lib/smail-acme-drill-20260917-234758`,权限 0700。主机上的测试密钥和账号继续受保护,不提交仓库。
|
||
|
||
| 项目 | 结果 |
|
||
| --- | --- |
|
||
| 线上续期源码 SHA256 | `6d0abbe9466f8becd61b1cb3c750bfffb938d16c5a9bcae0b96d1451227d4216` |
|
||
| 运行模式 | 测试环境 `renew`,模拟临近到期,使用 `--days 91 --ari-disable` 确定触发更新,保留 `--reuse-key --no-random-sleep` |
|
||
| Nginx 停止请求 | 北京时间 23:48:46.946 |
|
||
| Nginx 恢复完成 | 北京时间 23:48:56.215 |
|
||
| 停止请求至恢复 | 约 9.27 秒,不代表浏览器端精确中断时长 |
|
||
| systemd 结果 | success,退出码 0,运行 10.052 秒 |
|
||
| 峰值内存 | systemd 输出约 72.6 MiB,无交换空间使用 |
|
||
| 续期产物 | 证书内容已改变,原密钥复用,密钥匹配,五个 SAN 完全一致 |
|
||
| 正式文件 | 程序、正式证书、正式私钥及现有站点配置摘要未变 |
|
||
|
||
CA 日志明确记录五个域名授权仍有效并跳过挑战。因此本轮证明了真实测试环境续期、资源限制和服务恢复,但不证明在相同限额下完成了全新公网 TLS-ALPN-01 挑战。未更改系统时间,也未等待证书自然临近到期。
|
||
|
||
测试证书没有部署到正式服务。本轮不覆盖正式 CA 到期换证、正式部署钩子的完整执行或外部失败告警。
|
||
|
||
## 超时自动恢复
|
||
|
||
证据目录:`/var/tmp/smail-renewal-drill-20260917-235019-timeout`。
|
||
|
||
在 Nginx 停止后模拟续期任务挂起,由测试单元的 20 秒启动超时终止进程。正式续期服务的 240 秒总超时未改动;本轮缩短的是临时测试单元期限。
|
||
|
||
| 项目 | 结果 |
|
||
| --- | --- |
|
||
| 停止请求 | 北京时间 23:50:21.740 |
|
||
| systemd 结果 | 预期 timeout,进程由 SIGTERM 终止,ExecMainStatus 15 |
|
||
| 单元运行时间 | 20.126 秒 |
|
||
| 峰值内存 | 76,128,256 字节,约 72.6 MiB |
|
||
| 自动恢复证据 | 执行任何人工兜底启动前,Nginx 已 active;启动时间为 23:50:41,PID 578671 |
|
||
| 两个项目入口 | Smail 443 和 Scert 8004 均返回 200,系统证书校验结果均为 0 |
|
||
|
||
被终止的子进程没有机会写最终 JSON,`result.json` 中仍为 `running`。最终结论来自 `execution.log`、`unit-result.txt`、`automatic-recovery-state.txt` 及两个 HTTPS 恢复探测文件,不能仅凭子进程 JSON 判定仍在运行。
|
||
|
||
## 结束复核与任务状态
|
||
|
||
- [✓] 真实测试环境续期成功,正式部署文件未变。
|
||
- [✓] 实际超时终止后,systemd 自动恢复 Nginx;两个项目 HTTPS 入口恢复。
|
||
- [✓] Smail PID 574584 保持不变,NRestarts 0;Scert PID 576928、MySQL PID 549584、PostgreSQL PID 313101 的进程与监听仍存在。
|
||
- [✓] 七个 TLS/STARTTLS 入口及 Host/SNI 边界复测通过,正式叶证书指纹仍为 `608fb55e3b8add3426a63f672debd86a58389a1a78d0961b9603b2e1abecae43`。
|
||
- [✓] 原 128 MiB 保留预算的资源预检通过,无 OOM;生产批准仍为 false。
|
||
- [✓] 两个临时恢复定时器 inactive;正式续期定时器 active,下一计划执行时间为 2026-09-18 04:21:56 CST。
|
||
- [✓] 演练工具拒绝缺少维护授权、使用正式 ACME 目录、覆盖已有演练结果三种调用,均在停止服务之前以参数错误退出。
|
||
- [!] 全新挑战、正式换证完整链路、外部失败与到期告警、常规共用维护窗口仍需独立验证或确认。
|
||
- [!] 代理客户端 IP、公网恢复地址、完整浏览器流程、管理员恢复撤销、凭据轮换、容量与异机恢复等原有验收项不因本轮测试自动通过。
|
||
|
||
本轮解决的是授权维护窗口内的测试环境续期及任务终止恢复验证,不能签署整体生产放行。
|