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

将 IoT Central 与 Azure Pipelines 集成,以实现持续集成和持续交付

持续集成和持续交付 (CI/CD) 指的是,通过使用自动化管道,在较短且频繁的周期中开发和交付软件的过程。 本文介绍如何自动化 IoT Central 应用程序配置的生成、测试和部署。 此自动化使开发团队能够更频繁地提供可靠的版本。

持续集成从代码提交到源代码存储库中的分支开始。 然后,每个提交都将与其他开发人员的提交合并,以确保未引入任何冲突。 通过创建生成并针对该生成运行自动测试,更改会被进一步验证。 此过程最终会产生一个工件或部署包,此工件或部署包会部署到目标环境。 在本例中,目标为 Azure IoT Central 应用程序。

IoT Central 是 CI/CD 管道的一部分,就像 IoT Central 是更大的 IoT 解决方案的一部分一样。 CI/CD 管道应将整个 IoT 解决方案和所有配置部署到每个环境(从开发到生产环境):

显示典型 CI/CD 管道各阶段的示意图。

IoT Central 是一种应用程序平台即服务,其部署要求与平台即服务组件不同。 对于 IoT Central,可以部署配置和设备模板。 这些配置和设备模板通过使用 API 管理并集成到发布管道中。

虽然可以自动创建 IoT Central 应用,但在开发 CI/CD 管道之前,应在每个环境中创建应用。

通过使用 Azure IoT Central REST API,可以将 IoT Central 应用配置集成到发布管道中。

本指南逐步讲解如何创建基于 GitHub 中托管的配置文件更新 IoT Central 应用程序的新管道。 本指南提供了与 Azure Pipelines 集成的具体说明,但可以调整为在 Tekton、Jenkins、GitLab 或 GitHub Actions 等工具构建的任何发布管道中包含 IoT Central。

本指南将创建一个管道,该管道仅将 IoT Central 配置应用于 IoT Central 应用程序的单个实例。 应将这些步骤集成到一个更大的管道(可部署整个解决方案)中,并将其从开发升级到 QA,再到预生产,同时执行所有必要的测试

这些脚本当前不会在 IoT Central 实例之间传输以下设置:仪表板、视图、设备模板中的自定义设置、定价计划、UX 自定义、应用程序映像、规则、计划作业、已保存的作业和注册组。

脚本当前不会从配置文件中不存在的目标 IoT Central 应用程序中删除设置。

先决条件

若要完成本指南中的步骤,需要符合以下先决条件:

下载示例代码

若要开始,请为 IoT Central CI/CD GitHub 存储库创建分支,然后将分支克隆到本地计算机:

  1. 若要为 GitHub 存储库创建分支,请打开 IoT Central CI/CD GitHub 存储库,然后选择“创建分支”。

  2. 通过打开控制台或 bash 窗口并运行以下命令,将存储库的分支克隆到本地计算机。

    git clone https://github.com/{your GitHub username}/iot-central-CICD-sample
    

创建服务主体

虽然 Azure Pipelines 可以直接与密钥保管库集成,但管道需要一些动态密钥保管库交互的服务主体,例如提取机密以导出数据。

要创建范围限定为订阅的服务主体,请执行以下操作:

  1. 运行以下命令以创建新服务主体:

    az ad sp create-for-rbac -n DevOpsAccess --scopes /subscriptions/{your Azure subscription Id} --role Contributor
    
  2. 记下密码、appId 和租户,因为稍后需要这些值。

  3. 将服务主体密码作为名为 SP-Password 的机密添加到生产密钥保管库:

    az keyvault secret set --name SP-Password --vault-name {your production key vault name} --value {your service principal password}
    
  4. 授予服务主体从密钥保管库读取机密的权限:

    az keyvault set-policy --name {your production key vault name} --secret-permissions get list --spn {the appId of the service principal}
    

生成 IoT Central API 令牌

在本指南中,管道使用 API 令牌与 IoT Central 应用程序交互。 也可使用服务主体。

注意

IoT Central API 令牌在一年后过期。

为开发和生产 IoT Central 应用完成以下步骤。

  1. 在 IoT Central 应用中,选择“权限”和“API 令牌”。

  2. 选择“新建”。

  3. 为令牌指定名称,在应用中指定顶级组织,并将角色设置为“应用管理员”。

  4. 记下开发 IoT Central 应用程序中的 API 令牌。 稍后运行 IoTC-Config.ps1 脚本时将用到该脚本。

  5. 将生成的令牌作为名为 API-Token 的机密从生产 IoT Central 应用程序保存到生产密钥保管库:

    az keyvault secret set --name API-Token --vault-name {your production key vault name} --value '{your production app API token}'
    

生成配置文件

这些步骤基于现有的 IoT Central 应用程序为开发环境生成 JSON 配置文件。 还可从应用程序下载所有现有设备模板。

  1. 在 IoT Central CI/CD 存储库的本地副本中运行以下 PowerShell 7 脚本:

    cd .\iot-central-CICD-sample\PowerShell\
    .\IoTC-Config.ps1
    
  2. 按照说明登录 Azure 帐户。

  3. 登录后,脚本会显示 IoTC 配置选项菜单。 该脚本可以从现有的 IoT Central 应用程序生成配置文件,并将配置应用到另一个 IoT Central 应用程序。

  4. 选择选项 1 以生成配置文件。

  5. 输入必要的参数,然后按 Enter:

    • 为开发 IoT Central 应用程序生成的 API 令牌。
    • 开发 IoT Central 应用程序的子域。
    • 输入 ..\Config\Dev 作为用于存储配置文件和设备模板的文件夹。
    • 开发密钥保管库的名称。
  6. 该脚本在存储库本地副本的 Config\Dev 文件夹中创建名为“IoTC Configuration”的文件夹。 此文件夹包含一个配置文件和一个名为“Device Models”的文件夹,用于存储应用程序中的所有设备模板。

修改配置文件

现在,你已拥有表示开发 IoT Central 应用程序实例设置的配置文件,请在将此配置应用到生产 IoT Central 应用程序实例之前进行任何必要的更改。

  1. 创建之前创建的 Dev 文件夹的副本,并将其称为“Production”。

  2. 使用文本编辑器在“Production”文件夹中打开 IoTC-Config.json。

  3. 此文件包含多个部分。 但是,如果应用程序不使用特定设置,则会从文件中省略该部分:

    {
      "APITokens": {
        "value": [
          {
            "id": "dev-admin",
            "roles": [
              {
                "role": "ca310b8d-2f4a-44e0-a36e-957c202cd8d4"
              }
            ],
            "expiry": "2023-05-31T10:47:08.53Z"
          }
        ]
      },
      "data exports": {
        "value": [
          {
            "id": "5ad278d6-e22b-4749-803d-db1a8a2b8529",
            "displayName": "All telemetry to blob storage",
            "enabled": false,
            "source": "telemetry",
            "destinations": [
              {
                "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63"
              }
            ],
            "status": "notStarted"
          }
        ]
      },
      "device groups": {
        "value": [
          {
            "id": "66f41d29-832d-4a12-9e9d-18932bee3141",
            "displayName": "MXCHIP Getting Started Guide - All devices"
          },
          {
            "id": "494dc749-0963-4ec1-89ff-e1de2228e750",
            "displayName": "RS40 Occupancy Sensor - All devices"
          },
          {
            "id": "dd87877d-9465-410b-947e-64167a7a1c39",
            "displayName": "Cascade 500 - All devices"
          },
          {
            "id": "91ceac5b-f98d-4df0-9ed6-5465854e7d9e",
            "displayName": "Simulated devices"
          }
        ]
      },
      "organizations": {
        "value": []
      },
      "roles": {
        "value": [
          {
            "id": "344138e9-8de4-4497-8c54-5237e96d6aaf",
            "displayName": "Builder"
          },
          {
            "id": "ca310b8d-2f4a-44e0-a36e-957c202cd8d4",
            "displayName": "Administrator"
          },
          {
            "id": "ae2c9854-393b-4f97-8c42-479d70ce626e",
            "displayName": "Operator"
          }
        ]
      },
      "destinations": {
        "value": [
          {
            "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63",
            "displayName": "Blob destination",
            "type": "blobstorage@v1",
            "authorization": {
              "type": "systemAssignedManagedIdentity",
              "endpointUri": "https://yourstorageaccount.blob.core.windows.net/",
              "containerName": "dataexport"
            },
            "status": "waiting"
          }
        ]
      },
      "file uploads": {
        "connectionString": "FileUpload",
        "container": "fileupload",
        "sasTtl": "PT1H"
      },
      "jobs": {
        "value": []
      }
    }
    
  4. 如果应用程序使用文件上传,脚本会在开发密钥保管库中创建机密,其中包含 connectionString 属性中显示的值。 在包含生产存储帐户的连接字符串的生产密钥保管库中创建具有相同名称的机密。 例如:

    az keyvault secret set --name FileUpload --vault-name {your production key vault name} --value '{your production storage account connection string}'
    
  5. 如果应用程序对数据导出目标使用托管标识,则没有任何机密可供你管理。 但是,你确实需要为生产 IoT Central 应用程序启用系统分配的托管标识,并向其授予写入目标所需的权限。

  6. 如果应用程序为数据导出目标使用连接字符串,请将目标机密添加到生产密钥保管库。 配置文件不包含目标的任何实际机密,机密存储在密钥保管库中。

  7. 使用密钥保管库中机密的名称更新配置文件中的机密。

    目标类型 要更改的属性
    服务总线队列 connectionString
    服务总线主题 connectionString
    Azure 数据资源管理器 clientSecret
    Azure Blob 存储 connectionString
    事件中心 connectionString
    Webhook 无身份验证 不可用

    例如:

    "destinations": {
      "value": [
        {
          "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63",
          "displayName": "Blob destination",
          "type": "blobstorage@v1",
          "authorization": {
            "type": "connectionString",
            "connectionString": "Storage-CS",
            "containerName": "dataexport"
          },
          "status": "waiting"
        }
      ]
    }
    
  8. 若要将 Configuration 文件夹上传到 GitHub 存储库,请从 IoTC-CICD-howto 文件夹运行以下命令。

     git add Config
     git commit -m "Adding config directories and files"
     git push
    

创建管道

  1. 转到 https://dev.azure.com/{your DevOps organization},在 Web 浏览器中打开 Azure DevOps 组织
  2. 选择“新建项目”以创建新项目。
  3. 为项目提供名称和可选说明,然后选择“创建”。
  4. 在“欢迎使用项目”页上,选择“管道”,然后选择“创建管道”。
  5. 选择 GitHub 作为代码的位置。
  6. 选择“授权 Azure Pipelines”以允许 Azure Pipelines 访问 GitHub 帐户。
  7. 在“选择存储库”页上,选择 IoT Central CI/CD GitHub 存储库的分支。
  8. 当系统提示登录 GitHub 并为 Azure Pipelines 提供访问存储库的权限时,请选择“批准并安装”
  9. 在“配置管道”页上,选择“初学者管道”以开始使用。 将显示 azure-pipelines.yml 供你编辑。

创建变量组

使用变量组是将密钥保管库机密集成到管道中的一种简单方法。 使用变量组可确保部署脚本可以使用正确的机密。 创建变量组:

  1. 在左侧菜单的“管道”部分选择“库”。

  2. 选择“+ Variable group”。

  3. 输入 keyvault 作为变量组的名称。

  4. 启用切换以从 Azure 密钥保管库链接机密。

  5. 选择 Azure 订阅并对其授权。 然后选择生产密钥保管库名称。

  6. 选择“添加”以开始向组添加变量。

  7. 添加以下机密:

    • 生产应用的 IoT Central API 密钥。 创建此机密 API-Token 时需要调用它。
    • 之前创建的服务主体的密码。 创建此机密 SP-Password 时需要调用它。
  8. 选择“确定”。

  9. 选择“保存”以保存变量组。

配置管道

现在,配置管道,使其将配置更改推送到 IoT Central 应用程序:

  1. 在左侧菜单的“管道”部分选择“管道”。

  2. 将管道 YAML 的内容替换为以下 YAML。 配置假定生产密钥保管库包含以下内容:

    • 名为 API-Token 的机密中生产 IoT Central 应用的 API 令牌。
    • 名为 SP-Password 的机密中的服务主体密码。

    -AppName-KeyVault 的值替换为生产实例的适当值。

    创建服务主体时记下的 -AppId-TenantId

    trigger:
    - master
    variables:
    - group: keyvault
    - name: buildConfiguration
      value: 'Release'
    steps:
    - task: PowerShell@2
      displayName: 'IoT Central'
      inputs:
        filePath: 'PowerShell/IoTC-Task.ps1'
        arguments: '-ApiToken "$(API-Token)" -ConfigPath "Config/Production/IoTC Configuration" -AppName "{your production IoT Central app name}" -ServicePrincipalPassword (ConvertTo-SecureString "$(SP-Password)" -AsPlainText -Force) -AppId "{your service principal app id}" -KeyVault "{your production key vault name}" -TenantId "{your tenant id}"'
        pwsh: true
        failOnStderr:  true
    
  3. 选择“保存并运行”。

  4. YAML 文件保存到 GitHub 存储库,因此需要提供提交消息,然后再次选择“保存并运行”。

管道已排队。 运行可能需要几分钟时间。

首次运行管道时,系统会提示授予管道权限以访问订阅和密钥保管库。 对于每个资源,选择两次“允许”。

管道作业成功完成后,登录到生产 IoT Central 应用程序,并验证配置是否按预期应用。

促进从开发到生产的更改

拥有一个工作管道之后,即可使用配置更改直接管理 IoT Central 实例。 可将新设备模板上传到 Device Models 文件夹中,并直接对配置文件进行更改。 此方法使你可以将 IoT Central 应用程序的配置视为与任何其他代码相同的配置。

下一步

了解如何将 IoT Central 配置集成到 CI/CD 管道后,接下来建议了解如何管理和监视 IoT Central 应用程序