You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使Kubernetes Nginx Ingress结合AWS ELB实现WebSocket正常运行?

解决Kubernetes Nginx Ingress + AWS ELB + Rails WebSocket的问题

我之前处理过几乎一模一样的生产配置场景,你的问题核心是WebSocket升级请求被代理层拦截、代理头传递不完整,再加上TCP模式下的重定向逻辑冲突导致的。下面是一步步的修复方案:

1. 修正ELB控制器服务的配置错误

首先你的注解里有个小笔误(ssl-cert后面多了一个冒号),这会直接导致SSL证书配置失效,先修正这个:

service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:iam::xxx:server-certificate/staging

然后保持ELB的SSL终止模式(后端用HTTP协议),同时补充代理头传递的配置,确保Ingress能正确识别请求协议:

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:iam::xxx:server-certificate/staging
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
# 新增:让ELB传递协议和客户端IP头,解决重定向和来源识别问题
service.beta.kubernetes.io/aws-load-balancer-x-forwarded-proto: "true"
service.beta.kubernetes.io/aws-load-balancer-x-forwarded-for: "true"

2. 更新Ingress注解以支持WebSocket

Nginx Ingress默认不会自动处理WebSocket的Upgrade请求,需要添加专门的注解来配置头转发和指定WebSocket服务:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 保留你已有的CORS配置
    nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/service-upstream: true
    # 保留强制HTTPS重定向,但依赖ELB传递的X-Forwarded-Proto头来判断
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    # 新增WebSocket核心配置
    # 替换成你的Rails服务名称,指定处理WebSocket请求的后端服务
    nginx.ingress.kubernetes.io/websocket-services: "your-rails-app-service"
    # 配置Nginx转发WebSocket升级所需的头和HTTP版本
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_http_version 1.1;
      # 可选:增加超时时间,避免WebSocket连接被Nginx过早断开
      proxy_connect_timeout 7d;
      proxy_send_timeout 7d;
      proxy_read_timeout 7d;

3. 调整Rails应用的代理信任配置

因为流量经过ELB和Ingress两层代理,Rails需要信任这些代理才能正确识别WebSocket请求的来源和协议:
config/environments/production.rb(或对应环境配置文件)中添加:

# 信任代理集群的IP(如果集群IP范围固定,建议用具体CIDR更安全)
config.action_dispatch.trusted_proxies = %w(0.0.0.0/0)
# 配置ActionCable(如果你用的是Rails自带的WebSocket服务)
config.action_cable.allowed_request_origins = [/https?:\/\/your-domain\.com/]
config.action_cable.url = "wss://your-domain.com/cable"

4. 为什么TCP模式会导致无限重定向?

当你把ELB改成TCP模式时,ELB不再终止SSL,而是直接把原始TCP流量转发到Ingress的80端口。此时Ingress检测到请求是HTTP(因为收到的是未加密流量),触发force-ssl-redirect重定向到HTTPS,但ELB又把这个HTTPS请求转发到Ingress的80端口,形成死循环。所以保持ELB的SSL终止模式才是正确的选择。

完成以上调整后,重启Ingress控制器和Rails应用,用浏览器开发者工具检查WebSocket请求:确认Upgrade: websocketConnection: upgrade头被正确传递,并且返回状态码101,就说明配置生效了。

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

火山引擎 最新活动