Udostępnij za pośrednictwem


Omówienie integracji .NET AspireAzure

Azure jest najpopularniejszą platformą w chmurze do tworzenia i wdrażania aplikacji .NET. Zestaw SDK Azure dla .NET umożliwia łatwe zarządzanie usługami Azure i korzystanie z nich. .NET Aspire zapewnia zestaw integracji z usługami Azure. Ten artykuł zawiera szczegółowe informacje o niektórych typowych aspektach wszystkich integracji Azure w .NET Aspire i ma na celu ułatwienie zrozumienia sposobu ich używania.

Dodaj zasoby Azure

Wszystkie hostowane integracje .NET AspireAzure udostępniają zasoby Azure i zgodnie z konwencją są dodawane przy użyciu interfejsów API AddAzure*. Po dodaniu tych zasobów do hosta aplikacji .NET Aspire reprezentują one usługę Azure. Interfejs API AddAzure* zwraca IResourceBuilder<T>, w którym T jest typem zasobu Azure. Te interfejsy IResourceBuilder<T> (konstruktora) zapewniają płynny interfejs API, który umożliwia skonfigurowanie bazowego zasobu Azure w ramach modelu aplikacji .

Typowe środowisko deweloperskie

Gdy host aplikacji .NET Aspire zawiera zasoby Azure i jest uruchamiany lokalnie (zazwyczaj deweloper F5 lub środowisko dotnet run), zasoby Azure są aprowizowane w ramach subskrypcji Azure. To pozwala Tobie jako deweloperowi debugować je lokalnie w kontekście Twojego hosta aplikacji.

.NET .NET Aspire ma na celu zminimalizowanie kosztów domyślnie Basic lub StandardStock Keeping Unit (SKU) na potrzeby integracji z Azure. Chociaż te rozsądne wartości domyślne są dostępne, można dostosować zasoby Azure zgodnie z potrzebami. Ponadto niektóre integracje obsługują emulatory lub kontenery , które są przydatne w przypadku lokalnego programowania, testowania i debugowania. Domyślnie po uruchomieniu aplikacji lokalnie zasoby Azure używają rzeczywistej usługi Azure. Można je jednak skonfigurować tak, aby korzystały z lokalnych emulatorów lub kontenerów, unikając kosztów związanych z rzeczywistą usługą Azure podczas programowania lokalnego.

Emulatory lokalne

Niektóre usługi Azure można uruchamiać lokalnie w emulatorach. Obecnie .NET Aspire obsługuje następujące emulatory Azure:

Integracja hostingu Opis
Azure Cosmos DB Wywołaj AzureCosmosExtensions.RunAsEmulator na IResourceBuilder<AzureCosmosDBResource>, aby skonfigurować zasób Cosmos DB, który ma być emulowany przy użyciu interfejsu API NoSQL.
Azure Event Hubs Wywołaj AzureEventHubsExtensions.RunAsEmulator na IResourceBuilder<AzureEventHubsResource>, aby skonfigurować zasób usługi Event Hubs do emulacji .
Azure Storage Wywołaj AzureStorageExtensions.RunAsEmulator na IResourceBuilder<AzureStorageResource>, aby skonfigurować zasób magazynu, który ma być emulowany za pomocąAzurite.

Aby zasoby Azure używały lokalnych emulatorów, wywołaj łańcuchowo metodę RunAsEmulator na konstruktorze Azure zasobów. Ta metoda konfiguruje zasób Azure do używania lokalnego emulatora zamiast rzeczywistej usługi Azure.

Ważny

Wywoływanie dowolnego z dostępnych interfejsów API RunAsEmulator w konstruktorze zasobów Azure nie wpływa na manifest publikowania . Podczas publikowania aplikacji wygenerowany plik Bicep odzwierciedla rzeczywistą usługę Azure, a nie emulator lokalny.

Kontenery lokalne

Niektóre usługi Azure można uruchamiać lokalnie w kontenerach. Aby uruchomić usługę Azure lokalnie w kontenerze, połącz wywołanie metody RunAsContainer w konstruktorze zasobów Azure. Ta metoda konfiguruje zasób Azure do uruchamiania lokalnego w kontenerze zamiast rzeczywistej usługi Azure.

Obecnie usługa .NET Aspire obsługuje następujące usługi Azure jako kontenery:

Integracja hostingu Szczegóły
Azure Cache for Redis Wywołaj AzureRedisExtensions.RunAsContainer na IResourceBuilder<AzureRedisCacheResource>, aby skonfigurować go do uruchamiania lokalnego w kontenerze na podstawie obrazu docker.io/library/redis.
Azure PostgreSQL elastyczne Server Wywołaj AzurePostgresExtensions.RunAsContainer na IResourceBuilder<AzurePostgresFlexibleServerResource>, aby skonfigurować go do lokalnego uruchamiania w kontenerze na podstawie obrazu docker.io/library/postgres.
Azure SQL Server Wywołaj AzureSqlExtensions.RunAsContainer na IResourceBuilder<AzureSqlServerResource>, aby skonfigurować go do lokalnego uruchamiania w kontenerze z wykorzystaniem obrazu mcr.microsoft.com/mssql/server.

Notatka

Podobnie jak w przypadku emulatorów, wywoływanie RunAsContainer na konstruktorze zasobów Azure nie wpływa na manifest publikowania . Podczas publikowania aplikacji, wygenerowany plik Bicep odzwierciedla rzeczywistą usługę Azure, a nie lokalny kontener.

Omówienie interfejsów API integracji Azure

.NET .NET Aspiresiła leży w jego zdolności do zapewnienia niesamowitej wewnętrznej pętli deweloperów. Integracje Azure niczym się nie różnią. Udostępniają zestaw typowych interfejsów API i wzorców, które są współużytkowane we wszystkich zasobach Azure. Te interfejsy API i wzorce zostały zaprojektowane tak, aby ułatwić pracę z zasobami Azure w spójny sposób.

W poprzedniej sekcji kontenerów pokazano, jak uruchamiać usługi Azure lokalnie w kontenerach. Jeśli znasz .NET.NET Aspire, możesz się zastanawiać, jak wywoływanie AddAzureRedis("redis").RunAsContainer() w celu uzyskania kontenera docker.io/library/redis lokalnego różni się od AddRedis("redis")— ponieważ oba te elementy powodują ten sam kontener lokalny.

Odpowiedź to, że przy lokalnym uruchomieniu nie ma różnicy. Jednak po ich opublikowaniu otrzymujesz różne zasoby:

Interfejs Programowania Aplikacji (API) Tryb pracy Tryb publikowania
AddAzureRedis("redis"). RunAsContainer() Lokalny kontener Redis Azure Cache for Redis
AddRedis("redis") Kontener lokalny Redis Azure aplikacja kontenerowa z obrazem Redis

To samo dotyczy usług SQL i PostgreSQL:

API Tryb pracy Tryb publikowania
AddAzurePostgresFlexibleServer("postgres").RunAsContainer() Lokalny kontener PostgreSQL Azure PostgreSQL elastyczne Server
AddPostgres("postgres") Lokalny kontener PostgreSQL Azure aplikacja kontenera z obrazem PostgreSQL
AddAzureSqlServer("sql").RunAsContainer() Lokalny kontener SQL Server Azure SQL Server
AddSqlServer("sql") Lokalny kontener SQL Server Azure aplikacja kontenerowa z obrazem SQL Server

Aby uzyskać więcej informacji na temat różnicy między trybami uruchamiania i publikowania, zobacz .NET.NET Aspire host aplikacji: kontekst wykonywania.

Infrastruktura jako kod

Zestaw SDK Azure dla .NET udostępnia 📦Azure. Pakiet NuGet do aprowizacji oraz zestaw pakietów do aprowizacji specyficznych dla usług Azure. Te biblioteki aprowizacyjne Azure ułatwiają deklaratywne definiowanie infrastruktury Azure natywnie w .NET. Ich API umożliwiają pisanie infrastruktury zorientowanej obiektowo w języku C#, w wyniku czego powstaje Bicep. Bicep to język specyficzny dla domeny (DSL) do deklaratywnego wdrażania zasobów Azure.

Chociaż można aprowizować zasoby Azure ręcznie, .NET Aspire upraszcza proces, udostępniając zestaw interfejsów API do wyrażania Azure zasobów. Te interfejsy API są dostępne jako metody rozszerzeń w .NET AspireAzure bibliotek hostingu, rozszerzając interfejs IDistributedApplicationBuilder. Gdy dodasz zasoby Azure do hosta aplikacji, automatycznie zostaje dodana odpowiednia funkcja aprowizacji. Innymi słowy, nie musisz bezpośrednio wywoływać żadnych interfejsów API prowizjonowania.

Ponieważ modele .NET Aspire zasoby Azure w integracjach hostingu Azure, zestaw SDK Azure służy do aprowizowania zasobów. Pliki Bicep są generowane, które definiują potrzebne zasoby Azure. Wygenerowane pliki Bicep są tworzone razem z plikiem manifestu podczas publikowania aplikacji.

Istnieje kilka sposobów wpływania na wygenerowane pliki Bicep:

Lokalne zaopatrzenie i Azure.Provisioning

Aby uniknąć mieszania terminów i pomóc w uściślaniu "przygotowania", ważne jest, aby zrozumieć rozróżnienie pomiędzy aprowizacją lokalną i Azure aprowizacją:

  • Lokalne dostarczanie:

    Domyślnie podczas wywoływania dowolnego z Azure hostowania interfejsów API integracji w celu dodania Azure zasobów interfejs API AddAzureProvisioning(IDistributedApplicationBuilder) jest wywoływany niejawnie. Ten interfejs API rejestruje usługi w kontenerze wstrzykiwania zależności (DI), używane do przygotowywania zasobów Azure podczas startu hosta aplikacji. Ta koncepcja jest znana jako lokalne zaopatrzenie. Aby uzyskać więcej informacji, zobacz local Azure provisioning.

  • Azure.Provisioning:

    Azure.Provisioning odnosi się do pakietu NuGet i jest zestawem bibliotek, które umożliwiają generowanie Bicep za pomocą języka C#. Azure integracje hostingowe w .NET Aspire używają tych bibliotek w tle do generowania plików Bicep, które definiują zasoby Azure, których potrzebujesz. Aby uzyskać więcej informacji, zobacz Azure.Provisioning dostosowywanie.

dostosowywanie Azure.Provisioning

Wszystkie integracje hostingu .NET AspireAzure uwidaczniają różne zasoby Azure i wszystkie są podklasami typu AzureProvisioningResource — który dziedziczy AzureBicepResource. To umożliwia rozszerzeniom, które są ograniczone generycznymi typami do tego typu, korzystanie z płynnego interfejsu API do dostosowywania infrastruktury do własnych potrzeb. Mimo że .NETi.NET Aspire udostępniają wartości domyślne, możesz wpływać na wygenerowany Bicep, korzystając z tych interfejsów API.

Konfigurowanie infrastruktury

Niezależnie od zasobu Azure, z którym pracujesz, aby skonfigurować jego podstawową infrastrukturę, należy utworzyć połączenie z metodą rozszerzenia ConfigureInfrastructure. Ta metoda umożliwia personalizację infrastruktury zasobu Azure przez przekazanie delegata configure typu Action<AzureResourceInfrastructure>. Typ AzureResourceInfrastructure jest podklasą Azure.Provisioning.Infrastructure. Ten typ uwidacznia ogromny obszar powierzchni interfejsu API na potrzeby konfigurowania podstawowej infrastruktury zasobu Azure.

Rozważmy następujący przykład:

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)
        };
    });

Powyższy kod:

  • Dodaje parametr o nazwie storage-sku.
  • Dodaje usługę Azure Storage przy użyciu interfejsu API AddAzureStorage o nazwie storage.
  • Połączenie wywołania do ConfigureInfrastructure w celu dostosowania infrastruktury przechowywania Azure:

Spowoduje to przepływ parametru zewnętrznego do infrastruktury magazynu Azure, co spowoduje, że wygenerowany plik Bicep odzwierciedla żądaną konfigurację.

Dodaj infrastrukturę Azure

Nie wszystkie usługi Azure są udostępniane jako integracje .NET Aspire. Choć mogą być dostępne później, nadal można świadczyć usługi, które są dostępne w bibliotekach Azure.Provisioning.*. Wyobraź sobie scenariusz, w którym masz serwis pracownika odpowiedzialny za zarządzanie rejestrem kontenerów Azure. Teraz wyobraź sobie, że projekt hosta aplikacji przyjmuje zależność od 📦Azure.Provisioning.ContainerRegistry pakietu NuGet.

Interfejs API AddAzureInfrastructure umożliwia dodanie infrastruktury usługi Azure Container Registry do hosta aplikacji:

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));

Powyższy kod:

  • Wywołuje AddAzureInfrastructure z nazwą acr.
  • Udostępnia delegata configureInfrastructure w celu dostosowania infrastruktury usługi Azure Container Registry:
    • Tworzy wystąpienie ContainerRegistryService o nazwie acr i standardowej jednostce SKU.
    • Dodaje usługę Azure Container Registry do zmiennej infra.
    • Tworzy wystąpienie ProvisioningOutput o nazwie registryName, o typie stringi o wartości odpowiadającej nazwie rejestru kontenerów Azure.
    • Dodaje dane wyjściowe do zmiennej infra.
  • Dodaje projekt o nazwie worker do konstruktora.
  • Powiązuje wywołanie do WithEnvironment, aby ustawić zmienną środowiskową ACR_REGISTRY_NAME w projekcie na wartość wyniku registryName.

Funkcja pokazuje, jak dodać infrastrukturę Azure do projektu hosta aplikacji, nawet jeśli usługa Azure nie jest bezpośrednio uwidoczniona jako integracja z .NET Aspire. Dodatkowo pokazano, jak kierować wyniki rejestru kontenerów Azure do środowiska projektu zależnego.

Przeanalizuj wynikowy plik 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

Plik Bicep odzwierciedla żądaną konfigurację Azure Container Registry zgodnie z definicją w interfejsie API AddAzureInfrastructure.

Użyj niestandardowych szablonów Bicep

Jeśli jako docelowego dostawcę usług w chmurze wybierzesz Azure, możesz użyć narzędzia Bicep do definiowania infrastruktury jako kodu. Ma ona na celu drastyczne uproszczenie środowiska tworzenia przy użyciu czystszej składni i lepszej obsługi modułowości i ponownego użycia kodu.

Chociaż .NET.NET Aspire udostępnia zestaw wstępnie utworzonych szablonów Bicep, mogą wystąpić czasy, kiedy chcesz dostosować szablony lub utworzyć własne. W tej sekcji opisano pojęcia i odpowiednie interfejsy API, których można użyć do dostosowywania szablonów Bicep.

Ważny

Ta sekcja nie jest przeznaczona do nauki Bicep, ale raczej do zapewnienia wskazówek dotyczących sposobu tworzenia niestandardowych szablonów Bicep do użycia z .NET.NET Aspire.

W ramach scenariusza wdrażania Azure dla .NET Aspireprogram Azure Developer CLI (azd) dostarcza wgląd w projekt .NET Aspire oraz umożliwia jego wdrażanie do Azure. Interfejs wiersza polecenia azd używa szablonów Bicep w celu wdrożenia aplikacji do Azure.

Instalowanie pakietu Aspire.Hosting.Azure

Jeśli chcesz odwołać się do plików Bicep, możliwe, że nie korzystasz z żadnej z integracji hostingowych Azure. W takim przypadku nadal można odwoływać się do plików Bicep, instalując pakiet Aspire.Hosting.Azure. Ten pakiet udostępnia niezbędne interfejsy API do odwoływania się do plików Bicep i dostosowywania zasobów Azure.

Napiwek

Jeśli używasz dowolnej z Azure integracji hostingu, nie musisz instalować pakietu Aspire.Hosting.Azure, ponieważ jest to zależność przechodnia.

Aby użyć dowolnej z tych funkcji, należy zainstalować pakiet NuGet: 📦Aspire.Hosting.Azure

dotnet add package Aspire.Hosting.Azure

Aby uzyskać więcej informacji, zobacz dotnet add package lub Zarządzaj zależnościami pakietów w aplikacjach .NET.

Czego można oczekiwać na podstawie przykładów

We wszystkich przykładach w tej sekcji założono, że używasz przestrzeni nazw Aspire.Hosting.Azure. Ponadto w przykładach założono, że masz wystąpienie IDistributedApplicationBuilder:

using Aspire.Hosting.Azure;

var builder = DistributedApplication.CreateBuilder(args);

// Examples go here...

builder.Build().Run();

Domyślnie podczas wywoływania dowolnego API związanego z Bicepem, również wykonywane jest wywołanie do AddAzureProvisioning, które dodaje wsparcie dla generowania zasobów Azure dynamicznie podczas uruchamiania aplikacji. Aby uzyskać więcej informacji, zobacz Local provisioning and Azure.Provisioning.

Odwołania do plików Bicep

Załóżmy, że masz szablon Bicep w pliku o nazwie storage.bicep, który tworzy konto magazynowe 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'
  }
}

Aby dodać odwołanie do pliku Bicep na dysku, wywołaj metodę AddBicepTemplate. Rozważmy następujący przykład:

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

Powyższy kod dodaje odwołanie do pliku Bicep znajdującego się w ../infra/storage.bicep. Ścieżki plików powinny być względem projektu hosta aplikacji . Ta referencja powoduje dodanie AzureBicepResource do kolekcji zasobów aplikacji z nazwą "storage", a interfejs API zwraca instancję klasy IResourceBuilder<AzureBicepResource>, której można użyć do dalszego dostosowywania zasobu.

Odwołanie do elementu Bicep w tekście

Posiadanie pliku Bicep na dysku jest najczęstszym scenariuszem, ale można również dodać szablony Bicep w trybie inline. Szablony wbudowane mogą być przydatne, gdy chcesz zdefiniować szablon w kodzie lub gdy chcesz dynamicznie wygenerować szablon. Aby dodać wbudowany szablon Bicep, wywołaj metodę AddBicepTemplateString, używając szablonu Bicep jako string. Rozważmy następujący przykład:

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
            }
          }
        }
        """
    );

W tym przykładzie szablon Bicep jest definiowany jako element wbudowany string i dodawany do kolekcji zasobów aplikacji pod nazwą "ai". W tym przykładzie udostępnianie zasobu sztucznej inteligencji Azure.

Przekazywanie parametrów do szablonów Bicep

Bicep obsługuje akceptowanie parametrów, które mogą służyć do dostosowywania zachowania szablonu. Aby przekazać parametry do szablonu Bicep z .NET.NET Aspire, łańcuch wywołań metody WithParameter, jak pokazano w poniższym przykładzie:

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

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

Powyższy kod:

  • Dodaje parametr o nazwie "region" do wystąpienia builder.
  • Dodaje odniesienie do pliku Bicep znajdującego się w ../infra/storage.bicep.
  • Przekazuje parametr "region" do szablonu Bicep, który jest rozwiązywany za pomocą standardowej metody rozwiązywania parametrów.
  • Przekazuje parametr do szablonu Bicep z zakodowaną na stałe wartością .
  • Przekazuje parametr "tags" do szablonu Bicep z tablicą ciągów.

Aby uzyskać więcej informacji, zobacz Parametry zewnętrzne.

Dobrze znane parametry

.NET .NET Aspire udostępnia zestaw dobrze znanych parametrów, które można przekazać do szablonów Bicep. Te parametry służą do dostarczania informacji o aplikacji i środowisku do szablonów Bicep. Dostępne są następujące dobrze znane parametry:

Pole Opis Wartość
AzureBicepResource.KnownParameters.KeyVaultName Nazwa zasobu magazynu kluczy używana do przechowywania tajnych danych wyjściowych. "keyVaultName"
AzureBicepResource.KnownParameters.Location Lokalizacja zasobu. Jest to wymagane dla wszystkich zasobów. "location"
AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId Identyfikator zasobu obszaru roboczego usługi Log Analytics. "logAnalyticsWorkspaceId"
AzureBicepResource.KnownParameters.PrincipalId Identyfikator główny bieżącego użytkownika lub tożsamości zarządzanej. "principalId"
AzureBicepResource.KnownParameters.PrincipalName Główna nazwa bieżącego użytkownika lub tożsamości zarządzanej. "principalName"
AzureBicepResource.KnownParameters.PrincipalType Typ główny obecnego użytkownika lub tożsamości zarządzanej. User lub ServicePrincipal. "principalType"

Aby użyć dobrze znanego parametru, przekaż nazwę parametru do metody WithParameter, takiej jak WithParameter(AzureBicepResource.KnownParameters.KeyVaultName). Nie przekazujesz wartości dla dobrze znanych parametrów, ponieważ .NET.NET Aspire rozpoznaje je w Twoim imieniu.

Rozważmy przykład, w którym chcesz skonfigurować webhook Azure usługi Event Grid. Szablon Bicep można zdefiniować w następujący sposób:

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

Ten szablon Bicep definiuje kilka parametrów, w tym topicName, webHookEndpoint, principalId, principalTypei opcjonalny location. Aby przekazać te parametry do szablonu Bicep, możesz użyć następującego fragmentu kodu:

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);
  • Projekt webHookApi jest dodawany jako odwołanie do builder.
  • Parametr topicName jest przekazywany jako wartość nazwy zakodowanej na stałe.
  • Parametr webHookEndpoint jest przekazywany jako wyrażenie rozpoznawane jako adres URL z punktu końcowego "https" api projektu z trasą /hook.
  • Parametry principalId i principalType są przekazywane jako dobrze znane parametry.

Dobrze znane parametry są oparte na konwencji i nie powinny być dołączone do odpowiedniej wartości podczas przekazywania przy użyciu interfejsu API WithParameter. Znane parametry upraszczają niektóre typowe funkcje, takie jak przypisania ról, gdy są dodane do szablonów Bicep, co pokazano w poprzednim przykładzie. Przypisania ról są wymagane, aby webhook usługi Event Grid mógł wysyłać zdarzenia do określonego punktu końcowego. Aby uzyskać więcej informacji, zobacz przypisanie roli nadawcy danych w Event Grid.

Pobieranie danych wyjściowych z odwołań Bicep

Oprócz przekazywania parametrów do szablonów Bicep można również uzyskać dane wyjściowe z szablonów Bicep. Rozważmy następujący szablon Bicep, który definiuje output o nazwie 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

Bicep definiuje dane wyjściowe o nazwie endpoint. Aby pobrać dane wyjściowe z szablonu Bicep, wywołaj metodę GetOutput w wystąpieniu IResourceBuilder<AzureBicepResource>, jak pokazano w poniższym fragmencie kodu języka C#:

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

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

W tym przykładzie dane wyjściowe z szablonu Bicep są pobierane i przechowywane w zmiennej endpoint. Zazwyczaj te dane wyjściowe są przekazywane jako zmienna środowiskowa do innego zasobu, który na nim bazuje. Jeśli na przykład masz projekt interfejsu API ASP.NET Core minimalny, który zależy od tego punktu końcowego, możesz przekazać dane wyjściowe jako zmienną środowiskową do projektu przy użyciu następującego fragmentu kodu:

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);

Aby uzyskać więcej informacji, zobacz dane wyjściowe Bicepa.

Uzyskaj tajne dane wyjściowe z odwołań Bicep

Ważne jest, aby unikać danych wyjściowych dla tajnych informacji podczas pracy z Bicep. Jeśli dane wyjściowe są uznawane za tajemnicę , co oznacza, że nie powinny być widoczne w dziennikach lub innych miejscach, można je traktować jako takie. Można to osiągnąć, przechowując tajemnicę w Azure Key Vault i odnosząc się do niej w szablonie Bicep. Integracja .NET AspireAzure zapewnia wzorzec bezpiecznego przechowywania danych wyjściowych z szablonu Bicep, pozwalając zasobom na użycie parametru keyVaultName do przechowywania wpisów tajnych w Azure Key Vault.

Rozważmy następujący szablon Bicep jako przykład, który pomaga zademonstrować tę koncepcję zabezpieczania tajnych danych wyjściowych:

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}'
        }
    }
}

Powyższy szablon Bicep oczekuje parametru keyVaultName, wśród różnych innych parametrów. Następnie definiuje zasób Azure Cosmos DB i umieszcza tajny wpis w Azure Key Vaulto nazwie connectionString, który reprezentuje w pełni określony łańcuch połączenia do instancji Cosmos DB. Aby uzyskać dostęp do tej wartości tajnego ciągu połączenia, możesz użyć następującego kodu:

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);

W poprzednim fragmencie kodu szablon cosmos Bicep jest dodawany jako odwołanie do builder. Tajne dane wyjściowe connectionString są pobierane z szablonu Bicep i przechowywane w zmiennej. Tajne dane wyjściowe są następnie przekazywane jako zmienna środowiskowa (ConnectionStrings__cosmos) do projektu api. Ta zmienna środowiskowa służy do nawiązywania połączenia z wystąpieniem Cosmos DB.

Po wdrożeniu tego zasobu podstawowy mechanizm wdrażania automatycznie odwołania do wpisów tajnych z Azure Key Vault. Aby zagwarantować tajną izolację, .NET.NET Aspire tworzy Key Vault dla każdego źródła.

Notatka

W trybie lokalnej aprowizacji wpis tajny jest wyodrębniany z usługi Key Vault i ustawiany w zmiennej środowiskowej. Aby uzyskać więcej informacji, zobacz local Azure provisioning.

Publikacja

Podczas publikowania aplikacji Azure aprowizacja wygenerowana przez aplikację Bicep jest używana przez Azure Developer CLI do tworzenia zasobów Azure w ramach subskrypcji Azure. .NET .NET Aspire generuje manifest publikowania oznaczony jako , który jest również istotną częścią procesu publikowania. Azure Developer CLI to narzędzie wiersza polecenia, które udostępnia zestaw poleceń do zarządzania zasobami Azure.

Aby uzyskać więcej informacji na temat publikowania i wdrażania, zobacz Wdróż projekt .NET Aspire na Azure Container Apps przy użyciu Azure Developer CLI (szczegółowy przewodnik).