Visão geral das integrações .NET AspireAzure
Azure é a plataforma de nuvem mais popular para criar e implantar aplicativos .NET. O SDK Azure para .NET permite a gestão e utilização fácil de serviços Azure. .NET Aspire fornece um conjunto de integrações com Azure serviços, onde você é livre para adicionar novos recursos ou conectar-se aos existentes. Este artigo detalha alguns aspetos comuns de todas as integrações Azure no .NET Aspire e tem como objetivo ajudá-lo a entender como usá-las.
Adicionar recursos Azure
Todas as integrações de hospedagem .NET AspireAzure expõem recursos Azure e, por convenção, são adicionadas usando APIs AddAzure*
. Quando você adiciona esses recursos ao host do aplicativo .NET Aspire, eles representam um serviço Azure. A API AddAzure*
retorna um IResourceBuilder<T> em que T
é o tipo de recurso Azure. Essas interfaces IResourceBuilder<T>
(construtor) fornecem uma API fluente que permite configurar o recurso Azure subjacente dentro do modelo de aplicativo . Há APIs para adicionar novos recursos de Azure, marcar recursos como existentes e configurar como os recursos se comportam em vários contextos de execução.
Experiência típica de desenvolvedor
Quando o host da aplicação .NET Aspire possui recursos Azure e você o executa localmente (como é típico na experiência de desenvolvimento com usando F5 ou dotnet run
), os recursos Azure são provisionados na sua subscrição do Azure. Isso permite que, como desenvolvedor, efetue testes de depuração com eles localmente no ambiente do host da sua aplicação.
.NET .NET Aspire tem como objetivo minimizar os custos, definindo por padrão Básico ou StandardStock Keeping Unit (SKU) para as suas integrações Azure. Embora esses padrões sensatos sejam fornecidos, você pode personalizar os recursos Azure para atender às suas necessidades. Além disso, algumas integrações suportam os emuladores ou contentores, que são úteis para desenvolvimento, teste e depuração locais. Por padrão, quando você executa seu aplicativo localmente, os recursos Azure usam o serviço Azure real. No entanto, você pode configurá-los para usar emuladores ou contêineres locais, evitando custos associados ao serviço de Azure real durante o desenvolvimento local.
Emuladores locais
Alguns Azure serviços podem ser emulados para serem executados localmente. Atualmente, o .NET Aspire suporta os seguintes emuladores de Azure:
Integração de hospedagem | Descrição |
---|---|
Azure Cosmos DB | Chame AzureCosmosExtensions.RunAsEmulator no IResourceBuilder<AzureCosmosDBResource> para configurar o recurso Cosmos DB para ser emulado com a API NoSQL. |
Azure Event Hubs | Ligue AzureEventHubsExtensions.RunAsEmulator no IResourceBuilder<AzureEventHubsResource> para configurar o recurso Hubs de Eventos para ser emulado. |
Azure Service Bus | Chame AzureServiceBusExtensions.RunAsEmulator no IResourceBuilder<AzureServiceBusResource> para configurar o recurso do Service Bus a ser emulado com o emulador do Service Bus. |
Azure SignalR Service | Chame AzureSignalRExtensions.RunAsEmulator no IResourceBuilder<AzureSignalRResource> para configurar o recurso SignalR a ser emulado com AzureSignalR emulador. |
Azure Armazenamento | Chame AzureStorageExtensions.RunAsEmulator no IResourceBuilder<AzureStorageResource> para configurar o recurso de armazenamento como emulado com Azurite. |
Para que os seus recursos Azure usem os emuladores locais, encadeie uma chamada ao método RunAsEmulator
no construtor de recursos Azure. Esse método configura o recurso Azure para usar o emulador local em vez do serviço Azure real.
Importante
Chamar qualquer uma das RunAsEmulator
APIs disponíveis num construtor de recursos Azure não afeta o manifesto de publicação . Quando você publica sua aplicação, o ficheiro Bicep gerado reflete o serviço real, não o emulador local.
Contentores locais
Alguns recursos Azure podem ser substituídos localmente usando contêineres de código aberto ou locais. Para substituir um recurso Azure localmente em um contêiner, encadeie uma chamada para o método RunAsContainer
no Azure construtor de recursos. Esse método configura o recurso Azure para usar uma versão em contêiner do serviço para desenvolvimento e teste locais, em vez do serviço Azure real.
Atualmente, o .NET Aspire oferece suporte aos seguintes serviços Azure como contêineres:
Integração de hospedagem | Detalhes |
---|---|
Azure Cache for Redis | Chame AzureRedisExtensions.RunAsContainer no IResourceBuilder<AzureRedisCacheResource> para configurá-lo para ser executado localmente em um contêiner, com base na imagem docker.io/library/redis . |
Azure PostgreSQL flexível Server | Chame AzurePostgresExtensions.RunAsContainer no IResourceBuilder<AzurePostgresFlexibleServerResource> para configurá-lo para ser executado localmente em um contêiner, com base na imagem docker.io/library/postgres . |
Azure SQL Server | Chame AzureSqlExtensions.RunAsContainer no IResourceBuilder<AzureSqlServerResource> para configurá-lo para ser executado localmente em um contêiner, com base na imagem mcr.microsoft.com/mssql/server . |
Observação
Tal como os emuladores, chamar RunAsContainer
em um builder de recursos Azure não afeta o manifesto de publicação . Quando publicas a tua aplicação, o arquivo Bicep gerado reflete o serviço efetivo, não o contêiner local.
Como compreender as APIs de integração Azure
A força do .NET.NET Aspirereside na sua capacidade de proporcionar um incrível ciclo interno de desenvolvimento. As integrações Azure não são diferentes. Eles fornecem um conjunto de APIs e padrões comuns que são compartilhados em todos os recursos Azure. Essas APIs e padrões são projetados para facilitar o trabalho com recursos Azure de maneira consistente.
Na seção de contêineres anterior, você viu como executar Azure serviços localmente em contêineres. Se você estiver familiarizado com .NET.NET Aspire, pode se perguntar como chamar AddAzureRedis("redis").RunAsContainer()
para obter um contêiner docker.io/library/redis
local difere de AddRedis("redis")
—já que ambos resultam no mesmo contêiner local.
A resposta é que não há diferença ao executar localmente. No entanto, quando são publicados, obtém recursos diferentes:
API | Modo de execução | Modo de publicação |
---|---|---|
AddAzureRedis("redis").RunAsContainer() | Contentor local Redis | Azure Cache for Redis |
AddRedis("redis") | Contentor local Redis | Azure Aplicativo de Contêiner com imagem Redis |
O mesmo vale para SQL e serviços PostgreSQL:
API | Modo de execução | Modo de publicação |
---|---|---|
AddAzurePostgresFlexibleServer("postgres").RunAsContainer() | Contentor local PostgreSQL | Azure PostgreSQL flexível Server |
AddPostgres("postgres") | Contentor local PostgreSQL | Azure Aplicativo de Contêiner com imagem PostgreSQL |
AddAzureSqlServer("sql"). RunAsContainer() | Contentor local SQL Server | Azure SQL Server |
AddSqlServer("sql") | Contentor local SQL Server | Azure Aplicativo de Contêiner com imagem SQL Server |
Para obter mais informações sobre a diferença entre os modos de execução e publicação, consulte .NET.NET Aspire host do aplicativo: contexto de execução.
APIs para expressar recursos Azure em diferentes modos
O construtor de aplicativo distribuído, parte do host de aplicativo, utiliza o padrão de construção para AddAzure*
recursos ao modelo de aplicativo. Os desenvolvedores podem configurar esses recursos e definir seu comportamento em diferentes contextos de execução.
Azure integrações de hospedagem fornecem APIs para especificar como esses recursos devem ser "publicados" e "executados".
Quando o host do aplicativo é executado, o contexto de execução é usado para determinar se o host do aplicativo está no modo Run ou Publish. As convenções de nomenclatura para essas APIs indicam a ação pretendida para o recurso.
A tabela a seguir resume as convenções de nomenclatura usadas para expressar recursos Azure:
Observação
Nem todas as APIs estão disponíveis em todos os recursos Azure. Por exemplo, alguns recursos Azure podem ser conteinerizados ou emulados, enquanto outros não.
Para obter mais informações sobre modos de execução, consulte Contexto de execução.
Casos de uso gerais da API do modo de execução
Use RunAsExisting quando precisar interagir dinamicamente com um recurso existente durante o tempo de execução sem precisar implantá-lo ou atualizá-lo. Use PublishAsExisting ao declarar recursos existentes como parte de uma configuração de implantação, garantindo que os escopos e permissões corretos sejam aplicados. Finalmente, use AsExisting<T>(IResourceBuilder<T>, IResourceBuilder<ParameterResource>, IResourceBuilder<ParameterResource>) ao declarar recursos existentes em ambas as configurações, com um requisito para parametrizar as referências.
Você pode consultar se um recurso está marcado como um recurso existente, chamando o método de extensão IsExisting(IResource) no IResource. Para obter mais informações, consulte Usar recursos de Azure existentes.
Utilizar os recursos existentes de Azure
.NET Aspire fornece suporte para referenciar recursos Azure existentes. Você marca um recurso existente por meio das APIs PublishAsExisting
, RunAsExisting
e AsExisting
. Essas APIs permitem que os desenvolvedores façam referência a recursos Azure já implantados, configurem-nos e gerem manifestos de implantação apropriados usando modelos Bicep.
Os recursos existentes referenciados com essas APIs podem ser aprimorados com atribuições de função e outras personalizações disponíveis com as capacidades de infraestrutura como código do .NET.NET Aspire. Essas APIs são limitadas a recursos de Azure que podem ser implantados com templates Bicep.
Configurar recursos Azure existentes para o modo de execução
O método RunAsExisting é usado quando um aplicativo distribuído está sendo executado no modo "executar". Nesse modo, ele assume que o recurso de Azure referenciado já existe e se integra a ele durante a execução sem provisionar o recurso. Para marcar um recurso Azure como existente, chame o método RunAsExisting
no construtor de recursos. Considere o seguinte exemplo:
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");
O código anterior:
- Cria uma nova instância
builder
. - Adiciona um parâmetro chamado
existingServiceBusName
ao construtor. - Adiciona um recurso Azure Service Bus chamado
messaging
ao construtor. - Chama o método
RunAsExisting
no construtor de recursosserviceBus
, passando o parâmetroexistingServiceBusName
— alternativamente, podes usar a sobrecarga de parâmetrosstring
. - Adiciona uma fila chamada
queue
ao recursoserviceBus
.
Por padrão, presume-se que a referência de parâmetro do Service Bus esteja no mesmo grupo de recursos Azure. No entanto, se estiver em um grupo de recursos diferente, você poderá passar o grupo de recursos explicitamente como um parâmetro para especificar corretamente o agrupamento de recursos apropriado.
Configurar recursos de Azure existentes para o modo de publicação
O método PublishAsExisting é usado no modo "publish" quando a intenção é declarar e fazer referência a um recurso Azure já existente durante o modo de publicação. Esta API facilita a criação de manifestos e modelos que incluem definições de recursos que correspondem a recursos existentes no Bicep.
Para marcar um recurso Azure como existente no modo "publicar", chame o método PublishAsExisting
no construtor de recursos. Considere o seguinte exemplo:
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");
O código anterior:
- Cria uma nova instância
builder
. - Adiciona um parâmetro chamado
existingServiceBusName
ao construtor. - Adiciona um recurso Azure Service Bus chamado
messaging
ao construtor. - Chama o método
PublishAsExisting
no construtor de recursosserviceBus
, passando o parâmetroexistingServiceBusName
— alternativamente, podes usar a sobrecarga de parâmetrosstring
. - Adiciona uma fila chamada
queue
ao recursoserviceBus
.
Depois que o host do aplicativo for executado no modo de publicação, o arquivo de manifesto gerado incluirá o parâmetro existingResourceName
, que pode ser usado para fazer referência ao recurso Azure existente. Considere o seguinte trecho parcial gerado do arquivo de manifesto:
"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}"
}
Para obter mais informações sobre o arquivo de manifesto, consulte .NET.NET Aspire formato de manifesto para construtores de ferramentas de implantação.
Além disso, o modelo Bicep gerado inclui o parâmetro existingResourceName
, que pode ser usado para fazer referência ao recurso Azure existente. Considere o seguinte modelo Bicep gerado:
@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
Para obter mais informações sobre os modelos Bicep gerados, consulte infraestrutura como de código e considerar outras APIs de publicação.
Advertência
Ao interagir com recursos existentes que exigem autenticação, verifique se a estratégia de autenticação que você está configurando no modelo de aplicativo .NET.NET Aspire está alinhada com a estratégia de autenticação permitida pelo recurso existente. Por exemplo, não é possível usar a identidade gerenciada em um recurso de AzurePostgreSQL existente que não esteja configurado para permitir a identidade gerenciada. Da mesma forma, se um recurso AzureRedis existente desabilitou as chaves de acesso, não é possível usar a autenticação de chave de acesso.
Configurar os recursos de Azure existentes em todos os modos
O método AsExisting<T>(IResourceBuilder<T>, IResourceBuilder<ParameterResource>, IResourceBuilder<ParameterResource>) é usado quando o aplicativo distribuído está sendo executado no modo "executar" ou "publicar". Como o método AsExisting
opera em ambos os cenários, ele oferece suporte apenas a uma referência parametrizada ao nome do recurso ou ao nome do grupo de recursos. Essa abordagem ajuda a evitar o uso do mesmo recurso em ambientes de teste e produção.
Para marcar um recurso Azure como existente, chame o método AsExisting
no construtor de recursos. Considere o seguinte exemplo:
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");
O código anterior:
- Cria uma nova instância
builder
. - Adiciona um parâmetro chamado
existingServiceBusName
ao construtor. - Adiciona um recurso Azure Service Bus chamado
messaging
ao construtor. - Chama o método
AsExisting
noserviceBus
construtor de recursos, passando o parâmetroexistingServiceBusName
. - Adiciona uma fila chamada
queue
ao recursoserviceBus
.
Adicione recursos Azure já existentes com cadeias de conexão
.NET .NET Aspire fornece a capacidade de se conectar a recursos existentes, incluindo recursos Azure. A expressão de cadeias de conexão é útil quando você tem recursos de Azure existentes que deseja usar em seu aplicativo .NET Aspire. A API AddConnectionString é usada com o contexto de execução do host do aplicativo para adicionar condicionalmente uma cadeia de conexão ao modelo do aplicativo.
Observação
As cadeias de conexão são usadas para representar uma ampla gama de informações de conexão, incluindo conexões de banco de dados, agentes de mensagens, URIs de ponto de extremidade e outros serviços. Na nomenclatura .NET.NET Aspire, o termo "cadeia de conexão" é usado para representar qualquer tipo de informação de conexão.
Considere o exemplo a seguir, em que, no modo de publicação , se adiciona um recurso de armazenamento Azure, enquanto no modo de execução se adiciona uma cadeia de conexão a um armazenamento Azure existente:
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...
O código anterior:
- Cria uma nova instância
builder
. - Adiciona um recurso de armazenamento de Azure chamado
storage
no modo "publicar". - Adiciona uma cadeia de conexão a um armazenamento existente de Azure chamado
storage
no modo "run". - Adiciona um projeto chamado
api
ao construtor. - O projeto
api
faz referência ao recursostorage
, independentemente do modo.
O projeto de API de consumo usa as informações da cadeia de conexão sem saber como o host do aplicativo o configurou. No modo "publicar", o código adiciona um novo recurso de armazenamentoAzure, que seria refletido no manifesto de implantação em conformidade. Quando no modo "executar", a cadeia de conexão corresponde a um valor de configuração visível para o host do aplicativo. Supõe-se que todas as atribuições de função para o recurso de destino estejam configuradas. Isso significa que você provavelmente configuraria uma variável de ambiente ou um segredo de usuário para armazenar a cadeia de conexão. A configuração é resolvida a partir da chave de configuração ConnectionStrings__storage
(ou ConnectionStrings:storage
). Esses valores de configuração podem ser visualizados quando o aplicativo é executado. Para obter mais informações, consulte Detalhes do recurso.
Ao contrário dos recursos modelados existentes com a API de primeira classe AsExisting
, os recursos modelados como cadeias de conexão não podem ser melhorados com atribuições de função adicionais ou personalizações de infraestrutura.
Publicar como aplicação de contêiner Azure
.NET .NET Aspire permite publicar recursos primitivos como Azure Container Apps, uma plataforma sem servidor que reduz o gerenciamento de infraestrutura. Os tipos de recursos suportados incluem:
- ContainerResource: Representa um contêiner especificado.
- ExecutableResource: Representa um processo executável especificado.
- ProjectResource: Representa um projeto .NET especificado.
Para publicar esses recursos, use as seguintes APIs:
- AzureContainerAppContainerExtensions.PublishAsAzureContainerApp<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure,ContainerApp>)
- AzureContainerAppExecutableExtensions.PublishAsAzureContainerApp<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure,ContainerApp>)
- AzureContainerAppProjectExtensions.PublishAsAzureContainerApp<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure,ContainerApp>)
Essas APIs configuram o recurso a ser publicado como um aplicativo de contêiner Azure e implicitamente chamam AddAzureContainerAppsInfrastructure(IDistributedApplicationBuilder) para adicionar a infraestrutura necessária e os arquivos Bicep ao host do aplicativo. Como exemplo, considere o seguinte código:
var builder = DistributedApplication.CreateBuilder();
var env = builder.AddParameter("env");
var api = builder.AddProject<Projects.AspireApi>("api")
.PublishAsAzureContainerApp<Projects.AspireApi>((infra, app) =>
{
app.Template.Containers[0].Value!.Env.Add(new ContainerAppEnvironmentVariable
{
Name = "Hello",
Value = env.AsProvisioningParameter(infra)
});
});
O código anterior:
- Cria uma nova instância
builder
. - Adiciona um parâmetro chamado
env
ao construtor. - Adiciona um projeto chamado
api
ao gerador. - Chama o método
PublishAsAzureContainerApp
no construtor de recursosapi
, passando uma expressão lambda que configura a infraestrutura do Container App Azure, ondeinfra
é o AzureResourceInfrastructure eapp
é o ContainerApp.- Adiciona uma variável de ambiente chamada
Hello
ao aplicativo de contêiner, usando o parâmetroenv
. - O método
AsProvisioningParameter
é utilizado para tratarenv
como um novo ProvisioningParameter na infraestrutura ou para reutilizar um parâmetro de bicep existente, caso já haja um com o mesmo nome.
- Adiciona uma variável de ambiente chamada
Para obter mais informações, consulte ContainerApp e AsProvisioningParameter.
Infraestrutura como código
O SDK Azure para .NET fornece o pacote NuGet 📦Azure.Provisioning e um conjunto de pacotes de provisionamento específicos para serviços Azure. Estas bibliotecas de provisionamento Azure facilitam a especificação declarativa da infraestrutura Azure nativamente no .NET. Suas APIs permitem que você escreva infraestrutura orientada a objeto em C#, resultando em Bicep. Bicep é uma linguagem específica de domínio (DSL) para implantar recursos Azure declarativamente.
Embora seja possível provisionar recursos Azure manualmente, .NET Aspire simplifica o processo fornecendo um conjunto de APIs para expressar Azure recursos. Essas APIs estão disponíveis como métodos de extensão em bibliotecas de hospedagem .NET AspireAzure, estendendo a interface IDistributedApplicationBuilder. Quando você adiciona recursos de Azure ao host do aplicativo, eles adicionam a funcionalidade de provisionamento apropriada implicitamente. Em outras palavras, você não precisa chamar nenhuma API de provisionamento diretamente.
Dado que o .NET Aspire modela os Azure recursos dentro das integrações de hospedagem Azure, o SDK Azure é usado para provisionar esses recursos. São gerados arquivos Bicep que definem os recursos Azure que você precisa. Os arquivos Bicep gerados são enviados ao lado do arquivo de manifesto quando você publica seu aplicativo.
Existem várias maneiras de influenciar os arquivos Bicep gerados:
-
Azure. Personalização de aprovisionamento:
- Configurar infraestrutura: Personalizar a infraestrutura de recursos Azure.
- Adicionar Azure infraestrutura: adicione manualmente Azure infraestrutura ao host da aplicação.
-
Use modelos Bicep personalizados:
- Referência de arquivo Bicep: Adicione uma referência a um arquivo Bicep em disco.
- Referência Bicep inline: Adicione um modelo Bicep inline.
Provisionamento local e Azure.Provisioning
Para evitar confundir termos e ajudar a desambiguar o "provisionamento", é importante entender a distinção entre provisionamento local e Azure provisionamento:
Provisionamento local:
Por padrão, quando você chama qualquer uma das APIs de integração de hospedagem Azure para adicionar recursos Azure, a API AddAzureProvisioning(IDistributedApplicationBuilder) é chamada implicitamente. Esta API regista serviços no contentor de injeção de dependências (DI) que são usados para provisionar recursos Azure quando o anfitrião da aplicação inicia. Esse conceito é conhecido como provisionamento local . Para obter mais informações, consulte o provisionamento local Azure.
Azure.Provisioning
:Azure.Provisioning
refere-se ao pacote NuGet e é um conjunto de bibliotecas que permite usar C# para gerar Bicep. ** As integrações de hospedagem Azure em .NET Aspire usam essas bibliotecas internamente para gerar ficheiros Bicep que definem os recursos Azure de que precisa. Para obter mais informações, consulteAzure.Provisioning
personalização.
Azure.Provisioning
personalização
Todas as integrações de hospedagem .NET AspireAzure expõem vários recursos Azure, e todas elas são subclasses do tipo AzureProvisioningResource — que por si só herda o AzureBicepResource. Isso permite extensões que são genericamente restritas a esse tipo, permitindo que uma API fluente personalize a infraestrutura ao seu gosto. Embora .NET.NET Aspire forneça padrões, você é livre para influenciar o Bicep gerado usando essas APIs.
Configurar infraestrutura
Independentemente do recurso Azure com o qual você está trabalhando, para configurar sua infraestrutura subjacente, você encadeia uma chamada para o método de extensão ConfigureInfrastructure. Esse método permite que tu personalizes a infraestrutura do recurso Azure passando uma delegação configure
do tipo Action<AzureResourceInfrastructure>
. O tipo AzureResourceInfrastructure é uma subclasse do Azure.Provisioning.Infrastructure. Esse tipo expõe uma enorme área de superfície da API para configurar a infraestrutura subjacente do recurso Azure.
Considere o seguinte exemplo:
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)
};
});
O código anterior:
- Adiciona um parâmetro chamado
storage-sku
. - Adiciona Azure Storage com a API de AddAzureStorage chamada
storage
. - Encadeia uma chamada para
ConfigureInfrastructure
para personalizar a infraestrutura de armazenamento Azure:- Obtém os recursos provisionáveis.
- Filtrar para apenas um StorageAccount.
- Atribui o parâmetro
storage-sku
à propriedade StorageAccount.Sku:- Uma nova instância do StorageSku tem sua propriedade
Name
atribuída a partir do resultado da API AsProvisioningParameter.
- Uma nova instância do StorageSku tem sua propriedade
Exemplifica o processo de conduzir um parâmetro externo para a infraestrutura de armazenamento Azure, resultando num arquivo Bicep gerado que reflete a configuração desejada.
Adicionar infraestrutura Azure
Nem todos os serviços Azure são expostos como integrações .NET Aspire. Embora possam ser disponibilizados mais tarde, ainda é possível provisionar serviços que estão disponíveis nas bibliotecas Azure.Provisioning.*
. Imagina um cenário em que tens um serviço de trabalho responsável pelo gerenciamento de um Registo de Contentores Azure. Agora imagine que um projeto hospedador de aplicação depende do pacote NuGet 📦Azure.Provisioning.ContainerRegistry.
Você pode usar a API AddAzureInfrastructure
para adicionar a infraestrutura do Registro de Contêiner Azure ao host do aplicativo:
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));
O código anterior:
- Chama AddAzureInfrastructure com o nome de
acr
. - Fornece um
configureInfrastructure
delegado para personalizar a infraestrutura do Azure Container Registry:- Instancia um ContainerRegistryService com o nome
acr
e uma SKU standard. - Adiciona o serviço Azure Container Registry à variável
infra
. - Instancia um ProvisioningOutput com o nome
registryName
, um tipo destring
e um valor que corresponde ao nome do Azure Container Registry. - Adiciona a saída à variável
infra
.
- Instancia um ContainerRegistryService com o nome
- Adiciona um projeto chamado
worker
ao construtor. - Encadeia uma chamada a WithEnvironment para definir a variável de ambiente
ACR_REGISTRY_NAME
no projeto com o valor do resultado deregistryName
.
A funcionalidade demonstra como adicionar Azure infraestrutura ao seu projeto anfitrião da aplicação, mesmo que o serviço Azure não seja apresentado diretamente como uma integração .NET Aspire. Ele mostra ainda como canalizar a saída do Azure Container Registry para o ambiente de um projeto dependente.
Considere o arquivo Bicep resultante:
@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
O arquivo Bicep reflete a configuração desejada do Azure Container Registry, conforme definido pela API AddAzureInfrastructure
.
Usar modelos personalizados do Bíceps
Quando está escolhendo o Azure como o seu provedor de nuvem desejado, pode usar o Bicep para codificar a sua infraestrutura. O objetivo é simplificar drasticamente a experiência de criação com uma sintaxe mais limpa e melhor suporte para modularidade e reutilização de código.
Embora .NET.NET Aspire forneça um conjunto de modelos Bicep pré-construídos, pode haver momentos em que você queira personalizar os modelos ou criar o seu próprio. Esta seção explica os conceitos e as APIs correspondentes que você pode usar para personalizar os modelos do Bicep.
Importante
Esta seção não se destina a ensinar Bicep, mas sim fornecer orientação sobre como criar modelos personalizados de Bicep para uso com .NET.NET Aspire.
Como parte do plano de implementação do Azure para .NET Aspire, o Azure Developer CLI (azd
) fornece uma compreensão do seu projeto .NET Aspire e a capacidade de o implementar em Azure. A CLI do azd
usa os modelos Bicep para implantar o aplicativo em Azure.
Instalar pacote Aspire.Hosting.Azure
Quando você quiser fazer referência a arquivos Bicep, é possível que você não esteja usando nenhuma das integrações de hospedagem Azure. Nesse caso, você ainda pode fazer referência a arquivos Bicep instalando o pacote Aspire.Hosting.Azure
. Este pacote fornece as APIs necessárias para fazer referência a arquivos Bicep e personalizar os recursos Azure.
Dica
Se você estiver usando qualquer uma das integrações de hospedagem Azure, não precisará instalar o pacote Aspire.Hosting.Azure
, pois é uma dependência transitiva.
Para usar qualquer uma dessas funcionalidades, o 📦Aspire.Hosting.Azure pacote NuGet deve estar instalado:
dotnet add package Aspire.Hosting.Azure
Para obter mais informações, consulte dotnet add package ou Gerir dependências de pacotes em aplicações .NET.
O que esperar dos exemplos
Todos os exemplos nesta seção pressupõem que você esteja usando o namespace Aspire.Hosting.Azure. Além disso, os exemplos pressupõem que você tenha uma IDistributedApplicationBuilder instância:
using Aspire.Hosting.Azure;
var builder = DistributedApplication.CreateBuilder(args);
// Examples go here...
builder.Build().Run();
Por padrão, quando você chama qualquer uma das APIs relacionadas ao Bicep, também é feita uma chamada para AddAzureProvisioning que adiciona suporte para gerar recursos de Azure dinamicamente durante a inicialização do aplicativo. Para obter mais informações, consulte Provisionamento local e Azure.Provisioning
.
Arquivos de referência Bicep
Imagine que você tem um modelo Bicep em um arquivo chamado storage.bicep
que provisiona uma conta de armazenamento Azure:
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'
}
}
Para adicionar uma referência ao arquivo Bicep no disco, chame o método AddBicepTemplate. Considere o seguinte exemplo:
builder.AddBicepTemplate(
name: "storage",
bicepFile: "../infra/storage.bicep");
O código anterior adiciona uma referência a um arquivo Bicep localizado em ../infra/storage.bicep
. Os caminhos de arquivo devem ser relativos ao projeto host da aplicação. Esta referência resulta em um AzureBicepResource a ser adicionado à coleção de recursos do aplicativo com o nome "storage"
, e a API retorna uma instância IResourceBuilder<AzureBicepResource>
que pode ser usada para personalizar ainda mais o recurso.
Bíceps de referência em linha
Embora ter um arquivo Bicep no disco seja o cenário mais comum, você também pode adicionar modelos Bicep diretamente. Os modelos embutidos podem ser úteis quando você deseja definir um modelo no código ou quando deseja gerar o modelo dinamicamente. Para adicionar um template Bicep inline, chame o método AddBicepTemplateString com o modelo Bicep como um string
. Considere o seguinte exemplo:
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
}
}
}
"""
);
Neste exemplo, o modelo Bicep é definido como um string
embutido e adicionado à coleção de recursos da aplicação com o nome "ai"
. Este exemplo fornece um recurso de IA Azure.
Passar parâmetros para modelos Bicep
Bicep suporta a aceitação de parâmetros, que podem ser usados para personalizar o comportamento do modelo. Para passar parâmetros para um modelo Bicep de .NET.NET Aspire, encadeie chamadas para o método WithParameter, conforme mostrado no exemplo a seguir:
var region = builder.AddParameter("region");
builder.AddBicepTemplate("storage", "../infra/storage.bicep")
.WithParameter("region", region)
.WithParameter("storageName", "app-storage")
.WithParameter("tags", ["latest","dev"]);
O código anterior:
- Adiciona um parâmetro chamado
"region"
à instânciabuilder
. - Adiciona uma referência a um arquivo Bicep localizado em
../infra/storage.bicep
. - Passa o parâmetro
"region"
para o modelo Bicep, que é resolvido através da resolução padrão de parâmetros. - Passa o parâmetro
para o modelo Bicep com um valor fixo . - Passa o parâmetro
"tags"
para o modelo Bicep com uma matriz de cadeias de caracteres.
Para obter mais informações, consulte Parâmetros externos.
Parâmetros bem conhecidos
.NET .NET Aspire fornece um conjunto de parâmetros bem conhecidos que podem ser passados para modelos Bicep. Esses parâmetros são usados para fornecer informações sobre o aplicativo e o ambiente dos modelos Bicep. Estão disponíveis os seguintes parâmetros bem conhecidos:
Campo | Descrição | Valor |
---|---|---|
AzureBicepResource.KnownParameters.KeyVaultName | O nome do recurso do cofre de chaves utilizado para armazenar resultados secretos. | "keyVaultName" |
AzureBicepResource.KnownParameters.Location | A localização do recurso. Isso é necessário para todos os recursos. | "location" |
AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId | O ID de recurso do espaço de trabalho de análise de logs. | "logAnalyticsWorkspaceId" |
AzureBicepResource.KnownParameters.PrincipalId | O ID principal do usuário atual ou da identidade gerenciada. | "principalId" |
AzureBicepResource.KnownParameters.PrincipalName | O nome principal do usuário atual ou da identidade gerenciada. | "principalName" |
AzureBicepResource.KnownParameters.PrincipalType | O tipo principal do usuário atual ou identidade gerenciada. Ou User ou ServicePrincipal . |
"principalType" |
Para usar um parâmetro conhecido, passe o nome do parâmetro para o método WithParameter, como WithParameter(AzureBicepResource.KnownParameters.KeyVaultName)
. Você não passa valores para parâmetros conhecidos, pois .NET.NET Aspire os resolve em seu nome.
Considere um exemplo em que pretende configurar um webhook do Event Grid Azure. Você pode definir o modelo Bicep da seguinte maneira:
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
Este modelo Bicep define vários parâmetros, incluindo o topicName
, webHookEndpoint
, principalId
, principalType
e o location
opcional . Para passar esses parâmetros para o modelo Bicep, você pode usar o seguinte trecho de código:
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);
- O projeto
webHookApi
é adicionado como referência aobuilder
. - É atribuído ao parâmetro
topicName
um valor de nome pré-definido. - O parâmetro
webHookEndpoint
é passado como uma expressão que resulta na URL do endpoint "https" das referências do projetoapi
com a rota/hook
. - Os parâmetros
principalId
eprincipalType
são passados como parâmetros conhecidos.
Os parâmetros bem conhecidos são baseados em convenções e não devem ser acompanhados de um valor correspondente quando passados usando a API WithParameter
. Parâmetros bem conhecidos simplificam algumas funcionalidades comuns, como atribuições de função, quando adicionados aos modelos Bicep, como mostrado no exemplo anterior. As atribuições de função são necessárias para que o webhook do Event Grid envie eventos para o ponto de extremidade especificado. Para obter mais informações, consulte Atribuição de função do remetente de dados do Event Grid.
Obter resultados das referências do Bicep
Além de passar parâmetros para modelos Bicep, você também pode obter saídas dos modelos Bicep. Considere o seguinte modelo Bicep, que define um output
chamado endpoint
:
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
O Bicep define uma saída chamada endpoint
. Para obter a saída do modelo Bicep, chame o método GetOutput em uma instância IResourceBuilder<AzureBicepResource>
, conforme demonstrado no seguinte trecho de código C#:
var storage = builder.AddBicepTemplate(
name: "storage",
bicepFile: "../infra/storage.bicep"
);
var endpoint = storage.GetOutput("endpoint");
Neste exemplo, a saída do modelo Bicep é recuperada e armazenada em uma variável endpoint
. Normalmente, você passaria essa saída como uma variável de ambiente para outro recurso que depende dela. Por exemplo, se tivesses um projeto de API mínima ASP.NET Core que dependesse deste endpoint, poderias passar a saída como uma variável de ambiente para o projeto usando o seguinte trecho de código:
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);
Para obter mais informações, consulte saídas do bíceps.
Obtenha saídas secretas a partir de referências do Bicep
É importante evitar saídas de segredos ao trabalhar com Bicep. Se uma saída for considerada um segredo, o que significa que não deve ser exposta em logs ou outros locais, pode tratá-la dessa forma. Isso pode ser conseguido armazenando o segredo em Azure Key Vault e referenciando-o no modelo Bicep. A integração .NET Aspire do Azurefornece um padrão para armazenar com segurança saídas do modelo Bicep, permitindo que os recursos usem o parâmetro keyVaultName
para armazenar segredos em Azure Key Vault.
Considere o seguinte modelo Bicep como um exemplo que ajuda a demonstrar esse conceito de proteger saídas secretas:
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}'
}
}
}
O modelo Bicep anterior espera um parâmetro keyVaultName
, juntamente com vários outros parâmetros. Em seguida, ele define um recurso de Azure Cosmos DB e armazena um segredo em Azure Key Vault, chamado connectionString
que representa a cadeia de conexão totalmente qualificada para a instância Cosmos DB. Para acessar esse valor de cadeia de conexão secreta, você pode usar o seguinte trecho de código:
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);
No trecho de código anterior, o modelo cosmos
Bicep é adicionado como uma referência ao builder
. A saída secreta connectionString
é recuperada do modelo Bicep e armazenada em uma variável. A saída secreta é então passada como uma variável de ambiente (ConnectionStrings__cosmos
) para o projeto api
. Essa variável de ambiente é usada para se conectar à instância Cosmos DB.
Quando este recurso é implantado, o mecanismo subjacente de implantação irá automaticamente referenciar segredos de Azure Key Vault. Para garantir o isolamento secreto, o .NET.NET Aspire cria um Cofre de Chaves para cada origem.
Observação
No modo de provisionamento local,
Publicação
Quando publica a sua aplicação, o provisionamento gerado pelo Bicep Azure é usado pelo Azure Developer CLI para criar os recursos Azure na sua subscrição Azure. .NET .NET Aspire produz um manifesto de publicação , isso também é uma parte vital do processo de publicação. O Azure Developer CLI é uma ferramenta de linha de comando que fornece um conjunto de comandos para gerenciar Azure recursos.
Para obter mais informações sobre publicação e implementação, consulte o guia detalhado para implementar um projeto .NET Aspire em Azure Container Apps utilizando o Azure Developer CLI.