K8s中AMQP协议Service与Ingress配置及端口转发方案咨询
问题背景
Java SpringBoot应用需通过443/80端口发送请求,转发至运行AMQP协议的RabbitMQ Pod,但客户端代理仅开放443/80端口,不愿开放RabbitMQ的5671 TLS端口。
我们尝试创建了如下Ingress资源:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ing-rabbitmq-amqp annotations: kubernetes.io/ingress.class: nginx spec: rules: - http: paths: - path: /amqp pathType: Prefix backend: service: name: rabbitmq-amqp port: number: 5671
但Java应用连接时出现报错:
2023-02-03 07:13:51.031 INFO 1 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' 2023-02-03 07:13:51.106 INFO 1 --- [ main] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [10.25.119.247/amqp:80] 2023-02-03 07:13:51.125 INFO 1 --- [ main] o.s.a.r.l.SimpleMessageListenerContainer : Broker not available; cannot force queue declarations during start: java.net.UnknownHostException: 10.25.119.247/amqp
通常应用连接RabbitMQ 5671端口成功时的日志为:
2023-02-03 07:15:44.087 INFO 1 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler' 2023-02-03 07:15:44.150 INFO 1 --- [ main] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [10.25.119.247:5671] 2023-02-03 07:15:46.182 INFO 1 --- [ main] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#2f01783a:0/SimpleConnection@5b202a3a [delegate=amqp://test_bot_user@10.25.119.247:5671/test, localPort= 58840]
同时nginx-ingress-controller Pod报错:
2023/02/03 07:20:08 [error] 4299#4299: *209766772 recv() failed (104: Connection reset by peer) while proxying and reading from upstream, client: 10.25.119.247, server: 0.0.0.0:5671, upstream: "192.168.52.60:5671", bytes from/to client:5467/6570, bytes from/to upstream:6570/5467 [5.161.119.202] [03/Feb/2023:07:20:08 +0000] TCP 200 6570 5467 263.959
服务器IP:10.25.119.247
RabbitMQ Pod IP:192.168.52.60
问题
- Kubernetes是否支持创建AMQP等非HTTP/HTTPS协议的Service与Ingress资源?
- 若不支持或当前方案不可行,如何实现SpringBoot应用通过443/80端口连接RabbitMQ Pod?
解答
问题1:Kubernetes对非HTTP/HTTPS协议的Service与Ingress支持情况
- Service:完全支持。Kubernetes Service本质是四层(TCP/UDP)负载均衡,可代理任何基于TCP/UDP的协议(包括AMQP、Redis、MySQL等),只需在
spec.ports中指定对应协议(默认TCP)和端口即可。 - Ingress:标准Ingress资源仅支持HTTP/HTTPS协议。Ingress是七层(应用层)路由,依赖Ingress Controller(如NGINX Ingress)处理HTTP请求的路由规则。你用HTTP Ingress代理AMQP协议必然失败——NGINX会把AMQP二进制数据当作HTTP请求解析,导致协议不匹配,出现连接重置或解析错误。
问题2:实现SpringBoot通过443/80端口连接RabbitMQ的可行方案
方案1:使用NGINX Ingress的TCP/UDP代理功能
NGINX Ingress Controller支持配置TCP/UDP端口转发,绕过HTTP路由直接做四层代理,步骤如下:
- 修改NGINX Ingress Controller配置:
在Controller的Deployment/DaemonSet中添加环境变量TCP_CONFIG_MAP,指向一个ConfigMap,例如--tcp-services-configmap=default/nginx-tcp-configmap;同时在Controller的Service中添加要暴露的端口(如80或443),将其转发到内部TCP端口。 - 创建TCP代理ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: nginx-tcp-configmap namespace: default data: # 格式:外部端口:命名空间/服务名:服务端口 "80": "default/rabbitmq-amqp:5671" - 更新Ingress Controller Service:
在Service的spec.ports中添加:- name: tcp-80 protocol: TCP port: 80 targetPort: 80 - SpringBoot应用配置:
直接配置RabbitMQ地址为10.25.119.247:80,无需添加路径/amqp——四层代理无路径概念。
方案2:使用socat做Pod内协议转发
若无法修改Ingress Controller,可在RabbitMQ同命名空间部署socat Pod,将80端口的TCP流量转发到RabbitMQ的5671端口:
- 创建socat Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: rabbitmq-proxy spec: replicas: 1 selector: matchLabels: app: rabbitmq-proxy template: metadata: labels: app: rabbitmq-proxy spec: containers: - name: socat image: alpine/socat command: ["socat", "TCP-LISTEN:80,fork", "TCP:rabbitmq-amqp:5671"] ports: - containerPort: 80 - 创建对应Service:
apiVersion: v1 kind: Service metadata: name: rabbitmq-proxy-service spec: selector: app: rabbitmq-proxy ports: - port: 80 targetPort: 80 - 配置Ingress转发到代理Service:
使用标准HTTP Ingress即可(路径不影响,socat仅做TCP转发),SpringBoot应用连接10.25.119.247:80。
方案3:启用RabbitMQ Web STOMP插件
若可启用RabbitMQ的Web STOMP插件,SpringBoot可通过WebSocket(基于HTTP/HTTPS)连接RabbitMQ,直接用标准Ingress转发:
- 启用Web STOMP插件:
在RabbitMQ配置中执行rabbitmq-plugins enable rabbitmq_web_stomp - 配置Service暴露Web STOMP端口:
默认Web STOMP端口为15674(HTTP)或15675(HTTPS) - 配置Ingress转发到Web STOMP端口:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rabbitmq-web-stomp annotations: kubernetes.io/ingress.class: nginx spec: rules: - http: paths: - path: /stomp pathType: Prefix backend: service: name: rabbitmq-amqp port: number: 15674 - SpringBoot应用配置:
使用Spring WebSocket STOMP客户端连接ws://10.25.119.247/stomp,实现与RabbitMQ的通信。
内容的提问来源于stack exchange,提问作者James Taylor
相关产品推荐
相关产品推荐

