You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NGINX Ingress Controller动态代理WebSocket连接异常求助

问题:Ingress动态代理WebSocket连接,消息无法到达后端Pod

我通过Ingress片段配置动态代理WebSocket连接,Ingress已接受并升级连接,但WebSocket消息始终无法到达后端Pod。怀疑是NGINX Controller自行完成了连接升级,未代理给Pod处理。

相关配置与测试信息

Ingress资源配置

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  annotations:
    nginx.org/path-regex: "case_insensitive"
    nginx.org/proxy-read-timeout: "86400s"
    nginx.org/proxy-send-timeout: "86400s"
    nginx.org/proxy-buffering: "False"
    nginx.org/server-snippets: |
      resolver kube-dns.kube-system.svc.cluster.local valid=30s;
      location ~* "^/ws/(?<username>[^/]+)$" {
          # Prevent malicious characters in the username
          if ($username ~ "[^a-zA-Z0-9_-]") {
              return 400;
          }

          set $service_name svc-$username;
          set $namespace default;

          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "Upgrade";

          # Forward necessary headers
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-Host $http_host;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-Forwarded-For $remote_addr;

          # Upgrade HTTP to WebSocket
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "Upgrade";

          # Disable proxy buffering for WebSocket
          proxy_buffering off;

          # Bypass caching
          proxy_cache_bypass $http_upgrade;

          # Pass the WebSocket connection to the user-specific service
          proxy_pass http://$service_name.$namespace.svc.cluster.local;
      }
spec:
  ingressClassName: nginx
  rules:
    - host: "localhost"
      http:
        paths:
          - path: /api/session/start/
            pathType: Prefix
            backend:
              service:
                name: controller-service
                port:
                  number: 8080

测试命令及结果

# WebSocket连接测试
wscat -c ws://localhost/ws/testuser                                 
Hello

# 后端Pod日志(无连接及消息记录)
kubectl logs pod/pod-testuser                                       
INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
<---- 此处应有连接日志,但实际无输出

后端Python WebSocket代码

# WebSocket endpoint with dynamic username path
@app.websocket("/ws/{username}")
async def websocket_endpoint(websocket: WebSocket, username: str):
    print("Waiting to accept a websocket connection...")
    await websocket.accept()
    print(f"Connected. Waiting for messages from user: {username}")
    while True:
        try:
            message = await websocket.receive_text()
            print(f"Received message from {username}: {message}")
            await websocket.send_text(
                f"Message from user: {username}."
            )
        except WebSocketDisconnect:
            print(f"WebSocket connection closed for user: {username}")
            break

排查方向与解决方案

1. 检查后端Service端口映射

核心问题大概率是后端Service的端口未正确映射到Pod的8000端口:
Ingress配置中proxy_pass默认请求后端Service的80端口,但后端Pod的Uvicorn服务运行在8000端口。需确保对应Service的targetPort指向8000:

apiVersion: v1
kind: Service
metadata:
  name: svc-testuser
spec:
  selector:
    app: testuser
  ports:
    - name: http
      port: 80
      targetPort: 8000

2. 清理Ingress配置中的冗余项

配置中重复设置了Upgrade和Connection头,虽不影响功能,但建议删除重复内容,优化后的server-snippets如下:

nginx.org/server-snippets: |
  resolver kube-dns.kube-system.svc.cluster.local valid=30s;
  location ~* "^/ws/(?<username>[^/]+)$" {
      if ($username ~ "[^a-zA-Z0-9_-]") {
          return 400;
      }

      set $service_name svc-$username;
      set $namespace default;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Host $http_host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header Origin ""; # 避免跨域相关问题

      proxy_buffering off;
      proxy_cache_bypass $http_upgrade;

      proxy_pass http://$service_name.$namespace.svc.cluster.local;
  }

3. 验证NGINX Controller生成的配置

执行以下命令查看NGINX实际生效的配置,确认server-snippets中的location块已正确加载:

kubectl exec -it <nginx-controller-pod-name> -- cat /etc/nginx/nginx.conf

同时验证配置有效性:

kubectl exec -it <nginx-controller-pod-name> -- nginx -t

若配置有效,可重启NGINX Controller或触发配置重载。

4. 测试后端服务的可达性

在NGINX Controller Pod内执行WebSocket握手测试,确认后端服务能正常响应:

curl http://svc-testuser.default.svc.cluster.local/ws/testuser -i \
-H "Upgrade: websocket" \
-H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13"

若后端正常,应返回101 Switching Protocols响应。

内容的提问来源于stack exchange,提问作者Francisco Aguilera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 06:50:57