I want to run an MQTT broker and two clients inside a Kubernetes cluster and be able to send messages back and forth.
Therefore I wanted to use the eclipse-mosquitto Docker image and two custom clients that use the paho-mqtt Python library:
import paho.mqtt.client as mqtt
import time
broker_address = "localhost"
port = 1883
client_id = "client1"
counter = 0
def on_message(client, userdata, message):
global counter
counter += 1
print(f"Client 1 received: {message.payload.decode()} - counter: {counter}")
time.sleep(1)
client.publish("test/topic", f"Client 1: {counter}")
client = mqtt.Client(client_id)
client.on_message = on_message
client.connect(broker_address, port=port)
client.subscribe("test/topic")
client.loop_start()
while True:
client.publish("test/topic", f"Client 1: {counter}")
This works perfectly fine in Docker when putting all of them on the same Docker network. The broker container is named mosquitto-broker
which can then be found by the clients. They subscribe to a topic and publish messages on it.
However, recreating the same use-case on a Kubernetes cluster seems to require a different approach, since K8s has an own networking ecosystem and the broker_address
will be different. Since my docker images mqtt_client_1
and mqtt_client_2
are local, I set the imagePullPolicy
to Never
.
apiVersion: apps/v1
kind: Deployment
metadata:
name: mqtt-deployment
labels:
app: mqtt
spec:
replicas: 1
selector:
matchLabels:
app: mqtt
template:
metadata:
labels:
app: mqtt
spec:
containers:
- name: eclipse-mosquitto
image: eclipse-mosquitto
imagePullPolicy: IfNotPresent
ports:
- containerPort: 1883
volumeMounts:
- name: mosquitto-config
mountPath: /mosquitto/config/mosquitto.conf
subPath: mosquitto.conf
- name: mqtt-client1
image: mqtt_client_1
imagePullPolicy: Never
command:
- python
- /app/client1.py
- name: mqtt-client2
image: mqtt_client_2
imagePullPolicy: Never
command:
- python
- /app/client2.py
volumes:
- name: mosquitto-config
configMap:
name: mosquitto-config
I also use a configmap:
apiVersion: v1
kind: ConfigMap
metadata:
name: mosquitto-config
data:
mosquitto.conf: |-
listener 1883
allow_anonymous true
However, the client pod exits with Name or service not known
when trying to connect on the broker_address
and port
. How can I make client and server communicate via MQTT on the same network?
You will need to include a kubernetes Service description that points to the Deployment.
The name of the service will then be the hostname you use in the client code to connect to the broker.
e.g.
apiVersion: v1
kind: Service
metadata:
name: mqtt-broker
spec:
selector:
app: mqtt
ports:
- name: mqtt-native
targetPort: 1883
port: 1883
You would use mqtt-broker
as the hostname (or mqtt-broker.<namespace>
for cross namespace accesss)