你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
教程:在嵌套的 IoT Edge 层次结构上部署连接注册表
在本教程中,你将使用 Azure CLI 命令创建 Azure IoT Edge 设备的两层层次结构,并在每个层将连接注册表部署为模块。 在此方案中,上层中有一个设备与云注册表通信。 下层中有一个设备与其上层中的连接注册表父级通信。
有关将连接的注册表与 IoT Edge 结合使用的概述,请参阅将连接的注册表与 Azure IoT Edge 结合使用。
先决条件
在 Azure Cloud Shell 中使用 Bash 环境。 有关详细信息,请参阅 Azure Cloud Shell 中的 Bash 快速入门。
如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI。
如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录。
出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展详细信息,请参阅使用 Azure CLI 的扩展。
运行 az version 以查找安装的版本和依赖库。 若要升级到最新版本,请运行 az upgrade。
Azure IoT 中心。 有关部署步骤,请参阅使用 Azure 门户创建 IoT 中心。
Azure 中的两项连接注册表资源。 有关部署步骤,请使用 Azure CLI 或 Azure 门户查看快速入门。
- 对于上层,连接注册表可能处于 ReadWrite 或 ReadOnly 模式。 本文假定它处于 ReadWrite 模式,且连接注册表名称存储在环境变量
$CONNECTED_REGISTRY_RW
中。 - 对于下层,连接注册表必须处于 ReadOnly 模式。 本文假定连接注册表名称存储在环境变量
$CONNECTED_REGISTRY_RO
中。
- 对于上层,连接注册表可能处于 ReadWrite 或 ReadOnly 模式。 本文假定它处于 ReadWrite 模式,且连接注册表名称存储在环境变量
将映像导入到云注册表
使用 az acr import 命令将以下容器映像导入到云注册表。 如果已导入这些映像,请跳过此步骤。
连接注册表映像
为了支持嵌套的 IoT Edge 方案,连接注册表运行时的容器映像必须在专用 Azure 容器注册表中可用。 使用 az acr import 命令将连接注册表映像导入专用注册表。
# Use the REGISTRY_NAME variable in the following Azure CLI commands to identify the registry
REGISTRY_NAME=<container-registry-name>
az acr import \
--name $REGISTRY_NAME \
--source mcr.microsoft.com/acr/connected-registry:0.8.0
IoT Edge 和 API 代理映像
若要支持嵌套 IoT Edge 上连接的注册表,需要为 IoT Edge 和 API 代理部署模块。 将这些映像导入专用注册表。
IoT Edge API 代理模块允许 IoT Edge 设备在同一端口(例如 443)上使用 HTTPS 协议公开多个服务。
az acr import \
--name $REGISTRY_NAME \
--source mcr.microsoft.com/azureiotedge-agent:1.2.4
az acr import \
--name $REGISTRY_NAME \
--source mcr.microsoft.com/azureiotedge-hub:1.2.4
az acr import \
--name $REGISTRY_NAME \
--source mcr.microsoft.com/azureiotedge-api-proxy:1.1.2
az acr import \
--name $REGISTRY_NAME \
--source mcr.microsoft.com/azureiotedge-diagnostics:1.2.4
Hello-world 映像
若要测试连接注册表,请导入 hello-world
映像。 此存储库将与连接注册表同步,并由连接注册表客户端拉取。
az acr import \
--name $REGISTRY_NAME \
--source mcr.microsoft.com/hello-world:1.1.2
检索连接注册表配置
若要将每个连接注册表部署到层次结构中的 IoT Edge 设备,需要从 Azure 中的已连接注册表资源检索配置设置。 如果需要,请为每个连接注册表运行 az acr connected-registry get-settings 命令,以检索配置。
默认情况下,设置信息不包括同步令牌密码,部署连接注册表时也需要该密码。 (可选)通过传递 --generate-password 1
或 --generate-password 2
参数来生成密码之一。 将生成的密码保存到安全位置。 无法再次检索该密码。
警告
重新生成密码将轮换同步令牌凭据。 如果使用旧密码配置了设备,则需要更新配置。
# Use the REGISTRY_NAME variable in the following Azure CLI commands to identify the registry
REGISTRY_NAME=<container-registry-name>
# Run the command for each registry resource in the hierarchy
az acr connected-registry get-settings \
--registry $REGISTRY_NAME \
--name $CONNECTED_REGISTRY_RW \
--parent-protocol https
az acr connected-registry get-settings \
--registry $REGISTRY_NAME \
--name $CONNECTED_REGISTRY_RO \
--parent-protocol https
命令输出包括注册表连接字符串和相关设置。 下例输出显示了与父级注册表 contosoregistry 连接的名为 myconnectedregistry 的注册表的连接字符串 :
{
"ACR_REGISTRY_CONNECTION_STRING": "ConnectedRegistryName=myconnectedregistry;SyncTokenName=myconnectedregistry-sync-token;SyncTokenPassword=xxxxxxxxxxxxxxxx;ParentGatewayEndpoint=contosoregistry.eastus.data.azurecr.io;ParentEndpointProtocol=https"
}
配置部署清单
部署清单是一个 JSON 文档,用于描述要部署到 IoT Edge 设备的模块。 有关详细信息,请参阅了解如何使用、配置并重复使用 IoT Edge 模块。
若要使用 Azure CLI 在每个 IoT Edge 设备上部署连接注册表模块,请将以下部署清单本地保存为 JSON 文件。 使用之前部分中的信息更新每个清单中的相关 JSON 值。 在下一部分运行命令以将配置应用到设备时,会用到这些文件路径。
顶层的部署清单
对于位于顶层的设备,请创建包含以下内容的部署清单文件 deploymentTopLayer.json
。 此清单与快速入门:将连接注册表部署到 IoT Edge 设备中使用的类似。
注意
如果已使用快速入门将连接注册表部署到上层 IoT Edge 设备,则可将其用于嵌套层次结构的上层。 修改本教程中的部署步骤,以在层次结构(未显示)中配置它。
连接注册表模块设置
使用前面部分中的令牌凭据和连接字符串更新
env
节点中的相关 JSON 值。以下环境变量在
env
节点中是可选的:变量 说明 ACR_REGISTRY_LOGIN_SERVER
指定唯一的主机名或 FQDN。 如果使用,则连接注册表仅接受对此登录服务器值的请求。
如果未提供值,则可以通过任何登录服务器值访问连接注册表。ACR_REGISTRY_CERTIFICATE_VOLUME
如果可以通过 HTTPS 访问连接注册表,则指向存储 HTTPS 证书的卷。
如果未设置,则默认位置为/var/acr/certs
。ACR_REGISTRY_DATA_VOLUME
覆盖连接注册表将存储映像的默认位置 /var/acr/data
。
此位置必须与容器的卷绑定匹配。重要
如果连接注册表侦听 80 和 443 以外的端口,则
ACR_REGISTRY_LOGIN_SERVER
值(若指定)必须包含该端口。 示例:192.168.0.100:8080
。如果未使用 API 代理模块,应设置连接注册表的
HostPort
绑定。 示例:"createOptions": "{\"HostConfig\":{\"Binds\":[\"/home/azureuser/connected-registry:/var/acr/data\"],\"PortBindings\":{\"8080/tcp\":[{\"HostPort\":\"8080\"}]}}}"
API 代理模块设置
- API 代理将侦听配置为
NGINX_DEFAULT_PORT
的端口 8000。 有关 API 代理设置的更多信息,请参阅 IoT Edge GitHub 存储库。
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"modules": {
"connected-registry": {
"settings": {
"image": "<REPLACE_WITH_CLOUD_REGISTRY_NAME>.azurecr.io/acr/connected-registry:0.8.0",
"createOptions": "{\"HostConfig\":{\"Binds\":[\"/home/azureuser/connected-registry:/var/acr/data\"]}}"
},
"type": "docker",
"env": {
"ACR_REGISTRY_CONNECTION_STRING": {
"value": "ConnectedRegistryName=<REPLACE_WITH_CONNECTED_REGISTRY_NAME>;SyncTokenName=<REPLACE_WITH_SYNC_TOKEN_NAME>;SyncTokenPassword=REPLACE_WITH_SYNC_TOKEN_PASSWORD;ParentGatewayEndpoint=<REPLACE_WITH_CLOUD_REGISTRY_NAME>.<REPLACE_WITH_CLOUD_REGISTRY_REGION>.data.azurecr.io;ParentEndpointProtocol=https"
}
},
"status": "running",
"restartPolicy": "always",
"version": "1.0"
},
"IoTEdgeAPIProxy": {
"settings": {
"image": "<REPLACE_WITH_CLOUD_REGISTRY_NAME>.azurecr.io/azureiotedge-api-proxy:1.1.2",
"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"8000/tcp\":[{\"HostPort\":\"8000\"}]}}}"
},
"type": "docker",
"env": {
"NGINX_DEFAULT_PORT": {
"value": "8000"
},
"CONNECTED_ACR_ROUTE_ADDRESS": {
"value": "connected-registry:8080"
},
"BLOB_UPLOAD_ROUTE_ADDRESS": {
"value": "AzureBlobStorageonIoTEdge:11002"
}
},
"status": "running",
"restartPolicy": "always",
"version": "1.0"
}
},
"runtime": {
"settings": {
"minDockerVersion": "v1.25",
"registryCredentials": {
"cloudregistry": {
"address": "<REPLACE_WITH_CLOUD_REGISTRY_NAME>.azurecr.io",
"password": "<REPLACE_WITH_SYNC_TOKEN_PASSWORD>",
"username": "<REPLACE_WITH_SYNC_TOKEN_NAME>"
}
}
},
"type": "docker"
},
"schemaVersion": "1.1",
"systemModules": {
"edgeAgent": {
"settings": {
"image": "<REPLACE_WITH_CLOUD_REGISTRY_NAME>.azurecr.io/azureiotedge-agent:1.2.4",
"createOptions": ""
},
"type": "docker",
"env": {
"SendRuntimeQualityTelemetry": {
"value": "false"
}
}
},
"edgeHub": {
"settings": {
"image": "<REPLACE_WITH_CLOUD_REGISTRY_NAME>.azurecr.io/azureiotedge-hub:1.2.4",
"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
},
"type": "docker",
"status": "running",
"restartPolicy": "always"
}
}
}
},
"$edgeHub": {
"properties.desired": {
"routes": {
"route": "FROM /messages/* INTO $upstream"
},
"schemaVersion": "1.1",
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}
}
}
下层的部署清单
对于位于下层的设备,请创建包含以下内容的部署清单文件 deploymentLowerLayer.json。
总体而言,下层部署文件类似于顶层部署文件。 区别在于:
它从顶层连接注册表而不是云注册表拉取所需的映像。
设置上层连接注册表时,请确保它在本地同步所有所需的映像(包括
azureiotedge-agent
、azureiotedge-hub
、azureiotedge-api-proxy
和acr/connected-registry
)。 下层 IoT 设备需要从顶层连接注册表拉取这些映像。它使用在下层配置的同步令牌向顶层连接注册表进行身份验证。
它将父网关终结点配置为顶层连接注册表的 IP 地址或 FQDN,而不是云注册表的 FQDN。
重要
在下面的部署清单中,$upstream
用作托管父连接注册表的设备的 IP 地址或 FQDN。 但是,环境变量中不支持 $upstream
。 连接的注册表需要读取环境变量 ACR_PARENT_GATEWAY_ENDPOINT
以获取父网关终结点。 连接注册表支持从另一个环境变量动态解析 IP 地址或 FQDN,而不是使用 $upstream
。
在嵌套 IoT Edge 上,下层有一个环境变量 $IOTEDGE_PARENTHOSTNAME
等于父设备的 IP 地址或 FQDN。 将环境变量手动替换为连接字符串中的 ParentGatewayEndpoint
值,以避免对父 IP 地址或 FQDN 进行硬编码。 由于此示例中的父设备在端口 8000 上运行 nginx
,因此请传递 $IOTEDGE_PARENTHOSTNAME:8000
。 还需要在 ParentEndpointProtocol
中选择正确的协议。
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"modules": {
"connected-registry": {
"settings": {
"image": "$upstream:8000/acr/connected-registry:0.8.0",
"createOptions": "{\"HostConfig\":{\"Binds\":[\"/home/azureuser/connected-registry:/var/acr/data\"]}}"
},
"type": "docker",
"env": {
"ACR_REGISTRY_CONNECTION_STRING": {
"value": "ConnectedRegistryName=<REPLACE_WITH_CONNECTED_REGISTRY_NAME>;SyncTokenName=<REPLACE_WITH_SYNC_TOKEN_NAME>;SyncTokenPassword=<REPLACE_WITH_SYNC_TOKEN_PASSWORD>;ParentGatewayEndpoint=$IOTEDGE_PARENTHOSTNAME:8000;ParentEndpointProtocol=https"
}
},
"status": "running",
"restartPolicy": "always",
"version": "1.0"
},
"IoTEdgeApiProxy": {
"settings": {
"image": "$upstream:8000/azureiotedge-api-proxy:1.1.2",
"createOptions": "{\"HostConfig\": {\"PortBindings\": {\"8000/tcp\": [{\"HostPort\": \"8000\"}]}}}"
},
"type": "docker",
"version": "1.0",
"env": {
"NGINX_DEFAULT_PORT": {
"value": "8000"
},
"CONNECTED_ACR_ROUTE_ADDRESS": {
"value": "connected-registry:8080"
},
"NGINX_CONFIG_ENV_VAR_LIST": {
"value": "NGINX_DEFAULT_PORT,BLOB_UPLOAD_ROUTE_ADDRESS,CONNECTED_ACR_ROUTE_ADDRESS,IOTEDGE_PARENTHOSTNAME,DOCKER_REQUEST_ROUTE_ADDRESS"
},
"BLOB_UPLOAD_ROUTE_ADDRESS": {
"value": "AzureBlobStorageonIoTEdge:11002"
}
},
"status": "running",
"restartPolicy": "always",
"startupOrder": 3
}
},
"runtime": {
"settings": {
"minDockerVersion": "v1.25",
"registryCredentials": {
"connectedregistry": {
"address": "$upstream:8000",
"password": "<REPLACE_WITH_SYNC_TOKEN_PASSWORD>",
"username": "<REPLACE_WITH_SYNC_TOKEN_NAME>"
}
}
},
"type": "docker"
},
"schemaVersion": "1.1",
"systemModules": {
"edgeAgent": {
"settings": {
"image": "$upstream:8000/azureiotedge-agent:1.2.4",
"createOptions": ""
},
"type": "docker",
"env": {
"SendRuntimeQualityTelemetry": {
"value": "false"
}
}
},
"edgeHub": {
"settings": {
"image": "$upstream:8000/azureiotedge-hub:1.2.4",
"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
},
"type": "docker",
"status": "running",
"restartPolicy": "always"
}
}
}
},
"$edgeHub": {
"properties.desired": {
"routes": {
"route": "FROM /messages/* INTO $upstream"
},
"schemaVersion": "1.1",
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}
}
}
设置和部署连接注册表模块
以下步骤改编自教程:创建 IoT Edge 设备的层次结构,专用于在 IoT Edge 层次结构中部署连接注册表模块。 请参阅该教程以了解有关各个步骤的详细信息。
创建顶层和下层设备
使用现有 ARM 模板创建上层和下层虚拟机。 该模板还会安装 IoT Edge 代理。 如果要改为从自己的设备进行部署,请参阅教程:安装或卸载适用于 Linux 的 Azure IoT Edge,了解如何手动设置设备。
重要
为便于以后访问部署在顶层设备上的模块,请确保打开以下端口入站:8000、443、5671、8883。 有关配置步骤,请参阅如何使用 Azure 门户向虚拟机开放端口。
创建和配置层次结构
在 Azure CLI 或 Azure Cloud Shell 中按照以下步骤操作,使用 iotedge-config
工具创建和配置层次结构:
下载配置工具。
mkdir nested_iot_edge_tutorial cd ~/nested_iot_edge_tutorial wget -O iotedge_config.tar "https://github.com/Azure-Samples/iotedge_config_cli/releases/download/latest/iotedge_config_cli.tar.gz" tar -xvf iotedge_config.tar
这一步会在教程目录中创建
iotedge_config_cli_release
文件夹。 用于创建设备层次结构的模板文件是在iotedge_config.yaml
文件,可在~/nested_iot_edge_tutorial/iotedge_config_cli_release/templates/tutorial
中找到。 在同一个目录中,有顶层和下层的两个部署清单:deploymentTopLayer.json
和deploymentLowerLayer.json
文件。用你的信息编辑
iotedge_config.yaml
。 编辑iothub_hostname
、iot_name
、上层和下层的部署清单文件名,以及你创建用于从每个层拉取上游映像的客户端令牌凭据。 下面是一个示例配置文件:config_version: "1.0" iothub: iothub_hostname: <REPLACE_WITH_HUB_NAME>.azure-devices.net iothub_name: <REPLACE_WITH_HUB_NAME> ## Authentication method used by IoT Edge devices: symmetric_key or x509_certificate authentication_method: symmetric_key ## Root certificate used to generate device CA certificates. Optional. If not provided a self-signed CA will be generated # certificates: # root_ca_cert_path: "" # root_ca_cert_key_path: "" ## IoT Edge configuration template to use configuration: template_config_path: "./templates/tutorial/device_config.toml" default_edge_agent: "$upstream:8000/azureiotedge-agent:1.2.4" ## Hierarchy of IoT Edge devices to create edgedevices: device_id: top-layer edge_agent: "<REPLACE_WITH_REGISTRY_NAME>.azurecr.io/azureiotedge-agent:1.2.4" ## Optional. If not provided, default_edge_agent will be used deployment: "./templates/tutorial/deploymentTopLayer.json" ## Optional. If provided, the given deployment file will be applied to the newly created device # hostname: "FQDN or IP" ## Optional. If provided, install.sh will not prompt user for this value nor the parent_hostname value container_auth: ## The token used to pull the image from cloud registry serveraddress: "<REPLACE_WITH_REGISTRY_NAME>.azurecr.io" username: "<REPLACE_WITH_SYNC_TOKEN_NAME_FOR_TOP_LAYER>" password: "<REPLACE_WITH_SYNC_TOKEN_PASSWORD_FOR_TOP_LAYER>" child: - device_id: lower-layer deployment: "./templates/tutorial/deploymentLowerLayer.json" ## Optional. If provided, the given deployment file will be applied to the newly created device # hostname: "FQDN or IP" ## Optional. If provided, install.sh will not prompt user for this value nor the parent_hostname value container_auth: ## The token used to pull the image from parent connected registry serveraddress: "$upstream:8000" username: "<REPLACE_WITH_SYNC_TOKEN_NAME_FOR_LOWER_LAYER>" password: "<REPLACE_WITH_SYNC_TOKEN_PASSWORD_FOR_LOWER_LAYER>"
准备上层和下层部署文件:deploymentTopLayer.json 和 deploymentLowerLayer.json。 将你在本文前面部分创建的部署清单文件复制到以下文件夹:
~/nestedIotEdgeTutorial/iotedge_config_cli_release/templates/tutorial
。导航到 iotedge_config_cli_release 目录,然后运行该工具以创建 IoT Edge 设备的层次结构。
cd ~/nestedIotEdgeTutorial/iotedge_config_cli_release ./iotedge_config --config ~/nestedIotEdgeTutorial/iotedge_config_cli_release/templates/tutorial/iotedge_config.yaml --output ~/nestedIotEdgeTutorial/iotedge_config_cli_release/outputs -f
如果使用
--output
参数,该工具会在所选目录中创建设备证书、证书捆绑包和日志文件。 如果使用-f
参数,该工具会自动查找 IoT 中心内现有的 IoT Edge 设备并将其删除,以避免错误并使中心干净整洁。该工具可能会运行几分钟。
使用
scp
将在上一步骤中生成的 top-layer.zip 和 lower-layer.zip 文件复制到相应的上层和下层虚拟机:scp <PATH_TO_CONFIGURATION_BUNDLE> <USER>@<VM_IP_OR_FQDN>:~
连接到顶层设备以安装配置捆绑包。
解压缩配置捆绑包。 首先需要安装 zip。
sudo apt install zip unzip ~/<PATH_TO_CONFIGURATION_BUNDLE>/<CONFIGURATION_BUNDLE>.zip #unzip top-layer.zip
运行
sudo ./install.sh
。 输入 IP 地址或主机名。 建议使用 IP 地址。运行
sudo iotedge list
以确认所有模块正在运行。
连接到下层设备以安装配置捆绑包。
解压缩配置捆绑包。 首先需要安装 zip。
sudo apt install zip unzip ~/<PATH_TO_CONFIGURATION_BUNDLE>/<CONFIGURATION_BUNDLE>.zip #unzip lower-layer.zip
运行
sudo ./install.sh
。 输入设备和父 IP 地址或主机名。 建议使用 IP 地址。运行
sudo iotedge list
以确认所有模块正在运行。
如果没有为设备配置指定部署文件,或者在上层或下层设备上出现部署问题(如部署清单无效),请手动部署模块。 请参阅以下部分。
手动部署连接注册表模块
使用以下命令在 IoT Edge 设备上手动部署连接注册表模块:
az iot edge set-modules \
--device-id <device-id> \
--hub-name <hub-name> \
--content <deployment-manifest-filename>
有关详细信息,请参阅使用 Azure CLI 部署 Azure IoT Edge 模块。
成功部署后,连接注册表显示 Online
状态。
要检查连接注册表的状态,请使用以下 az acr connected-registry show 命令:
az acr connected-registry show \
--registry $REGISTRY_NAME \
--name $CONNECTED_REGISTRY_RO \
--output table
可能需要等待几分钟,直到连接注册表部署完成。
成功部署后,连接注册表显示 Online
状态。
若要排查部署问题,请在受影响的设备上运行 iotedge check
。 有关详细信息,请参阅疑难解答。
后续步骤
本快速入门介绍了如何将连接注册表部署到嵌套的 IoT Edge 设备。 继续查看下一指南,了解如何从新部署的连接注册表拉取映像。