Azure IoT Edge 통합 테스트 템플릿 - Part.3

15773 단어

요약



이 문서는 azure-iot-edge-integration-test-template에 대한 일련의 문서 중 일부입니다. Part.2에 이어 이 글에서는 ManifestGenerator에 집중하겠습니다.



  • 목차


  • Deployment manifest
  • What ManifestGenerator does

  • Configurations
  • Extract credentials
  • Environment variables
  • appsettings.json

  • IoTEdgeObjectModel NuGet package
  • SAS token

  • 배포 매니페스트

    In this sample template, the .NET app ManifestGenerator running on Azure Pipelines agent generates Azure IoT Edge Deployment Manifest Azure IoT Hub에 배포합니다. IoT Hub에 연결된 IoT Edge 모듈은 매니페스트에서 가리키는 컨테이너 이미지를 가져옵니다.



    ManifestGenerator가 하는 일

    The main purpose of ManifestGenerator app is to generate manifest.json . It includes the information of all IoT Edge modules including system default and custom.

    • Default module: edgeAgent and edgeHub are default modules that manage modules and their communications.
    • Custom module: You can specify what modules you want to deploy to the IoT Edge environment.
    • IoT Edge communication route: You have to specify route name here. This is very important that those names are synchronized with routes defined in each module apps. For example, the route specified in the manifest is like FROM /messages/modules/IothubConnector/outputs/reportRequest INTO BrokeredEndpoint("/modules/WeatherObserver/inputs/reportRequest") . IothubConnector module needs to specify reportRequest route name on its send message method, and WeatherObserver to specify reportRequest route name on its callback method.
    • Image URL, Environment variables, Bind mount directory: You have to specify image URL, environment variables, bind mount directory, and other configurations like below.
    You can see a sample here - manifest.example.json

    "FileGenerator": {
      "version": "1.0",
      "type": "docker",
      "status": "running",
      "restartPolicy": "always",
      "settings": {
        "image": "crsample1.azurecr.io/file-generator:20220818.2",
        "createOptions": "{\"HostConfig\":{\"Binds\":[\"/edge/upload/reports:/genroot\"]}}"
      },
      "env": {
        "OUTPUT_DIRECTORY_PATH": {
          "value": "/genroot"
        },
        "ROS_TOPIC_NAME": {
          "value": "ros2_topic_download"
        }
      }
    },
    




    구성

    In this section, I am going to describe how to set configurations for manifest.json .

    자격 증명 추출

    manifest.json needs some credentials including IoT Hub connection string, Container Registry key, Storage Account key, local blob storage key. The first three can be extracted through Azure CLI command as Azure Pipelines agent has the access right with Azure Service Connection. For the local blob storage key, it could be anything of base64 string with length in 16 bytes. The Azure Pipeline agent generates the one randomly and sets it as environment variables.

    az extension add --name azure-iot
    iothubcs=$(az iot hub connection-string show --hub-name $(IOTHUB_NAME) -o tsv)
    echo "##vso[task.setvariable variable=iotHubCs]$iothubcs"
    acrkey=$(az acr credential show --name $(ACR_NAME) --query passwords[0].value -o tsv)
    echo "##vso[task.setvariable variable=AcrKey]$acrkey"
    storagekey=$(az storage account keys list --resource-group $(RESOURCE_GROUP_NAME) --account-name $(STORAGE_ACCOUNT_NAME) --query [0].value -o tsv)
    echo "##vso[task.setvariable variable=storageAccountKey]$storagekey"
    localstoragekey=$(openssl rand -base64 16)
    echo "##vso[task.setvariable variable=LocalStorageKey]$localstoragekey"
    

    환경 변수

    With Azure Pipelines .NET Core CLI task 실행 시 필요한 변수를 .NET 환경 변수로 ManifestGenerator 앱에 전달할 수 있습니다. 이러한 변수에는 이전 단계에서 생성된 자격 증명 Azure Pipelines 에이전트가 포함됩니다.

    - task: DotNetCoreCLI@2
      displayName: Generate/deploy IoT Edge manifest
      inputs:
        command: run
        projects: $(Build.SourcesDirectory)/src/apps/ManifestGenerator/ManifestGenerator/ManifestGenerator.csproj
        arguments: --configuration Release
      env:
        STORAGE_ACCOUNT_NAME: $(STORAGE_ACCOUNT_NAME)
        STORAGE_ACCOUNT_KEY: $(storageAccountKey)
        ACR_NAME: $(ACR_NAME)
        ACR_PASS: $(AcrKey)
        IOTHUB_CONNECTOR_IMAGE: $(ACR_NAME).azurecr.io/${{ parameters.EdgeImages.module1.repository }}:${{ parameters.EdgeImages.module1.tag }}
        WEATHER_OBSERVER_IMAGE: $(ACR_NAME).azurecr.io/${{ parameters.EdgeImages.module2.repository }}:${{ parameters.EdgeImages.module2.tag }}
        FILE_GENERATOR_IMAGE: $(ACR_NAME).azurecr.io/${{ parameters.EdgeImages.module3.repository }}:${{ parameters.EdgeImages.module3.tag }}
        FILE_UPLOADER_IMAGE: $(ACR_NAME).azurecr.io/${{ parameters.EdgeImages.module4.repository }}:${{ parameters.EdgeImages.module4.tag }}
        FILE_UPDATER_IMAGE: $(ACR_NAME).azurecr.io/${{ parameters.EdgeImages.module5.repository }}:${{ parameters.EdgeImages.module5.tag }}
        IOTHUB_DEVICE_ID: $(IOTHUB_DEVICE_ID)
        IOTHUB_CONNECTION_STRING: $(iotHubCs)
        LOCAL_STORAGE_KEY: $(LocalStorageKey)
        ORGANIZATION_NAME: $(TEST_ORGANIZATION_NAME)
    


    appsettings.json

    ManifestGenerator app retains appsettings.json 설계 값을 지정합니다. 바인드 마운트 경로 또는 SAS 토큰 만료 기간과 같은 디자인을 변경하지 않는 한 변경할 필요가 없습니다.

    {
      "RouteTelemetry": "telemetry",
      "RouteReportRequest": "reportRequest",
      "RouteReportResponse": "reportResponse",
      "RouteUpdateRequest": "updateRequest",
      "RouteUpdateResponse": "updateResponse",
      "Ros2Topic": "ros2_topic_download",
      "FileGeneratorContainerBind": "/edge/upload/reports:/genroot",
      "FileUploaderContainerBind": "/edge/upload:/uploadroot",
      "FileUpdaterContainerBind": "/edge/download:/downloadroot",
      "LocalBlobStorageBind": "/edge/localblob:/blobroot",
      "CloudBlobContainerName": "weather",
      "LocalBlobContainerName": "weather",
      "LocalBlobAccountName": "stlocal",
      "LocalBlobEndpoint": "http://LocalBlobStorage:11002",
      "FileGeneratorWorkdir": "/genroot",
      "FileUploaderWorkdir": "/uploadroot",
      "FileUpdaterWorkdir": "/downloadroot",
      "SasExpirationMonths": 6
    }
    


    IoTEdgeObjectModel NuGet 패키지

    This sample template uses IoTEdgeObjectModel NuGet 패키지. 이 패키지는 작성하는 코드 줄을 줄이는 데 도움이 됩니다manifest.json. 시스템 모듈 구성 또는 기타 기본 구성을 지정할 필요가 없습니다. 지난 프로젝트의 경험상 C# 사전 인스턴스를 사용하여 처음부터 manifest.json를 직접 작성했습니다. IoTEdgeObjectModel 패키지를 사용하면 약 50%의 코드를 줄일 수 있습니다.

    이 패키지의 세 가지 주요 클래스는 EdgeAgentDesiredProperties , EdgeHubDesiredProperties , ModuleSpecificationDesiredProperties 입니다.
    edgeAgent 클래스를 사용하여 아래와 같이 EdgeModuleSpecification 속성을 지정합니다.

    EdgeAgentDesiredProperties edgeAgentDesiredProperties = new ()
    {
        SystemModuleVersion = "1.3",
        RegistryCredentials = new List<RegistryCredential>()
        {
            new RegistryCredential(acrName, $"{acrName}.azurecr.io", acrName, acrPass),
        },
        EdgeModuleSpecifications = new List<EdgeModuleSpecification>()
        {
            new EdgeModuleSpecification(name:"IothubConnector", image:iothubConnectorImage, environmentVariables:iothubConnectorEnv),
            new EdgeModuleSpecification(name:"WeatherObserver", image:weatherObserverImage),
            new EdgeModuleSpecification(name:"FileGenerator", image:fileGeneratorImage, createOptions:fileGeneratorCreateOptions, environmentVariables:fileGeneratorEnv),
            new EdgeModuleSpecification(name:"FileUploader", image:fileUploaderImage, createOptions:fileUploaderCreateOptions, environmentVariables:fileUploaderEnv),
            new EdgeModuleSpecification(name:"FileUpdater", image:fileUpdaterImage, createOptions:fileUpdaterCreateOptions, environmentVariables:fileUpdaterEnv),
            new EdgeModuleSpecification(name:"LocalBlobStorage", image:localBlobStorageImage, createOptions:localBlobStorageCreateOptions, environmentVariables:localBlobStorageEnv),
        },
    };
    

    EdgeHubDesiredProperties는 주로 Azure IoT Edge 경로 통신을 지정합니다.

    EdgeHubDesiredProperties edgeHubConfig = new ()
    {
        Routes = new List<Route>()
        {
            new Route("route_telemetry", route_telemetry),
            new Route("route_c2w", route_c2w),
            new Route("route_w2c", route_w2c),
            new Route("route_w2u", route_w2u),
            new Route("route_u2w", route_u2w),
        },
    };
    

    ModuleSpecificationDesiredProperties는 사용자 지정 모듈 및 모듈 쌍 원하는 속성을 지정합니다.

    ModuleSpecificationDesiredProperties localBlobStorage = new ()
    {
        Name = "LocalBlobStorage",
        DesiredProperties = new Dictionary<string, object>
        {
            ["deviceAutoDeleteProperties"] = new Dictionary<string, object>
            {
                ["deleteOn"] = true,
                ["deleteAfterMinutes"] = 5,
                ["retainWhileUploading"] = true,
            },
            ["deviceToCloudUploadProperties"] = new Dictionary<string, object>
            {
                ["uploadOn"] = true,
                ["uploadOrder"] = "NewestFirst",
                ["deleteAfterUpload"] = true,
                ["cloudStorageConnectionString"] = cloudStorageSasConnectionString,
                ["storageContainersForUpload"] = new Dictionary<string, object>
                {
                    [localBlobContainerName] = new Dictionary<string, object>
                    {
                        ["target"] = iotHubDeviceId,
                    }
                },
            },
        },
    };
    


    SAS 토큰

  • ManifestGenerator has a service class SasService.cs 을 생성하는 SAS(Shared Access Signature) token . 이러한 방식으로 서로 다른 엔터티의 여러 에지 장치에 대해 하나의 Azure Blob Storage를 가질 수 있습니다. 이 SAS 토큰은 에지 장치가 보안 경계를 따르도록 하여 에지 장치가 다른 엔터티의 데이터에 액세스할 수 없도록 합니다.


  • 생성된 SAS 토큰을 연결 문자열로 변환하는 것이 중요합니다. 이 연결 문자열은 LocalBlobStorage의 환경 변수로 설정됩니다. FileUpdater의 경우 AzureSasCredential를 사용하여 SAS 토큰을 BlobClient에서 읽을 수 있는 토큰으로 변환할 수 있습니다.

  • string[] sasContents = weatherFileInfo.BlobSasUrl.Split('?');
    AzureSasCredential azureSasCredential = new (sasContents[1]);
    Uri blobUri = new (sasContents[0]);
    BlobClient blobClient = new (blobUri, azureSasCredential, null);
    await blobClient.DownloadToAsync(zipFilePath).ConfigureAwait(false);
    


    그러나 LocalBlobClient에는 기본적으로 SAS 토큰이 아닌 Blob 연결 문자열이 필요합니다. 따라서 ManfiestGenerator Program.cs에서 SAS 토큰을 blob 연결 문자열로 변환해야 합니다.

    string sasUri = directoryClient.GenerateSasUri(sasBuilder).ToString();
    string[] sasContents = sasUri.Split('?');
    string sasConnectionString = $"BlobEndpoint=https://{this.dataLakeServiceClient.AccountName}.blob.core.windows.net/{blobContainerName}/{sasDirectory};SharedAccessSignature={sasContents[1]}";
    

    좋은 웹페이지 즐겨찾기