最近在维护一套 Rancher 环境时,遇到了一个棘手的问题:用户无法在 Rancher UI 中查看容器日志,页面一直加载失败,浏览器控制台报错 WebSocket connection failed。经过一番排查,最终定位到问题出在两层 Nginx 反向代理的 WebSocket 支持配置上。本文将详细记录这个问题的排查过程、根本原因以及解决方案,希望能帮助遇到类似问题的同行。
一、问题现象
在 Rancher 管理界面中,点击某个 Pod 的"查看日志"按钮后,页面长时间显示"加载中",随后提示连接失败。打开浏览器开发者工具(F12),在 Network 标签中看到 WebSocket 请求状态为失败,具体错误信息类似:
text
WebSocket connection to 'wss://test.klg.cofco.com/v3/subscribe?sockId=2' failed:
二、环境架构
我们的网络拓扑如下:
-
域名
xxxx.com解析到一台公网服务器 194(有公网 IP)。 -
194 服务器 上运行 Nginx,配置了 SSL 证书,对外提供 HTTPS 服务。
-
194 服务器 将请求反向代理到内网服务器 170(无公网 IP)。
-
170 服务器 上同样运行 Nginx,再将请求转发到 Rancher 的 NodePort 端口
https://xxx:31043。
即:客户端 → 194(SSL) → 170(内网代理) → Rancher NodePort
三、排查过程
1. 初步判断 WebSocket 握手失败
浏览器报错明确指向 WebSocket 连接失败,而 Rancher 的日志查看和终端功能均依赖 WebSocket 长连接。因此,问题很可能出在 WebSocket 握手环节。
2. 检查后端 Rancher 是否正常
在 170 服务器上直接使用 curl 测试 Rancher NodePort 是否支持 WebSocket:
bash
curl -k https://xxxx:31043/v3/subscribe? -H "Upgrade: websocket" -H "Connection: Upgrade" -v
返回 101 Switching Protocols,说明 Rancher 后端本身是正常的。
3. 检查 170 服务器 Nginx 配置
查看 170 的 Nginx 配置,发现已正确添加 WebSocket 所需头部:
nginx
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
并且设置了较长的超时时间和关闭缓冲,看起来没有问题。
4. 检查 194 服务器 Nginx 配置
最终在 194 的 Nginx 配置中发现了问题所在。关键配置片段如下:
nginx
location / {
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive"; # ❌ 固定为 Keep-Alive
# 缺少 proxy_set_header Upgrade $http_upgrade;
...
}
-
缺少
Upgrade头传递 :WebSocket 握手需要客户端发送Upgrade: websocket,Nginx 必须通过proxy_set_header Upgrade $http_upgrade;将此头部转发给后端。 -
Connection头被硬编码为Keep-Alive:即使客户端发送Connection: Upgrade,Nginx 转发时也会强制改为Keep-Alive,导致后端无法识别这是一个 WebSocket 升级请求。
因此,当客户端发起 WebSocket 连接时,194 服务器根本没有将升级请求传递给 170 服务器,握手自然失败。
四、解决方案
修改 194 服务器 Nginx 配置
在 location / 中添加 WebSocket 支持,并移除冲突的 Connection 设置:
nginx
location / {
proxy_http_version 1.1;
# 传递 WebSocket 握手头部
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 删除或注释掉原来的 proxy_set_header Connection "Keep-Alive";
# proxy_set_header Connection "Keep-Alive";
# 其他原有配置保留(根据需要可调整超时等)
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
client_max_body_size 300m;
proxy_pass http://xxx; # upstream 指向 170 服务器
# 可选:关闭缓冲,提升日志实时性
proxy_buffering off;
}
重载 Nginx
在两台服务器上分别执行:
bash
sudo nginx -t && sudo nginx -s reload
验证
再次访问 Rancher 并尝试查看日志,打开浏览器开发者工具,查看 WebSocket 请求状态码应为 101 Switching Protocols,日志页面正常显示。
五、其他注意事项
即使 WebSocket 代理配置正确,以下因素也可能导致日志无法显示,建议一并检查:
-
服务器时钟同步
Rancher 的 WebSocket 认证依赖 JWT,若 Rancher Server 与集群节点时间差超过 5 分钟,会导致连接被拒绝。确保所有相关服务器(包括代理服务器和 Rancher 节点)已配置 NTP 同步。
-
容器日志驱动
确保容器运行时使用
json-file日志驱动(Kubernetes 默认要求),否则kubectl logs可能无法读取。 -
节点 Kubelet 健康状态
在集群节点上执行
kubectl logs <pod-name>测试,若无法获取日志,需检查 Kubelet 服务是否正常。 -
防火墙/安全组
确保代理服务器之间的端口(如 194→170 的 80 端口,170→Rancher NodePort 的端口)已放行。
六、总结
本次 Rancher 无法查看日志的问题,根本原因是 第一层 Nginx 代理未正确支持 WebSocket 协议 ,导致握手失败。在多级代理架构中,每一层都必须正确传递 Upgrade 和 Connection 头部,并确保超时设置足够长,以维持长连接。
希望通过本文的分享,能帮助大家在遇到类似 Rancher UI 功能异常时,快速定位到代理层配置问题,避免在错误的方向上花费过多时间。
彩蛋
如果使用 K3s 部署 Rancher,也可以尝试直接使用 Traefik Ingress 替代手动配置 Nginx,但生产环境仍需根据实际情况选择。