다음을 통해 공유


자습서: 사용자 지정 IoT Edge 모듈 만들기 및 배포

적용 대상:예 아이콘 IoT Edge 1.1

중요합니다

IoT Edge 1.1 지원 종료 날짜는 2022년 12월 13일이었습니다. 이 제품, 서비스, 기술 또는 API가 지원되는 방법에 대한 정보를 보려면 Microsoft 제품 수명 주기를 확인하세요. 최신 버전의 IoT Edge로 업데이트하는 방법에 대한 자세한 내용은 업데이트 IoT Edge를 참조하세요.

이 문서에서는 다운스트림 IoT 디바이스에서 메시지를 수신하고, 기계 학습 모델을 통해 데이터를 실행한 다음, IoT Hub에 인사이트를 전달하는 3개의 IoT Edge 모듈을 만듭니다.

IoT Edge 허브는 모듈 간 통신을 용이하게 합니다. IoT Edge 허브를 메시지 브로커로 사용하면 모듈이 서로 독립적으로 유지됩니다. 모듈은 메시지를 수락하는 입력과 메시지를 쓰는 출력을 지정하기만 하면 됩니다.

IoT Edge 디바이스에서 다음 네 가지를 수행하려고 합니다.

  • 다운스트림 디바이스에서 데이터를 받습니다.
  • 데이터를 보낸 디바이스의 남은 RUL(수명)을 예측합니다.
  • 디바이스에 대한 RUL을 사용하여 IoT Hub에 메시지를 보냅니다. 이 함수는 RUL이 지정된 수준 아래로 떨어지는 경우에만 데이터를 보내도록 수정할 수 있습니다.
  • 다운스트림 디바이스 데이터를 IoT Edge 디바이스의 로컬 파일에 저장합니다. 이 데이터 파일은 기계 학습 모델의 학습을 구체화하기 위해 주기적으로 IoT Hub에 업로드됩니다. 일정한 메시지 스트리밍 대신 파일 업로드를 사용하는 것이 비용 효율적입니다.

이러한 작업을 수행하기 위해 세 가지 사용자 지정 모듈을 사용합니다.

  • RUL 분류자:Azure Machine Learning 모델 학습 및 배포 에서 만든 turboFanRulClassifier 모듈은 "amlInput"이라는 입력과 "amlOutput"이라는 출력을 노출하는 표준 기계 학습 모듈입니다. "amlInput"은 해당 입력이 ACI 기반 웹 서비스에 보낸 입력과 정확히 같을 것으로 예상합니다. 마찬가지로 "amlOutput"은 웹 서비스와 동일한 데이터를 반환합니다.

  • Avro 기록기: 이 모듈은 "avroModuleInput" 입력에 대한 메시지를 수신하고 나중에 IoT Hub에 업로드할 수 있도록 Avro 형식의 메시지를 디스크에 유지합니다.

  • 라우터 모듈: 라우터 모듈은 다운스트림 디바이스에서 메시지를 수신한 다음, 메시지를 포맷하고 분류자에게 보냅니다. 그런 다음, 모듈은 분류자에서 메시지를 수신하고 메시지를 Avro 기록기 모듈에 전달합니다. 마지막으로 모듈은 RUL 예측만 IoT Hub로 보냅니다.

    • 입력:

      • deviceInput: 다운스트림 디바이스에서 메시지 수신
      • rulInput: "amlOutput"에서 메시지를 받습니다.
    • 출력:

      • classify: "amlInput"에 메시지를 보냅니다.
      • writeAvro: "avroModuleInput"에 메시지를 보냅니다.
      • toIotHub: $upstream 메시지를 전송하여 연결된 IoT Hub에 메시지를 전달합니다.

다음 다이어그램은 전체 솔루션에 대한 모듈, 입력, 출력 및 IoT Edge 허브 경로를 보여 줍니다.

IoT Edge 3개 모듈 아키텍처 다이어그램

이 문서의 단계는 일반적으로 클라우드 개발자가 수행합니다.

자습서의 이 섹션에서는 다음 방법을 알아봅니다.

  • 사용자 지정 코드에서 IoT Edge 모듈을 만듭니다.
  • 사용자 지정 모듈에서 Docker 이미지를 생성합니다.
  • 사용자 지정 모듈을 지원하도록 IoT Hub 라우팅을 다시 구성합니다.
  • 사용자 지정 모듈을 빌드, 게시 및 배포합니다.

필수 조건

이 문서는 IoT Edge에서 Azure Machine Learning을 사용하는 방법에 대한 자습서 시리즈의 일부입니다. 시리즈의 각 문서는 이전 문서의 작업을 기반으로 합니다. 이 문서에 직접 도착한 경우 시리즈의 첫 번째 문서를 방문하세요.

새 IoT Edge 솔루션 만들기

두 번째 Azure Notebook을 실행하는 동안 RUL 모델을 포함하는 컨테이너 이미지를 만들고 게시했습니다. Azure Machine Learning은 이미지 만들기 프로세스의 일부로 이미지를 Azure IoT Edge 모듈로 배포할 수 있도록 해당 모델을 패키징했습니다.

이 단계에서는 "Azure Machine Learning" 모듈을 사용하여 Azure IoT Edge 솔루션을 만들고, 모듈을 우리가 Azure Notebooks로 게시한 이미지에 연결합니다.

  1. 개발 VM에 대한 원격 데스크톱 세션을 엽니다.

  2. Visual Studio Code 에서 C:\source\IoTEdgeAndMlSample 폴더를 엽니다.

  3. 탐색기 패널(빈 공간)을 마우스 오른쪽 단추로 클릭하고 새 IoT Edge 솔루션을 선택합니다.

    새 IoT Edge 솔루션 만들기

  4. 기본 솔루션 이름 EdgeSolution을 적용합니다.

  5. 모듈 템플릿으로 Azure Machine Learning 을 선택합니다.

  6. 모듈의 이름을 turbofanRulClassifier로 지정합니다.

  7. 기계 학습 작업 영역을 선택합니다. 이 작업 영역은 자습서: Azure Machine Learning 모델 학습 및 배포에서 만든 turboFanDemo 작업 영역입니다.

  8. Azure Notebook을 실행하는 동안 만든 이미지를 선택합니다.

  9. 솔루션을 살펴보고 생성된 파일을 확인합니다.

    • deployment.template.json: 이 파일에는 솔루션의 각 모듈에 대한 정의가 포함되어 있습니다. 이 파일에는 세 가지 섹션이 있습니다.

      • 레지스트리 자격 증명: 솔루션에서 사용하는 사용자 지정 컨테이너 레지스트리 집합을 정의합니다. 지금은 Azure Machine Learning 이미지가 저장된 기계 학습 작업 영역의 레지스트리를 포함해야 합니다. 여러 컨테이너 레지스트리를 가질 수 있지만 간단히 하기 위해 모든 모듈에 이 하나의 레지스트리를 사용합니다.

        "registryCredentials": {
          "<your registry>": {
            "username": "$CONTAINER_REGISTRY_USERNAME_<your registry>",
            "password": "$CONTAINER_REGISTRY_PASSWORD_<your registry>",
            "address": "<your registry>.azurecr.io"
          }
        }
        
      • 모듈: 이 섹션에는 이 솔루션으로 이동하는 사용자 정의 모듈 집합이 포함되어 있습니다. turbofanRulClassifier 모듈 정의는 컨테이너 레지스트리의 이미지를 가리킵니다. 솔루션에 모듈을 더 추가하면 이 섹션에 표시됩니다.

        "modules": {
           "turbofanRulClassifier": {
             "version": "1.0",
             "type": "docker",
             "status": "running",
             "restartPolicy": "always",
             "settings": {
               "image": "turbofandemo2cd74296.azurecr.io/edgemlsample:1",
               "createOptions": {}
             }
           }
        }
        
      • 경로: 이 자습서에서는 꽤 많은 경로를 사용할 예정입니다. 경로는 모듈이 서로 통신하는 방법을 정의합니다. 템플릿에서 정의한 기존 경로가 필요한 라우팅과 일치하지 않습니다. 경로를 삭제합니다 turbofanRulClassifierToIoTHub .

        "$edgeHub": {
           "properties.desired": {
             "schemaVersion": "1.0",
             "routes": {
               "turbofanRulClassifierToIoTHub": "FROM /messages/modules/turbofanRulClassifier/outputs/* INTO $upstream"
             },
             "storeAndForwardConfiguration": {
               "timeToLiveSecs": 7200
             }
           }
        }
        
    • deployment.debug.template.json: 이 파일은 디버그 버전의 deployment.template.json. 일반적으로 이 파일은 deployment.template.json 파일의 콘텐츠와 동기화된 상태로 유지해야 하지만 이 자습서에서는 필요하지 않습니다.

    • .env: 이 파일은 레지스트리에 액세스하기 위한 사용자 이름과 암호를 제공해야 하는 위치입니다.

      CONTAINER_REGISTRY_USERNAME_<your registry name>=<ACR username>
      CONTAINER_REGISTRY_PASSWORD_<your registry name>=<ACR password>
      

      비고

      이 자습서에서는 개발 및 테스트 시나리오에 편리하게 사용할 수 있는 관리자 로그인 자격 증명을 Azure Container Registry에 사용합니다. 프로덕션 시나리오에 사용할 준비가 되면 서비스 주체 같은 최소 권한 인증 옵션을 사용하는 것이 좋습니다. 자세한 내용은 컨테이너 레지스트리에 대한 액세스 관리를 참조하세요.

  10. Visual Studio Code 탐색기에서 deployment.template.json 파일을 마우스 오른쪽 단추로 클릭하고 IoT Edge 솔루션 빌드를 선택합니다.

  11. 이 명령은 deployment.amd64.json 파일을 사용하여 구성 폴더를 만듭니다. 이 파일은 솔루션에 대한 구체적인 배포 템플릿입니다.

라우터 모듈 추가

다음으로, 솔루션에 라우터 모듈을 추가합니다. 라우터 모듈은 솔루션에 대한 몇 가지 책임을 처리합니다.

  • 다운스트림 디바이스에서 메시지 수신: 메시지가 다운스트림 디바이스에서 IoT Edge 디바이스에 도착하면 라우터 모듈은 메시지를 수신하고 메시지 라우팅을 오케스트레이션하기 시작합니다.
  • RUL 분류자 모듈에 메시지 보내기: 다운스트림 디바이스에서 새 메시지를 받으면 라우터 모듈은 메시지를 RUL 분류자에서 예상하는 형식으로 변환합니다. 라우터는 RUL 예측에 대한 메시지를 RUL 분류자로 보냅니다. 분류자는 예측을 수행한 후 라우터 모듈로 메시지를 다시 보냅니다.
  • IoT Hub에 RUL 메시지 보내기: 라우터가 분류자로부터 메시지를 받으면 필수 정보, 디바이스 ID 및 RUL만 포함하도록 메시지를 변환하고 약어 메시지를 IoT Hub로 보냅니다. 여기서 수행하지 않은 추가 구체화는 RUL 예측이 임계값 아래로 떨어지는 경우에만(예: RUL이 100주기 미만인 경우) IoT Hub로 메시지를 보냅니다. 이러한 방식으로 필터링하면 메시지 볼륨이 줄어들고 IoT Hub 비용이 절감됩니다.
  • Avro 기록기 모듈에 메시지 보내기: 다운스트림 디바이스에서 보낸 모든 데이터를 보존하기 위해 라우터 모듈은 분류자에서 받은 전체 메시지를 Avro 기록기 모듈로 보내며, IoT Hub 파일 업로드를 사용하여 데이터를 유지하고 업로드합니다.

라우터 모듈은 메시지가 올바른 순서로 처리되도록 하는 솔루션의 중요한 요소입니다.

모듈 만들기 및 파일 복사

  1. Visual Studio Code에서 모듈 폴더를 마우스 오른쪽 단추로 클릭하고 IoT Edge 모듈 추가를 선택합니다.

  2. 모듈 템플릿에 대한 C# 모듈 을 선택합니다.

  3. 모듈의 이름을 turbofanRouter로 지정합니다.

  4. Docker 이미지 리포지토리에 대한 메시지가 표시되면 기계 학습 작업 영역에서 레지스트리를 사용합니다( deployment.template.json 파일의 registryCredentials 노드에서 레지스트리를 찾을 수 있습니다). 이 값은 registry.azurecr.io/turbofanrouter> 같은< 레지스트리에 대한 정규화된 주소입니다.

    비고

    이 문서에서는 Azure Machine Learning 작업 영역에서 만든 Azure Container Registry를 사용합니다. 이것은 순전히 편의를 위한 것입니다. 새 컨테이너 레지스트리를 만들고 모듈을 게시했을 수 있습니다.

  5. 명령 프롬프트 셸을 사용하여 터미널에서 샘플 모듈의 파일을 솔루션으로 복사합니다.

    copy c:\source\IoTEdgeAndMlSample\EdgeModules\modules\turbofanRouter\*.cs c:\source\IoTEdgeAndMlSample\EdgeSolution\modules\turbofanRouter\
    
  6. program.cs 파일을 덮어쓰라는 메시지를 수락합니다.

라우터 모듈 빌드

  1. Visual Studio Code에서 터미널>기본 빌드 작업 구성을 선택합니다.

  2. 템플릿에서 tasks.json 파일 만들기를 선택합니다.

  3. .NET Core를 선택합니다.

  4. tasks.json 내용을 다음 코드로 바꿉니다.

    {
      "version": "2.0.0",
      "tasks": [
        {
          "label": "build",
          "command": "dotnet",
          "type": "shell",
          "group": {
            "kind": "build",
            "isDefault": true
          },
          "args": [
            "build",
            "${workspaceFolder}/modules/turbofanRouter"
          ],
          "presentation": {
            "reveal": "always"
          },
          "problemMatcher": "$msCompile"
        }
      ]
    }
    
  5. tasks.json저장하고 닫습니다.

  6. Ctrl + Shift + B 또는 터미널>실행 빌드 태스크로 빌드를 실행합니다.

모듈 경로 설정

위에서 설명한 것처럼 IoT Edge 런타임은 deployment.template.json 파일에 구성된 경로를 사용하여 느슨하게 결합된 모듈 간의 통신을 관리합니다. 이 섹션에서는 turbofanRouter 모듈에 대한 경로를 설정하는 방법을 자세히 설명합니다. 먼저 입력 경로를 다룬 다음 출력으로 이동합니다.

입력

  1. Program.cs Init() 메서드에서는 모듈에 대해 두 개의 콜백을 등록합니다.

    await ioTHubModuleClient.SetInputMessageHandlerAsync(EndpointNames.FromLeafDevice, LeafDeviceInputMessageHandler, ioTHubModuleClient);
    await ioTHubModuleClient.SetInputMessageHandlerAsync(EndpointNames.FromClassifier, ClassifierCallbackMessageHandler, ioTHubModuleClient);
    
  2. 첫 번째 콜백은 deviceInput 싱크로 전송된 메시지를 수신 대기합니다. 위의 다이어그램에서 다운스트림 디바이스의 메시지를 이 입력으로 라우팅하려고 합니다. deployment.template.json 파일에서 IoT Edge 모듈에서 보내지 않은 IoT Edge 디바이스에서 받은 메시지를 turbofanRouter 모듈의 "deviceInput"이라는 입력으로 라우팅하도록 에지 허브에 지시하는 경로를 추가합니다.

    "leafMessagesToRouter": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/turbofanRouter/inputs/deviceInput\")"
    
  3. 그런 다음, rulClassifier 모듈의 메시지에 대한 경로를 turbofanRouter 모듈에 추가합니다.

    "classifierToRouter": "FROM /messages/modules/turbofanRulClassifier/outputs/amloutput INTO BrokeredEndpoint(\"/modules/turbofanRouter/inputs/rulInput\")"
    

출력물

라우터 모듈의 출력을 처리하기 위해 $edgeHub 경로 매개 변수에 4개의 경로를 추가합니다.

  1. Program.cs 모듈 클라이언트를 사용하여 경로를 사용하여 RUL 분류자로 메시지를 보내는 SendMessageToClassifier() 메서드를 정의합니다.

    "routerToClassifier": "FROM /messages/modules/turbofanRouter/outputs/classOutput INTO BrokeredEndpoint(\"/modules/turbofanRulClassifier/inputs/amlInput\")"
    
  2. SendRulMessageToIotHub()는 모듈 클라이언트를 사용하여 경로를 통해 디바이스의 RUL 데이터만 IoT Hub로 보냅니다.

    "routerToIoTHub": "FROM /messages/modules/turboFanRouter/outputs/hubOutput INTO $upstream"
    
  3. SendMessageToAvroWriter()는 모듈 클라이언트를 사용하여 avroFileWriter 모듈에 추가된 RUL 데이터와 함께 메시지를 보냅니다.

    "routerToAvro": "FROM /messages/modules/turbofanRouter/outputs/avroOutput INTO BrokeredEndpoint(\"/modules/avroFileWriter/inputs/avroModuleInput\")"
    
  4. HandleBadMessage()는 실패한 메시지를 나중에 라우팅할 수 있는 IoT Hub 업스트림으로 보냅니다.

    "deadLetter": "FROM /messages/modules/turboFanRouter/outputs/deadMessages INTO $upstream"
    

모든 경로를 통합하면 "$edgeHub" 노드는 다음 JSON으로 표시됩니다.

"$edgeHub": {
  "properties.desired": {
    "schemaVersion": "1.0",
    "routes": {
      "leafMessagesToRouter": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/turbofanRouter/inputs/deviceInput\")",
      "classifierToRouter": "FROM /messages/modules/turbofanRulClassifier/outputs/amlOutput INTO BrokeredEndpoint(\"/modules/turbofanRouter/inputs/rulInput\")",
      "routerToClassifier": "FROM /messages/modules/turbofanRouter/outputs/classOutput INTO BrokeredEndpoint(\"/modules/turbofanRulClassifier/inputs/amlInput\")",
      "routerToIoTHub": "FROM /messages/modules/turboFanRouter/outputs/hubOutput INTO $upstream",
      "routerToAvro": "FROM /messages/modules/turbofanRouter/outputs/avroOutput INTO BrokeredEndpoint(\"/modules/avroFileWriter/inputs/avroModuleInput\")",
      "deadLetter": "FROM /messages/modules/turboFanRouter/outputs/deadMessages INTO $upstream"
    },
    "storeAndForwardConfiguration": {
      "timeToLiveSecs": 7200
    }
  }
}

비고

turbofanRouter 모듈을 추가하면 다음과 같은 추가 경로 turbofanRouterToIoTHub": "FROM /messages/modules/turbofanRouter/outputs/* INTO $upstream가 생성되었습니다. deployment.template.json 파일에 위에 나열된 경로만 그대로 두고 이 경로를 제거합니다.

Avro 기록기 모듈 추가

Avro 기록기 모듈에는 메시지를 저장하고 파일을 업로드하는 두 가지 책임이 솔루션에 있습니다.

  • 메시지 저장: Avro 기록기 모듈이 메시지를 받으면 Avro 형식으로 로컬 파일 시스템에 메시지를 씁니다. 디렉터리(이 경우 /data/avrofiles)를 모듈 컨테이너의 경로에 탑재하는 바인딩 탑재를 사용합니다. 이 마운트를 사용하면 모듈이 로컬 경로 (/avrofiles)에 쓰고 IoT Edge 디바이스에서 직접 해당 파일에 액세스할 수 있습니다.

  • 파일 업로드: Avro 기록기 모듈은 Azure IoT Hub 파일 업로드 기능을 사용하여 Azure Storage 계정에 파일을 업로드합니다. 파일이 성공적으로 업로드되면 모듈은 디스크에서 파일을 삭제합니다.

모듈 만들기 및 파일 복사

  1. Visual Studio Code에서 보기>를 선택하고, 명령 팔레트에서 Python: 인터프리터 선택을 검색하여 선택합니다.

  2. 설치된 Python 버전 3.7 이상을 선택합니다.

  3. Visual Studio Code에서 모듈 폴더를 마우스 오른쪽 단추로 클릭하고 IoT Edge 모듈 추가를 선택합니다.

  4. Python 모듈을 선택합니다.

  5. 모듈 avroFileWriter이름을 지정합니다.

  6. Docker 이미지 리포지토리에 대한 메시지가 표시되면 라우터 모듈을 추가할 때 사용한 것과 동일한 레지스트리를 사용합니다.

  7. 샘플 모듈에서 솔루션으로 파일을 복사합니다.

    copy C:\source\IoTEdgeAndMlSample\EdgeModules\modules\avroFileWriter\*.py C:\source\IoTEdgeAndMlSample\EdgeSolution\modules\avroFileWriter\
    
  8. main.py 덮어쓰기를 수락합니다.

  9. filemanager.py 및 schema.py 솔루션에 추가되었으며 main.py 업데이트되었습니다.

비고

Python 파일을 열면 pylint를 설치하라는 메시지가 표시될 수 있습니다. 이 자습서를 완료하기 위해 Linter를 설치할 필요가 없습니다.

데이터 파일에 대한 바인드 마운트

앞에서 설명한 것처럼 기록기 모듈은 바인딩 탑재의 존재에 의존하여 Avro 파일을 디바이스의 파일 시스템에 씁니다.

디바이스에 디렉터리 추가

  1. Azure portal에서 IoT Edge 디바이스 VM이 실행 중이지 않다면 시작합니다. SSH를 사용하여 연결합니다. 연결하려면 Azure Portal의 VM에 대한 개요 페이지에서 복사할 수 있는 DNS 이름이 필요합니다.

    ssh -l <user>@<vm name>.<region>.cloudapp.azure.com
    
  2. 로그인한 후 저장된 다운스트림 디바이스 메시지를 저장할 디렉터리를 만듭니다.

    sudo mkdir -p /data/avrofiles
    
  3. 컨테이너에서 쓸 수 있도록 디렉터리 권한을 업데이트합니다.

    sudo chmod ugo+rw /data/avrofiles
    
  4. 이제 디렉터리에 사용자, 그룹 및 소유자에 대한 쓰기(w) 권한이 부여되었는지 확인합니다.

    ls -la /data
    

    avrofiles에 대한 디렉터리 권한

모듈에 디렉터리 추가

모듈의 컨테이너에 디렉터리를 추가하려면 avroFileWriter 모듈과 연결된 Dockerfiles를 수정합니다. 모듈과 연결된 Dockerfile은 Dockerfile.amd64, Dockerfile.amd64.debug 및 Dockerfile.arm32v7입니다. arm32 디바이스를 디버그하거나 배포하려는 경우 이러한 파일을 동기화 상태로 유지해야 합니다. 이 문서에서는 Dockerfile.amd64에만 집중합니다.

  1. 개발 VM에서 C:\source\IoTEdgeAndMlSample\EdgeSolution\modules\avoFileWriter\Dockerfile.amd64 파일을 엽니다.

  2. 다음 예제와 같이 파일을 수정합니다.

    FROM ubuntu:xenial
    
    WORKDIR /app
    
    RUN apt-get update && apt-get install -y --no-install-recommends libcurl4-openssl-dev
    python3-pip libboost-python1.58-dev libpython3-dev && rm -rf /var/lib/apt/lists/*
    
    RUN pip3 install --upgrade pip
    COPY requirements.txt ./
    RUN pip install -r requirements.txt
    
    COPY . .
    
    RUN useradd -ms /bin/bash moduleuser
    RUN mkdir /avrofiles && chown moduleuser /avrofiles
    USER moduleuser
    
    CMD [ "python3", "-u", "./main.py" ]
    

    mkdirchown 명령은 Docker 빌드 프로세스에 이미지에서 /avrofiles라는 최상위 디렉터리를 만든 다음 모듈러를 해당 디렉터리의 소유자로 만들도록 지시합니다. 이 명령들은 반드시 모듈 사용자를 "useradd" 명령을 사용하여 이미지에 추가한 후 컨텍스트가 "moduleuser"로 전환되기 전에 삽입해야 합니다.

  3. 필요한 경우 Dockerfile.amd64.debug 및 Dockerfile.arm32v7을 변경합니다.

avroFileWriter에 바인딩 구성 추가

바인딩을 만드는 마지막 단계는 바인딩 정보로 deployment.template.json(및 deployment.debug.template.json) 파일을 업데이트하는 것입니다.

  1. deployment.template.json을 여세요.

  2. 컨테이너 디렉터리 /avrofiles를 가리키는 매개 변수를 에지 디바이스의 로컬 디렉터리에 추가하여 Binds avroFileWriter에 대한 모듈 정의를 수정합니다. 모듈 정의는 다음 예제와 일치해야 합니다.

    "avroFileWriter": {
      "version": "1.0",
      "type": "docker",
      "status": "running",
      "restartPolicy": "always",
      "settings": {
        "image": "${MODULES.avroFileWriter}",
        "createOptions": {
          "HostConfig": {
            "Binds": [
              "/data/avrofiles:/avrofiles"
            ]
          }
        }
      }
    }
    

config.yaml에 액세스하기 위한 바인드 마운트

기록기 모듈에 대해 바인딩을 하나 더 추가해야 합니다. 이 바인딩은 IoT Edge 디바이스의 /etc/iotedge/config.yaml 파일에서 연결 문자열을 읽을 수 있는 모듈 액세스 권한을 제공합니다. upload_blob_async 메서드를 호출하여 IoT Hub에 파일을 업로드할 수 있도록 IoTHubClient를 만들려면 연결 문자열이 필요합니다. 이 바인딩을 추가하는 단계는 이전 섹션의 단계와 비슷합니다.

디렉터리 권한 업데이트

  1. SSH를 사용하여 IoT Edge 디바이스에 연결합니다.

    ssh -l <user>@IoTEdge-<extension>.<region>.cloudapp.azure.com
    
  2. config.yaml 파일에 읽기 권한을 추가합니다.

    sudo chmod +r /etc/iotedge/config.yaml
    
  3. 사용 권한이 올바르게 설정되었는지 확인합니다.

    ls -la /etc/iotedge/
    
  4. config.yaml에 대한 사용 권한이 -r--r--r--인지 확인합니다.

모듈에 디렉터리 추가

  1. 개발 머신에서 Dockerfile.amd64 파일을 엽니다.

  2. 다음과 같이 파일에 추가 집합 mkdirchown 명령을 추가합니다.

    FROM ubuntu:xenial
    
    WORKDIR /app
    
    RUN apt-get update && apt-get install -y --no-install-recommends libcurl4-openssl-dev
    python3-pip libboost-python1.58-dev libpython3-dev && rm -rf /var/lib/apt/lists/\*
    
    RUN pip3 install --upgrade pip
    COPY requirements.txt ./
    RUN pip install -r requirements.txt
    
    COPY . .
    
    RUN useradd -ms /bin/bash moduleuser
    RUN mkdir /avrofiles && chown moduleuser /avrofiles
    RUN mkdir -p /app/iotconfig && chown moduleuser /app/iotconfig
    
    USER moduleuser
    
    CMD "python3", "-u", "./main.py"]
    
  3. Dockerfile.amd64.debug 및 Dockerfile.arm32v7을 변경합니다.

모듈 구성 업데이트

  1. deployment.template.json 파일을 엽니다.

  2. 컨테이너 디렉터리(/app/iotconfig)를 디바이스의 로컬 디렉터리(/etc/iotedge)로 가리키는 매개 변수에 두 번째 줄을 Binds 추가하여 avroFileWriter에 대한 모듈 정의를 수정합니다.

    "avroFileWriter": {
      "version": "1.0",
      "type": "docker",
      "status": "running",
      "restartPolicy": "always",
      "settings": {
        "image": "${MODULES.avroFileWriter}",
        "createOptions": {
          "HostConfig": {
            "Binds": [
              "/data/avrofiles:/avrofiles",
              "/etc/iotedge:/app/iotconfig"
            ]
          }
        }
      }
    }
    
  3. deployment.debug.template.json에 적절한 변경 사항을 하십시오.

종속성 설치

기록기 모듈은 fastavro 및 PyYAML이라는 두 개의 Python 라이브러리에 종속됩니다. 개발 머신에 종속성을 설치하고 Docker 빌드 프로세스에 모듈 이미지에 설치하도록 지시해야 합니다.

PyYAML

  1. 개발 컴퓨터에서 파일을 열고 파일의 C:\source\IoTEdgeAndMlSample\EdgeSolution\modules\avoFileWriter\requirements.txt 새 줄에 "pyyaml"을 추가합니다.

    azure-iothub-device-client~=1.4.3
    pyyaml
    
  2. Dockerfile.amd64 파일을 열고 setuptools를 pip install 업그레이드하는 명령을 추가합니다.

    FROM ubuntu:xenial
    
    WORKDIR /app
    
    RUN apt-get update && \
        apt-get install -y --no-install-recommends libcurl4-openssl-dev python3-pip libboost-python1.58-dev libpython3-dev && \
        rm -rf /var/lib/apt/lists/\*
    
    RUN pip3 install --upgrade pip
    RUN pip install -U pip setuptools
    COPY requirements.txt ./
    RUN pip install -r requirements.txt
    
    COPY . .
    
    RUN useradd -ms /bin/bash moduleuser
    RUN mkdir /avrofiles && chown moduleuser /avrofiles
    RUN mkdir -p /app/iotconfig && chown moduleuser /app/iotconfig
    USER moduleuser
    
    CMD [ "python3", "-u", "./main.py" ]
    
  3. 명령 프롬프트에서 개발 컴퓨터에 pyyaml을 설치합니다.

    pip install pyyaml
    

Fastavro

  1. requirements.txtpyyaml 후에 fastavro를 추가합니다.

    azure-iothub-device-client~=1.4.3
    pyyaml
    fastavro
    
  2. 개발 머신에 fastavro를 설치합니다.

    pip install fastavro
    

IoT Hub 다시 구성

IoT Edge 디바이스 및 모듈을 시스템에 도입함으로써 허브로 전송될 데이터와 용도에 대한 기대치를 변경했습니다. 새로운 현실을 처리하기 위해 허브에서 라우팅을 다시 구성해야 합니다.

비고

avroFileWriter 모듈이 올바르게 실행되려면 일부 허브 설정, 특히 파일 업로드를 올바르게 설정해야 하므로 모듈을 배포하기 전에 허브를 다시 구성합니다.

IoT Hub에서 RUL 메시지에 대한 경로 설정

라우터 및 분류자를 사용하면 디바이스 ID와 디바이스에 대한 RUL 예측만 포함하는 일반 메시지를 수신할 것으로 예상됩니다. 필요에 따라 디바이스의 상태를 모니터링하고, 보고서를 빌드하고, 경고를 실행할 수 있는 자체 스토리지 위치로 RUL 데이터를 라우팅하려고 합니다. 동시에 아직 IoT Edge 디바이스에 연결되지 않은 다운스트림 디바이스에서 직접 전송되는 모든 디바이스 데이터가 현재 스토리지 위치로 계속 라우팅되도록 합니다.

RUL 메시지 경로 만들기

  1. Azure Portal에서 IoT Hub로 이동합니다.

  2. 왼쪽 창의 메뉴에서 허브 설정에서 메시지 라우팅을 선택합니다.

  3. 경로 탭에서 추가를 선택합니다.

  4. 경로 이름을 RulMessageRoute로 지정합니다.

  5. 엔드포인트 선택기 오른쪽에 엔드포인트 추가를 선택하고 스토리지를 선택합니다.

  6. 스토리지 엔드포인트 추가 페이지에서 엔드포인트ruldata의 이름을 지정합니다.

  7. 컨테이너 선택을 선택합니다.

  8. Storage 계정 페이지에서 이 자습서 전체에서 사용 중인 스토리지 계정을 찾습니다. 이 계정은 iotedgeandml<고유 접미사>처럼 명명됩니다.

  9. ruldata 컨테이너를 선택하고 선택을 클릭합니다.

  10. 스토리지 엔드포인트 추가 페이지에서 만들기를 선택하여 스토리지 엔드포인트를 만듭니다.

  11. 경로 추가 페이지로 돌아가 라우팅 쿼리의 경우 true을(를) 다음 쿼리로 바꿉니다.

    IS_DEFINED($body.PredictedRul) AND NOT IS_DEFINED($body.OperationalSetting1)
    
  12. 테스트 섹션을 확장한 다음 메시지 본문 섹션을 확장합니다. 메시지 본문을 예상 메시지의 다음 예제로 바꿉다.

    {
      "ConnectionDeviceId": "aaLeafDevice_1",
      "CorrelationId": "b27e97bb-06c5-4553-a064-e9ad59c0fdd3",
      "PredictedRul": 132.62721409309165,
      "CycleTime": 64.0
    }
    
  13. 테스트 경로를 선택합니다. 테스트에 성공하면 "메시지가 쿼리와 일치함"이 표시됩니다.

  14. 저장을 클릭합니다.

turbofanDeviceDataToStorage 경로 업데이트

새 예측 데이터를 이전 스토리지 위치로 라우팅하지 않으려면 경로를 업데이트하여 방지합니다.

  1. IoT Hub 메시지 라우팅 페이지에서 경로 탭을 선택합니다.

  2. turbofanDeviceDataToStorage 또는 초기 디바이스 데이터 경로에 지정한 이름을 선택합니다.

  3. 라우팅 쿼리를 로 업데이트합니다.

    IS_DEFINED($body.OperationalSetting1)
    
  4. 테스트 섹션을 확장한 다음 메시지 본문 섹션을 확장합니다. 메시지를 예상 메시지의 다음 예제로 바꿉다.

    {
      "Sensor13": 2387.96,
      "OperationalSetting1": -0.0008,
      "Sensor6": 21.61,
      "Sensor11": 47.2,
      "Sensor9": 9061.45,
      "Sensor4": 1397.86,
      "Sensor14": 8140.39,
      "Sensor18": 2388.0,
      "Sensor12": 522.87,
      "Sensor2": 642.42,
      "Sensor17": 391.0,
      "OperationalSetting3": 100.0,
      "Sensor1": 518.67,
      "OperationalSetting2": 0.0002,
      "Sensor20": 39.03,
      "DeviceId": 19.0,
      "Sensor5": 14.62,
      "PredictedRul": 212.00132402791962,
      "Sensor8": 2388.01,
      "Sensor16": 0.03,
      "CycleTime": 42.0,
      "Sensor21": 23.3188,
      "Sensor15": 8.3773,
      "Sensor3": 1580.09,
      "Sensor10": 1.3,
      "Sensor7": 554.57,
      "Sensor19": 100.0
    }
    
  5. 테스트 경로를 선택합니다. 테스트에 성공하면 "메시지가 쿼리와 일치함"이 표시됩니다.

  6. 저장을 선택합니다.

파일 업로드 구성

파일 작성기 모듈이 스토리지에 파일을 업로드할 수 있도록 IoT Hub 파일 업로드 기능을 구성합니다.

  1. IoT Hub의 왼쪽 창 메뉴에서 허브 설정에서 파일 업로드를 선택합니다.

  2. Azure Storage 컨테이너를 선택합니다.

  3. 목록에서 스토리지 계정을 선택합니다.

  4. guid가 추가된 azureml-blobstore 로 시작하는 컨테이너를 선택하고 선택을 클릭합니다.

  5. 저장을 선택합니다. 저장이 완료되면 포털에서 알 수 있습니다.

비고

이 자습서에서는 업로드 알림을 켜지 않지만 파일 업로드 알림을 처리하는 방법에 대한 자세한 내용은 파일 업로드 알림 받기 를 참조하세요.

모듈 빌드, 게시 및 배포

구성을 변경했으므로 이미지를 빌드하고 Azure 컨테이너 레지스트리에 게시할 준비가 되었습니다. 빌드 프로세스는 deployment.template.json 파일을 사용하여 빌드해야 하는 모듈을 결정합니다. 버전을 포함한 각 모듈의 설정은 모듈 폴더의 module.json 파일에 있습니다. 빌드 프로세스는 먼저 module.json 파일에 있는 현재 구성과 일치하는 Dockerfiles에서 Docker 빌드를 실행하여 이미지를 만듭니다. 그런 다음 module.json 파일의 버전 태그와 일치하는 버전 태그를 사용하여 module.json 파일의 레지스트리에 이미지를 게시합니다. 마지막으로 IoT Edge 디바이스에 배포할 구성별 배포 매니페스트(예: deployment.amd64.json)를 생성합니다. IoT Edge 디바이스는 배포 매니페스트에서 정보를 읽고 지침에 따라 모듈을 다운로드하고 경로를 구성하며 원하는 속성을 설정합니다. 이 배포 방법에는 알아야 할 두 가지 부작용이 있습니다.

  • 배포 지연: IoT Edge 런타임은 다시 구성하기 전에 원하는 속성의 변경 내용을 인식해야 하므로 런타임이 모듈을 선택하고 IoT Edge 디바이스를 업데이트하기 시작할 때까지 모듈을 배포한 후 약간의 시간이 걸릴 수 있습니다.

  • 모듈 버전이 중요합니다. 이전 모듈과 동일한 버전 태그를 사용하여 컨테이너 레지스트리에 모듈 컨테이너의 새 버전을 게시하는 경우 런타임은 새 버전의 모듈을 다운로드하지 않습니다. 로컬 이미지의 버전 태그와 배포 매니페스트에서 원하는 이미지를 비교합니다. 해당 버전이 일치하면 런타임은 아무 작업도 수행하지 않습니다. 따라서 새 변경 내용을 배포할 때마다 모듈 버전을 증가해야 합니다. 변경하려는 모듈에 대한 module.json 파일의 태그 속성 아래에 있는 버전 속성을 변경하여 버전을 증분합니다. 그런 다음, 모듈을 빌드하고 게시합니다.

    {
      "$schema-version": "0.0.1",
      "description": "",
      "image": {
        "repository": "<your registry>.azurecr.io/avrofilewriter",
        "tag": {
          "version": "0.0.1",
          "platforms": {
            "amd64": "./Dockerfile.amd64",
            "amd64.debug": "./Dockerfile.amd64.debug",
            "arm32v7": "./Dockerfile.arm32v7"
          }
        },
        "buildOptions": []
      },
      "language": "python"
    }
    

빌드 및 게시

  1. 개발 VM에서 실행되고 있지 않은 경우 Docker를 시작합니다.

  2. Visual Studio Code에서 명령 프롬프트를 사용하여 새 터미널을 시작하고 ACR(Azure Container Registry)에 로그인합니다.

Azure Portal에서 필요한 사용자 이름, 암호 및 로그인 서버 값을 찾을 수 있습니다. 컨테이너 레지스트리 이름에는 "turbofandemo<고유 ID>" 형식이 있습니다. 왼쪽 창 메뉴의 설정에서 액세스 키를 선택하여 확인합니다.

docker login -u <ACR username> -p <ACR password> <ACR login server>
  1. Visual Studio Code에서 deployment.template.json 마우스 오른쪽 단추로 클릭하고 IoT Edge 솔루션 빌드 및 푸시를 선택합니다.

레지스트리에서 모듈 보기

빌드가 성공적으로 완료되면 Azure Portal을 사용하여 게시된 모듈을 검토할 수 있습니다.

  1. 이 자습서에 대한 Azure Container Registry를 엽니다. 컨테이너 레지스트리 이름에는 "turbofandemo<고유 ID>" 형식이 있습니다.

  2. 왼쪽 창 메뉴의 서비스 아래에서 리포지토리를 선택합니다.

  3. 만든 모듈인 avrofilewriterturbofanrouter는 모두 리포지토리로 표시됩니다.

  4. turbofanrouter를 선택하고 0.0.1-amd64로 태그가 지정된 이미지 하나를 게시했습니다.

    첫 번째 태그가 지정된 turbofanrouter 버전 보기

IoT Edge 디바이스에 모듈 배포

솔루션에서 모듈을 빌드하고 구성했으므로 이제 모듈을 IoT Edge 디바이스에 배포합니다.

  1. Visual Studio Code에서 구성 폴더의 deployment.amd64.json 파일을 마우스 오른쪽 단추로 클릭합니다.

  2. 단일 디바이스에 대한 배포 만들기를 선택합니다.

  3. IoT Edge 디바이스 aaTurboFanEdgeDevice를 선택합니다.

  4. Visual Studio Code 탐색기에서 Azure IoT Hub 디바이스 패널을 새로 고칩니다. 세 개의 새 모듈이 배포되었지만 아직 실행되고 있지 않은 것을 볼 수 있습니다.

  5. 몇 분 후에 다시 새로 고치면 모듈이 실행되는 것을 볼 수 있습니다.

    Visual Studio Code에서 실행 중인 모듈 보기

비고

모듈이 시작되고 안정적인 실행 상태로 전환되는 데 몇 분 정도 걸릴 수 있습니다. 이 시간 동안 모듈이 IoT Edge 허브 모듈과의 연결을 설정하려고 할 때 시작 및 중지되는 것을 볼 수 있습니다.

오류 진단

이 섹션에서는 모듈 또는 모듈에서 무엇이 잘못되었는지 이해하기 위한 몇 가지 기술을 공유합니다. Visual Studio Code의 상태에서 오류를 먼저 발견할 수 있는 경우가 많습니다.

실패한 모듈 식별

  • Visual Studio Code: Azure IoT Hub 디바이스 패널을 살펴봅니다. 대부분의 모듈이 실행 중 상태이지만 한 모듈이 중지된 경우 중지된 모듈을 추가로 조사해야 합니다. 모든 모듈이 오랜 시간 동안 중지된 상태인 경우 실패를 나타낼 수도 있습니다.

  • Azure Portal: 포털에서 IoT Hub로 이동한 다음 디바이스 세부 정보 페이지(IoT Edge에서 디바이스로 드릴 인)를 찾으면 모듈이 오류를 보고했거나 IoT Hub에 아무것도 보고하지 않은 것을 발견할 수 있습니다.

디바이스에서 진단

IoT Edge 디바이스(이 경우 Linux VM)에 로그인하면 모듈의 상태에 대한 다양한 정보에 액세스할 수 있습니다. 사용하는 주요 메커니즘은 디바이스에서 컨테이너 및 이미지를 검사할 수 있는 Docker 명령입니다.

  1. IoT Edge 디바이스에 로그인합니다.

    ssh -l <user>@IoTEdge-<extension>.<region>.cloudapp.azure.com
    
  2. 실행 중인 모든 컨테이너를 나열합니다. 각 모듈에 대해 모듈에 해당하는 이름을 가진 컨테이너를 볼 것으로 예상합니다. 또한 이 명령은 예상과 일치할 수 있도록 버전을 포함하여 컨테이너에 대한 정확한 이미지를 나열합니다. 명령에서 "컨테이너"에 대해 "image"를 대체하여 이미지를 나열할 수도 있습니다.

    sudo docker container ls
    
  3. 컨테이너에 대한 로그를 가져옵니다. 이 명령은 컨테이너의 StdErr 및 StdOut에 기록된 내용을 출력합니다. 이 명령은 어떤 이유로 시작한 후 사망한 컨테이너에 대해 작동합니다. edgeAgent 또는 edgeHub 컨테이너에서 발생한 일을 이해하는 데에도 유용합니다.

    sudo docker container logs <container id>
    
  4. 컨테이너를 검사합니다. 이 명령은 이미지에 대한 많은 정보를 제공합니다. 원하는 항목에 따라 데이터를 필터링할 수 있습니다. 예를 들어 avroFileWriter의 바인딩이 올바른지 확인하려면 다음 명령을 사용할 수 있습니다.

    sudo docker container inspect -f "{{ json .Mounts }}" avroFileWriter | python -m json.tool
    
  5. 실행 중인 컨테이너에 연결합니다. 이 명령은 컨테이너가 실행되는 동안 검사하려는 경우에 유용할 수 있습니다.

    sudo docker exec -it avroFileWriter bash
    

자원을 정리하세요

이 자습서는 각 문서가 이전 문서에서 수행한 작업을 기반으로 빌드되는 집합의 일부입니다. 최종 자습서를 완료할 때까지 리소스를 정리해 주세요.

다음 단계

이 문서에서는 분류자, 라우터 및 파일 작성기/업로더의 세 가지 모듈을 사용하여 Visual Studio Code에서 IoT Edge 솔루션을 만들었습니다. 모듈이 에지 디바이스에서 서로 통신할 수 있도록 경로를 설정했습니다. 에지 디바이스의 구성을 수정하고 Dockerfiles를 업데이트하여 종속성을 설치하고 모듈의 컨테이너에 바인딩 탑재를 추가했습니다.

다음으로, 형식에 따라 메시지를 라우팅하고 파일 업로드를 처리하도록 IoT Hub의 구성을 업데이트했습니다. 모든 것이 준비되었으므로 모듈을 IoT Edge 디바이스에 배포하고 모듈이 올바르게 실행되고 있는지 확인했습니다.

다음 문서로 이동하여 데이터 보내기를 시작하고 작동 중인 솔루션을 확인합니다.