我无法通过 Kubernetes(RPI 集群上的 K3s)连接到 MQTT

I cant connect to MQTT over Kubernetes (K3s on RPI Cluster)

大家好,我遇到了一些障碍。我能够成功 运行 我的 yaml 文件并为 MQTT 获取容器 运行ning。问题是当我尝试连接到它时,它就是不起作用。这是我的 YAML 文件

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kompose.cmd: kompose convert
    kompose.version: 1.22.0 (955b78124)
  creationTimestamp: null
  labels:
    io.kompose.service: mqtt
  name: mqtt
  namespace: mqtt
spec:
  replicas: 2
  selector:
    matchLabels:
      io.kompose.service: mqtt
  strategy:
    type: Recreate
  template:
    metadata:
      annotations:
        kompose.cmd: kompose convert
        kompose.version: 1.22.0 (955b78124)
      creationTimestamp: null
      labels:
        io.kompose.service: mqtt
    spec:
      containers:
        - image: eclipse-mosquitto
          name: mqtt
          ports:
            - containerPort: 1883
            - containerPort: 9001
          resources: {}
          volumeMounts:
            - name: mosquitto-config-file
              mountPath: /mosquitto/config
            - name: mosquitto-pwfile
              mountPath: /mosquitto/config/pwfile
            - name: mqtt-data-pvc
              mountPath: /mosquitto/data
            - name: mqtt-log-pvc
              mountPath: /mosquitto/log
      restartPolicy: Always
      volumes:
        - name: mosquitto-config-file
          configMap:
            name: mosquitto-config
        - name: mosquitto-pwfile
          secret:
            secretName: mosquitto-pwfile
        - name: mqtt-data-pvc
          persistentVolumeClaim:
            claimName: mqtt-data-pvc
        - name: mqtt-log-pvc
          persistentVolumeClaim:
            claimName: mqtt-log-pvc
status: {}
---
apiVersion: v1
kind: Service
metadata:
  name: mqtt
  namespace: mqtt
spec:
  ports:
    - name: "1883"
      port: 1883
      targetPort: 1883
    - name: "9001"
      port: 9001
      targetPort: 9001
  selector:
    io.kompose.service: mqtt
status:
  loadBalancer: {}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mosquitto-config
  namespace: mqtt
data:
  mosquitto.conf: |

    persistence true
    persistence_location /mosquitto/data
    log_dest file /mosquitto/log/mosquitto.log

    listener 1883
    protocol mqtt

    listener 9001
    protocol websockets 

    allow_anonymous false
    password_file /mosquitto/config/pwfile/pwfile
---
apiVersion: v1
kind: Secret
metadata:
  name: mosquitto-pwfile
  namespace: mqtt
type: Opaque
data:
  pwfile: |
    <BASE64 USERNAME:PW>
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mosquitto-data-pv
  namespace: mqtt
spec:
  capacity:
    storage: 100Mi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-path
  local:
    path: /home/pi/Software/mqtt/storage/mosquitto/data
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - masternode
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mqtt-data-pvc
  namespace: mqtt
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
status: {}
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mosquitto-log-pv
  namespace: mqtt
spec:
  capacity:
    storage: 100Mi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-path
  local:
    path: /home/pi/Software/mqtt/storage/mosquitto/log
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - masternode
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mqtt-log-pvc
  namespace: mqtt
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
status: {}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mqtt-ingress
  namespace: mqtt
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  rules:
  - host: mqtt.local
    http:
      paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: mqtt
              port: 
                number: 1883

当我检查我的容器是否 运行ning 时,它们 运行ning 正常。当我检查日志时,它显示以下内容

1618785757: mosquitto version 2.0.10 starting
1618785757: Config loaded from /mosquitto/config/mosquitto.conf.
1618785757: Opening ipv4 listen socket on port 1883.
1618785757: Opening ipv6 listen socket on port 1883.
1618785757: Opening websockets listen socket on port 9001.
1618785757: mosquitto version 2.0.10 running

我尝试在端口 1883 上连接 mqtt.local(根据入口),但日志没有更新,它只是说使用我的 iPad 应用连接

如果我在浏览器上访问 mqtt.local,日志会更新(我相信他们正在使用 websockets) 它显示以下内容

1618786368: Client <unknown> disconnected due to protocol error.
1618786368: New connection from 10.42.1.3:48912 on port 1883.
1618786368: Client <unknown> disconnected due to protocol error.
1618786368: New connection from 10.42.1.3:57298 on port 1883.
1618786368: Client <unknown> disconnected due to protocol error.

我会说实话。我很困惑。十几次确认用户名和密码。如果有人想分享一些想法,请敞开心扉。提前致谢

您的 Ingress 声明指向端口 1883,它是 运行 基于 TCP 的本机 MQTT。

Ingress 设置一个指向该服务的 HTTP 反向代理,因为 MQTT 不是 HTTP,所以这将不起作用。

正如评论中所指出的,一种选择是将 Ingress 更改为指向端口 9001,这是代理上的 WebSocket 侦听器

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mqtt-ingress
  namespace: mqtt
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  rules:
  - host: mqtt.local
    http:
      paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: mqtt
              port: 
                number: 9001

然后您将能够连接任何支持 MQTT over Websockets 的 MQTT 客户端,因为该协议是通过 HTTP 引导的。

还值得指出的是,Ingress 反向代理将在端口 80 上公开此路由。

唯一的其他连接方式是直接连接到作为 运行 MQTT 代理的集群节点。但这意味着将 ServiceType 更改为 NodePort 或 LoadBalancer 并映射外部 IP 地址。

我刚刚检查了上面的 post,我猜问题是“应用”的顺序 - 如果 kubectl 应用是使用上面的 yaml 文件创建的,那么首先加载部署,然后加载 configMap (s) 稍后。必须首先加载 configMap,以便部署组件可以使用它们。