Test connectivity to MQTT broker with MQTT clients
Important
This page includes instructions for managing Azure IoT Operations components using Kubernetes deployment manifests, which is in preview. This feature is provided with several limitations, and shouldn't be used for production workloads.
See the Supplemental Terms of Use for Microsoft Azure Previews for legal terms that apply to Azure features that are in beta, preview, or otherwise not yet released into general availability.
This article shows different ways to test connectivity to MQTT broker with MQTT clients in a nonproduction environment.
By default, MQTT broker:
Deploys a TLS-enabled listener on port 18883 with ClusterIp as the service type. ClusterIp means that the broker is accessible only from within the Kubernetes cluster. To access the broker from outside the cluster, you must configure a service of type LoadBalancer or NodePort.
Accepts Kubernetes service accounts for authentication for connections from within the cluster. To connect from outside the cluster, you must configure a different authentication method.
Caution
For production scenarios, you should use TLS and service accounts authentication to secure your IoT solution. For more information, see:
- Configure TLS with automatic certificate management to secure MQTT communication in MQTT broker
- Configure authentication in MQTT broker
- Expose Kubernetes services to external devices using port forwarding or a virtual switch with Azure Kubernetes Services Edge Essentials.
Before you begin, install or configure IoT Operations. Use the following options to test connectivity to MQTT broker with MQTT clients in a nonproduction environment.
Connect to the default listener inside the cluster
The first option is to connect from within the cluster. This option uses the default configuration and requires no extra updates. The following examples show how to connect from within the cluster using plain Alpine Linux and a commonly used MQTT client, using the service account and default root CA certificate.
First, create a file named client.yaml
with the following configuration:
apiVersion: v1
kind: ServiceAccount
metadata:
name: mqtt-client
namespace: azure-iot-operations
---
apiVersion: v1
kind: Pod
metadata:
name: mqtt-client
# Namespace must match MQTT broker BrokerListener's namespace
# Otherwise use the long hostname: aio-broker.azure-iot-operations.svc.cluster.local
namespace: azure-iot-operations
spec:
# Use the "mqtt-client" service account created from above
# Otherwise create it with `kubectl create serviceaccount mqtt-client -n azure-iot-operations`
serviceAccountName: mqtt-client
containers:
# Mosquitto and mqttui on Alpine
- image: alpine
name: mqtt-client
command: ["sh", "-c"]
args: ["apk add mosquitto-clients mqttui && sleep infinity"]
volumeMounts:
- name: broker-sat
mountPath: /var/run/secrets/tokens
- name: trust-bundle
mountPath: /var/run/certs
volumes:
- name: broker-sat
projected:
sources:
- serviceAccountToken:
path: broker-sat
audience: aio-internal # Must match audience in BrokerAuthentication
expirationSeconds: 86400
- name: trust-bundle
configMap:
name: azure-iot-operations-aio-ca-trust-bundle # Default root CA cert
Then, use kubectl
to deploy the configuration. It should only take a few seconds to start.
kubectl apply -f client.yaml
Once the pod is running, use kubectl exec
to run commands inside the pod.
For example, to publish a message to the broker, open a shell inside the pod:
kubectl exec --stdin --tty mqtt-client --namespace azure-iot-operations -- sh
Inside the pod's shell, run the following command to publish a message to the broker:
mosquitto_pub --host aio-broker --port 18883 --message "hello" --topic "world" --debug --cafile /var/run/certs/ca.crt -D CONNECT authentication-method 'K8S-SAT' -D CONNECT authentication-data $(cat /var/run/secrets/tokens/broker-sat)
The output should look similar to the following:
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'world', ... (5 bytes))
Client (null) sending DISCONNECT
The mosquitto client uses the service account token mounted at /var/run/secrets/tokens/broker-sat
to authenticate with the broker. The token is valid for 24 hours. The client also uses the default root CA cert mounted at /var/run/certs/ca.crt
to verify the broker's TLS certificate chain.
Tip
You can use kubectl
to download the default root CA certificate to use with other clients. For example, to download the default root CA certificate to a file named ca.crt
:
kubectl get configmap azure-iot-operations-aio-ca-trust-bundle -n azure-iot-operations -o jsonpath='{.data.ca\.crt}' > ca.crt
To subscribe to the topic, run the following command:
mosquitto_sub --host aio-broker --port 18883 --topic "world" --debug --cafile /var/run/certs/ca.crt -D CONNECT authentication-method 'K8S-SAT' -D CONNECT authentication-data $(cat /var/run/secrets/tokens/broker-sat)
The output should look similar to the following:
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending SUBSCRIBE (Mid: 1, Topic: world, QoS: 0, Options: 0x00)
Client (null) received SUBACK
Subscribed (mid: 1): 0
The mosquitto client uses the same service account token and root CA cert to authenticate with the broker and subscribe to the topic.
To remove the pod, run kubectl delete pod mqtt-client -n azure-iot-operations
.
Connect clients from outside the cluster
Since the default broker listener is set to ClusterIp service type, you can't connect to the broker from outside the cluster directly. To prevent unintentional disruption to communication between internal Azure IoT Operations components, we recommend keeping the default listener unmodified and dedicated for AIO internal communication. While it's possible to create a separate Kubernetes LoadBalancer service to expose the cluster IP service, it's better to create a separate listener with different settings, like more common MQTT port 1883 and 8883, to avoid confusion and potential security risks.
Node port
The easiest way to test connectivity is to use the NodePort service type in the listener. With that, you can use <nodeExternalIP>:<NodePort>
to connect like in Kubernetes documentation.
For example, to create a new broker listener with node port service type, service name aio-broker-nodeport
, and listening on port 1884 (node port 31884):
In the Azure portal, go to your IoT Operations instance.
Under Components, select MQTT Broker.
Select MQTT broker listener for NodePort > Create. You can only create one listener per service type. If you already have a listener of the same service type, you can add more ports to the existing listener.
Caution
Setting authentication to None and not configuring TLS turns off authentication and TLS for testing purposes only.
Enter the following settings:
Setting Value Name aio-broker-nodeport
Service name Leave empty or aio-broker-nodeport
Port 1884 Authentication Choose from existing or None Authorization Choose from existing or None Protocol Choose MQTT Node port 31884 Add TLS settings to the listener by selecting TLS > Add on the port. This step isn't required if you don't need TLS for testing. For more information, see BrokerListener.
Select Create to create the listener.
Note
By Kubernetes default, the node port number must be in the range 30000-32767.
Get the node's external IP address:
kubectl get nodes -o yaml | grep ExternalIP -C 1
The output should look similar to the following:
- address: 104.197.41.11
type: ExternalIP
allocatable:
--
- address: 23.251.152.56
type: ExternalIP
allocatable:
...
Use the external IP address and the node port to connect to the broker. For example, to publish a message to the broker:
mosquitto_pub --host <EXTERNAL_IP> --port 31884 --message "hello" --topic "world" --debug # Add authentication and TLS options matching listener settings
If there's no external IP in the output, you might be using a Kubernetes setup that doesn't expose the node's external IP address by default, like many setups of k3s, k3d, or minikube. In that case, you can access the broker with the internal IP along with the node port from machines on the same network. For example, to get the internal IP address of the node:
kubectl get nodes -o yaml | grep InternalIP -C 1
The output should look similar to the following:
- address: 172.19.0.2
type: InternalIP
allocatable:
Then, use the internal IP address and the node port to connect to the broker from a machine within the same cluster. If Kubernetes is running on a local machine, like with single-node k3s, you can often use localhost
instead of the internal IP address. If Kubernetes is running in a Docker container, like with k3d, the internal IP address corresponds to the container's IP address, and should be reachable from the host machine.
Load balancer
Another way to expose the broker to the internet is to use the LoadBalancer service type. This method is more complex and might require additional configuration, like setting up port forwarding.
For example, to create a new broker listener with load balancer service type, service name aio-broker-loadbalancer
, and listening on port 1883:
In the Azure portal, go to your IoT Operations instance.
Under Components, select MQTT Broker.
Select MQTT broker listener for NodePort > Create. You can only create one listener per service type. If you already have a listener of the same service type, you can add more ports to the existing listener.
Caution
Setting authentication to None and not configuring TLS turns off authentication and TLS for testing purposes only.
Enter the following settings:
Setting Value Name aio-broker-loadbalancer
Service name Leave empty or aio-broker-loadbalancer
Port 1883 Authentication Choose from existing or None Authorization Choose from existing or None Protocol Choose MQTT Add TLS settings to the listener by selecting TLS > Add on the port. This step isn't required if you don't need TLS for testing. For more information, see BrokerListener.
Select Create to create the listener.
Select Create to create the listener.
Get the external IP address for the broker's service:
kubectl get service aio-broker-loadbalancer --namespace azure-iot-operations
If the output looks similar to the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
aio-broker-loadbalancer LoadBalancer 10.x.x.x x.x.x.x 1883:30382/TCP 83s
This means that an external IP has been assigned to the load balancer service, and you can use the external IP address and the port to connect to the broker. For example, to publish a message to the broker:
mosquitto_pub --host <EXTERNAL_IP> --port 1883 --message "hello" --topic "world" --debug # Add authentication and TLS options matching listener settings
If the external IP is not assigned, you might need to use port forwarding or a virtual switch to access the broker.
Use port forwarding
With minikube, kind, and other cluster emulation systems, an external IP might not be automatically assigned. For example, it might show as Pending state.
To access the broker, forward the broker listener port to the host.
# Using aio-broker-loadbalancer service name and listener port 1883 as example kubectl port-forward --namespace azure-iot-operations service/aio-broker-loadbalancer <HOST_PORT>:1883
Leave the port forwarding command running in the terminal.
Connect to the broker at the host port with the same authentication and TLS configuration as the example without port forwarding.
For more information about minikube, see Use Port Forwarding to Access Applications in a Cluster
Port forwarding on AKS Edge Essentials
For Azure Kubernetes Services Edge Essentials, you need to perform a few additional steps. With AKS Edge Essentials, getting the external IP address might not be enough to connect to the broker. You might need to set up port forwarding and open the port on the firewall to allow traffic to the broker's service.
First, get the external IP address of the broker's load balancer listener:
kubectl get service broker-loadbalancer --namespace azure-iot-operations
Output should look similar to the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE broker-loadbalancer LoadBalancer 10.x.x.x 192.168.0.4 1883:30366/TCP 14h
Set up port forwarding to the
broker-loadbalancer
service on the external IP address192.168.0.4
and port1883
:netsh interface portproxy add v4tov4 listenport=1883 connectport=1883 connectaddress=192.168.0.4
Open the port on the firewall to allow traffic to the broker's service:
New-NetFirewallRule -DisplayName "AIO MQTT Broker" -Direction Inbound -Protocol TCP -LocalPort 1883 -Action Allow
Use the host's public IP address to connect to the MQTT broker.
For more information about port forwarding, see Expose Kubernetes services to external devices.
Access through localhost
Some Kubernetes distributions can expose MQTT broker to a port on the host system (localhost) as part of cluster configuration. Use this approach to make it easier for clients on the same host to access MQTT broker.
For example, to create a K3d cluster with mapping the MQTT broker's default MQTT port 1883 to localhost:1883
:
k3d cluster create --port '1883:1883@loadbalancer'
Or to update an existing cluster:
k3d cluster edit <CLUSTER_NAME> --port-add '1883:1883@loadbalancer'
Then, use localhost
and the port to connect to the broker. For example, to publish a message to the broker:
mosquitto_pub --host localhost --port 1883 --message "hello" --topic "world" --debug # Add authentication and TLS options matching listener settings
Only turn off TLS and authentication for testing
The reason that MQTT broker uses TLS and service accounts authentication by default is to provide a secure-by-default experience that minimizes inadvertent exposure of your IoT solution to attackers. You shouldn't turn off TLS and authentication in production. Exposing MQTT broker to the internet without authentication and TLS can lead to unauthorized access and even DDOS attacks.
Warning
If you understand the risks and need to use an insecure port in a well-controlled environment, you can turn off TLS and authentication for testing purposes by removing the tls
and authenticationRef
settings from the listener configuration.
In the Azure portal, go to your IoT Operations instance.
Under Components, select MQTT Broker.
Select MQTT broker listener for NodePort or MQTT broker listener for LoadBalancer > Create. You can only create one listener per service type. If you already have a listener of the same service type, you can add more ports to the existing listener.
Caution
Setting authentication to None and not configuring TLS turns off authentication and TLS for testing purposes only.
Enter the following settings:
Setting Value Name Enter a name for the listener Service name Enter a service name Port Enter a port number Authentication Choose None Authorization Choose None Protocol Choose MQTT Node port Enter a number between 30000-32767 if using node port Select Create to create the listener.