如何使用Istio在Kubernetes上运行Mosquitto?

问题描述

订阅和发布到运行在Kubernetes集群上的Mosquitto服务器时遇到麻烦。

我知道我的服务和吊舱正在运行。我可以使用mosquitto服务作为主机从集群内部进行订阅和发布。

我还有一个正常工作的HTTPS网关,因此我可以从外部访问https://mosquittourl.com.br,并且可以看到它到达了端口1883上的mosquitto容器。容器日志:

New connection from 127.0.0.1 on port 1883.
Client <unkNown> disconnected due to protocol error.

我猜这是预期的行为。因为我通过https而不是mqtt访问它。

现在,我无法使用以下方式连接到容器

$ mosquitto_pub --url mqtt://mosquittourl.com.br:<port>/test

如何正确设置Istio资源,以便可以订阅和发布到mosquitto服务器?有没有一种方法可以配置Istio接受mqtt请求并将其重定向到我的mosquitto服务?

解决方法

我最近能够设置 Istio 以将 TLS 加密的 MQTT 连接路由到 Mosquitto 在 Kubernetes 的容器中运行。您应该使用 TLS 作为 Istio Gateway 中端口的 protocol。最终,Istio 可能会像支持 gRPC 和 Mongo 一样支持 MQTT,但现在您需要使用 TCP 来处理未加密的 MQTT 流量,并使用 TLS 来确保安全的 MQTT 连接。

您需要确保正确配置才能使其正常工作。

  1. Istio 操作员配置文件 yaml 文件

    对于为 Istio 配置主负载均衡器的 IstioOperator,您需要确保设置正确的端口。对于安全的 MQTT 流量,即 8883(从技术上讲,您可以使用任何端口,但 8883 是默认端口)。

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    accessLogFile: /dev/stdout
  components:
    egressGateways:
      - name: istio-egressgateway
        enabled: true
        k8s:
          resources:
            requests:
              cpu: 10m
              memory: 40Mi

    ingressGateways:
      - name: istio-ingressgateway
        enabled: true
        k8s:
          resources:
            requests:
              cpu: 10m
              memory: 40Mi
          service:
            ports:
              - port: 15021
                targetPort: 15021
                name: status-port
              - port: 31400
                targetPort: 31400
                name: tcp
                # This is the port where sni routing happens
              - port: 15443
                targetPort: 15443
                name: tls
              - port: 8883
                targetPort: 8883
                name: mqtt-secure

    pilot:
      k8s:
        env:
          - name: PILOT_TRACE_SAMPLING
            value: "100"
        resources:
          requests:
            cpu: 10m
            memory: 100Mi

  values:
    global:
      proxy:
        resources:
          requests:
            cpu: 10m
            memory: 40Mi

    pilot:
      autoscaleEnabled: false

    gateways:
      istio-egressgateway:
        autoscaleEnabled: false
      istio-ingressgateway:
        autoscaleEnabled: false
        runAsRoot: true
  1. Istio 网关 yaml 文件

这里的重要部分是确保您指定您在 Kubernetes 机密中已有的 SSL 证书的名称,并使用您在 IstioOperator 中所做的相同端口,并确保协议是 TLS。 tls: 块告诉网关使用指定的 SSL 证书进行 TLS 终止。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-mqtt-ssl-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
    - port:
        number: 8883
        name: mqtt-secure
        protocol: TLS
      hosts:
        - "*"
      tls:
        credentialName: cert-my.certname.com
        mode: SIMPLE
        privateKey: sds
        serverCertificate: sds
  1. Istio 虚拟服务 yaml 文件

最后一步是设置 Istio 虚拟服务,该服务从 Istio 网关获取流量并将其路由到正确的 Pod。更新目标中的 pod 名称。另一方面是匹配 8883 端口,并将流量重新路由到 1883 端口上的 mosquitto,因为流量已经在 Istio 网关中被 TLS 终止。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-mqtt-vs
spec:
  hosts:
    - "*"
  gateways:
    - my-mqtt-ssl-gateway
  tcp:
    - match:
        - port: 8883
      route:
        - destination:
            host: my-mqtt-broker-pod-name
            port:
              number: 1883