首页能打开,部署就算完成了吗
这次检查博客时,HTTP 首页、健康检查和文章接口都正常,容器也是 healthy。但切换到 HTTPS 就握手失败,说明“服务在运行”和“用户访问链路正确”是两件事。
继续看宿主机 Nginx 配置,才发现 443 上已有另一个学习站点,而且使用的是明文 HTTP。监听了通常属于 HTTPS 的端口,并不会自动让流量加密;TLS 仍需要对应的监听配置和证书。
修复还涉及两个较小的问题:默认站点名称 _ 重复产生警告,以及宿主机请求体上限低于后台支持的图片大小。
先把三段链路分开检查
我把请求路径拆成三个位置:容器应用、宿主机代理、公网入口。
浏览器
-> 公网 80 / 443
-> 宿主机 Nginx
-> 127.0.0.1:8080
-> 博客容器
容器应用的 /healthz 返回 ok,只能说明这一路局部正常。接下来还要检查域名解析、代理目标、HTTP 状态、TLS 握手,以及页面里的 canonical、RSS 和站点地图是否使用正确地址。
这样排查时,证据会比较清楚:本机上游正常而 HTTPS 握手失败,应先看公网协议入口,而不是反复重建应用。
原来的明文 443 入口还需要继续使用
直接把原监听改成 TLS,会改变面试学习网站既有的访问方式。当前采用 Nginx stream 预读协议,把 TLS 流量与明文 HTTP 分到两个回环后端,方法可以对照 Nginx ssl_preread 官方文档。
最终拓扑是:
| 公网流量 | 本机目标 | 用途 |
|---|---|---|
| 80 | 博客 HTTP server | ACME 验证;其他请求跳转 HTTPS |
| 443,TLS | 127.0.0.1:8443 | 博客 HTTPS |
| 443,明文 HTTP | 127.0.0.1:8444 | 原面试学习网站 |
8443、8444 和容器 8080 都只监听本机。stream 转发还通过 PROXY protocol 传递原客户端地址;后端配套启用并只信任本机来源,避免日志和代理头全部变成回环地址。
这是当前服务器为了兼容已有入口作出的选择。普通单站点服务器如果没有这项约束,不必为了配置 HTTPS 就引入相同拓扑。
证书和应用地址要一起调整
证书通过 HTTP webroot 验证签发,80 端口单独保留 /.well-known/acme-challenge/,其他路径跳转到主域名。www 也有证书,并统一跳转到 https://yellowtt.cn。
应用的构建地址也同步改成 HTTPS。这个博客会用它生成 canonical、RSS、站点地图,并检查后台写请求的来源;只在代理外面加 TLS,而应用还认为自己属于另一个地址,会留下链接和后台操作问题。
新镜像先完成类型检查、生产构建和独立容器里的后台集成测试,再替换线上容器。原镜像、Nginx 配置、环境文件与文章数据都提前留有备份。
413 应当在哪一层修
应用允许单张图片最多 5 MiB,原来的宿主机 Nginx 却会更早拒绝大请求。请求连应用都到不了,修改上传函数没有作用。
博客 server 现在配置 client_max_body_size 6m,让应用继续执行自己的 5 MiB 校验。验证时实际发送了 1 MiB 以上和 5 MiB 的未登录请求,得到应用返回的 401,说明请求通过了 Nginx,没有创建上传文件。
只手写一个很大的 Content-Length 却不发送请求体,并不能完成这项验证;代理允许以后会等待剩余正文,等待超时不等于应用停止工作。
最后检查用户真的会走到的地方
这次上线核对了 23 项公开端点,以及 31 项浏览器页面和跳转;桌面、手机、搜索和主题保存都通过。后台实际登录与退出也正常,会话 Cookie 带 Secure 和 HttpOnly。
原学习网站首页与博客文章数据的 SHA-256 在切换前后保持一致。Nginx 配置检查不再出现名称冲突,证书模拟续期与续期后的重新加载也成功,自动续期任务已启用。
这次最值得保留的排障顺序是:先确定失败发生在哪段链路,再修改那一层;切换之前准备恢复材料,切换之后用真实入口验证。容器 healthy 是其中一项证据,不能替代整条访问路径的检查。