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 hivemq
Deployed 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 hivemq
Create 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-ws
Finally, apply the configuration:
kubectl apply -f hivemq-vs-ws.yaml -n hivemq
Create 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-1883
Finally, apply the configuration:
kubectl apply -f hivemq-mqtt-1883-transportserver.yaml -n hivemq
If TLS is terminated on the nginx side then follow the below steps:
Ensure you have the
tls.key
andtls.crt
ready to create a secret for use in the TransportServer resource:
kubectl create secret tls nginx-tls-secret --cert=tls.crt --key=tls.key -n hivemq
Next, 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-1883
Finally, apply the configuration:
kubectl apply -f hivemq-mqtt-1883-transportserver -n hivemq
Create 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-8883
Finally, apply the configuration:
kubectl apply -f hivemq-mqtt-8883-transportserver.yaml -n hivemq
use the following commands to verify the listeners:
WebSocket Listener:
mqtt sub -h ws.testhivemq.com -p 80 -t test -ws -d
MQTT Listener:
mqtt sub -h mqtt.testhivemq.com -p 1883 -t test1 -d
when TLS terminated on nginx:
mqtt sub -h testhivemq.com -p 1883 -t test1 -d --cafile ca.crt -d -s
MQTT 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