자습서: Azure Functions를 IoT Edge 모듈로 배포

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

Important

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

Azure Functions를 사용하여 비즈니스 논리를 구현하는 코드를 Azure IoT Edge 디바이스에 직접 배포할 수 있습니다. 이 자습서에서는 시뮬레이션된 IoT Edge 디바이스에서 센서 데이터를 필터링하는 Azure 함수를 만들고 배포하는 과정을 안내합니다. 빠른 시작에서 만든 시뮬레이션된 IoT Edge 디바이스를 사용합니다. 이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • Visual Studio Code를 사용하여 Azure Function을 만듭니다.
  • Visual Studio Code 및 Docker를 사용하여 Docker 이미지를 만들고 컨테이너 레지스트리에 게시합니다.
  • 컨테이너 레지스트리에서 IoT Edge 디바이스로 모듈을 배포합니다.
  • 필터링된 데이터를 봅니다.

Diagram of function architecture, showing how to stage and deploy a function module.

이 자습서에서 만드는 Azure 함수는 디바이스에서 생성한 온도 데이터를 필터링합니다. 함수는 온도가 지정된 임계값을 초과하는 경우에만 azure IoT Hub에 업스트림 메시지를 보냅니다.

Azure를 구독하고 있지 않다면 시작하기 전에 Azure 체험 계정을 만듭니다.

필수 조건

이 자습서를 시작하기 전에 Visual Studio Code를 사용하여 Azure IoT Edge 모듈을 개발하여 Linux 컨테이너 개발을 위한 개발 환경을 설정하는 자습서를 수행합니다. 이 자습서를 완료하여 다음과 같은 필수 구성 요소를 갖추어야 합니다.

Azure Functions를 사용하여 IoT Edge 모듈을 개발하려면 개발 머신에 추가 필수 구성 요소를 설치합니다.

함수 프로젝트 만들기

필수 구성 요소에 설치한 Visual Studio Code용 Azure IoT Edge는 관리 기능과 일부 코드 템플릿을 제공합니다. 이 섹션에서는 Visual Studio Code를 사용하여 Azure Function을 포함하는 IoT Edge 솔루션을 만듭니다.

새 프로젝트 만들기

다음 단계에 따라 사용자 지정할 수 있는 C# 함수 솔루션 템플릿을 만듭니다.

  1. 개발 머신에서 Visual Studio Code를 엽니다.

  2. 명령 팔레트 보기를>선택하여 Visual Studio Code 명령 팔레트엽니다.

  3. 명령 팔레트에서 Azure IoT Edge: 새 IoT Edge 솔루션 명령을 추가하고 실행합니다. 명령 팔레트에서 다음 프롬프트에 따라 솔루션을 만듭니다.

    • 폴더 선택: Visual Studio Code용 개발 머신의 위치를 선택하여 솔루션 파일을 만듭니다.
    • 솔루션 이름을 제공합니다. 솔루션에 대한 설명이 포함된 이름(예: FunctionSolution)을 추가하거나 기본값을 적용합니다.|
    • 모듈 템플릿 선택: Azure Functions - C#을 선택합니다.
    • 모듈 이름 입력 | 모듈 이름을 CSharpFunction으로 지정합니다.
    • 모듈에 대한 Docker 이미지 리포지토리를 제공합니다. 이미지 리포지토리에는 컨테이너 레지스트리의 이름과 컨테이너 이미지의 이름이 포함됩니다. 컨테이너 이미지는 마지막 단계에서 미리 채워집니다. localhost:5000을 Azure Container Registry의 로그인 서버 값으로 바꿉다. Azure Portal의 컨테이너 레지스트리 개요 페이지에서 로그인 서버를 검색할 수 있습니다. 마지막 문자열은 <레지스트리 이름>.azurecr.io/csharpfunction과 같습니다.

    Screenshot showing where to add your Docker image repository name in Visual Studio Code.

레지스트리 자격 증명 추가

솔루션의 환경 파일은 컨테이너 레지스트리에 대한 자격 증명을 저장하고 IoT Edge 런타임과 공유합니다. IoT Edge 디바이스로 프라이빗 이미지를 끌어오려면 런타임에 이러한 자격 증명이 필요합니다.

Visual Studio Code의 IoT Edge 확장은 Azure에서 컨테이너 레지스트리 자격 증명을 끌어와 환경 파일에 채우려고 합니다. 자격 증명이 이미 파일에 있는지 확인합니다. 그렇지 않은 경우 지금 추가합니다.

  1. Visual Studio Code 탐색기에서 파일을 엽니다 .env .
  2. 필드를 Azure 컨테이너 레지스트리에서 복사한 사용자 이름암호 값으로 업데이트합니다. Azure에서 컨테이너 레지스트리로 이동하여 설정>Access 키 페이지를 확인하여 다시 찾을 수 있습니다.
  3. 이 파일을 저장합니다.

참고 항목

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

대상 아키텍처를 AMD64로 설정

IoT Edge에서 Azure Functions 모듈 실행은 Linux AMD64 기반 컨테이너에서만 지원됩니다. Visual Studio Code의 기본 대상 아키텍처는 Linux AMD64이지만 여기서는 Linux AMD64로 명시적으로 설정합니다.

  1. 명령 팔레트를 열고 Azure IoT Edge를 검색 합니다. Edge 솔루션에 대한 기본 대상 플랫폼을 설정합니다.

  2. 명령 팔레트의 옵션 목록에서 AMD64 대상 아키텍처를 선택합니다.

사용자 지정 코드를 사용하여 모듈 업데이트

CSharpFunction 모듈이 IoT Hub에 전달하기 전에 에지에서 메시지를 처리하도록 코드를 추가해 보겠습니다.

  1. Visual Studio Code 탐색기에서 모듈>CSharpFunction>CSharpFunction.cs 엽니다.

  2. CSharpFunction.cs 파일의 내용을 다음 코드로 바꿉니다. 이 코드는 앰비언트 및 컴퓨터 온도에 대한 원격 분석을 수신하고, 컴퓨터 온도가 정의된 임계값을 초과하는 경우에만 메시지를 IoT Hub에 전달합니다.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Client;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.EdgeHub;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    
    namespace Functions.Samples
    {
        public static class CSharpFunction
        {
            [FunctionName("CSharpFunction")]
            public static async Task FilterMessageAndSendMessage(
                [EdgeHubTrigger("input1")] Message messageReceived,
                [EdgeHub(OutputName = "output1")] IAsyncCollector<Message> output,
                ILogger logger)
            {
                const int temperatureThreshold = 20;
                byte[] messageBytes = messageReceived.GetBytes();
                var messageString = System.Text.Encoding.UTF8.GetString(messageBytes);
    
                if (!string.IsNullOrEmpty(messageString))
                {
                    logger.LogInformation("Info: Received one non-empty message");
                    // Get the body of the message and deserialize it.
                    var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);
    
                    if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)
                    {
                        // Send the message to the output as the temperature value is greater than the threshold.
                        using (var filteredMessage = new Message(messageBytes))
                        {
                             // Copy the properties of the original message into the new Message object.
                             foreach (KeyValuePair<string, string> prop in messageReceived.Properties)
                             {filteredMessage.Properties.Add(prop.Key, prop.Value);}
                             // Add a new property to the message to indicate it is an alert.
                             filteredMessage.Properties.Add("MessageType", "Alert");
                             // Send the message.
                             await output.AddAsync(filteredMessage);
                             logger.LogInformation("Info: Received and transferred a message with temperature above the threshold");
                        }
                    }
                }
            }
        }
        //Define the expected schema for the body of incoming messages.
        class MessageBody
        {
            public Machine machine {get; set;}
            public Ambient ambient {get; set;}
            public string timeCreated {get; set;}
        }
        class Machine
        {
            public double temperature {get; set;}
            public double pressure {get; set;}
        }
        class Ambient
        {
            public double temperature {get; set;}
            public int humidity {get; set;}
        }
    }
    
  3. 파일을 저장합니다.

IoT Edge 솔루션 빌드 및 푸시

이전 섹션에서는 IoT Edge 솔루션을 만들고 CSharpFunction을 수정하여 보고된 컴퓨터 온도가 허용 가능한 임계값 미만인 메시지를 필터링했습니다. 이제 솔루션을 컨테이너 이미지로 빌드하고 컨테이너 레지스트리로 푸시해야 합니다.

  1. 보기>터미널을 선택하여 Visual Studio Code 통합 터미널을 엽니다.

  2. 터미널에서 다음 명령을 입력하여 Docker에 로그인합니다. Azure Container Registry의 사용자 이름, 암호 및 로그인 서버로 로그인합니다. Azure Portal에서 레지스트리의 액세스 키 섹션에서 이러한 값을 검색할 수 있습니다.

    docker login -u <ACR username> -p <ACR password> <ACR login server>
    

    --password-stdin 사용을 권장하는 보안 경고가 표시될 수 있습니다. 이 모범 사례는 프로덕션 시나리오에 권장되지만 이 자습서의 범위를 벗어납니다. 자세한 내용은 docker 로그인 참조를 참조하세요.

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

    빌드 및 푸시 명령은 세 가지 작업을 시작합니다. 먼저, 배포 템플릿 및 기타 솔루션 파일의 정보로 작성된 전체 배포 매니페스트를 포함하는 config라는 솔루션에 새 폴더를 만듭니다. 둘째, 대상 아키텍처에 적합한 dockerfile을 기반으로 컨테이너 이미지를 빌드하기 위해 실행됩니다 docker build . 그런 다음, 이미지 리포지토리를 컨테이너 레지스트리에 푸시하기 위해 실행됩니다 docker push .

    이 프로세스는 처음 몇 분 정도 걸릴 수 있지만 다음에 명령을 실행할 때 더 빠릅니다.

컨테이너 이미지 보기

Visual Studio Code는 컨테이너 이미지가 컨테이너 레지스트리에 푸시될 때 성공 메시지를 출력합니다. 작업이 성공적으로 수행되었는지 확인하려면 레지스트리에서 이미지를 볼 수 있습니다.

  1. Azure Portal에서 Azure 컨테이너 레지스트리로 이동합니다.
  2. 서비스 리포지토리를>선택합니다.
  3. 목록에 csharpfunction 리포지토리가 표시됩니다. 자세한 내용을 보려면 이 리포지토리를 선택합니다.
  4. 태그 섹션에 0.0.1-amd64 태그가 표시됩니다. 이 태그는 빌드한 이미지의 버전과 플랫폼을 나타냅니다. 이러한 값은 CSharpFunction 폴더의 module.json 파일에 설정됩니다.

솔루션 배포 및 실행

Azure Portal을 사용하여 빠른 시작에서 했던 것처럼 함수 모듈을 IoT Edge 디바이스에 배포할 수 있습니다. 또한 Visual Studio Code 내에서 모듈을 배포하고 모니터링할 수 있습니다. 다음 섹션에서는 필수 구성 요소에 나열된 Visual Studio Code용 Azure IoT Edge 및 IoT Hub를 사용합니다. 아직 설치하지 않은 경우 지금 확장을 설치합니다.

  1. Visual Studio Code 탐색기의 Azure IoT Hub 섹션에서 디바이스를 확장하여 IoT 디바이스 목록을 표시합니다.

  2. IoT Edge 디바이스의 이름을 마우스 오른쪽 단추로 클릭한 다음, 단일 디바이스용 배포 만들기를 선택합니다.

  3. CSharpFunction이 포함된 솔루션 폴더를 찾습니다. 구성 폴더를 열고, deployment.amd64.json 파일을 선택한 다음, Edge 배포 매니페스트 선택을 선택합니다.

  4. 디바이스에서 모듈을 확장하여 배포되고 실행 중인 모듈 목록을 확인합니다. 새로 고침 단추를 클릭합니다. SimulatedTemperatureSensor 모듈 및 $edgeAgent 및 $edgeHub 함께 실행되는 새 CSharpFunction이 표시됩니다.

    모듈을 시작하는 데 몇 분 정도 걸릴 수 있습니다. IoT Edge 디바이스는 IoT Hub에서 새 배포 정보를 검색하고 새 컨테이너를 시작한 다음 상태 IoT Hub에 다시 보고해야 합니다.

    Screenshot showing how to view deployed modules in Visual Studio Code.

생성된 데이터 보기

Azure IoT Hub를 실행 하여 모든 디바이스에서 IoT Hub에 도착하는 모든 메시지를 볼 수 있습니다. 명령 팔레트에서 기본 제공 이벤트 엔드포인트 모니터링을 시작합니다. 메시지 모니터링을 중지하려면 명령 팔레트에서 Azure IoT Hub: 기본 제공 이벤트 엔드포인트 모니터링 중지 명령을 실행합니다.

보기를 필터링하여 특정 디바이스에서 IoT Hub에 도착하는 모든 메시지를 볼 수도 있습니다. Visual Studio Code 탐색기의 Azure IoT Hub>디바이스 섹션에서 디바이스를 마우스 오른쪽 단추로 클릭하고 기본 제공 이벤트 엔드포인트 모니터링 시작을 선택합니다.

리소스 정리

권장되는 다음 문서를 계속 진행하려는 경우 만든 리소스와 구성을 그대로 유지하고 다시 사용할 수 있습니다. 테스트 디바이스와 동일한 IoT Edge 디바이스를 계속 사용해도 됩니다.

그렇지 않은 경우 요금 청구를 방지하도록 이 문서에서 만든 로컬 구성 및 Azure 리소스를 삭제할 수 있습니다.

Azure 리소스 삭제

Azure 리소스와 리소스 그룹을 삭제하면 되돌릴 수 없습니다. 잘못된 리소스 그룹 또는 리소스를 자동으로 삭제하지 않도록 해야 합니다. 유지하려는 리소스가 있는 기존 리소스 그룹 내에 IoT Hub를 만든 경우 리소스 그룹이 아닌 IoT Hub 리소스 자체만 삭제합니다.

리소스를 삭제하려면:

  1. Azure Portal에 로그인한 다음, 리소스 그룹을 선택합니다.

  2. IoT Edge 테스트 리소스가 포함된 리소스 그룹의 이름을 선택합니다.

  3. 리소스 그룹에 포함된 리소스 목록을 검토합니다. 모두 삭제하려면 리소스 그룹 삭제를 선택할 수 있습니다. 일부만 삭제하려면 각 리소스를 클릭하여 개별적으로 삭제할 수 있습니다.

다음 단계

이 자습서에서는 IoT Edge 디바이스에서 생성된 원시 데이터를 필터링하는 코드가 포함된 Azure Function 모듈을 만들었습니다.

다음 자습서를 계속 진행하여 Azure IoT Edge가 데이터를 에지의 비즈니스 인사이트로 전환하는 데 도움이 되는 다른 방법을 알아봅니다.