연속 통합 및 지속적인 업데이트를 위해 Azure Pipelines와 IoT Central 통합

CI/CD(연속 통합 및 지속적인 업데이트)는 자동화 파이프라인을 사용하여 짧고 빈번한 주기로 소프트웨어를 개발하고 제공하는 프로세스를 의미합니다. 이 문서에서는 IoT Central 애플리케이션 구성의 빌드, 테스트 및 배포를 자동화하는 방법을 보여 줍니다. 이 자동화를 통해 개발 팀은 신뢰할 수 있는 릴리스를 더 자주 제공할 수 있습니다.

연속 통합은 소스 코드 리포지토리의 분기에 코드 커밋으로 시작됩니다. 각 커밋은 충돌이 발생하지 않도록 다른 개발자의 커밋과 병합됩니다. 변경 내용은 빌드를 만들고 해당 빌드에 대해 자동화된 테스트를 실행함으로써 추가로 유효성이 검사됩니다. 이 프로세스는 궁극적으로 아티팩트 또는 배포 번들이 대상 환경에 배포되도록 합니다. 이 경우 대상은 Azure IoT Central 애플리케이션입니다.

IoT Central이 더 큰 IoT 솔루션의 일부인 것처럼 IoT Central은 CI/CD 파이프라인의 일부입니다. CI/CD 파이프라인은 전체 IoT 솔루션과 모든 구성을 개발부터 프로덕션까지 각 환경에 배포해야 합니다.

일반적인 CI/CD 파이프라인의 단계를 보여 주는 다이어그램.

IoT Central은 Platform as a Service 구성 요소와 다른 배포 요구 사항이 있는 애플리케이션 Platform as a Service입니다. 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 토큰은 1년 후에 만료됩니다.

개발 및 프로덕션 IoT Central 앱 모두에 대해 다음 단계를 완료합니다.

  1. IoT Central 앱에서 권한, API 토큰을 차례로 선택합니다.

  2. 새로 만들기를 선택합니다.

  3. 토큰에 이름을 지정하고, 앱에서 최상위 조직을 지정하고, 역할을 앱 관리자로 설정합니다.

  4. 개발 IoT Central 애플리케이션의 API 토큰을 기록해 둡니다. 나중에 IoTC-Config.ps1 스크립트를 실행할 때 사용합니다.

  5. 프로덕션 IoT Central 애플리케이션에서 생성된 토큰을 API-Token이라는 비밀로 프로덕션 키 자격 증명 모음에 저장합니다.

    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": "connectionString",
              "connectionString": "DefaultEndpointsProtocol=https;AccountName=yourexportaccount;AccountKey=*****;EndpointSuffix=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. 애플리케이션에서 데이터 내보내기를 사용하는 경우 대상에 대한 비밀을 프로덕션 키 자격 증명 모음에 추가합니다. 구성 파일에는 대상에 대한 실제 비밀이 포함되지 않으며 비밀은 키 자격 증명 모음에 저장됩니다.

  6. 구성 파일의 비밀을 키 자격 증명 모음의 비밀 이름으로 업데이트합니다.

    대상 형식 변경할 속성
    Service Bus 큐 connectionString
    Service Bus 토픽 connectionString
    Azure Data Explorer clientSecret
    Azure Blob Storage connectionString
    Event Hubs connectionString
    웹후크 인증 없음 해당 없음

    예시:

    "destinations": {
      "value": [
        {
          "id": "393adfc9-0ed8-45f4-aa29-25b5c96ecf63",
          "displayName": "Blob destination",
          "type": "blobstorage@v1",
          "authorization": {
            "type": "connectionString",
            "connectionString": "Storage-CS",
            "containerName": "dataexport"
          },
          "status": "waiting"
        }
      ]
    }
    
  7. 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}으로 이동하여 웹 브라우저에서 Azure DevOps 조직을 엽니다.
  2. 새 프로젝트를 선택하여 프로젝트를 만듭니다.
  3. 프로젝트에 이름과 설명(선택 사항)을 지정한 다음, 만들기를 선택합니다.
  4. 프로젝트 시작 페이지에서 파이프라인을 선택한 다음, 파이프라인 만들기를 선택합니다.
  5. 코드의 위치로 GitHub를 선택합니다.
  6. AzurePipelines 권한 부여를 선택하여 GitHub 계정에 액세스하도록 Azure Pipelines에 권한을 부여합니다.
  7. 리포지토리 선택 페이지에서 IoT Central CI/CD GitHub 리포지토리의 포크를 선택합니다.
  8. GitHub에 로그인하고 Azure Pipelines가 리포지토리에 액세스할 수 있는 권한을 제공하라는 메시지가 표시되면 설치 및 승인을 선택합니다.
  9. 시작하려면 파이프라인 구성 페이지에서 스타터 파이프라인을 선택합니다. 편집할 수 있도록 azure-pipelines.yml이 표시됩니다.

변수 그룹 만들기

키 자격 증명 모음 비밀을 파이프라인에 통합하는 쉬운 방법은 변수 그룹을 사용하는 것입니다. 변수 그룹을 사용하여 올바른 비밀을 배포 스크립트에 사용할 수 있는지 확인합니다. 변수 그룹을 만들려면 다음을 수행합니다.

  1. 왼쪽 메뉴의 파이프라인 섹션에서 라이브러리를 선택합니다.

  2. + 변수 그룹을 선택합니다.

  3. 변수 그룹의 이름으로 keyvault를 입력합니다.

  4. 토글을 사용하여 Azure Key Vault에서 비밀을 연결합니다.

  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 애플리케이션 관리 및 모니터링 방법을 배우는 것입니다.