Kubernetes中Nginx代理WebSocket超时50秒问题求助
客户端应用通过Nginx代理(用于校验请求头)连接SSL加密的WebSocket应用,该WebSocket在正常使用时运行正常。本地环境下,空闲状态的WebSocket连接可通过Nginx的proxy_read_timeout维持正常连接;但部署到Kubernetes后,WebSocket连接会在约50.29±0.05秒时被强制断开。
环境信息
- Kubernetes版本:
version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.16", GitCommit:"51e33fadff13065ae5518db94e84598293965939", GitTreeState:"clean", BuildDate:"2023-07-19T12:19:24Z", GoVersion:"go1.20.6", Compiler:"gc", Platform:"linux/amd64"}
- 非公有云(如Google/AWS)环境
- Ingress控制器:
registry.k8s.io/ingress-nginx/controller:v1.9.3 - 使用Octavia负载均衡器
已尝试的配置
Nginx配置片段
upstream myUpstream { server myUpstream:443; keepalive 32; } location /ws { proxy_http_version 1.1; proxy_pass_request_headers on; proxy_set_header Connection 'Upgrade'; proxy_set_header Upgrade $http_upgrade; proxy_read_timeout 1800s; proxy_connect_timeout 1800s; proxy_send_timeout 1800s; send_timeout 1800s; proxy_pass http://myUpstream/ws; }
Ingress资源注解
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/proxy-body-size: "16m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" nginx.ingress.kubernetes.io/proxy-buffer-size: "256k" name: url-routing
测试时将proxy_read_timeout调低至30秒,连接会在30.29±0.05秒正常断开;同命名空间内另一个通过Nginx代理的WebSocket服务无此断开问题。
需明确:是什么因素强制触发了50秒的默认超时?如何在不添加WebSocket心跳的前提下解决该问题?
50秒超时的根源
这个50秒的超时大概率来自Octavia负载均衡器的默认空闲超时设置。Octavia的默认空闲连接超时就是50秒,当连接处于空闲状态时,负载均衡器会主动断开连接,这和你观察到的50.29±0.05秒的断开时间高度吻合。
同命名空间的另一个WebSocket服务无问题,可能是该服务本身存在隐性心跳机制(比如业务层定时发送小数据包),或者其关联的Octavia负载均衡器超时配置被单独修改过。
无心跳前提下的解决办法
1. 修改Octavia负载均衡器的空闲超时配置
通过OpenStack控制台或CLI工具,找到关联当前Ingress的Octavia负载均衡器,定位到对应的HTTP/HTTPS listener,将其**空闲超时(idle timeout)**设置为目标时长(比如和Nginx一致的1800秒)。具体操作需参考你的OpenStack环境文档:
- 找到与Ingress绑定的Octavia负载均衡器实例
- 进入对应的listener配置页面
- 更新
idle timeout参数为所需值
2. 配置Nginx发送TCP保活包
在Nginx的/ws location块中添加TCP保活相关参数,让Nginx主动发送保活探测包,避免Octavia判定连接空闲:
location /ws { # 原有配置保留 proxy_http_version 1.1; proxy_pass_request_headers on; proxy_set_header Connection 'Upgrade'; proxy_set_header Upgrade $http_upgrade; proxy_read_timeout 1800s; proxy_connect_timeout 1800s; proxy_send_timeout 1800s; send_timeout 1800s; # 添加TCP保活配置 proxy_socket_keepalive on; tcp_keepalive_time 30s; tcp_keepalive_intvl 30s; tcp_keepalive_probes 3; proxy_pass http://myUpstream/ws; }
这些参数会让Nginx每隔30秒发送一次TCP保活包,确保Octavia认为连接处于活跃状态,不会触发50秒的空闲超时。
3. 确认Ingress控制器的超时配置生效
检查Ingress控制器生成的实际Nginx配置,确保你的注解已正确覆盖默认值:
- 进入Ingress控制器Pod:
kubectl exec -it <ingress-controller-pod-name> -n <ingress-namespace> -- /bin/bash - 查看生成的配置文件:
cat /etc/nginx/nginx.conf - 搜索
/ws对应的location块,确认proxy_read_timeout等参数是否为1800秒
若配置未生效,需检查Ingress资源注解是否有误,或重启Ingress控制器Pod让配置重载。
内容的提问来源于stack exchange,提问作者Laurent Erignoux

