How to access MQTT, Websocket ports using TransportServer/VirtualServer resource with nginx ingress controller
This article helps with step by step guide about how to access MQTT, MQTT TLS, and WebSocket listener ports using the VirtualServer and TransportServer with Nginx ingress controller.
Prerequisites
Helm version v3+
Running Kubernetes cluster version 1.30.0 or higher
kubectl latest version
Instructions
Deployed Ingress NGINX Controller:
We deployed the NGINX Ingress controller with the following configuration:kubectl create ns hivemq helm upgrade --install nginx-ingress oci://ghcr.io/nginxinc/charts/nginx-ingress \ --set controller.enableCustomResources=true \ --set controller.globalConfiguration.create=true \ --set controller.service.type=LoadBalancer \ --set "controller.globalConfiguration.spec.listeners[0].name=mqtt-1883" \ --set "controller.globalConfiguration.spec.listeners[0].port=1883" \ --set "controller.globalConfiguration.spec.listeners[0].protocol=TCP" \ --set "controller.globalConfiguration.spec.listeners[1].name=mqtts-8883" \ --set "controller.globalConfiguration.spec.listeners[1].port=8883" \ --set "controller.globalConfiguration.spec.listeners[1].protocol=TCP" \ --set "controller.globalConfiguration.spec.listeners[2].name=ws-8001" \ --set "controller.globalConfiguration.spec.listeners[2].port=8001" \ --set "controller.globalConfiguration.spec.listeners[2].protocol=TCP" \ --set "controller.service.customPorts[0].name=mqtt-1883" \ --set "controller.service.customPorts[0].port=1883" \ --set "controller.service.customPorts[0].targetPort=1883" \ --set "controller.service.customPorts[0].protocol=TCP" \ --set "controller.service.customPorts[1].name=mqtts-8883" \ --set "controller.service.customPorts[1].port=8883" \ --set "controller.service.customPorts[1].targetPort=8883" \ --set "controller.service.customPorts[1].protocol=TCP" \ --set "controller.service.customPorts[2].name=ws-8001" \ --set "controller.service.customPorts[2].port=8001" \ --set "controller.service.customPorts[2].targetPort=8001" \ --set "controller.service.customPorts[2].protocol=TCP"Deployed HiveMQ Platform Operator:
We deployed the HiveMQ Platform Operator using the default settings:helm install platform-op hivemq/hivemq-platform-operator -n hivemqDeployed HiveMQ Platform:
We enabled MQTT (1883), MQTT TLS (8883), and WebSocket (8001) listeners using the following command:helm upgrade --install -f values.yaml hivemq hivemq/hivemq-platform -n hivemqCreate VirtualServer to Expose WebSocket Listener on Port 80:
Please note: VirtualServer resource do not expose TCP/UDP ports but only HTTP and HTTPs.apiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: hivemq-vs-ws namespace: hivemq spec: host: ws.testhivemq.com ingressClassName: nginx upstreams: - name: hivemq-ws service: hivemq-hivemq-ws-8001 port: 8001 lb-method: round_robin routes: - path: / action: pass: hivemq-wsFinally, apply the configuration:
kubectl apply -f hivemq-vs-ws.yaml -n hivemqCreate TransportServer Resource to Expose MQTT 1883 Listener:
apiVersion: k8s.nginx.org/v1 kind: TransportServer metadata: name: hivemq-mqtt-1883-transportserver spec: ingressClassName: nginx listener: name: mqtt-1883 protocol: TCP upstreams: - name: hivemq-hivemq-mqtt-1883 service: hivemq-hivemq-mqtt-1883 port: 1883 loadBalancingMethod: least_conn action: pass: hivemq-hivemq-mqtt-1883Finally, apply the configuration:
kubectl apply -f hivemq-mqtt-1883-transportserver.yaml -n hivemqIf TLS is terminated on the nginx side then follow the below steps:
Ensure you have the
tls.keyandtls.crtready to create a secret for use in the TransportServer resource:
kubectl create secret tls nginx-tls-secret --cert=tls.crt --key=tls.key -n hivemqNext, create the TransportServer resource file (
hivemq-mqtt-1883-transportserver.yaml):
apiVersion: k8s.nginx.org/v1 kind: TransportServer metadata: name: hivemq-mqtt-1883-transportserver spec: ingressClassName: nginx tls: secret: nginx-tls-secret listener: name: mqtt-1883 protocol: TCP upstreams: - name: hivemq-hivemq-mqtt-1883 service: hivemq-hivemq-mqtt-1883 port: 1883 loadBalancingMethod: round_robin action: pass: hivemq-hivemq-mqtt-1883Finally, apply the configuration:
kubectl apply -f hivemq-mqtt-1883-transportserver -n hivemqCreate TransportServer Resource for MQTT TLS (8883) Listener Exposed on Port 443: (TLS is terminated on broker side)
To access a TLS MQTT listener, redeploy nginx-ingress controller by adding an extra parameter to the existing shared command by us.
--set controller.enableTLSPassthrough=true and then deploy TransportServer Resource for MQTT TLS (8883).
apiVersion: k8s.nginx.org/v1
kind: TransportServer
metadata:
name: hivemq-mqtt-8883-transportserver
spec:
ingressClassName: nginx
host: testhivemq.com
listener:
name: tls-passthrough
protocol: TLS_PASSTHROUGH
upstreams:
- name: hivemq-hivemq-mqtt-8883
service: hivemq-hivemq-mqtt-8883
port: 8883
loadBalancingMethod: round_robin
action:
pass: hivemq-hivemq-mqtt-8883Finally, apply the configuration:
kubectl apply -f hivemq-mqtt-8883-transportserver.yaml -n hivemquse the following commands to verify the listeners:
WebSocket Listener:
mqtt sub -h ws.testhivemq.com -p 80 -t test -ws -dMQTT Listener:
mqtt sub -h mqtt.testhivemq.com -p 1883 -t test1 -dwhen TLS terminated on nginx:
mqtt sub -h testhivemq.com -p 1883 -t test1 -d --cafile ca.crt -d -sMQTT TLS Listener:(certs were generated with CN name as testhivemq.com(TLS terminated on Broke end)
mqtt sub -h testhivemq.com -p 443 -t test -s --cafile ~/projects/tickets/hivemq-3244/hivemq-server-cert.pem -d