다음을 통해 공유


TypeScript 함수 API를 사용하여 Azure 리소스 그룹 관리

이 자습서에서는 API를 사용하여 로컬 TypeScript Azure Function 앱을 만들어 Azure 리소스 그룹을 관리하고 Azure에 앱을 배포합니다.

기능 및 기능:

  • Visual Studio Code에서 로컬 TypeScript Azure Function 앱 프로젝트 만들기
  • Visual Studio Code에서 함수 API 상용구 코드 만들기
  • Visual Studio Code에서 Azure Functions에 배포
  • Azure CLI에서 서비스 주체 만들기
  • Visual Studio Code를 사용하여 로컬 및 원격 애플리케이션 설정 구성
  • 암호 없는 연결을 위해 로컬 및 원격 환경 모두에서 DefaultAzureCredential 사용
  • Azure ID 및 Azure Resource Management SDK를 사용하여 Azure 리소스 관리
  • 로컬 및 클라우드 API를 사용하여 구독에서 리소스 그룹 만들기, 삭제 및 나열

소스 코드는 TypeScript로 작성되지만 소스 코드는 간단합니다. async/await를 사용하는 최신 JavaScript에 익숙한 경우 코드가 익숙할 것입니다.

기존 Azure 구독 만들기 또는 사용

활성 구독이 있는 Azure 사용자 계정이 필요합니다. 체험 계정 만들기

필수 조건

애플리케이션 아키텍처

앱은 다음 API 엔드포인트를 제공합니다.

메서드 URL 설명
POST,DELETE http://localhost:7071/api/resourcegroup 리소스 그룹을 추가하거나 삭제합니다. 추가하는 동안 태그(키/값 쌍)를 포함하여 나중에 그룹의 용도를 식별합니다.
GET http://localhost:7071/api/resourcegroups 구독의 모든 리소스 그룹을 나열합니다.
GET http://localhost:7071/api/resources 구독 또는 리소스 그룹의 모든 리소스를 나열합니다.

이러한 엔드포인트는 공용 이지만 라이브 환경에 배포하기 전에 인증 및 권한 부여를 사용하여 API 엔드포인트를 보호해야 합니다 .

이 앱은 서비스 주체를 만들 때 지정된 범위이므로 구독으로 제한됩니다.

1. 환경 준비

Azure ID SDK를 사용하려면 로컬 및 클라우드 환경을 준비해야 합니다.

Azure CLI에 로그인

bash 터미널에서 다음 명령을 사용하여 Azure CLI에 로그인합니다.

az login

Azure 구독 ID 가져오기

  1. bash 터미널에서 구독을 가져오고 사용하려는 구독 ID를 찾습니다. 다음 쿼리는 구독 이름별로 정렬된 구독 ID, 구독 이름 및 테넌트 ID를 반환합니다.

    az account list --query "sort_by([].{Name:name, SubscriptionId:id, TenantId:tenantId}, &Name)" --output table
    
  2. 구독 ID를 이전 임시 파일에 복사합니다. 이 설정은 나중에 필요합니다.

Azure 서비스 주체 만들기

Azure 서비스 주체는 개인 사용자 자격 증명을 사용하지 않고도 Azure에 대한 액세스를 제공합니다. 이 자습서에서는 로컬 및 클라우드 환경에서 서비스 주체를 모두 사용할 수 있습니다. 엔터프라이즈 환경에서는 각 환경에 대해 별도의 서비스 주체를 원합니다.

  1. 나중에 서비스 주체를 쉽게 찾을 수 있도록 서비스 주체 이름 형식을 결정합니다. 예를 들어 몇 가지 형식 아이디어는 다음과 같습니다.

    • 프로젝트 및 소유자: resource-management-john-smith.
    • 부서 및 날짜: IT-2021-September
    • 고유 식별자: 00000000-0000-0000-0000-000000000000
  2. bash 터미널에서 az ad sp create-for-rbac를 사용하여 서비스 주체 를 만듭니다. <SUBSCRIPTION-ID>는 구독 ID로 바꿉니다.

    az ad sp create-for-rbac --name YOUR-SERVICE-PRINCIPAL-NAME --role Contributor --scopes /subscriptions/<SUBSCRIPTION-ID>
    
  3. 전체 출력 결과를 임시 파일에 복사합니다. 이러한 설정은 나중에 필요합니다.

    {
      "appId": "YOUR-SERVICE-PRINCIPAL-ID",
      "displayName": "YOUR-SERVICE-PRINCIPAL-NAME",
      "name": "http://YOUR-SERVICE-PRINCIPAL-NAME",
      "password": "YOUR-SERVICE-PRINCIPAL-PASSWORD",
      "tenant": "YOUR-TENANT-ID"
    }
    

2. Visual Studio Code에서 로컬 Azure Function 앱 만들기

Visual Studio Code에서 Azure 함수 앱을 만들어 Azure 리소스 그룹을 관리합니다.

함수 앱 만들기

Visual Studio Code를 사용하여 로컬 함수 앱을 만듭니다.

  1. bash 터미널에서 새 디렉터리를 만들고 변경합니다.

    mkdir my-function-app && cd my-function-app
    
  2. bash 터미널에서 Visual Studio Code를 엽니다.

    code .
    
  3. Visual Studio Code 명령 팔레트를 엽니다(Ctrl + Shift + p).

  4. Azure Functions: create new project를 입력합니다. 다음 테이블을 사용하여 프롬프트를 완료합니다.

    prompt
    함수 프로젝트를 포함할 폴더 선택 기본(현재) 디렉터리 선택
    언어 선택 TypeScript를 선택합니다.
    TypeScript 프로그래밍 모델 선택 모델 V4 선택 (미리 보기)
    프로젝트의 첫 번째 함수에 사용할 템플릿 선택 HTTP 트리거를 선택합니다.
    새 HTTP 트리거 만들기 의 API 이름을 입력합니다 resourcegroups.
    권한 부여 수준 익명을 선택합니다. 이 문서 이후에 이 프로젝트를 계속 진행하는 경우 권한 부여 수준을 함수로 변경합니다. 함수 수준 권한 부여에 대해 자세히 알아봅니다.

    프로젝트 상용구가 만들어지고 종속성이 설치됩니다.

local.settings.json 파일에 서비스 주체 설정 추가

  1. ./local.settings.json 프로젝트 루트 디렉터리에서 파일을 열고 다음 5개의 환경 변수를 사용하여 VALUES 섹션을 추가합니다.

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "",
        "FUNCTIONS_WORKER_RUNTIME": "node",
        "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
        "AZURE_CLIENT_ID": "REPLACE-WITH-SERVICE-PRINCIPAL-APPID",
        "AZURE_CLIENT_SECRET": "REPLACE-WITH-SERVICE-PRINCIPAL-PASSWORD",
        "AZURE_SUBSCRIPTION_ID":"REPLACE-WITH-SUBSCRIPTION-ID",
        "AZURE_TENANT_ID":"REPLACE-WITH-SERVICE-PRINCIPAL-TENANT",
        "NODE_ENV":"development"
      }
    }
    
  2. 값을 추가하려면 이전 섹션의 설정을 참조하세요. 이러한 환경 변수는 컨텍스트에서 DefaultAzureCredential을 사용하는 데 필요합니다.

    • AZURE_TENANT_ID: 위의 서비스 주체 출력의 tenant입니다.
    • AZURE_CLIENT_ID: 위의 서비스 주체 출력의 appId입니다.
    • AZURE_CLIENT_SECRET: 위의 서비스 주체 출력의 password입니다.
  3. 또한 구독 ID를 설정해야 합니다. 리소스 관리에 Azure SDK를 사용해야 합니다.

    • AZURE_SUBSCRIPTION_ID: 리소스 그룹을 포함하는 기본 구독입니다.

local.settings.json 파일은 의도적으로 로컬 git 에서 무시되므로 실수로 소스 코드에 커밋하지 않습니다.

Azure ID 및 리소스 관리를 위한 npm 종속성 설치

Visual Studio Code 통합 bash 터미널에서 Azure ID 및 리소스 관리를 위한 Azure SDK 종속성을 설치합니다.

npm install @azure/identity @azure/arm-resources

JavaScript를 사용하여 구독의 모든 리소스 그룹 나열

  1. ./src/functions/resourcegroups.ts 파일을 열고 내용을 다음으로 바꿉니다.

    import { ResourceGroup } from '@azure/arm-resources';
    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      createResourceGroup,
      deleteResourceGroup
    } from '../lib/azure-resource-groups';
    import { processError } from '../lib/error';
    
    export async function resourcegroup(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        console.log(JSON.stringify(request.query));
        console.log(JSON.stringify(request.params));
    
        const name: string = request.query.get('name');
        const location: string = request.query.get('location');
        console.log(`name: ${name}`);
        console.log(`location: ${location}`);
    
        switch (request.method) {
          case 'POST': // wait for create to complete before returning
            if (!name || !location) {
              return { body: 'Missing required parameters.', status: 400 };
            }
    
            if (request.headers.get('content-type') === 'application/json') {
              // create with tags
    
              const body: Record<string, unknown> =
                (await request.json()) as Record<string, string>;
              const tags: Record<string, string> = body?.tags
                ? (body?.tags as Record<string, string>)
                : null;
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                tags
              );
              return { jsonBody: resourceGroup, status: 200 };
            } else {
              // create without tags
    
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                null
              );
              return { jsonBody: resourceGroup, status: 200 };
            }
    
          case 'DELETE': // wait for delete to complete before returning
            if (!name) {
              return { body: 'Missing required parameters.', status: 400 };
            }
            await deleteResourceGroup(name);
            return { status: 204 };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    
    app.http('resourcegroup', {
      methods: ['DELETE', 'POST'],
      authLevel: 'anonymous',
      handler: resourcegroup
    });
    

    이 파일은 API 요청에 응답하고 /api/resourcegroups 구독의 모든 리소스 그룹 목록을 반환합니다.

  2. 명명 lib 된 하위 디렉터리를 src 만들고 해당 디렉터리에 새 azure-resource-groups.ts파일을 만듭니다.

  3. 다음 코드를 파일에 복사합니다 ./src/lib/azure-resource-groups.ts .

    // Include npm dependencies
    import {
      ResourceGroup, ResourceManagementClient
    } from '@azure/arm-resources';
    import { DefaultAzureCredential } from '@azure/identity';
    import { getSubscriptionId } from './environment-vars';
    
    const subscriptionId = getSubscriptionId();
    
    // Create Azure authentication credentials
    const credentials = new DefaultAzureCredential();
    
    // Create Azure SDK client for Resource Management such as resource groups
    const resourceManagement = new ResourceManagementClient(
      credentials,
      subscriptionId
    );
    
    // all resources groups in subscription
    export const listResourceGroups = async (): Promise<{
      list: ResourceGroup[];
      subscriptionId: string;
    }> => {
      const list: ResourceGroup[] = [];
      for await (const resourceGroup of resourceManagement.resourceGroups.list()) {
        list.push(resourceGroup);
      }
      return {
        subscriptionId,
        list
      };
    };
    export const createResourceGroup = async (
      resourceGroupName: string,
      location: string,
      tags: { [propertyName: string]: string }
    ): Promise<ResourceGroup> => {
      const resourceGroupParameters = {
        location: location,
        tags
      };
    
      return await resourceManagement.resourceGroups.createOrUpdate(
        resourceGroupName,
        resourceGroupParameters
      );
    };
    export const deleteResourceGroup = async (
      resourceGroupName: string
    ): Promise<void> => {
      return await resourceManagement.resourceGroups.beginDeleteAndWait(
        resourceGroupName
      );
    };
    

    이 파일은 다음을 완료합니다.

    • 구독 ID를 가져옵니다.
    • DefaultAzureCredential 컨텍스트를 만듭니다.
    • 리소스 관리 SDK를 사용하는 데 필요한 ResourceManagementClient를 만듭니다.
    • 구독의 모든 리소스 그룹을 가져옵니다.
  4. 디렉터리에 새 environment-vars.ts 파일을 ./src/lib 만들고 다음 코드를 해당 파일에 복사합니다.

    export const checkAzureAuth = () => {
      // The following code is only used to check you have environment
      // variables configured. The DefaultAzureCredential reads your
      // environment - it doesn't read these variables.
      const tenantId = process.env['AZURE_TENANT_ID'];
      if (!tenantId)
        throw Error('AZURE_TENANT_ID is missing from environment variables.');
      const clientId = process.env['AZURE_CLIENT_ID'];
      if (!clientId)
        throw Error('AZURE_CLIENT_ID is missing from environment variables.');
      const secret = process.env['AZURE_CLIENT_SECRET'];
      if (!secret)
        throw Error('AZURE_CLIENT_SECRET is missing from environment variables.');
    };
    
    export const getSubscriptionId = (): string => {
      checkAzureAuth();
    
      // Get subscription from environment variables
      const subscriptionId = process.env['AZURE_SUBSCRIPTION_ID'];
      if (!subscriptionId)
        throw Error('Azure Subscription is missing from environment variables.');
      return subscriptionId;
    };
    

    이 파일은 구독 ID를 반환하기 전에 환경 변수를 검사.

  5. 디렉터리에 새 error.ts 파일을 ./src/lib 만들고 다음 코드를 해당 파일에 복사합니다.

    export function processError(err: unknown): any {
      if (typeof err === 'string') {
        return { body: err.toUpperCase(), status: 500 };
      } else if (
        err['stack'] &&
        process.env.NODE_ENV.toLowerCase() !== 'production'
      ) {
        return { jsonBody: { stack: err['stack'], message: err['message'] } };
      } else if (err instanceof Error) {
        return { body: err.message, status: 500 };
      } else {
        return { body: JSON.stringify(err) };
      }
    }
    

    이 파일은 오류 메시지와 함께 500 오류를 반환합니다. 변수가 .로 설정production되지 않은 경우 NODE_ENV 스택이 반환됩니다.

로컬 함수 테스트

  1. Visual Studio Code 통합 터미널에서 로컬 프로젝트를 실행합니다.

    npm start
    
  2. 통합 bash 터미널에 실행 중인 함수의 URL이 표시될 때까지 기다립니다.

    Azure Function이 로컬로 실행되고 함수 앱에서 API에 대한 로컬 URL을 표시하는 경우 Visual Studio Code의 통합 bash 터미널 부분 스크린샷

  3. Visual Studio Code, Ctrl + Shift + 5에서 두 번째 통합 bash 터미널을 열고 다음 GET cURL 명령을 사용하여 API를 사용합니다.

    curl http://localhost:7071/api/resourcegroups
    

    구독에 리소스 그룹이 많은 경우 더 쉽게 검토할 수 있도록 출력을 파일로 파이프할 수 있습니다.

    curl http://localhost:7071/api/resourcegroups > resourcegroups.json
    
  4. 응답에는 해당 구독의 모든 리소스 그룹이 포함 subscriptionIdlist 됩니다.

    {
      "subscriptionId": "ABC123",
      "list": [
            {
              "id": "/subscriptions/ABC123/resourceGroups/vmagelo-cloudshell",
              "name": "jsmith-cloudshell",
              "type": "Microsoft.Resources/resourceGroups",
              "properties": {
                "provisioningState": "Succeeded"
              },
              "location": "westeurope"
            },
            ... REMOVED FOR BREVITY ...
        ]
    }
    

문제 해결

이 문서를 완료할 수 없는 경우 다음 표에서 문제를 검사. 테이블에 문제가 나열되지 않으면 이 설명서 페이지에서 문제를 엽니다.

문제 해결
앱이 시작되지 않았습니다. 오류를 검토합니다. 필요한 종속성을 설치했는지 확인합니다.
앱이 시작되었지만 200개 응답을 받을 수 없습니다. curl 명령이 올바른 로컬 경로에서 요청하는지 확인합니다.
API가 200 응답을 반환했지만 결과를 반환하지 않았습니다. Azure 리소스용 Visual Studio Code 확장을 사용하여 구독에 리소스 그룹이 있는지 확인합니다. 리소스 그룹이 표시되지 않으면 걱정하지 마세요. 이 자습서에서는 구독에서 리소스 그룹을 만들고 삭제하는 API를 추가합니다. 이 API는 소스 코드를 Azure에 처음 배포한 후에 추가되므로 코드를 다시 배포하는 방법을 배울 수 있습니다.

3. 클라우드 기반 Azure Function 앱 만들기

  1. Visual Studio Code에서 Azure 아이콘을 선택하여 Azure 탐색기를 엽니다.

  2. 아이콘을 + 선택하여 Azure 클라우드에서 새 Azure Function 앱을 만듭니다.

    Azure Function 앱 아이콘이 강조 표시된 Visual Studio Code의 Azure 탐색기 스크린샷

  3. Azure에서 함수 앱 만들기를 선택합니다.

  4. 새 함수 앱의 전역적으로 고유한 이름을 입력합니다. 이름은 모든 Azure 함수에서 고유해야 합니다. 예들 들어 jsmith-rg-management입니다.

  5. 로컬 함수 앱을 만들 때 선택한 것과 동일한 Node.js 18+ LTS 런타임 을 선택합니다.

  6. 미국 서부 3과 같이 가까운 지리적 위치를 선택합니다.

  7. 리소스가 만들어질 때까지 기다립니다. 자세한 내용은 Azure: 활동 로그를 볼 수 있습니다.

    리소스 만들기 상태 보여 주는 Visual Studio Code의 Azure 활동 로그 스크린샷

4. 클라우드 기반 Azure Function 앱 구성

Azure Function 앱에 연결하려면 Azure 앱 설정을 구성해야 합니다. 로컬에서 이러한 설정은 local.settings.json 파일에 있습니다. 이 프로세스는 이러한 값을 클라우드 앱에 추가합니다.

  1. Visual Studio Code의 Azure 탐색기의 리소스 섹션에서 함수 앱을 확장한 다음, 함수 앱을 선택합니다.

  2. 애플리케이션 설정 마우스 오른쪽 단추로 클릭하고 새 설정 추가를 선택합니다.

  3. 이름과 값이 정확히 같은 네 개의 값을 추가합니다 local.settings.json .

    • AZURE_TENANT_ID: 위의 서비스 주체 출력의 tenant입니다.
    • AZURE_CLIENT_ID: 위의 서비스 주체 출력의 appId입니다.
    • AZURE_CLIENT_SECRET: 위의 서비스 주체 출력의 password입니다.
    • AZURE_SUBSCRIPTION_ID: 리소스 그룹을 포함하는 기본 구독입니다.
    • AzureWebJobsFeatureFlags:EnableWorkerIndexing

원격/클라우드 함수의 앱 설정을 보여 주는 Visual Studio Code의 Azure 탐색기의 부분 스크린샷

5. Resource Manager 함수 앱 배포

Visual Studio Code에서 Azure Function 앱을 배포하여 Azure 리소스 그룹을 관리합니다.

Visual Studio Code 확장을 사용하여 호스팅 환경에 배포

  1. VS Code에서 파일을 열어 local.settings.json 표시합니다. 이렇게 하면 해당 이름과 값을 복사하는 다음 단계가 더 쉬워질 것입니다.

  2. Azure 로고를 선택하여 Azure 탐색기를다음, Functions에서 클라우드 아이콘을 선택하여 앱을 배포합니다.

    클라우드 배포 아이콘이 강조 표시된 Visual Studio Code의 로컬 작업 영역 스크린샷

    또는 Ctrl + Shift + p사용하여 명령 팔레트열고, Azure Functions: 함수 앱에 배포 명령을 입력deploy to function app하고 실행하여 배포할 수 있습니다.

  3. 함수 앱에 배포를 선택합니다.

  4. 이전 섹션에서 만든 함수 앱 이름을 선택합니다.

  5. 배포할 것인지 묻는 메시지가 표시되면 배포를 선택합니다.

  6. Azure Functions에 대한 VS Code 출력 패널에 진행률이 표시됩니다. 배포할 때 전체 Functions 애플리케이션이 배포되므로 모든 개별 함수에 대한 변경 내용이 한 번에 배포됩니다.

브라우저에서 Functions 앱을 사용할 수 있는지 확인

  1. Visual Studio Code에 있는 동안 Azure Functions 탐색기를 사용하고, Azure 구독에 대한 노드를 확장하고, Functions 앱의 노드를 확장한 다음, Functions(읽기 전용)를 확장합니다. 함수 이름을 마우스 오른쪽 단추로 클릭하고 함수 URL 복사를 선택합니다.

    함수의 URL을 복사할 위치를 보여주는 Visual Studio Code의 Azure 탐색기 부분 스크린샷.

  2. URL을 브라우저에 붙여넣고 Enter 키를 눌러 클라우드 API에서 리소스 그룹 목록을 요청합니다.

6. 함수 앱에 API 추가 및 Azure에 다시 배포

다음 API를 추가한 다음, Visual Studio Code에서 Azure Function 앱을 다시 배포합니다.

  • 리소스 그룹 추가 및 삭제
  • 리소스 그룹 또는 구독의 리소스를 나열합니다.

자습서의 이 시점에서 구독의 리소스 그룹을 나열하는 하나의 API가 있는 로컬 함수 앱을 만들고 Azure에 해당 앱을 배포했습니다. Azure 개발자는 프로세스 자동화 파이프라인의 일부로 리소스 그룹을 만들거나 삭제할 수 있습니다.

함수 앱에 대한 리소스 그룹 API 만들기

Azure Functions용 Visual Studio Code 확장을 사용하여 함수 앱에 TypeScript 파일을 추가하여 리소스 그룹을 만들고 삭제합니다.

  1. Visual Studio Code 명령 팔레트를 엽니다(Ctrl + Shift + p).

  2. Enter Azure Functions: Create Function 키를 누른 다음 프로세스를 시작합니다.

  3. 다음 표를 사용하여 /api/resourcegroup API를 만듭니다.

    prompt
    함수의 템플릿 선택 HTTP 트리거
    함수 이름 제공 resourcegroup
    권한 부여 수준 익명을 선택합니다. 이 프로젝트를 계속 진행하는 경우 권한 부여 수준을 함수로 변경합니다. 함수 수준 권한 부여에 대해 자세히 알아봅니다.
  4. ./src/functions/resourcegroup.ts 파일을 열고 전체 파일을 다음 소스 코드로 바꿉다.

    import { ResourceGroup } from '@azure/arm-resources';
    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      createResourceGroup,
      deleteResourceGroup
    } from '../lib/azure-resource-groups';
    import { processError } from '../lib/error';
    
    export async function resourcegroup(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        console.log(JSON.stringify(request.query));
        console.log(JSON.stringify(request.params));
    
        const name: string = request.query.get('name');
        const location: string = request.query.get('location');
        console.log(`name: ${name}`);
        console.log(`location: ${location}`);
    
        switch (request.method) {
          case 'POST': // wait for create to complete before returning
            if (!name || !location) {
              return { body: 'Missing required parameters.', status: 400 };
            }
    
            if (request.headers.get('content-type') === 'application/json') {
              // create with tags
    
              const body: Record<string, unknown> =
                (await request.json()) as Record<string, string>;
              const tags: Record<string, string> = body?.tags
                ? (body?.tags as Record<string, string>)
                : null;
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                tags
              );
              return { jsonBody: resourceGroup, status: 200 };
            } else {
              // create without tags
    
              const resourceGroup: ResourceGroup = await createResourceGroup(
                name,
                location,
                null
              );
              return { jsonBody: resourceGroup, status: 200 };
            }
    
          case 'DELETE': // wait for delete to complete before returning
            if (!name) {
              return { body: 'Missing required parameters.', status: 400 };
            }
            await deleteResourceGroup(name);
            return { status: 204 };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    
    app.http('resourcegroup', {
      methods: ['DELETE', 'POST'],
      authLevel: 'anonymous',
      handler: resourcegroup
    });
    
  5. 파일에는 ./src/lib/azure-resource-groups.ts 리소스 그룹을 추가하고 삭제하는 코드가 이미 포함되어 있습니다.

함수 앱에 대한 리소스 API 만들기

Azure Functions용 Visual Studio Code 확장을 사용하여 함수 앱에 TypeScript 파일을 추가하여 리소스 그룹의 리소스를 나열합니다.

  1. Visual Studio Code 명령 팔레트를 엽니다(Ctrl + Shift + p).

  2. Enter Azure Functions: Create Function 키를 누른 다음 프로세스를 시작합니다.

  3. 다음 표를 사용하여 /api/resources API를 만듭니 .

    prompt
    함수의 템플릿 선택 HTTP 트리거
    함수 이름 제공 resources
    권한 부여 수준 익명을 선택합니다. 이 프로젝트를 계속 진행하는 경우 권한 부여 수준을 함수로 변경합니다. 함수 수준 권한 부여에 대해 자세히 알아봅니다.
  4. ./src/functions/resources.ts 파일을 열고 전체 파일을 다음 소스 코드로 바꿉다.

    import {
      app,
      HttpRequest,
      HttpResponseInit,
      InvocationContext
    } from '@azure/functions';
    import {
      listResourceByResourceGroup, listResourceBySubscription
    } from '../lib/azure-resource';
    import { processError } from '../lib/error';
    
    export async function resources(
      request: HttpRequest,
      context: InvocationContext
    ): Promise<HttpResponseInit> {
      try {
        const resourceGroupName: string = request.query.get('resourceGroupName');
        context.log(`resourceGroupName: '${resourceGroupName}'`);
    
        if (resourceGroupName) {
          const resourcesByName = await listResourceByResourceGroup(
            resourceGroupName
          );
          return { jsonBody: resourcesByName };
        } else {
          const resourcesBySubscription = await listResourceBySubscription();
          return { jsonBody: resourcesBySubscription };
        }
      } catch (err: unknown) {
        return processError(err);
      }
    }
    app.http('resources', {
      methods: ['GET'],
      authLevel: 'anonymous',
      handler: resources
    });
    
  5. ./src/lib/azure-resource.ts 파일을 만들고 다음 코드를 복사하여 리소스 그룹의 리소스를 나열합니다.

    // Include npm dependencies
    import { Resource, ResourceManagementClient } from '@azure/arm-resources';
    import { DefaultAzureCredential } from '@azure/identity';
    import { getSubscriptionId } from './environment-vars';
    
    const subscriptionId = getSubscriptionId();
    
    // Create Azure authentication credentials
    const credentials = new DefaultAzureCredential();
    
    // Create Azure SDK client for Resource Management such as resource groups
    const resourceManagement = new ResourceManagementClient(
      credentials,
      subscriptionId
    );
    
    // all resources groups in subscription
    export const listResourceBySubscription = async (): Promise<{
      list: Resource[];
      subscriptionId: string;
    }> => {
      const list: Resource[] = [];
    
      for await (const resource of resourceManagement.resources.list()) {
        list.push(resource);
      }
    
      return {
        subscriptionId,
        list
      };
    };
    // all resources groups in resource group
    export const listResourceByResourceGroup = async (
      resourceGroupName: string
    ): Promise<{
      list: Resource[];
      subscriptionId: string;
      resourceGroupName: string;
    }> => {
      const list: Resource[] = [];
    
      for await (const resource of resourceManagement.resources.listByResourceGroup(
        resourceGroupName
      )) {
        list.push(resource);
      }
    
      return {
        subscriptionId,
        resourceGroupName,
        list
      };
    };
    

로컬 함수 앱 시작 및 새 API 테스트

  1. Visual Studio Code 통합 터미널에서 로컬 프로젝트를 실행합니다.

    npm start
    
  2. 통합 bash 터미널에 실행 중인 함수의 URL이 표시될 때까지 기다립니다.

    Azure Function이 로컬로 실행되고 함수 앱에서 API에 대한 로컬 URL을 표시하는 경우 Visual Studio Code의 통합 bash 터미널 부분 스크린샷

  3. 다른 통합 bash 터미널에서 다음 curl 명령을 사용하여 API를 호출하고 구독에 리소스 그룹을 추가합니다. 고유한 명명 규칙을 사용하도록 리소스 그룹의 이름을 변경합니다.

    curl -X POST 'http://localhost:7071/api/resourcegroup?name=my-test-1&location=westus'
    
    curl -X POST 'http://localhost:7071/api/resourcegroup?name=my-test-1&location=westus' \
      -H 'content-type: application/json' \
      -d '{"tags": {"a":"b"}}'
    
  4. 다음 curl 명령을 사용하여 구독에 나열된 새 리소스 그룹을 확인합니다.

    curl http://localhost:7071/api/resource-groups
    
  5. 다음 curl 명령을 사용하여 방금 추가한 리소스 그룹을 삭제합니다.

    curl -X DELETE 'http://localhost:7071/api/resourcegroup?name=my-test-1' \
      -H 'Content-Type: application/json'
    

새 API를 사용하여 함수 앱을 Azure에 다시 배포

  1. VS Code에서 Ctrl + Shift + p사용하여 명령 팔레트열고, Azure Functions: 함수 앱에 배포 명령을 입력deploy to function app하고 실행하여 배포합니다.

  2. 앱 목록에서 함수 앱을 선택합니다.

  3. 팝업 창에서 배포를 선택합니다.

  4. 배포가 완료될 때까지 기다립니다.

브라우저로 함수 API 확인

이전 cURL 명령을 사용하여 localhost 주소를 http://localhost:7071 Azure Function 리소스 이름(예: .)으로 https://myfunction.azurewebsites.net바꿉니다.

7. 함수 앱 로그 보기 및 쿼리

Azure Portal에서 Azure Function 앱 로그를 보고 쿼리합니다.

Azure Function 로그 쿼리

Azure Portal을 사용하여 함수 로그를 보고 쿼리합니다.

  1. VS Code에서 Azure 로고를 선택하여 Azure 탐색기를 연 다음 Functions에서 함수 앱을 마우스 오른쪽 단추로 클릭한 다음 포털에서 열기를 선택합니다.

    그러면 Azure Function에 대한 Azure Portal이 열립니다.

  2. 설정 Application Insights를 선택한 다음 Application Insights 데이터 보기를 선택합니다.

    메뉴 선택을 보여 주는 브라우저 스크린샷 설정 Application Insights를 선택한 다음 Application Insights 데이터 보기를 선택합니다.

    이 링크는 VS Code를 사용하여 Azure Function을 만들 때 만들어진 별도의 메트릭 리소스로 이동합니다.

  3. 모니터링 섹션에서 로그를 선택합니다. 쿼리 팝업 창이 표시되면 팝업의 오른쪽 위 모퉁이에 있는 X를 선택하여 닫습니다.

  4. 스키마 및 필터 창의 테이블 탭에서 추적 테이블을 두 번 클릭합니다.

    그러면 Kusto 쿼리, traces가 쿼리 창에 입력됩니다.

  5. API 호출을 검색하도록 쿼리를 편집합니다.

    traces 
    | where message startswith "Executing "
    
  6. 실행을 선택합니다.

    로그에 결과가 표시되지 않는 경우 Azure Function에 대한 HTTP 요청과 Kusto의 로그 가용성 사이에 몇 분 정도 지연이 있기 때문일 수 있습니다. 몇 분 정도 기다린 후 쿼리를 다시 실행합니다.

    추적 테이블에 대한 Azure Portal Kusto 쿼리 결과를 보여 주는 브라우저 스크린샷

    Azure Function 앱을 만들 때 Application Insights 리소스가 추가되었으므로 이 로깅 정보를 가져오기 위해 추가 작업을 수행할 필요가 없었습니다.

    • 함수 앱이 사용자를 위해 Application Insights를 추가했습니다.
    • 쿼리 도구는 Azure Portal에 포함되어 있습니다.
    • 로그에서 최소 정보를 얻기 위해 Kusto 쿼리작성하는 방법을 학습하는 대신 선택할 traces 수 있습니다.

8. Azure 리소스 정리

리소스 그룹 삭제

  1. VS Code에서 Azure 로고를 선택하여 Azure 탐색기를 연 다음 Functions에서 함수 앱을 마우스 오른쪽 단추로 클릭한 다음 포털에서 열기를 선택합니다. 그러면 Azure Function에 대한 Azure Portal이 열립니다.

  2. 개요 섹션에서 리소스 그룹 이름을 찾아 선택합니다. 이 작업을 수행하면 Azure Portal의 리소스 그룹으로 이동합니다.

  3. 리소스 그룹 페이지에는 이 자습서와 연결된 모든 리소스가 나열됩니다.

  4. 최상위 메뉴에서 리소스 그룹 삭제를 선택합니다.

  5. 사이드 메뉴에서 리소스 그룹의 이름을 입력한 다음 삭제를 선택합니다.

서비스 주체 삭제

서비스 주체를 삭제하려면 다음 명령을 실행합니다. 서비스 주체의 이름으로 바꿉 <YOUR-SERVICE-PRINCIPAL-NAME> 습니다.

az ad sp delete --id <YOUR-SERVICE-PRINCIPAL-NAME>

샘플 코드

다음 단계