如何在Kubernetes中配置Nginx以实现WS与WSS正常运行?
解决Kubernetes中Nginx Pod的WSS握手错误问题
我之前也踩过这个一模一样的坑——独立服务器上WS和WSS都好好的,一部署到K8s的Nginx Pod里,WSS就开始握手失败。结合你的配置和场景,我来帮你梳理问题根源,一步步搞定它。
问题根源分析
你的default.conf目前只配置了80端口的HTTP/WS代理逻辑,但WSS本质是WebSocket over SSL/TLS,默认走443端口。你说独立服务器上WSS不用证书也能工作,大概率是因为客户端和服务器在同一个信任网络,或者有其他前置代理帮你处理了SSL层;但K8s的NodePort环境下,流量从客户端到Pod的路径更长,必须明确处理SSL或者适配外部的SSL终结逻辑。
解决方案分两种场景
场景1:让Nginx Pod直接处理SSL(用自签证书快速验证)
如果你的场景不需要正式域名证书,用自签证书就能解决问题:
- 给Nginx Pod添加SSL证书
你可以在构建Nginx镜像时生成自签证书,或者用ConfigMap挂载证书文件。比如在Dockerfile里加这段命令:# 创建证书目录并生成自签证书 RUN mkdir -p /etc/nginx/ssl && \ openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/nginx/ssl/nginx.key \ -out /etc/nginx/ssl/nginx.crt \ -subj "/CN=localhost" - 修改Nginx配置,添加443端口的WSS代理
更新你的default.conf,新增443端口的server块:server { listen 80; location / { proxy_pass http://ip:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; } } server { listen 443 ssl; # 指定证书路径 ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key; location / { proxy_pass http://ip:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; # 转发SSL相关的头部,让后端服务识别请求协议 proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; } } - 更新Kubernetes Service,暴露443端口
修改你的Service配置,把443端口也映射为NodePort:apiVersion: v1 kind: Service metadata: name: nginx-ws-service spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30080 # 可选,自定义端口 - port: 443 targetPort: 443 nodePort: 30443 # 可选,自定义端口 selector: app: nginx-ws-pod # 替换成你的Pod标签
场景2:外部已有SSL终结(比如Ingress/负载均衡器处理SSL)
如果你的K8s集群已经有Ingress或者外部负载均衡器处理了SSL,客户端的WSS请求会被转为HTTP的WS请求发给Nginx Pod。这时候需要调整配置,适配代理后的流量:
- 修改Nginx的http块和server块
更新default.conf,添加map指令处理Connection头部,并完善代理配置:
这个配置的核心是用http { # 动态设置Connection头部,非WebSocket请求时用close map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; location / { proxy_pass http://ip:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; # 使用动态的Connection头部值 proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; # 转发外部的SSL协议标识 proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; } } }map指令动态判断是否需要Upgrade,避免在非WebSocket请求时发送错误的Connection头部。
验证步骤
- 重新部署Nginx Pod,或者在Pod里重载配置:
kubectl exec <你的Pod名称> -- nginx -s reload - 用
wscat工具测试WSS连接:- 场景1测试命令:
wscat -wss wss://<Node节点IP>:30443/ - 场景2测试命令:
wscat -wss wss://<你的域名>/(确保域名指向Ingress/负载均衡器)
- 场景1测试命令:
内容的提问来源于stack exchange,提问作者AATHITH RAJENDRAN
相关产品推荐
相关产品推荐

