Rediger

Del via


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 an MQTT broker with MQTT clients in a nonproduction environment.

By default, an MQTT broker:

Caution

For production scenarios, use TLS and service accounts authentication to secure your IoT solution. For more information, see:

Before you begin, install or configure Azure IoT Operations. Use the following options to test connectivity to the 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 by using plain Alpine Linux and a commonly used MQTT client by using the service account and default root Certificate Authority (CA) certificate.

Download the mqtt-client.yaml deployment from the GitHub sample repository.

Important

Don't use the MQTT client in production. The client is for testing purposes only.

wget https://raw.githubusercontent.com/Azure-Samples/explore-iot-operations/main/samples/quickstarts/mqtt-client.yaml -O mqtt-client.yaml

Apply the deployment file with kubectl:

kubectl apply -f mqtt-client.yaml
pod/mqtt-client created

After 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 example:

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 certificate 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 example:

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 certificate 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

Because the default broker listener is set to the ClusterIp service type, you can't connect to the broker from outside the cluster directly. To prevent unintentional disruption to communication between internal IoT Operations components, we recommend that you keep the default listener unmodified and dedicated for IoT Operations internal communication. Although 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 ports 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 method, you can use <nodeExternalIP>:<NodePort> to connect as shown in the Kubernetes documentation.

For example, to create a new broker listener with the NodePort service type, service name aio-broker-nodeport, and listening on port 1884 (node port 31884), follow these steps.

  1. In the Azure portal, go to your IoT Operations instance.

  2. Under Components, select MQTT Broker.

  3. Select MQTT broker listener for NodePort > Create. You can create only 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 use aio-broker-nodeport.
    Port 1884
    Authentication Choose from existing or None.
    Authorization Choose from existing or None.
    Protocol Choose MQTT.
    Node port 31884
  4. 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.

  5. Select Create to create the listener.

Note

By Kubernetes default, the node port number must be in the range of 30000 to 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 example:

    - 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 example:

    - 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 more configuration, like setting up port forwarding.

For example, to create a new broker listener with the LoadBalancer service type, service name aio-broker-loadbalancer, and listening on port 1883, follow these steps.

  1. In the Azure portal, go to your IoT Operations instance.

  2. Under Components, select MQTT Broker.

  3. Select MQTT broker listener for NodePort > Create. You can create only 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 use aio-broker-loadbalancer.
    Port 1883
    Authentication Choose from existing or None.
    Authorization Choose from existing or None.
    Protocol Choose MQTT.
  4. 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.

  5. Select Create to create the listener.

  6. 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 example:

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

Then an external IP was assigned to the load balancer service. 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 isn't 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, the state might show as Pending.

  1. 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
    
  2. Leave the port forwarding command running in the terminal.

  3. 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 AKS Edge Essentials, you need to perform a few more 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.

  1. 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 example:

    NAME                    TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
    broker-loadbalancer     LoadBalancer   10.x.x.x       192.168.0.4   1883:30366/TCP   14h
    
  2. Set up port forwarding to the broker-loadbalancer service on the external IP address 192.168.0.4 and port 1883:

    netsh interface portproxy add v4tov4 listenport=1883 connectport=1883 connectaddress=192.168.0.4
    
  3. 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
    
  4. 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 the 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 the MQTT broker.

For example, to create a k3d cluster that maps 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 the 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 the MQTT broker to the internet without authentication and TLS can lead to unauthorized access and even distributed denial-of-service 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.

  1. In the Azure portal, go to your IoT Operations instance.

  2. Under Components, select MQTT Broker.

  3. Select MQTT broker listener for NodePort or MQTT broker listener for LoadBalancer > Create. You can create only 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 to 32767 if using node port.
  4. Select Create to create the listener.