IoT Edge에서 모듈을 배포하고 경로를 설정하는 방법 알아보기

적용 대상:IoT Edge 1.4 checkmark IoT Edge 1.4

Important

IoT Edge 1.4는 지원되는 릴리스입니다. 이전 릴리스에 있는 경우 IoT Edge 업데이트를 참조하세요.

각 IoT Edge 디바이스는 적어도 $edgeAgent 및 $edgeHub라는 두 개의 모듈을 실행합니다. 두 모듈은 IoT Edge 런타임의 일부입니다. IoT Edge 디바이스는 개수에 관계 없는 프로세스에 대해 여러 모듈을 실행할 수 있습니다. 배포 매니페스트를 사용하여 설치할 모듈 및 함께 작동하도록 구성하는 방법을 디바이스에 알립니다.

배포 매니페스트는 다음 항목을 설명하는 JSON 문서입니다.

  • 다음 세 가지 구성 요소를 포함하는 IoT Edge 에이전트 모듈 쌍
    • 디바이스에서 실행되는 각 모듈의 컨테이너 이미지
    • 모듈 이미지를 포함하는 프라이빗 컨테이너 레지스트리에 액세스하기 위한 자격 증명
    • 각 모듈을 만들고 관리하는 방법에 대한 지침
  • 모듈 간 및 궁극적으로 IoT Hub에 대한 메시지 흐름 방법을 포함하는 IoT Edge 허브 모듈 쌍입니다.
  • 추가 모듈 쌍의 원하는 속성(선택 사항)

모든 IoT Edge 디바이스는 배포 매니페스트로 구성해야 합니다. 새로 설치된 IoT Edge 런타임은 유효한 매니페스트로 구성될 때까지 오류 코드를 보고합니다.

Azure IoT Edge 자습서에서는 Azure IoT Edge 포털의 마법사를 통해 배포 매니페스트를 빌드합니다. REST 또는 IoT Hub 서비스 SDK를 사용하여 프로그래밍 방식으로 배포 매니페스트를 적용할 수도 있습니다. 자세한 내용은 IoT Edge 배포 이해를 참조하세요.

배포 매니페스트 만들기

상위 수준에서 배포 매니페스트는 원하는 속성으로 구성된 모듈 쌍의 목록입니다. 배포 매니페스트는 설치할 모듈과 구성 방법을 IoT Edge 디바이스(또는 디바이스 그룹)에 알려 줍니다. 배포 매니페스트에는 각 모듈 쌍의 ‘원하는 속성’이 포함되어 있습니다. IoT Edge 디바이스는 각 모듈에 대해 ‘보고된 속성’을 다시 보고합니다.

모든 배포 매니페스트에는 $edgeAgent$edgeHub라는 두 개의 모듈이 필요합니다. 두 모듈은 IoT Edge 디바이스와 이 디바이스에서 실행되는 모듈을 관리하는 IoT Edge 런타임의 일부입니다. 이러한 모듈에 대한 자세한 내용은 IoT Edge 런타임 및 해당 아키텍처 이해를 참조하세요.

두 개의 런타임 모듈 외에도 IoT Edge 디바이스에서 실행할 고유한 모듈을 최대 50개까지 추가할 수 있습니다.

IoT Edge 런타임(edgeAgent 및 edgeHub)만 포함하는 배포 매니페스트가 유효합니다.

배포 매니페스트는 다음 구조를 따릅니다.

{
  "modulesContent": {
    "$edgeAgent": { // required
      "properties.desired": {
        // desired properties of the IoT Edge agent
        // includes the image URIs of all deployed modules
        // includes container registry credentials
      }
    },
    "$edgeHub": { //required
      "properties.desired": {
        // desired properties of the IoT Edge hub
        // includes the routing information between modules, and to IoT Hub
      }
    },
    "module1": {  // optional
      "properties.desired": {
        // desired properties of module1
      }
    },
    "module2": {  // optional
      "properties.desired": {
        // desired properties of module2
      }
    }
  }
}

모듈 구성

IoT Edge 런타임에서 사용자 배포에 모듈을 설치하는 방법을 정의합니다. IoT Edge 에이전트는 IoT Edge 디바이스에 대한 설치, 업데이트 및 상태 보고를 관리하는 런타임 구성 요소입니다. 따라서 $edgeAgent 모듈 쌍에는 모든 모듈에 대한 구성 및 관리 정보가 포함되어 있습니다. 이 정보에는 IoT Edge 에이전트 자체에 대한 구성 매개 변수가 포함됩니다.

$edgeAgent 속성은 다음과 같은 구조를 따릅니다.

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "runtime": {
          "settings":{
            "registryCredentials":{
              // give the IoT Edge agent access to container images that aren't public
            }
          }
        },
        "systemModules": {
          "edgeAgent": {
            // configuration and management details
          },
          "edgeHub": {
            // configuration and management details
          }
        },
        "modules": {
          "module1": {
            // configuration and management details
          },
          "module2": {
            // configuration and management details
          }
        }
      }
    },
    "$edgeHub": { ... },
    "module1": { ... },
    "module2": { ... }
  }
}

IoT Edge 에이전트 스키마 버전 1.1은 IoT Edge 버전 1.0.10 함께 출시되었으며 모듈 시작 순서를 사용하도록 설정합니다. 1.0.10 이상 버전을 실행하는 IoT Edge 배포의 경우 스키마 버전 1.1이 권장됩니다.

모듈 구성 및 관리

IoT Edge 에이전트의 원하는 속성 목록에서는 IoT Edge 디바이스에 배포되는 모듈과 구성 및 관리 방법을 정의합니다.

포함될 수 있거나 포함되어야 하는 원하는 속성의 전체 목록은 IoT Edge 에이전트 및 IoT Edge 허브의 속성을 참조하세요.

예시:

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "runtime": { ... },
        "systemModules": {
          "edgeAgent": { ... },
          "edgeHub": { ... }
        },
        "modules": {
          "module1": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 2,
            "settings": {
              "image": "myacr.azurecr.io/module1:latest",
              "createOptions": "{}"
            }
          },
          "module2": { ... }
        }
      }
    },
    "$edgeHub": { ... },
    "module1": { ... },
    "module2": { ... }
  }
}

모든 모듈에는 모듈 이미지, 컨테이너 레지스트리의 컨테이너 이미지에 대한 주소, 시작 시 이미지를 구성하는 createOptions가 포함된 settings 속성이 있습니다. 자세한 내용은 IoT Edge 모듈에 대한 컨테이너 만들기 옵션 구성 방법을 참조하세요.

EdgeHub 모듈 및 사용자 지정 모듈에는 IoT Edge 에이전트에 관리 방법을 알려주는 세 가지 속성도 있습니다.

  • Status: 모듈을 처음 배포할 때 실행 중이어야 하는지 아니면 중지되어야 하는지를 나타냅니다. 필수입니다.

  • RestartPolicy: 모듈이 중지된 경우 IoT Edge 에이전트가 모듈을 다시 시작해야 하는지 여부 및 다시 시작해야 하는 시기를 나타냅니다. 모듈이 오류 없이 중지되면 자동으로 시작되지 않습니다. 자세한 내용은 Docker Docs - 컨테이너 자동 시작을 참조하세요. 필수입니다.

  • StartupOrder: IoT Edge 버전 1.0.10에 도입되었습니다. IoT Edge 에이전트가 처음 배포될 때 모듈을 시작해야 하는 순서입니다. 이 순서는 정수를 사용하여 선언됩니다. 여기서 시작 값이 0인 모듈이 먼저 시작된 다음, 시작 값이 더 높은 모듈이 다음에 시작됩니다. edgeAgent 모듈은 항상 먼저 시작되기 때문에 시작 값이 없습니다. 선택 사항.

    IoT Edge 에이전트는 시작 값 순서로 모듈을 시작하지만 각 모듈이 완료될 때까지 기다리지 않고 다음 모듈로 이동합니다.

    시작 순서는 일부 모듈이 다른 모듈에 의존하는 경우에 유용합니다. 예를 들어 다른 모듈이 시작될 때 메시지를 라우팅할 준비가 되도록 edgeHub 모듈을 먼저 시작할 수 있습니다. 또는 데이터를 전송하는 모듈을 시작하기 전에 스토리지 모듈을 시작할 수도 있습니다. 그러나 항상 다른 모듈의 실패를 처리하도록 모듈을 디자인해야 합니다. 언제든지 횟수에 관계없이 중지 및 다시 시작될 수 있는 것이 컨테이너의 특성입니다.

    참고 항목

    모듈의 속성을 변경하면 해당 모듈이 다시 시작됩니다. 예를 들어 다음에 대한 속성을 변경하면 다시 시작이 발생합니다.

    • 모듈 이미지
    • Docker 만들기 옵션
    • 환경 변수
    • 다시 시작 정책
    • 이미지 끌어오기 정책
    • version
    • 시작 순서

    모듈 속성이 변경되지 않으면 모듈이 다시 시작되지 않습니다.

경로 선언

IoT Edge 허브는 모듈, IoT Hub 및 다운스트림 디바이스 간의 통신을 관리합니다. 따라서 $edgeHub 모듈 쌍에는 메시지가 배포 내에서 전달되는 방식을 선언하는 ‘경로’라는 원하는 속성이 포함되어 있습니다. 동일한 배포 내에 여러 경로가 있을 수 있습니다.

경로는 다음과 같은 구문을 사용하여 $edgeHub 원하는 속성에 선언됩니다.

{
  "modulesContent": {
    "$edgeAgent": { ... },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "routes": {
          "route1": "FROM <source> WHERE <condition> INTO <sink>",
          "route2": {
            "route": "FROM <source> WHERE <condition> INTO <sink>",
            "priority": 0,
            "timeToLiveSecs": 86400
          }
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 10
        }
      }
    },
    "module1": { ... },
    "module2": { ... }
  }
}

IoT Edge 허브 스키마 버전 1은 IoT Edge 버전 1.0.10과 함께 릴리스되었으며 경로 우선 순위 지정 및 TTL(Time To Live)을 사용하도록 설정합니다. 1.0.10 이상 버전을 실행하는 IoT Edge 배포의 경우 스키마 버전 1.1이 권장됩니다.

모든 경로에는 메시지가 제공된 원본과 메시지가 이동하는 싱크가 필요합니다. 조건은 메시지를 필터링하는 데 사용할 수 있는 선택적 부분입니다.

메시지를 먼저 처리하려는 경로에 우선 순위를 할당할 수 있습니다. 이 기능은 업스트림 연결이 약하거나 제한되고 표준 원격 분석 메시지보다 우선적으로 고려해야 하는 중요한 데이터가 있는 시나리오에서 유용합니다.

원본

원본은 메시지가 발생한 위치를 지정합니다. IoT Edge는 모듈 또는 다운스트림 디바이스의 메시지를 라우팅할 수 있습니다.

IoT SDK를 사용하여 모듈은 ModuleClient 클래스를 사용하여 메시지에 대한 특정 출력 큐를 선언할 수 있습니다. 출력 큐는 필요하지 않지만 여러 경로를 관리하는 데 유용합니다. 다운스트림 디바이스는 IoT Hub에 메시지를 전송하는 것과 동일한 방식으로 IoT SDK의 DeviceClient 클래스를 사용하여 IoT Edge 게이트웨이 디바이스에 메시지를 보낼 수 있습니다. 자세한 내용은 Azure IoT Hub SDK 이해 및 사용을 참조하세요.

원본 속성은 다음 값 중 하나일 수 있습니다.

원본 설명
/* 모든 모듈 또는 다운스트림 디바이스의 모든 디바이스-클라우드 메시지 또는 트윈 변경 알림
/twinChangeNotifications 모든 모듈 또는 다운스트림 디바이스에서 발생하는 모든 트윈 변경(보고된 속성)
/messages/* 일부 출력을 통하거나 어떠한 출력도 없이 모듈 또는 다운스트림 디바이스에서 보낸 모든 디바이스-클라우드 메시지
/messages/modules/* 일부 출력을 통하거나 어떠한 출력도 없이 모듈에서 보낸 모든 디바이스-클라우드 메시지
/messages/modules/<moduleId>/* 일부 출력을 통하거나 어떠한 출력도 없이 특정 모듈에서 보낸 모든 디바이스-클라우드 메시지
/messages/modules/<moduleId>/outputs/* 일부 출력을 통해 특정 모듈에서 보낸 모든 디바이스-클라우드 메시지
/messages/modules/<moduleId>/outputs/<output> 특정 출력을 통해 특정 모듈에서 보낸 모든 디바이스-클라우드 메시지

조건

조건은 경로 선언의 선택 사항입니다. 원본으로 싱크로 모든 메시지를 전달하려는 경우 전체 WHERE 절을 그대로 둡니다. 또는 IoT Hub 쿼리 언어를 사용하여 조건을 만족하는 특정 메시지 또는 메시지 유형에 대해 필터링할 수 있습니다. IoT Edge 경로는 쌍 태그 또는 속성을 기반으로 하는 메시지 필터링을 지원하지 않습니다.

IoT Edge의 모듈 간에 전달되는 메시지는 디바이스와 Azure IoT Hub 간에 전달되는 메시지와 동일한 서식이 지정됩니다. 모든 메시지는 JSON으로 서식이 지정되고 systemProperties, appPropertiesbody 매개 변수를 포함합니다.

다음 구문을 사용하여 3개 매개 변수 중 하나를 중심으로 쿼리를 작성할 수 있습니다.

  • 시스템 속성: $<propertyName> 또는 {$<propertyName>}
  • 애플리케이션 속성: <propertyName>
  • 본문 속성: $body.<propertyName>

메시지 속성에 대한 쿼리를 만드는 방법에 대한 예제는 디바이스-클라우드 메시지 경로에 대한 쿼리 식을 참조하세요.

IoT Edge에 특정되는 예제는 다운스트림 디바이스에서 게이트웨이 디바이스에 도착하는 메시지를 필터링하려는 경우입니다. 모듈에서 전송된 메시지에는 connectionModuleId라는 시스템 속성이 포함되어 있습니다. 따라서 다운스트림 디바이스에서 IoT Hub로 직접 메시지를 라우팅하려는 경우 다음 경로를 사용하여 모듈 메시지를 제외합니다.

FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream

sink

싱크는 메시지를 보낼 위치를 정의합니다. 모듈 및 IoT Hub만 메시지를 받을 수 있습니다. 메시지를 다른 디바이스로 라우팅할 수 없습니다. 싱크 속성에는 와일드카드 옵션이 없습니다.

싱크 속성은 다음 값 중 하나일 수 있습니다.

싱크 설명
$upstream 메시지를 IoT Hub로 보냅니다.
BrokeredEndpoint("/modules/<moduleId>/inputs/<input>") 특정 모듈의 특정 입력으로 메시지 보내기

IoT Edge는 최소 한 번의 보장을 제공합니다. IoT Edge 허브는 경로에서 해당 싱크로 메시지를 전달할 수 없는 경우 로컬에 메시지를 저장합니다. 예를 들어 IoT Edge 허브에서 IoT Hub에 연결할 수 없거나 대상 모듈이 연결되지 않은 경우입니다.

IoT Edge 허브는 IoT Edge 허브 원하는 속성storeAndForwardConfiguration.timeToLiveSecs 속성에서 지정된 시간까지 메시지를 저장합니다.

우선 순위 및 TTL(Time to Live)

경로는 경로를 정의하는 문자열 또는 경로 문자열, 우선 순위 정수 및 TTL(Time-to-Live) 정수를 사용하는 개체로 선언할 수 있습니다.

옵션 1:

"route1": "FROM <source> WHERE <condition> INTO <sink>",

IoT Edge 허브 스키마 버전 1.1이 있는 IoT Edge 버전 1.0.10에 도입된 옵션 2:

"route2": {
  "route": "FROM <source> WHERE <condition> INTO <sink>",
  "priority": 0,
  "timeToLiveSecs": 86400
}

우선 순위 값은 0-9 범위일 수 있습니다. 여기서 0은 가장 높은 우선 순위입니다. 메시지는 엔드포인트에 따라 큐에 대기됩니다. 특정 엔드포인트를 대상으로 하는 모든 우선 순위 0 메시지는 동일한 엔드포인트를 대상으로 하는 우선 순위 1 메시지가 처리되기 전에 처리되며 이러한 방식이 철저히 준수됩니다. 동일한 엔드포인트에 대한 여러 경로의 우선 순위가 같으면 해당 메시지는 선착순으로 처리됩니다. 우선 순위를 지정하지 않으면 경로가 가장 낮은 우선 순위에 할당됩니다.

timeToLiveSecs 속성은 명시적으로 설정하지 않는 한, IoT Edge 허브의 storeAndForwardConfiguration에서 해당 값을 상속합니다. 값은 임의의 양의 정수일 수 있습니다.

우선 순위 큐를 관리하는 방법에 대한 자세한 내용은 경로 우선 순위 및 Time-to-Live에 대한 참조 페이지를 참조하세요.

원하는 속성 정의 또는 업데이트

배포 매니페스트는 IoT Edge 디바이스에 배포된 각 모듈의 원하는 속성을 지정합니다. 배포 매니페스트의 원하는 속성은 현재 모듈 쌍에 있는 원하는 속성을 모두 덮어씁니다.

배포 매니페스트에서 모듈 쌍의 원하는 속성을 지정하지 않으면 IoT Hub는 어떤 방식으로든 모듈 쌍을 수정하지 않습니다. 대신, 원하는 속성을 프로그래밍 방식으로 설정할 수 있습니다.

디바이스 쌍을 수정할 수 있게 해주는 동일한 메커니즘이 모듈 쌍을 수정하는 데 사용됩니다. 자세한 내용은 모듈 쌍 개발자 가이드를 참조하세요.

배포 매니페스트 예제

다음 예제에서는 유효한 배포 매니페스트 문서의 모양을 보여 줍니다.

{
  "modulesContent": {
    "$edgeAgent": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "runtime": {
          "type": "docker",
          "settings": {
            "minDockerVersion": "v1.25",
            "loggingOptions": "",
            "registryCredentials": {
              "ContosoRegistry": {
                "username": "myacr",
                "password": "<password>",
                "address": "myacr.azurecr.io"
              }
            }
          }
        },
        "systemModules": {
          "edgeAgent": {
            "type": "docker",
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-agent:1.4",
              "createOptions": "{}"
            }
          },
          "edgeHub": {
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 0,
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-hub:1.4",
              "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
            }
          }
        },
        "modules": {
          "SimulatedTemperatureSensor": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 2,
            "settings": {
              "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
              "createOptions": "{}"
            }
          },
          "filtermodule": {
            "version": "1.0",
            "type": "docker",
            "status": "running",
            "restartPolicy": "always",
            "startupOrder": 1,
            "env": {
              "tempLimit": {"value": "100"}
            },
            "settings": {
              "image": "myacr.azurecr.io/filtermodule:latest",
              "createOptions": "{}"
            }
          }
        }
      }
    },
    "$edgeHub": {
      "properties.desired": {
        "schemaVersion": "1.1",
        "routes": {
          "sensorToFilter": {
            "route": "FROM /messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/input1\")",
            "priority": 0,
            "timeToLiveSecs": 1800
          },
          "filterToIoTHub": {
            "route": "FROM /messages/modules/filtermodule/outputs/output1 INTO $upstream",
            "priority": 1,
            "timeToLiveSecs": 1800
          }
        },
        "storeAndForwardConfiguration": {
          "timeToLiveSecs": 100
        }
      }
    }
  }
}

다음 단계