使用Kubernetes Ingress时Nginx返回400状态码问题排查
解决Nginx Ingress下WebSocket 400错误的方案
既然你已经确认端口转发Pod能正常连接Socket服务,那问题肯定出在Nginx Ingress的WebSocket配置上——虽然你加了超时注解,但还缺了几个关键配置项,我帮你一步步排查:
1. 添加WebSocket服务指定注解
Nginx Ingress需要明确知道哪个Service处理WebSocket请求,你需要在Ingress的annotations里添加:
nginx.ingress.kubernetes.io/websocket-services: "web"
这个注解告诉Ingress控制器,web服务需要处理WebSocket握手请求,没有它的话,Ingress可能不会正确转发Upgrade头。
2. 强制转发WebSocket握手头部
有时候默认的Nginx配置不会正确传递WebSocket握手所需的Upgrade和Connection头部,需要通过配置片段手动添加:
nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
这会确保客户端发送的握手头部被正确转发到后端Socket服务。
3. 修改后的完整Ingress配置
把上面两个注解加入你的Ingress配置,最终版本应该是这样:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress namespace: {{ include "namespace" . }} labels: helm.sh/chart: {{ include "chartname" . }} app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/stage: {{ .Values.stage }} annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" # 添加WebSocket服务指定 nginx.ingress.kubernetes.io/websocket-services: "web" # 添加握手头部转发 nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; spec: tls: - secretName: tls-certificate hosts: {{ range .Values.hosts }} - {{ . | quote }} {{ end }} rules: - host: mydomain.tk http: paths: - path: / backend: serviceName: web servicePort: http - path: /socket backend: serviceName: web servicePort: socket
4. 验证配置生效
应用修改后的Ingress配置后,你可以进入Nginx Ingress Pod检查生成的配置是否正确:
kubectl exec -it <your-nginx-ingress-controller-pod-name> -n <ingress-namespace> -- cat /etc/nginx/nginx.conf
找到对应/socket的location块,确认里面包含以下内容:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
同时确认websocket-services的配置已经生效,Ingress控制器会为指定的服务启用WebSocket支持。
额外检查点
- 确认你的Service中
socket端口的targetPort和Pod容器中暴露的Socket端口名称一致(你已经通过端口转发验证过,这一步大概率没问题,但可以再确认下)。 - 由于你使用的是GKE 1.11.7(相对较老的版本),确保Nginx Ingress控制器版本和GKE集群版本兼容——不过最新版的Nginx Ingress通常向下兼容到1.11.x,所以这个问题概率较低。
应用这些修改后,重新测试WebSocket连接,应该就能解决400错误了。
内容的提问来源于stack exchange,提问作者Stefan Gies
相关产品推荐
相关产品推荐

