Rancher 日志无法显示?WebSocket 代理配置是罪魁祸首

最近在维护一套 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 代理配置正确,以下因素也可能导致日志无法显示,建议一并检查:

  1. 服务器时钟同步

    Rancher 的 WebSocket 认证依赖 JWT,若 Rancher Server 与集群节点时间差超过 5 分钟,会导致连接被拒绝。确保所有相关服务器(包括代理服务器和 Rancher 节点)已配置 NTP 同步。

  2. 容器日志驱动

    确保容器运行时使用 json-file 日志驱动(Kubernetes 默认要求),否则 kubectl logs 可能无法读取。

  3. 节点 Kubelet 健康状态

    在集群节点上执行 kubectl logs <pod-name> 测试,若无法获取日志,需检查 Kubelet 服务是否正常。

  4. 防火墙/安全组

    确保代理服务器之间的端口(如 194→170 的 80 端口,170→Rancher NodePort 的端口)已放行。

六、总结

本次 Rancher 无法查看日志的问题,根本原因是 第一层 Nginx 代理未正确支持 WebSocket 协议 ,导致握手失败。在多级代理架构中,每一层都必须正确传递 UpgradeConnection 头部,并确保超时设置足够长,以维持长连接。

希望通过本文的分享,能帮助大家在遇到类似 Rancher UI 功能异常时,快速定位到代理层配置问题,避免在错误的方向上花费过多时间。


彩蛋

如果使用 K3s 部署 Rancher,也可以尝试直接使用 Traefik Ingress 替代手动配置 Nginx,但生产环境仍需根据实际情况选择。

相关推荐
F1FJJ2 小时前
开源实践:用 Go 实现浏览器直连内网 RDP/SSH/VNC
运维·网络·网络协议·网络安全·golang·ssh
23.2 小时前
【分析】HTTP请求端口错误诊断:404、502与连接拒绝的区别
网络·网络协议·http
Bear on Toilet2 小时前
HTTP + JSON 接口调用清单总结
网络协议·http·json
辉视广播对讲2 小时前
私有协议 IP 广播对讲 vs SIP 广播对讲多维度对比分析报告
网络·网络协议·tcp/ip
wanhengidc2 小时前
高防IP的主要功能有哪些?
运维·服务器·网络·网络协议·tcp/ip·游戏
好多渔鱼好多2 小时前
【IPC】HLS(HTTP Live Streaming)技术介绍
网络·网络协议·http·hls
2301_805962933 小时前
ESP32 HTTP OTA 本地测试教程
网络·网络协议·http
Rabbit_QL3 小时前
【HTTP协议解读】01小白篇:理解互联网的通信语言HTTP
网络·网络协议·http
__zRainy__3 小时前
使用 OpenSSL 创建本地开发环境受信任的 HTTPS 证书
网络协议·http·https