다음을 통해 공유


.NET Aspire Azure 통합 개요

애플리케이션을 빌드하고 배포하는 데 가장 인기 있는 클라우드 플랫폼입니다. SDK를 사용하면 서비스를 쉽게 관리하고 사용할 수 있습니다. .NET Aspire 새 리소스를 추가하거나 기존 리소스에 연결할 수 있는 Azure 서비스와의 통합 집합을 제공합니다. 이 문서는 Azure 통합의 모든 일반적인 측면을 .NET Aspire에서 자세히 설명하며, 그 사용 방법을 이해하는 데 도움을 주는 것을 목표로 합니다.

Azure 리소스 추가

모든 .NET AspireAzure 호스팅 통합은 Azure 리소스를 노출하고 규칙에 따라 AddAzure* API를 사용하여 추가됩니다. 이러한 리소스를 .NET Aspire 앱 호스트에 추가하면 Azure 서비스를 나타냅니다. AddAzure* API는 IResourceBuilder<T>T 리소스의 형식인 Azure을 반환합니다. 이 IResourceBuilder<T> 인터페이스('작성기')는 Azure내에서 기본 리소스를 구성할 수 있도록 하는 유창한 API를 제공합니다. 새 Azure 리소스를 추가하고, 리소스를 기존 리소스로 표시하고, 다양한 실행 컨텍스트에서 리소스가 작동하는 방식을 구성하는 API가 있습니다.

일반적인 개발자 환경

.NET Aspire 앱 호스트에 Azure 리소스가 포함되어 있고 로컬로 실행하는 경우(일반적인 개발자 F5 또는 dotnet run 환경) Azure 프로비전됩니다. 이를 통해 개발자인 당신이 앱 호스트의 컨텍스트에서 로컬로 디버그할 수 있습니다.

.NET .NET Aspire는 기본 또는 StandardSKU(Stock Keeping Unit)를 사용하여 Azure 통합의 비용을 최소화하는 것을 목표로 합니다. 이러한 합리적인 기본값이 제공되지만 필요에 맞게 Azure 리소스를 사용자 지정할 수 있습니다. 또한 일부 통합은 로컬 개발, 테스트 및 디버깅에 유용한 에뮬레이터 또는 컨테이너지원합니다. 기본적으로 앱을 로컬로 실행하면 Azure 리소스는 실제 Azure 서비스를 사용합니다. 그러나 로컬 에뮬레이터 또는 컨테이너를 사용하도록 구성하여 로컬 개발 중에 실제 Azure 서비스와 관련된 비용을 방지할 수 있습니다.

로컬 에뮬레이터

일부 Azure 서비스를 에뮬레이트하여 로컬로 실행할 수 있습니다. 현재 .NET Aspire 다음 Azure 에뮬레이터를 지원합니다.

호스팅 통합 묘사
Azure Cosmos DB 에서 호출하여 리소스를 NoSQL API로 에뮬레이트되도록 구성합니다.
Azure Event Hubs 을(를) 에서 호출하여 Event Hubs 리소스를에뮬레이트되도록 구성합니다.
Azure Service Bus IResourceBuilder<AzureServiceBusResource>에서 AzureServiceBusExtensions.RunAsEmulator을(를) 호출하여 Service Bus 에뮬레이터 에뮬레이트되도록 Service Bus 리소스를 구성합니다.
Azure SignalR Service IResourceBuilder<AzureSignalRResource>에서 AzureSignalRExtensions.RunAsEmulator을 호출하여 SignalR 리소스를 AzureSignalR 에뮬레이터 에뮬레이트 하도록 구성합니다.
Azure 저장소 에서 을 호출하여 Storage 리소스를 Azurite으로 에뮬레이트되도록 구성합니다.

Azure 리소스가 로컬 에뮬레이터를 사용하도록 하려면 RunAsEmulator 리소스 작성기에서 Azure 메서드 호출을 연결합니다. 이 메서드는 실제 Azure 서비스 대신 로컬 에뮬레이터를 사용하도록 Azure 리소스를 구성합니다.

중요하다

RunAsEmulator 리소스 작성기에서 사용 가능한 Azure API를 호출해도 게시 매니페스트영향을 주지 않습니다. 앱을 게시할 때 생성된 Bicep 파일은 로컬 에뮬레이터가 아닌 실제 Azure 서비스를 반영합니다.

로컬 컨테이너

일부 Azure 리소스는 오픈 소스 또는 온-프레미스 컨테이너를 사용하여 로컬로 대체할 수 있습니다. 컨테이너에서 로컬로 Azure 리소스를 대체하려면 Azure 리소스 작성기에서 RunAsContainer 메서드에 대한 호출을 연결합니다. 이 메서드는 실제 Azure 서비스가 아닌 로컬 개발 및 테스트에 컨테이너화된 버전의 서비스를 사용하도록 Azure 리소스를 구성합니다.

.NET Aspire는 현재 컨테이너로서 다음의 Azure 서비스를 지원합니다.

호스팅 통합 세부 정보
Azure Cache for Redis AzureRedisExtensions.RunAsContainer 명령을 IResourceBuilder<AzureRedisCacheResource>에서 실행하여 docker.io/library/redis 이미지를 기반으로 컨테이너 내에서 로컬로 실행되도록 구성합니다.
Azure PostgreSQL 유연한 Server AzurePostgresExtensions.RunAsContainer 명령을 IResourceBuilder<AzurePostgresFlexibleServerResource>에서 실행하여 docker.io/library/postgres 이미지를 기반으로 컨테이너 내에서 로컬로 실행되도록 구성합니다.
Azure SQL Server AzureSqlExtensions.RunAsContainer 명령을 IResourceBuilder<AzureSqlServerResource>에서 실행하여 mcr.microsoft.com/mssql/server 이미지를 기반으로 컨테이너 내에서 로컬로 실행되도록 구성합니다.

메모

에뮬레이터와 마찬가지로 RunAsContainer 리소스 작성기에서 Azure을 호출한다고 해서 게시 매니페스트에 영향을 주지 않습니다. 앱을 게시하면 에 의해 생성된 Bicep 파일은 로컬 컨테이너가 아닌 실제 Azure 서비스를 반영합니다.

Azure 통합 API 이해

.NET .NET Aspire강점은 놀라운 개발자 내부 루프를 제공하는 능력에 있습니다. Azure 통합도 다르지 않습니다. 모든 Azure 리소스에서 공유되는 일반적인 API 및 패턴 집합을 제공합니다. 이러한 API 및 패턴은 일관된 방식으로 Azure 리소스로 쉽게 작업할 수 있도록 설계되었습니다.

이전 컨테이너 섹션에서는 컨테이너에서 로컬로 Azure 서비스를 실행하는 방법을 알아보았습니다. .NET .NET Aspire을 잘 알고 있다면, AddAzureRedis("redis").RunAsContainer()를 호출하여 로컬 docker.io/library/redis 컨테이너를 가져오는 것이 AddRedis("redis")와 어떻게 다른지 궁금할 수 있습니다.

대답은 로컬로 실행할 때 차이가 없다는 것입니다. 그러나 게시되면 다른 리소스가 제공됩니다.

API (응용 프로그래밍 인터페이스) 실행 모드 게시 모드
AddAzureRedis("redis").RunAsContainer() 로컬 Redis 컨테이너 Azure Cache for Redis
AddRedis("redis") 로컬 Redis 컨테이너 Azure 이미지를 사용하여 컨테이너 앱 Redis

SQL 및 PostgreSQL 서비스의 경우도 마찬가지입니다.

API (응용 프로그래밍 인터페이스) 실행 모드 게시 모드
AddAzurePostgresFlexibleServer("postgres").RunAsContainer() 로컬 PostgreSQL 컨테이너 Azure PostgreSQL 유연한 Server
AddPostgres("postgres") 로컬 PostgreSQL 컨테이너 Azure 이미지를 사용하여 컨테이너 앱 PostgreSQL
AddAzureSqlServer("sql").RunAsContainer() 로컬 SQL Server 컨테이너 Azure SQL Server
AddSqlServer("sql") 로컬 SQL Server 컨테이너 Azure 이미지를 사용하여 컨테이너 앱 SQL Server

실행 모드와 게시 모드의 차이점에 대한 자세한 내용은 .NET.NET Aspire 앱 호스트: 실행 컨텍스트참조하세요.

다른 모드에서 Azure 리소스를 표현하기 위한 API

앱 호스트일부인 분산 애플리케이션 빌더는 작성기 패턴을 사용하여 리소스를 AddAzure*하고, 이를 앱 모델에 추가합니다. 개발자는 이러한 리소스를 구성하고 다양한 실행 컨텍스트에서 해당 동작을 정의할 수 있습니다. Azure 호스팅 통합은 이러한 리소스를 "게시" 및 "실행"하는 방법을 지정하는 API를 제공합니다.

앱 호스트가 실행되면 실행 컨텍스트 사용하여 앱 호스트가 Run 모드인지 아니면 Publish 모드인지를 확인합니다. 이러한 API에 대한 명명 규칙은 리소스에 대한 의도된 작업을 나타냅니다.

다음 표에는 Azure 리소스를 표현하는 데 사용되는 명명 규칙이 요약되어 있습니다.

수술 API (응용 프로그래밍 인터페이스) 묘사
출판하다 PublishAsConnectionString 매니페스트에서 연결 문자열 참조로 게시할 리소스를 변경합니다.
출판하다 PublishAsExisting 애플리케이션이 배포될 때 새 리소스를 만드는 대신 기존 Azure 리소스를 사용합니다.
달려라 RunAsContainer 로컬에서 실행되도록 동등한 컨테이너를 구성합니다. 자세한 내용은 로컬 컨테이너 참조하세요.
달려라 RunAsEmulator 에뮬레이트할 Azure 리소스를 구성합니다. 자세한 내용은 로컬 에뮬레이터참조하세요.
달려라 RunAsExisting 새 리소스를 만드는 대신 애플리케이션이 실행 중일 때 기존 리소스를 사용합니다.
게시 및 실행 AsExisting 작업에 관계없이 기존 리소스를 사용합니다.

메모

모든 Azure 리소스에서 모든 API를 사용할 수 있는 것은 아닙니다. 예를 들어 일부 Azure 리소스는 컨테이너화하거나 에뮬레이트할 수 있지만 다른 리소스는 컨테이너화하거나 에뮬레이트할 수 없습니다.

실행 모드에 대한 자세한 내용은 실행 컨텍스트참조하세요.

일반 실행 모드 API 사용 사례

배포하거나 업데이트할 필요 없이 런타임 중에 기존 리소스와 동적으로 상호 작용해야 하는 경우 RunAsExisting 사용합니다. 배포 구성의 일부로 기존 리소스를 선언할 때 PublishAsExisting 사용하여 올바른 범위와 사용 권한이 적용되도록 합니다. 마지막으로, 참조를 매개 변수화해야 하는 요구 사항과 함께 두 구성에서 기존 리소스를 선언할 때 AsExisting<T>(IResourceBuilder<T>, IResourceBuilder<ParameterResource>, IResourceBuilder<ParameterResource>) 사용합니다.

IResource IsExisting(IResource) 확장 메서드를 호출하여 리소스가 기존 리소스로 표시되는지 여부를 쿼리할 수 있습니다. 자세한 내용은 기존 Azure 리소스사용을 참조하세요.

기존 Azure 리소스 사용

.NET Aspire 기존 Azure 리소스 참조를 지원합니다. PublishAsExisting, RunAsExistingAsExisting API를 통해 기존 리소스를 표시합니다. 개발자는 이러한 API를 통해 이미 배포된 Azure 리소스를 참조하고, 구성하고, Bicep 템플릿을 사용하여 적절한 배포 매니페스트를 생성할 수 있습니다.

기존 리소스는 이러한 API로 참조될 때 .NET.NET Aspire의 코드 기능을 활용하여 역할 할당 및 기타 사용자 지정으로 향상될 수 있습니다. 이러한 API는 Bicep 템플릿을 사용하여 배포할 수 있는 Azure 리소스로 제한됩니다.

실행 모드에 대한 기존 Azure 리소스 구성

RunAsExisting 메서드는 분산 애플리케이션이 "실행" 모드에서 실행될 때 사용됩니다. 이 모드에서는 참조된 Azure 리소스가 이미 존재하고 리소스를 프로비전하지 않고 실행 중에 통합된다고 가정합니다. Azure 리소스를 기존 리소스로 표시하려면 리소스 작성기에서 RunAsExisting 메서드를 호출합니다. 다음 예제를 고려하세요.

var builder = DistributedApplication.CreateBuilder();

var existingServiceBusName = builder.AddParameter("existingServiceBusName");
var existingServiceBusResourceGroup = builder.AddParameter("existingServiceBusResourceGroup");

var serviceBus = builder.AddAzureServiceBus("messaging")
                        .RunAsExisting(existingServiceBusName, existingServiceBusResourceGroup);

serviceBus.AddServiceBusQueue("queue");

앞의 코드는 다음과 같습니다.

  • builder 인스턴스를 만듭니다.
  • 작성기에서 existingServiceBusName 매개 변수를 추가합니다.
  • 작성기에 Azure Service Bus 리소스를 messaging이라는 이름으로 추가합니다.
  • serviceBus 리소스 작성기에서 RunAsExisting 메서드를 호출하여 existingServiceBusName 매개 변수를 전달합니다. 또는 string 매개 변수 오버로드를 사용할 수 있습니다.
  • queue 큐를 serviceBus 리소스에 추가합니다.

기본적으로 Service Bus 매개 변수 참조는 동일한 Azure 리소스 그룹에 있는 것으로 간주됩니다. 그러나 다른 리소스 그룹에 있는 경우 리소스 그룹을 매개 변수로 명시적으로 전달하여 적절한 리소스 그룹을 올바르게 지정할 수 있습니다.

게시 모드에 대한 기존 Azure 리소스 구성

PublishAsExisting 메서드는 게시 모드에서 기존 Azure 리소스를 선언하고 참조하려는 경우 "게시" 모드에서 사용됩니다. 이 API를 사용하면 Bicep의 기존 리소스에 매핑되는 리소스 정의를 포함하는 매니페스트 및 템플릿을 쉽게 만들 수 있습니다.

Azure 리소스를 "게시" 모드에 대한 기존 리소스로 표시하려면 리소스 작성기에서 PublishAsExisting 메서드를 호출합니다. 다음 예제를 고려하세요.

var builder = DistributedApplication.CreateBuilder();

var existingServiceBusName = builder.AddParameter("existingServiceBusName");
var existingServiceBusResourceGroup = builder.AddParameter("existingServiceBusResourceGroup");

var serviceBus = builder.AddAzureServiceBus("messaging")
                        .PublishAsExisting(existingServiceBusName, existingServiceBusResourceGroup);

serviceBus.AddServiceBusQueue("queue");

앞의 코드는 다음과 같습니다.

  • builder 인스턴스를 만듭니다.
  • 작성기에서 existingServiceBusName 매개 변수를 추가합니다.
  • 작성기에 Azure Service Bus이라는 이름의 messaging 리소스를 추가합니다.
  • serviceBus 리소스 작성기에서 PublishAsExisting 메서드를 호출하여 existingServiceBusName 매개 변수를 전달합니다. 또는 string 매개 변수 오버로드를 사용할 수 있습니다.
  • serviceBus 리소스에 queue 큐를 추가합니다.

앱 호스트가 게시 모드에서 실행되면 생성된 매니페스트 파일에는 기존 Azure 리소스를 참조하는 데 사용할 수 있는 existingResourceName 매개 변수가 포함됩니다. 매니페스트 파일의 다음과 같이 생성된 부분 코드 조각을 고려합니다.

"messaging": {
  "type": "azure.bicep.v0",
  "connectionString": "{messaging.outputs.serviceBusEndpoint}",
  "path": "messaging.module.bicep",
  "params": {
    "existingServiceBusName": "{existingServiceBusName.value}",
    "principalType": "",
    "principalId": ""
  }
},
"queue": {
  "type": "value.v0",
  "connectionString": "{messaging.outputs.serviceBusEndpoint}"
}

매니페스트 파일에 대한 자세한 내용은 배포 도구 작성기 대한.NET.NET Aspire 매니페스트 형식을 참조하세요.

또한 생성된 Bicep 템플릿에는 기존 Azure 리소스를 참조하는 데 사용할 수 있는 existingResourceName 매개 변수가 포함됩니다. 다음과 같이 생성된 Bicep 템플릿을 고려하십시오.

@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param existingServiceBusName string

param principalType string

param principalId string

resource messaging 'Microsoft.ServiceBus/namespaces@2024-01-01' existing = {
  name: existingServiceBusName
}

resource messaging_AzureServiceBusDataOwner 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(messaging.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419'))
  properties: {
    principalId: principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')
    principalType: principalType
  }
  scope: messaging
}

resource queue 'Microsoft.ServiceBus/namespaces/queues@2024-01-01' = {
  name: 'queue'
  parent: messaging
}

output serviceBusEndpoint string = messaging.properties.serviceBusEndpoint

생성된 Bicep 템플릿에 대한 자세한 내용은 코드로서의 인프라을 참조하세요.

경고

인증이 필요한 기존 리소스와 상호 작용하는 경우 .NET.NET Aspire 애플리케이션 모델에서 구성하는 인증 전략이 기존 리소스에서 허용하는 인증 전략과 일치하는지 확인합니다. 예를 들어 관리 ID를 허용하도록 구성되지 않은 기존 AzurePostgreSQL 리소스에 대해 관리 ID를 사용할 수 없습니다. 마찬가지로 기존 AzureRedis 리소스에서 액세스 키를 사용하지 않도록 설정한 경우 액세스 키 인증을 사용할 수 없습니다.

모든 모드에서 기존 Azure 리소스 구성

AsExisting<T>(IResourceBuilder<T>, IResourceBuilder<ParameterResource>, IResourceBuilder<ParameterResource>) 메서드는 분산 애플리케이션이 "실행" 또는 "게시" 모드에서 실행될 때 사용됩니다. AsExisting 메서드는 두 시나리오 모두에서 작동하므로 리소스 이름 또는 리소스 그룹 이름에 대한 매개 변수가 있는 참조만 지원합니다. 이 방법을 사용하면 테스트 환경과 프로덕션 환경 모두에서 동일한 리소스를 사용하지 않도록 방지할 수 있습니다.

Azure 리소스를 기존 리소스로 표시하려면 리소스 작성기에서 AsExisting 메서드를 호출합니다. 다음 예제를 고려하세요.

var builder = DistributedApplication.CreateBuilder();

var existingServiceBusName = builder.AddParameter("existingServiceBusName");
var existingServiceBusResourceGroup = builder.AddParameter("existingServiceBusResourceGroup");

var serviceBus = builder.AddAzureServiceBus("messaging")
                        .AsExisting(existingServiceBusName, existingServiceBusResourceGroup);

serviceBus.AddServiceBusQueue("queue");

앞의 코드는 다음과 같습니다.

  • builder 인스턴스를 만듭니다.
  • 작성기에서 existingServiceBusName 매개 변수를 추가합니다.
  • 작성기에 Azure Service Bus이라는 이름의 messaging 리소스를 추가합니다.
  • serviceBus 리소스 작성기에서 AsExisting 메서드를 호출하고 existingServiceBusName 매개 변수를 전달합니다.
  • serviceBus 리소스에 queue 큐를 추가합니다.

연결 문자열을 사용하여 기존 Azure 리소스 추가

리소스를 포함하여기존 리소스에 연결할 수 있는 기능을 제공합니다. 연결 문자열을 표현하는 것은 Azure 앱에서 사용하려는 기존 .NET Aspire 리소스가 있는 경우에 유용합니다. AddConnectionString API는 앱 호스트의 실행 컨텍스트 사용하여 앱 모델에 연결 문자열을 조건부로 추가합니다.

메모

연결 문자열은 데이터베이스 연결, 메시지 브로커, 엔드포인트 URI 및 기타 서비스를 비롯한 광범위한 연결 정보를 나타내는 데 사용됩니다. .NET .NET Aspire 명명법에서 "연결 문자열"이라는 용어는 모든 종류의 연결 정보를 나타내는 데 사용됩니다.

다음 예제를 살펴보겠습니다. 게시 모드에서 Azure Storage 리소스를 추가하고, 실행 모드에서 기존 Azure Storage에 연결 문자열을 추가하는 경우입니다.

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.ExecutionContext.IsPublishMode
    ? builder.AddAzureStorage("storage")
    : builder.AddConnectionString("storage");

builder.AddProject<Projects.Api>("api")
       .WithReference(storage);

// After adding all resources, run the app...

앞의 코드는 다음과 같습니다.

  • builder 인스턴스를 만듭니다.
  • "게시" 모드에서 Azure 저장소 리소스 storage을(를) 추가합니다.
  • "실행 모드에서 Azure의 기존 storage Storage에 연결 문자열을 추가합니다."
  • api 프로젝트를 빌더에 추가합니다.
  • api 프로젝트는 모드에 관계없이 storage 리소스를 참조합니다.

사용 중인 API 프로젝트는 앱 호스트가 구성한 방법에 대한 지식이 없는 연결 문자열 정보를 사용합니다. "게시" 모드에서 코드는 새 Storage 리소스를 추가합니다. 이 리소스는 그에 따라 배포 매니페스트에 반영됩니다. "실행" 모드에서 연결 문자열은 앱 호스트에 표시되는 구성 값에 해당합니다. 대상 리소스에 대한 모든 역할 할당이 구성된 것으로 가정합니다. 즉, 연결 문자열을 저장하도록 환경 변수 또는 사용자 암호를 구성할 수 있습니다. 구성은 ConnectionStrings__storage(또는 ConnectionStrings:storage) 구성 키에서 확인됩니다. 이러한 구성 값은 앱이 실행될 때 볼 수 있습니다. 자세한 내용은 리소스 세부 정보참조하세요.

일류 AsExisting API 모델링된 기존 리소스와 달리 연결 문자열로 모델링된 기존 리소스는 추가 역할 할당 또는 인프라 사용자 지정을 통해 향상될 수 없습니다.

코드로서의 인프라

Azure SDK는 .NET을 위해 📦Azure를 제공합니다. 또한, 프로비저닝을 위해 NuGet 패키지와 서비스별 Azure 프로비저닝 패키지 제품군도제공합니다. 이 Azure 프로비저닝 라이브러리를 사용하면 Azure에 네이티브로 .NET 인프라를 선언적으로 쉽게 지정할 수 있습니다. 해당 API를 사용하면 C#에서 개체 지향 인프라를 작성할 수 있으므로 Bicep이 생성됩니다. Bicep은 도메인별 언어(DSL)로서 Azure 리소스를 선언적으로 배포하기 위한 것입니다.

Azure 리소스를 수동으로 프로비전할 수 있지만 .NET AspireAzure 리소스를 표현하는 API 집합을 제공하여 프로세스를 간소화합니다. 이러한 API는 .NET AspireAzure 호스팅 라이브러리에서 확장 메서드로 사용할 수 있으며 IDistributedApplicationBuilder 인터페이스를 확장합니다. 앱 호스트에 Azure 리소스를 추가하면 적절한 프로비저닝 기능이 암시적으로 추가됩니다. 즉, 프로비전 API를 직접 호출할 필요가 없습니다.

.NET Aspire 모델은 Azure 호스팅 통합 내에서 리소스를 Azure하며, Azure SDK는 이러한 리소스를 프로비전하는 데 사용됩니다. 필요한 Azure 리소스를 정의하는 Bicep 파일이 생성됩니다. 생성된 Bicep 파일은 앱을 게시할 때 매니페스트 파일과 함께 출력됩니다.

생성된 Bicep 파일에 영향을 주는 방법에는 여러 가지가 있습니다.

로컬 프로비저닝 및 Azure.Provisioning

용어의 혼동을 피하고 "프로비저닝"이라는 용어를 명확히 하기 위해서는 로컬 프로비저닝Azure 프로비저닝간의 차이점을 이해하는 것이 중요합니다.

  • 로컬 프로비저닝:

    기본적으로 Azure 호스팅 통합 API를 호출하여 Azure 리소스를 추가하면 AddAzureProvisioning(IDistributedApplicationBuilder) API가 암시적으로 호출됩니다. 이 API는 앱 호스트가 시작될 때 Azure 리소스를 프로비전하는 데 사용되는 DI(종속성 주입) 컨테이너에 서비스를 등록합니다. 이 개념은 로컬 프로비저닝으로 알려져 있습니다. 자세한 내용은 로컬 Azure 프로비저닝를 참조하세요.

  • Azure.Provisioning:

    Azure.Provisioning NuGet 패키지를 참조하며 C#을 사용하여 Bicep을 생성할 수 있는 라이브러리 집합입니다. Azure 호스팅 통합은 .NET Aspire에서 이러한 라이브러리를 배후에서 사용하여 필요한 Azure 리소스를 정의하는 Bicep 파일을 생성합니다. 자세한 내용은 Azure.Provisioning 사용자 지정참조하세요.

Azure.Provisioning 사용자 지정

모든 .NET AspireAzure 호스팅 통합은 다양한 Azure 리소스를 노출하며, 이들은 모두 AzureProvisioningResource를 상속받는 AzureBicepResource 유형의 하위 클래스입니다. 이것은 일반적으로 형식 제약이 있는 확장 기능을 가능하게 하여, 유창한 API로 사용자가 원하는 대로 인프라를 사용자 지정할 수 있게 합니다. .NET .NET Aspire 기본값을 제공하지만 이러한 API를 사용하여 생성된 Bicep에 자유롭게 영향을 줄 수 있습니다.

인프라 구성

작업 중인 Azure 리소스에 관계없이 기본 인프라를 구성하려면 ConfigureInfrastructure 확장 메서드에 대한 호출을 연결합니다. 이 메서드를 사용하면 Azure형식의 configure 대리자를 전달하여 Action<AzureResourceInfrastructure> 리소스의 인프라를 사용자 지정할 수 있습니다. AzureResourceInfrastructure 형식은 Azure.Provisioning.Infrastructure하위 클래스입니다. 이 형식은 Azure 리소스의 기본 인프라를 구성하기 위한 대규모 API 노출 영역을 노출합니다.

다음 예제를 고려하세요.

var sku = builder.AddParameter("storage-sku");

var storage = builder.AddAzureStorage("storage")
    .ConfigureInfrastructure(infra =>
    {
        var resources = infra.GetProvisionableResources();

        var storageAccount = resources.OfType<StorageAccount>().Single();

        storageAccount.Sku = new StorageSku
        {
            Name = sku.AsProvisioningParameter(infra)
        };
    });

앞의 코드는 다음과 같습니다.

  • storage-sku매개 변수를 추가합니다.
  • Azure AddAzureStorage API를 사용하여 storage Storage를 추가합니다.
  • ConfigureInfrastructure Storage 인프라를 사용자 지정하기 위해 Azure 호출을 연결합니다.

이는 외부 매개 변수이 Azure 저장소 인프라로 흘러 들어가 구성이 반영된 Bicep 파일을 생성하는 예시입니다.

Azure 인프라 추가

모든 Azure 서비스가 .NET Aspire 통합으로 노출되는 것은 아닙니다. 나중에 제공될 수도 있지만 Azure.Provisioning.* 라이브러리에서 사용할 수 있는 서비스를 프로비전할 수 있습니다. Azure Container Registry 관리를 담당하는 작업자 서비스가 있는 시나리오를 상상해 보십시오. 이제 앱 호스트 프로젝트가 📦Azure종속성을 사용하여 Provisioning.ContainerRegistry NuGet 패키지에 의존한다고 상상해 보십시오.

AddAzureInfrastructure API를 사용하여 앱 호스트에 Azure Container Registry 인프라를 추가할 수 있습니다.

var acr = builder.AddAzureInfrastructure("acr", infra =>
{
    var registry = new ContainerRegistryService("acr")
    {
        Sku = new()
        {
            Name = ContainerRegistrySkuName.Standard
        },
    };
    infra.Add(registry);

    var output = new ProvisioningOutput("registryName", typeof(string))
    {
        Value = registry.Name
    };
    infra.Add(output);
});

builder.AddProject<Projects.WorkerService>("worker")
       .WithEnvironment(
            "ACR_REGISTRY_NAME",
            new BicepOutputReference("registryName", acr.Resource));

앞의 코드는 다음과 같습니다.

  • 이름이 AddAzureInfrastructureacr을 호출합니다.
  • configureInfrastructure 대리자를 제공하여 Azure 컨테이너 레지스트리 인프라를 사용자 지정합니다.
    • ContainerRegistryService을(를) 이름 acr 및 표준 SKU로 인스턴스화합니다.
    • Azure Container Registry 서비스를 infra 변수에 추가합니다.
    • ProvisioningOutput을(를) registryName이라는 이름과 string라는 형식으로, Azure Container Registry의 이름에 해당하는 값으로 인스턴스화합니다.
    • 출력을 infra 변수에 추가합니다.
  • worker 프로젝트를 빌더에 추가합니다.
  • WithEnvironment 호출을 연결하여 프로젝트의 ACR_REGISTRY_NAME 환경 변수를 registryName 출력 값으로 설정합니다.

이 기능은 Azure 서비스가 Azure 통합으로 직접 노출되지 않더라도 앱 호스트 프로젝트에 .NET Aspire 인프라를 추가하는 방법을 보여 줍니다. 또한 Azure Container Registry의 출력을 종속 프로젝트의 환경으로 이동하는 방법을 보여 줍니다.

결과로 생성된 Bicep 파일을 확인하세요.

@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

resource acr 'Microsoft.ContainerRegistry/registries@2023-07-01' = {
  name: take('acr${uniqueString(resourceGroup().id)}', 50)
  location: location
  sku: {
    name: 'Standard'
  }
}

output registryName string = acr.name

Bicep 파일은 Azure API에 정의된 대로 AddAzureInfrastructure Container Registry의 원하는 구성을 반영합니다.

사용자 지정 Bicep 템플릿을 사용하기

Azure 원하는 클라우드 공급자로 대상으로 지정할 때 Bicep을 사용하여 인프라를 코드로 정의할 수 있습니다. 보다 명확한 구문을 사용하여 제작 환경을 대폭 간소화하고 모듈성 및 코드 재사용에 대한 지원을 향상하는 것을 목표로 합니다.

.NET .NET Aspire 미리 빌드된 Bicep 템플릿 집합을 제공하지만 템플릿을 사용자 지정하거나 직접 만들려는 경우가 있을 수 있습니다. 이 섹션에서는 Bicep 템플릿을 사용자 지정하는 데 사용할 수 있는 개념 및 해당 API에 대해 설명합니다.

중요하다

이 섹션은 Bicep을 가르치는 것이 목적이 아니라, .NET.NET Aspire에서 사용할 사용자 지정 Bicep 템플릿을 작성하는 방법에 대한 지침을 제공하기 위한 것입니다.

대한 배포 스토리의 일부로 ()는 프로젝트와 배포하는 기능을 이해합니다. azd CLI는 Bicep 템플릿을 사용하여 애플리케이션을 Azure에 배포합니다.

Aspire.Hosting.Azure 패키지 설치

Bicep 파일을 참조하려는 경우 Azure 호스팅 통합을 사용하지 않을 수 있습니다. 이 경우 Aspire.Hosting.Azure 패키지를 설치하여 Bicep 파일을 계속 참조할 수 있습니다. 이 패키지는 Bicep 파일을 참조하고 Azure 리소스를 사용자 지정하는 데 필요한 API를 제공합니다.

Azure 호스팅 통합을 사용하는 경우 전이적 종속성이기 때문에 Aspire.Hosting.Azure 패키지를 설치할 필요가 없습니다.

이 기능을 사용하려면 📦Aspire. 호스팅.Azure NuGet 패키지를 설치해야 합니다.

dotnet add package Aspire.Hosting.Azure

자세한 내용은 dotnet add package 또는 .NET 애플리케이션의 패키지 종속성을 관리하는 방법를 참조하세요.

예제에서 예상할 사항

이 섹션의 모든 예제에서는 Aspire.Hosting.Azure 네임스페이스를 사용한다고 가정합니다. 또한 예제에서는 IDistributedApplicationBuilder 인스턴스가 있다고 가정합니다.

using Aspire.Hosting.Azure;

var builder = DistributedApplication.CreateBuilder(args);

// Examples go here...

builder.Build().Run();

기본적으로 Bicep 관련 API를 호출할 때, AddAzureProvisioning에 대한 호출도 이루어져 애플리케이션 시작 시 동적으로 Azure 리소스를 생성하는 지원을 추가합니다. 자세한 내용은 로컬 프로비저닝 및 Azure.Provisioning참조하세요.

Bicep 파일 참조하기

storage.bicep Storage 계정을 프로비전하는 Azure 파일에 Bicep 템플릿이 있다고 상상해 보세요.

param location string = resourceGroup().location
param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}

디스크의 Bicep 파일에 대한 참조를 추가하려면 AddBicepTemplate 메서드를 호출합니다. 다음 예제를 고려하세요.

builder.AddBicepTemplate(
    name: "storage",
    bicepFile: "../infra/storage.bicep");

앞의 코드는 ../infra/storage.bicep에 위치한 Bicep 파일에 대한 참조를 추가합니다. 파일 경로는 앱 호스트 프로젝트를 기준으로 해야 합니다. 이 참조는 AzureBicepResource이(가) "storage"이라는 이름으로 애플리케이션의 리소스 컬렉션에 포함되며, API는 리소스를 추가로 사용자 정의할 수 있는 IResourceBuilder<AzureBicepResource> 인스턴스를 반환합니다.

Bicep 인라인 참조

디스크에 Bicep 파일이 있는 것이 가장 일반적인 시나리오이지만 Bicep 템플릿을 인라인으로 추가할 수도 있습니다. 인라인 템플릿은 코드에서 템플릿을 정의하거나 템플릿을 동적으로 생성하려는 경우에 유용할 수 있습니다. Bicep 템플릿을 인라인으로 추가하려면 AddBicepTemplateString인 Bicep 템플릿을 사용해 string 메서드를 호출합니다. 다음 예제를 고려하세요.

builder.AddBicepTemplateString(
        name: "ai",
        bicepContent: """
        @description('That name is the name of our application.')
        param cognitiveServiceName string = 'CognitiveService-${uniqueString(resourceGroup().id)}'

        @description('Location for all resources.')
        param location string = resourceGroup().location

        @allowed([
          'S0'
        ])
        param sku string = 'S0'

        resource cognitiveService 'Microsoft.CognitiveServices/accounts@2021-10-01' = {
          name: cognitiveServiceName
          location: location
          sku: {
            name: sku
          }
          kind: 'CognitiveServices'
          properties: {
            apiProperties: {
              statisticsEnabled: false
            }
          }
        }
        """
    );

이 예제에서 Bicep 템플릿은 인라인으로 string로 정의된 후, 이름이 "ai"로 하여 애플리케이션의 리소스 컬렉션에 추가됩니다. 이 예제에서는 Azure AI 리소스를 프로비전합니다.

Bicep 템플릿에 매개 변수 전달

Bicep은 매개 변수의 수락을 지원하며, 이를 통해 템플릿의 동작을 사용자 지정할 수 있습니다. Bicep 템플릿에 매개 변수를 전달하려면 .NET.NET Aspire에서, 다음 예제와 같이 WithParameter 메서드를 호출하여 연결하십시오.

var region = builder.AddParameter("region");

builder.AddBicepTemplate("storage", "../infra/storage.bicep")
       .WithParameter("region", region)
       .WithParameter("storageName", "app-storage")
       .WithParameter("tags", ["latest","dev"]);

앞의 코드는 다음과 같습니다.

  • "region" 인스턴스에 builder 매개 변수를 추가합니다.
  • ../infra/storage.bicep에 위치한 Bicep 파일에 참조를 추가합니다.
  • 표준 매개 변수 해석을 사용하여 해결되는 "region" 매개 변수를 Bicep 템플릿에 전달합니다.
  • "storageName" 값을 사용하여 매개 변수를 Bicep 템플릿에 전달합니다.
  • 문자열 배열을 사용하여 "tags" 매개 변수를 Bicep 템플릿에 전달합니다.

자세한 내용은외부 매개 변수를 참조하세요.

잘 알려진 매개 변수

.NET .NET Aspire Bicep 템플릿에 전달할 수 있는 잘 알려진 매개 변수 집합을 제공합니다. 이러한 매개 변수는 애플리케이션 및 환경에 대한 정보를 Bicep 템플릿에 제공하는 데 사용됩니다. 다음과 같은 잘 알려진 매개 변수를 사용할 수 있습니다.

분야 묘사
AzureBicepResource.KnownParameters.KeyVaultName 비밀 출력을 저장하는 데 사용되는 키 자격 증명 보관소 리소스의 이름입니다. "keyVaultName"
AzureBicepResource.KnownParameters.Location 리소스의 위치입니다. 이는 모든 리소스에 필요합니다. "location"
AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId 로그 분석 작업 영역의 리소스 ID입니다. "logAnalyticsWorkspaceId"
AzureBicepResource.KnownParameters.PrincipalId 현재 사용자 또는 관리 ID의 보안 주체 ID입니다. "principalId"
AzureBicepResource.KnownParameters.PrincipalName 현재 사용자 또는 관리 ID의 주체 이름입니다. "principalName"
AzureBicepResource.KnownParameters.PrincipalType 현재 사용자 또는 관리 ID의 주체 유형입니다. User 또는 ServicePrincipal. "principalType"

잘 알려진 매개 변수를 사용하려면 매개 변수 이름을 WithParameter같은 WithParameter(AzureBicepResource.KnownParameters.KeyVaultName) 메서드에 전달합니다. .NET와.NET Aspire이 알아서 해결하므로 잘 알려진 매개 변수에 대한 값을 전달하지 않습니다.

Azure Event Grid 웹후크를 설정하려는 예제를 생각해 보세요. 다음과 같이 Bicep 템플릿을 정의할 수 있습니다.

param topicName string
param webHookEndpoint string
param principalId string
param principalType string
param location string = resourceGroup().location

// The topic name must be unique because it's represented by a DNS entry. 
// must be between 3-50 characters and contain only values a-z, A-Z, 0-9, and "-".

resource topic 'Microsoft.EventGrid/topics@2023-12-15-preview' = {
  name: toLower(take('${topicName}${uniqueString(resourceGroup().id)}', 50))
  location: location

  resource eventSubscription 'eventSubscriptions' = {
    name: 'customSub'
    properties: {
      destination: {
        endpointType: 'WebHook'
        properties: {
          endpointUrl: webHookEndpoint
        }
      }
    }
  }
}

resource EventGridRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(topic.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7'))
  scope: topic
  properties: {
    principalId: principalId
    principalType: principalType
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7')
  }
}

output endpoint string = topic.properties.endpoint

이 Bicep 템플릿은 topicName, webHookEndpoint, principalId, principalType및 선택적 location포함한 여러 매개 변수를 정의합니다. 이러한 매개 변수를 Bicep 템플릿에 전달하려면 다음 코드 조각을 사용할 수 있습니다.

var webHookApi = builder.AddProject<Projects.WebHook_Api>("webhook-api");

var webHookEndpointExpression = ReferenceExpression.Create(
        $"{webHookApi.GetEndpoint("https")}/hook");

builder.AddBicepTemplate("event-grid-webhook", "../infra/event-grid-webhook.bicep")
       .WithParameter("topicName", "events")
       .WithParameter(AzureBicepResource.KnownParameters.PrincipalId)
       .WithParameter(AzureBicepResource.KnownParameters.PrincipalType)
       .WithParameter("webHookEndpoint", () => webHookEndpointExpression);
  • webHookApi 프로젝트는 builder대한 참조로 추가됩니다.
  • topicName 매개 변수는 하드 코딩된 이름 값으로 전달됩니다.
  • webHookEndpoint 매개 변수는 api 프로젝트 참조의 "https" 엔드포인트에서 나온 URL이 되는 표현식으로 전달되며, 그 과정에서 /hook 경로가 사용됩니다.
  • principalIdprincipalType 매개 변수는 잘 알려진 매개 변수로 전달됩니다.

잘 알려진 매개 변수는 규칙 기반이며 WithParameter API를 사용하여 전달될 때 해당 값과 함께 사용하면 안 됩니다. 널리 알려진 매개변수는, 앞선 예에서 보인 바와 같이, Bicep 템플릿에 추가할 때 역할 할당 등 몇 가지 일반적인 기능을 간소화합니다. Event Grid 웹후크가 지정된 엔드포인트에 이벤트를 보내려면 역할 할당이 필요합니다. 자세한 내용은 Event Grid 데이터 보낸 사람 역할 할당을 참조하세요.

Bicep 참조에서 출력 가져오기

Bicep 템플릿에 매개 변수를 전달하는 것 외에도 Bicep 템플릿에서 출력을 가져올 수 있습니다. 다음 Bicep 템플릿을 고려하세요, 여기서 outputendpoint로 명명되었습니다.

param storageName string
param location string = resourceGroup().location

resource myStorageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' = {
  name: storageName
  location: location
  kind: 'StorageV2'
  sku:{
    name:'Standard_LRS'
    tier: 'Standard'
  }
  properties: {
    accessTier: 'Hot'
  }
}

output endpoint string = myStorageAccount.properties.primaryEndpoints.blob

Bicep은 endpoint이라는 출력 이름을 정의합니다. Bicep 템플릿에서 출력을 얻으려면 다음 C# 코드 조각에 설명된 대로 GetOutput 인스턴스에서 IResourceBuilder<AzureBicepResource> 메서드를 호출합니다.

var storage = builder.AddBicepTemplate(
        name: "storage",
        bicepFile: "../infra/storage.bicep"
    );

var endpoint = storage.GetOutput("endpoint");

이 예제에서는 Bicep 템플릿의 출력을 검색하고 endpoint 변수에 저장합니다. 일반적으로 이 출력을 사용하는 다른 리소스에 환경 변수로 전달합니다. 예를 들어 이 엔드포인트에 종속된 ASP.NET Core 최소 API 프로젝트가 있는 경우 다음 코드 조각을 사용하여 출력을 환경 변수로 프로젝트에 전달할 수 있습니다.

var storage = builder.AddBicepTemplate(
                name: "storage",
                bicepFile: "../infra/storage.bicep"
            );

var endpoint = storage.GetOutput("endpoint");

var apiService = builder.AddProject<Projects.AspireSample_ApiService>(
        name: "apiservice"
    )
    .WithEnvironment("STORAGE_ENDPOINT", endpoint);

자세한 내용은 Bicep Output을 참조하세요.

Bicep 참조에서 비밀 출력 가져오기

Bicep으로 작업할 때 비밀 대한 출력을 피하는 것이 중요합니다. 출력이 비밀간주되어 로그 또는 다른 위치에 노출되지 않아야 하는 경우 다음과 같이 처리할 수 있습니다. 비밀을 Azure Key Vault에 저장하고 Bicep 템플릿에서 참조하여 이를 수행할 수 있습니다. .NET Aspire의 Azure 통합은 Bicep 템플릿의 출력을 안전하게 저장하기 위한 패턴을 제공하며, 리소스가 keyVaultName 매개 변수를 사용하여 비밀을 Azure Key Vault에 저장할 수 있도록 합니다.

다음 Bicep 템플릿을 예로 들어 비밀 출력을 보호하는 이 개념을 보여 줍니다.

param databaseAccountName string
param keyVaultName string

param databases array = []

@description('Tags that will be applied to all resources')
param tags object = {}

param location string = resourceGroup().location

var resourceToken = uniqueString(resourceGroup().id)

resource cosmosDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = {
    name: replace('${databaseAccountName}-${resourceToken}', '-', '')
    location: location
    kind: 'GlobalDocumentDB'
    tags: tags
    properties: {
        consistencyPolicy: { defaultConsistencyLevel: 'Session' }
        locations: [
            {
                locationName: location
                failoverPriority: 0
            }
        ]
        databaseAccountOfferType: 'Standard'
    }

    resource db 'sqlDatabases@2023-04-15' = [for name in databases: {
        name: '${name}'
        location: location
        tags: tags
        properties: {
            resource: {
                id: '${name}'
            }
        }
    }]
}

var primaryMasterKey = cosmosDb.listKeys(cosmosDb.apiVersion).primaryMasterKey

resource vault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
    name: keyVaultName

    resource secret 'secrets@2023-07-01' = {
        name: 'connectionString'
        properties: {
            value: 'AccountEndpoint=${cosmosDb.properties.documentEndpoint};AccountKey=${primaryMasterKey}'
        }
    }
}

앞의 Bicep 템플릿에는 여러 매개 변수 중 하나로 keyVaultName 매개 변수가 필요합니다. 그런 다음 Azure Cosmos DB 리소스를 정의하고 Azure Key Vault라는 이름의 비밀을 connectionString에 숨기는데, 이는 Cosmos DB 인스턴스에 대한 완전한 연결 문자열을 나타냅니다. 이 비밀 연결 문자열 값에 액세스하려면 다음 코드 조각을 사용할 수 있습니다.

var cosmos = builder.AddBicepTemplate("cosmos", "../infra/cosmosdb.bicep")
    .WithParameter("databaseAccountName", "fallout-db")
    .WithParameter(AzureBicepResource.KnownParameters.KeyVaultName)
    .WithParameter("databases", ["vault-33", "vault-111"]);

var connectionString =
    cosmos.GetSecretOutput("connectionString");

builder.AddProject<Projects.WebHook_Api>("api")
    .WithEnvironment(
        "ConnectionStrings__cosmos",
        connectionString);

위의 코드 조각에서 cosmos Bicep 템플릿은 builder에 대한 참조로 추가되었습니다. connectionString 비밀 출력은 Bicep 템플릿에서 검색되고 변수에 저장됩니다. 그런 다음 비밀 출력이 환경 변수(ConnectionStrings__cosmos)로 api 프로젝트에 전달됩니다. 이 환경 변수는 Cosmos DB 인스턴스에 연결하는 데 사용됩니다.

이 리소스가 배포되면, 기본 배포 메커니즘은 에서 비밀을 참조하여 자동으로 를 수행합니다. 비밀 격리를 보장하기 위해 .NET.NET Aspire 원본당 Key Vault를 만듭니다.

메모

로컬 프로비저닝 모드에서는 비밀이 Key Vault에서 추출되어 환경 변수로 설정됩니다. 자세한 내용은 로컬 Azure 프로비저닝를 참조하세요.

출판

앱을 게시할 때, Azure에 의해 생성된 프로비전 Bicep은 Azure Developer CLI에서 Azure 구독의 Azure 리소스를 만드는 데 사용됩니다. .NET .NET Aspire은 게시 매니페스트를 출력하며, 이는 출판 과정의 중요한 부분입니다. Azure Developer CLI Azure 리소스를 관리하는 명령 집합을 제공하는 명령줄 도구입니다.

게시 및 배포에 대해 더 알고 싶으시면, .NET Aspire 프로젝트를 Azure Container Apps에 배포하기 위해 Azure Developer CLI(심층 가이드)를 참조하세요.