你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将 Azure IoT MQ 预览版 MQTT 桥云连接器连接到其他 MQTT 代理

重要

Azure IoT 操作预览版(由 Azure Arc 启用)当前处于预览状态。 不应在生产环境中使用此预览版软件。

有关 beta 版本、预览版或尚未正式发布的版本的 Azure 功能所适用的法律条款,请参阅 Microsoft Azure 预览版的补充使用条款

可以使用 Azure IoT MQ 预览版 MQTT 桥连接到 Azure 事件网格或其他 MQTT 代理。 MQTT 桥接是将两个 MQTT 代理连接在一起的过程,以便它们交换消息。

  • 当两个代理被桥接时,一个代理上发布的消息会自动转发到另一个代理,反之亦然。
  • MQTT 桥接有助于创建相互通信的 MQTT 代理网络,并根据需要添加其他代理来扩展 MQTT 基础结构。
  • MQTT 桥接适用于多个物理位置、在边缘和云之间共享 MQTT 消息和主题,或者想要将 MQTT 与其他消息系统集成时。

若要桥接到另一个代理,Azure IoT MQ 必须知道远程代理终结点 URL、MQTT 版本、如何进行身份验证,以及要映射的主题。 为了以 Kubernetes 本机方式最大化可组合性和灵活性,这些值需配置为自定义 Kubernetes 资源 (CRD):MqttBridgeConnectorMqttBridgeTopicMap。 本指南介绍如何使用这些资源创建 MQTT 桥连接器。

  1. 创建一个 YAML 文件,该文件定义 MqttBridgeConnector 资源。 可以使用 YAML 示例,但请确保更改 namespace 以匹配已部署 Azure IoT MQ 的 YAML,以及与远程代理终结点 URL 匹配的 remoteBrokerConnection.endpoint

  2. 创建一个 YAML 文件,该文件定义 MqttBridgeTopicMap 资源。 可以使用示例 YAML,但请确保更改 namespace 以匹配已部署 Azure IoT MQ 的 YAML,以及更改 mqttBridgeConnectorRef 以匹配在上一步中创建的 MqttBridgeConnector 资源的名称。

  3. 使用 kubectl apply -f <filename> 部署 MQTT 桥连接器和主题映射。

    $ kubectl apply -f my-mqtt-bridge.yaml 
    mqttbridgeconnectors.mq.iotoperations.azure.com my-mqtt-bridge created
    $ kubectl apply -f my-topic-map.yaml
    mqttbridgetopicmaps.mq.iotoperations.azure.com my-topic-map created
    

部署后,使用 kubectl get pods 验证消息是否开始流向终结点和从终结点流出。

Configure MqttBridgeConnector

MqttBridgeConnector 资源定义可以与远程代理通信的 MQTT 桥连接器。 它包括以下组件:

  • 一个或多个 MQTT 桥连接器实例。 每个实例都是运行 MQTT 桥连接器的容器。
  • 远程代理连接。
  • 可选的本地代理连接。

以下示例演示了一个用于桥接到 Azure 事件网格 MQTT 代理的示例配置。 它使用系统分配的托管标识进行身份验证和 TLS 加密。

apiVersion: mq.iotoperations.azure.com/v1beta1
kind: MqttBridgeConnector
metadata:
  name: my-mqtt-bridge
  namespace: azure-iot-operations
spec:
  image: 
    repository: mcr.microsoft.com/azureiotoperations/mqttbridge 
    tag: 0.4.0-preview
    pullPolicy: IfNotPresent
  protocol: v5
  bridgeInstances: 1
  clientIdPrefix: factory-gateway-
  logLevel: debug
  remoteBrokerConnection:
    endpoint: example.westeurope-1.ts.eventgrid.azure.net:8883
    tls:
      tlsEnabled: true
    authentication:
      systemAssignedManagedIdentity:
        audience: https://eventgrid.azure.net
  localBrokerConnection:
    endpoint: aio-mq-dmqtt-frontend:8883
    tls:
      tlsEnabled: true
      trustedCaCertificateConfigMap: aio-ca-trust-bundle-test-only
    authentication:
      kubernetes: {}

下表描述了 MqttBridgeConnector 资源中的字段:

字段 必须 说明
图像 Kafka 连接器的图像。 可以指定映像的 pullPolicyrepositorytag。 上一示例中显示了合适的值。
protocol MQTT 协议版本。 可以是 v5v3。 请参阅 MQTT v3.1.1 支持
bridgeInstances 桥连接器的实例数。 默认为 1。 请参阅实例数
clientIdPrefix 动态生成的客户端 ID 的前缀。 默认为无前缀。 请参阅客户端 ID 配置
logLevel 日志级别。 可以是 debuginfo。 默认为 info
remoteBrokerConnection 要桥接到的远程代理的连接详细信息。 请参阅远程代理连接
localBrokerConnection 要桥接到的本地代理的连接详细信息。 显示值的默认值。 请参阅本地代理连接

MQTT v3.1.1 支持

可将桥连接器配置为将 MQTT v3.1.1 与 Azure IoT MQ 的本地代理连接和远程代理连接配合使用。 但是,如果远程代理不支持共享订阅,则这会中断共享订阅。 如果计划使用共享订阅,请将其保留为默认的 v5

实例数

若要实现高可用性和规模,请将 MQTT 桥连接器配置为使用多个实例。 消息流和路由在不同实例之间自动均衡。

spec:
  bridgeInstances: 2

客户端 ID 配置

Azure IoT MQ 使用指定的前缀为每个 MqttBridgeConnector 客户端生成客户端 ID,格式为 {clientIdPrefix}-{routeName}。 对于 Azure IoT MQ 来说,此客户端 ID 对于缓解消息丢失并避免与现有客户端 ID 发生冲突非常重要,因为 MQTT 规范仅允许每个客户端 ID 建立一个连接。

例如,如果 clientIdPrefix: "client-",并且主题映射中有两个 routes ,则客户端 ID 为:client-route1client-route2

远程代理连接

remoteBrokerConnection 字段定义桥接到远程代理的连接详细信息。 本部分包含以下字段:

字段 必须 说明
endpoint 具有端口的远程代理终结点 URL。 例如 example.westeurope-1.ts.eventgrid.azure.net:8883
tls 指定是否使用 TLS 和受信任的 CA 证书加密连接。 请参阅 TLS 支持
authentication 用于代理的 Azure IoT MQ 的身份验证详细信息。 必须是以下其中一个值:系统分配的托管标识或 X.509。 请参阅身份验证
protocol 用于定义使用 MQTT 或通过 WebSocket 使用 MQTT 的字符串值。 可以是 mqttwebSocket。 默认为 mqtt

身份验证

身份验证字段定义用于远程代理的 Azure IoT MQ 的身份验证方法。 本部分包含以下字段:

字段 必须 说明
systemAssignedManagedIdentity 使用系统分配的托管标识进行身份验证。 请参阅托管标识
x509 使用 X.509 证书进行身份验证。 请参阅 X.509

托管的标识

systemAssignedManagedIdentity 字段包含以下字段:

字段 必须 说明
audience 令牌的受众。 如果使用托管标识则需要。 对于事件网格,它是 https://eventgrid.azure.net

如果 Azure IoT MQ 部署为 Azure Arc 扩展,则默认情况下,它会获取系统分配的托管标识。 应使用 Azure IoT MQ 的托管标识来与 Azure 资源(包括事件网格 MQTT 代理)进行交互,因为它允许你无需进行凭据管理并保持高可用性。

若要使用托管标识对 Azure 资源进行身份验证,请先将适当的 Azure RBAC 角色(如 EventGrid TopicSpaces Publisher)分配给 Arc 提供的 Azure IoT MQ 托管标识。

然后,指定 MQTTBridgeConnector 并使用托管标识作为身份验证方法:

spec:
  remoteBrokerConnection:
    authentication:
      systemAssignedManagedIdentity:
        audience: https://eventgrid.azure.net

使用托管标识时,客户端 ID 不可配置,相当于 Azure 中的 Azure IoT MQ Azure Arc 扩展 Azure 资源管理器资源 ID。

系统分配的托管标识由 Azure Arc 提供。与托管标识关联的证书必须至少每 90 天续订一次,以避免进行手动恢复过程。 要了解详细信息,请参阅如何处理过期的已启用 Azure Arc 的 Kubernetes 资源?

X.509

x509 字段包括以下字段:

字段 必须 说明
secretName Kubernetes 机密包含客户端证书和私钥。 可以使用 Azure Key Vault 管理 Azure IoT MQ 的机密,而不是 Kubernetes 机密。 若要了解详细信息,请参阅使用 Azure Key Vault 或 Kubernetes 机密管理机密

许多 MQTT 代理(如事件网格)都支持 X.509 身份验证。 Azure IoT MQ 的 MQTT 桥可以提供客户端 X.509 证书并协商 TLS 通信。 使用 Kubernetes 机密存储 X.509 客户端证书、私钥和中间 CA。

kubectl create secret generic bridge-client-secret \
--from-file=client_cert.pem=mqttbridge.pem \
--from-file=client_key.pem=mqttbridge.key \
--from-file=client_intermediate_certs.pem=intermediate.pem

并使用 secretName 引用它:

spec:
  remoteBrokerConnection:
    authentication:
      x509:
        secretName: bridge-client-cert

本地代理连接

localBrokerConnection 字段定义桥接到远程代理的连接详细信息。

字段 必须 说明
endpoint 具有端口的远程代理终结点 URL。
tls 指定是否使用 TLS 和受信任的 CA 证书加密连接。 请参阅 TLS 支持
authentication 用于代理的 Azure IoT MQ 的身份验证详细信息。 唯一受支持的方法是 Kubernetes 服务帐户令牌 (SAT)。 若要使用 SAT,请指定 kubernetes: {}

默认情况下,IoT MQ 部署在命名空间 azure-iot-operations,且启用了 TLS 和 SAT 身份验证。

然后,必须将 MqttBridgeConnector 本地代理连接设置配置为相匹配的值。 MqttBridgeConnector 的部署 YAML 必须拥有与 remoteBrokerConnection 相同级别的 localBrokerConnection。 例如,将 TLS 与 SAT 身份验证配合使用,以便与默认的 IoT MQ 部署匹配:

spec:
  localBrokerConnection:
    endpoint: aio-mq-dmqtt-frontend:8883
    tls:
      tlsEnabled: true
      trustedCaCertificateConfigMap: aio-ca-trust-bundle-test-only
    authentication:
      kubernetes: {}

此处,trustedCaCertifcateName 是 Azure IoT MQ 根 CA 的 ConfigMap,类似远程代理根 CA 的 ConfigMap。 默认根 CA 存储在名为 aio-ca-trust-bundle-test-only 的 ConfigMap 中。

要详细了解如何获取根 CA,请参阅《使用自动证书管理配置 TLS,以保护 MQTT 通信》。

TLS 支持

tls 字段定义远程或本地代理连接的 TLS 配置。 本部分包含以下字段:

字段 必须 说明
tlsEnabled 是否启用了 TLS。
trustedCaCertificateConfigMap 连接到代理时要信任的 CA 证书。 如果启用了 TLS 则需要。

远程和本地代理连接均可使用 TLS 加密支持。

  • 对于远程代理连接:如果启用了 TLS,则应将受信任的 CA 证书指定为 Kubernetes ConfigMap 引用。 否则,TLS 握手可能会失败,除非远程终结点广受信任,受信任的 CA 证书已存在于 OS 证书存储中。 例如,事件网格使用广受信任的 CA 根,因此不需要指定。
  • 对于本地(Azure IoT MQ)代理连接:如果为 Azure IoT MQ 代理侦听器启用了 TLS,则颁发侦听器服务器证书的 CA 证书应指定为 Kubernetes ConfigMap 引用。

指定受信任的 CA 时,请创建一个包含 CA 公共部分的 ConfigMap,并在 trustedCaCertificateConfigMap 属性中指定 configmap 名称。 例如:

kubectl create configmap client-ca-configmap --from-file ~/.step/certs/root_ca.crt

配置 MqttBridgeTopicMap

MqttBridgeTopicMap 资源定义本地和远程代理之间的主题映射。 它必须与 MqttBridgeConnector 资源一起使用。 它包括以下组件:

  • 要链接到的 MqttBridgeConnector 资源的名称。
  • 用于桥接的路由列表。
  • 可选的共享订阅配置。

MqttBridgeConnector 可以使用多个与其链接的 MqttBridgeTopicMaps。 部署 MqttBridgeConnector 资源时,Azure IoT MQ 操作员将开始扫描与它关联的任何 MqttBridgeTopicMaps 的命名空间,并自动管理 MqttBridgeConnector 实例之间的消息流。 然后,部署完成后,MqttBridgeTopicMap 将与 MqttBridgeConnector 相关联。 每个 MqttBridgeTopicMap 只能与一个 MqttBridgeConnector 链接。

以下示例显示了一个 MqttBridgeTopicMap 配置,用于将消息从远程主题 remote-topic 桥接到本地主题 local-topic

apiVersion: mq.iotoperations.azure.com/v1beta1
kind: MqttBridgeTopicMap
metadata:
  name: my-topic-map
  namespace: azure-iot-operations 
spec:
  mqttBridgeConnectorRef: my-mqtt-bridge
  routes:
    - direction: remote-to-local
      name: first-route
      qos: 0
      source: remote-topic
      target: local-topic
      sharedSubscription:
        groupMinimumShareNumber: 3
        groupName: group1
    - direction: local-to-remote
      name: second-route
      qos: 1
      source: local-topic
      target: remote-topic

下表描述了 MqttBridgeTopicMap 资源中的字段:

字段 必须 说明
mqttBridgeConnectorRef 要链接的 MqttBridgeConnector 资源的名称。
routes 用于桥接的路由列表。 有关详细信息,请参阅《路由》。

路由

MqttBridgeTopicMap 可以有多个路由。 routes 字段定义路由列表。 本部分包含以下字段:

字段 必须 说明
direction 消息流的方向。 可以是 remote-to-locallocal-to-remote。 有关详细信息,请参阅《数据流》。
name 路由的名称。
qos MQTT 服务质量 (QoS)。 默认值为 1。
source 源 MQTT 主题。 可以有通配符,如 #+。 请参阅《源主题中的通配符》。
目标 目标 MQTT 主题。 不能有通配符。 如果未指定,则它与源相同。 请参阅《目标中的参考源主题》。
sharedSubscription 共享订阅配置。 激活已配置数量的客户端以增加规模。 有关详细信息,请参阅《共享订阅》。

Direction

例如,如果方向是本地到远程,Azure IoT MQ 会将指定的本地主题上的所有消息发布到远程主题:

routes:
  - direction: local-to-remote
    name: "send-alerts"
    source: "alerts"
    target: "factory/alerts"

如果方向相反,Azure IoT MQ 会从远程代理接收消息。 此处,将省略目标,远程代理上 commands/factory 主题中的所有消息都将在本地发布到同一主题中。

routes:
  - direction: remote-to-local
    name: "receive-commands"
    source: "commands/factory"

源主题中的通配符

若要从非静态主题进行桥接,请使用通配符定义主题模式的匹配方式和主题名称转换规则。 例如,若要桥接 telemetry 下所有子主题中的所有消息,请使用多级 # 通配符:

routes:
  - direction: local-to-remote
    name: "wildcard-source"
    source: "telemetry/#"
    target: "factory/telemetry"

在此示例中,如果消息发布到 telemetry 下的任何主题(如 telemetry/furnace/temperature)下,则 Azure IoT MQ 会将消息发布到静态 factory/telemetry 主题下的远程桥接代理。

对于单级主题通配符,请改用 +,如 telemetry/+/temperature

MQTT 桥连接器必须知道目标代理中的确切主题,即远程或 Azure IoT MQ,且没有任何歧义。 通配符仅作为 source 主题的一部分提供。

目标中的参考源主题

若要引用整个源主题,请完全省略路由中的目标主题配置。 支持通配符。

例如,在主题 my-topic/# 下发布的任何消息(如 my-topic/foomy-topic/bar)都桥接到同一主题下的远程代理:

routes:
  - direction: local-to-remote
    name: "target-same-as-source"
    source: "my-topic/#"
    # No target

不支持源主题引用的其他方法。

共享订阅

sharedSubscription 字段定义路由的共享订阅配置。 本部分包含以下字段:

字段 必须 说明
groupMinimumShareNumber 要用于共享订阅的客户端数。
groupName 共享订阅组名称。

共享订阅可帮助 Azure IoT MQ 为 MQTT 桥创建更多客户端。 可以为每个路由设置不同的共享订阅。 Azure IoT MQ 订阅来自源主题的消息,并使用轮循机制一次将其发送到一个客户端。 然后,相应客户端会将消息发布到桥接代理。

例如,如果使用共享订阅设置路由,并将 groupMinimumShareNumber 设置为 3

routes:
    - direction: local-to-remote
      qos: 1
      source: "shared-sub-topic"
      target: "remote/topic"
      sharedSubscription:
        groupMinimumShareNumber: 3
        groupName: "sub-group"

无论实例数如何,Azure IoT MQ 的 MQTT 桥都会创建三个订阅服务器客户端。 只有一个客户端可从 $share/sub-group/shared-sub-topic 获取每条消息。 然后,同一客户端在主题 remote/topic 下将消息发布到桥接远程代理。 下一条消息将转到下一个客户端。

这有助于平衡多个 ID 不同的客户端之间的消息流量。 如果你的桥接代理限制每个客户端可以发送的消息数,这非常有用。

Azure 事件网格 MQTT 代理支持

为了最大程度地减少凭据管理,建议使用系统分配的托管标识和 Azure RBAC 桥接 Azure IoT MQ 与 Azure 事件网格 MQTT 代理功能

有关端到端教程,请参阅教程:在 Azure IoT MQ 预览版和 Azure 事件网格之间配置 MQTT 桥

使用托管标识连接到事件网格 MQTT 代理

首先,使用 az k8s-extension show,找到 Azure IoT MQ Arc 扩展的主体 ID。 记下 identity.principalId 的输出值,应类似于 abcd1234-5678-90ab-cdef-1234567890ab

az k8s-extension show --resource-group <RESOURCE_GROUP> --cluster-name <CLUSTER_NAME> --name mq --cluster-type connectedClusters --query identity.principalId -o tsv

然后,使用 Azure CLI 将角色分配给 Azure IoT MQ Arc 扩展托管标识。 请务必将 <MQ_ID> 替换为在上一步中找到的主体 ID。 例如,若要分配 EventGrid TopicSpaces Publisher 角色:

az role assignment create --assignee <MQ_ID> --role 'EventGrid TopicSpaces Publisher' --scope /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.EventGrid/namespaces/<EVENT_GRID_NAMESPACE>

提示

若要优化最小特权原则,可以将角色分配给主题空间,而不是整个事件网格命名空间。 若要了解详细信息,请参阅《事件网格 RBAC》和《主题空间》。

然后,创建 MQTTBridgeConnector,并选择托管标识作为身份验证方法。 创建 MqttBridgeTopicMaps,并使用 kubectl 部署 MQTT 桥。

每个身份验证名称的最大客户端会话数

如果 bridgeInstances 设置为高于 1,请配置事件网格 MQTT 代理配置>每个身份验证名称的最大客户端会话数 以匹配实例数。 此配置可防止“错误 151 配额超过”等问题。

连接限制

如果无法使用托管标识,请在设计设置时牢记事件网格 MQTT 代理的连接限制。 发布时,连接的每个方向限制为 100 条消息/秒。 若要增加 MQTT 桥吞吐量,请使用共享订阅增加为每个路由提供服务的客户端数。

从另一个代理桥接到 Azure IoT MQ 预览版

Azure IoT MQ 是合规的 MQTT 代理,其他代理可以使用相应的身份验证和授权凭据桥接它。 例如,请参阅《MQTT 桥文档》,了解 HiveMQVerneMQEMQX,以及 Mosquitto