Udostępnij za pośrednictwem


Wdrażaj projekt .NET Aspire do Azure Container Apps za pomocą Azure Developer CLI (szczegółowy przewodnik)

Azure Developer CLI (azd) został rozszerzony w celu obsługi wdrażania projektów .NET.NET Aspire. Skorzystaj z tego przewodnika, aby zapoznać się z procesem tworzenia i wdrażania projektu .NET Aspire do Azure Container Apps przy użyciu Azure Developer CLI. W tym samouczku poznasz następujące pojęcia:

  • Dowiedz się, jak działa integracja azd z projektami .NET.NET Aspire
  • Zapewnij i wdrażaj zasoby na Azure dla projektu .NET Aspire przy użyciu azd
  • Generowanie infrastruktury Bicep i innych plików szablonów przy użyciu azd

Warunki wstępne

Aby pracować z .NET.NET Aspire, musisz mieć następujące elementy zainstalowane lokalnie:

Aby uzyskać więcej informacji, zobacz .NET.NET Aspire setup and toolingi .NET.NET Aspire SDK.

Konieczne będzie również zainstalowanie Azure Developer CLIlokalnie. Typowe opcje instalacji obejmują następujące elementy:

winget install microsoft.azd

Jak działa integracja Azure Developer CLI

Przepływ pracy azd init zapewnia dostosowaną obsługę projektów .NET.NET Aspire. Na poniższym diagramie przedstawiono sposób działania tego przepływu koncepcyjnie oraz sposób integracji azd i .NET.NET Aspire:

Ilustracja przedstawiająca wewnętrzne przetwarzanie

  1. Gdy azd jest ukierunkowany na projekt .NET.NET Aspire, uruchamia AppHost za pomocą specjalnego polecenia (dotnet run --project AppHost.csproj --output-path manifest.json --publisher manifest), co generuje plik manifestu Aspire.
  2. Plik manifestu jest przesłuchiwany przez logikę poleceń podrzędnych azd provision w celu wygenerowania tylko plików Bicep w pamięci (domyślnie).
  3. Po wygenerowaniu plików Bicep wdrożenie jest wyzwalane za pomocą interfejsów API ARM Azure, które celują w wcześniej określoną subskrypcję i grupę zasobów.
  4. Po skonfigurowaniu podstawowych zasobów Azure jest wykonywana logika polecenia podrzędnego azd deploy, która używa tego samego pliku manifestu Aspire.
  5. W ramach wdrażania azd, wywołuje on dotnet publish, używając wbudowanej obsługi publikacji kontenerów w .NET, w celu generowania obrazów kontenerów.
  6. Po utworzeniu obrazów kontenerów azd wypycha je do rejestru ACR, który został utworzony w trakcie fazy aprowizacji.
  7. Na koniec, gdy obraz kontenera znajduje się w ACR, azd aktualizuje zasób przy użyciu ARM, aby rozpocząć korzystanie z nowej wersji obrazu kontenera.

Uwaga

azd umożliwia również zapisanie wygenerowanego kodu Bicep do folderu infra w projekcie, o czym można przeczytać więcej w sekcji Generowanie Bicep z modelu aplikacji .NET.NET Aspire.

Aprowizuj i wdróż aplikację startową .NET.NET Aspire

W krokach w tej sekcji pokazano, jak utworzyć aplikację startową .NET Aspire i zarządzać aprowizowaniem oraz wdrażaniem zasobów aplikacji do Azure przy użyciu azd.

Tworzenie aplikacji startowej .NET.NET Aspire

Utwórz nowy projekt .NET.NET Aspire przy użyciu polecenia dotnet new. Projekt można również utworzyć przy użyciu Visual Studio.

dotnet new aspire-starter --use-redis-cache -o AspireSample
cd AspireSample
dotnet run --project AspireSample.AppHost\AspireSample.AppHost.csproj

Poprzednie polecenia tworzą nowy projekt .NET.NET Aspire na podstawie szablonu aspire-starter, który zawiera zależność od pamięci podręcznej Redis. Uruchamia projekt .NET.NET Aspire, który sprawdza, czy wszystko działa prawidłowo.

Inicjowanie szablonu

  1. Otwórz nowe okno terminalu i cd w katalogu projektu AppHost rozwiązania .NET.NET Aspire.

  2. Wykonaj polecenie azd init, aby zainicjować projekt przy użyciu azd, co spowoduje sprawdzenie struktury katalogów lokalnych i określenie typu aplikacji.

    azd init
    

    Aby uzyskać więcej informacji na temat polecenia azd init, zobacz azd init.

  3. Wybierz pozycję Użyj kodu w bieżącym katalogu, gdy azd wyświetli monit o dwie opcje inicjowania aplikacji.

    ? How do you want to initialize your app?  [Use arrows to move, type to filter]
    > Use code in the current directory
      Select a template
    
  4. Po zeskanowaniu katalogu azd zostanie wyświetlony monit o potwierdzenie, że został znaleziony prawidłowy projekt .NET.NET AspireAppHost. Wybierz Potwierdź i inicjuj kontynuowanie mojej aplikacji.

    Detected services:
    
      .NET (Aspire)
      Detected in: D:\source\repos\AspireSample\AspireSample.AppHost\AspireSample.AppHost.csproj
    
    azd will generate the files necessary to host your app on Azure using Azure Container Apps.
    
    ? Select an option  [Use arrows to move, type to filter]
    > Confirm and continue initializing my app
      Cancel and exit
    
  5. Wprowadź nazwę środowiska, która będzie używana do nazywania przydzielonych zasobów w Azure oraz zarządzania różnymi środowiskami, takimi jak dev i prod.

    Generating files to run your app on Azure:
    
      (✓) Done: Generating ./azure.yaml
      (✓) Done: Generating ./next-steps.md
    
    SUCCESS: Your app is ready for the cloud!
    You can provision and deploy your app to Azure by running the azd up command in this directory. For more information on configuring your app, see ./next-steps.md
    

azd generuje wiele plików i umieszcza je w katalogu roboczym. Są to następujące pliki:

  • azure.yaml: opisuje usługi aplikacji, takie jak projekt .NET Aspire AppHost, i mapuje je na zasoby Azure.
  • .azure/config.json: plik konfiguracji, który informuje azd, jakie jest bieżące aktywne środowisko.
  • .azure/aspireazddev/.env: zawiera przesłonięcia specyficzne dla określonego środowiska.

Plik azure.yaml ma następującą zawartość:

# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

name: AspireSample
services:
  app:
    language: dotnet
    project: .\AspireSample.AppHost\AspireSample.AppHost.csproj
    host: containerapp

Nazewnictwo zasobów

Podczas tworzenia nowych zasobów Azure należy przestrzegać wymagań dotyczących nazewnictwa. W przypadku Azure Container Appsnazwa musi mieć długość od 2 do 32 znaków i składać się z małych liter, cyfr i łączników. Nazwa musi zaczynać się literą i kończyć znakiem alfanumerycznym.

Aby uzyskać więcej informacji, zobacz Reguły nazewnictwa i ograniczenia dotyczące zasobów Azure.

Początkowe wdrożenie

  1. Aby wdrożyć projekt .NET Aspire, należy uwierzytelnić się w usłudze Azure AD w celu wywołania interfejsów API zarządzania zasobami Azure.

    azd auth login
    

    Poprzednie polecenie spowoduje uruchomienie przeglądarki w celu uwierzytelnienia sesji wiersza polecenia.

  2. Po uwierzytelnieniu uruchom następujące polecenie z katalogu projektu AppHost, aby aprowizować i wdrażać aplikację.

    azd up
    

    Ważny

    Aby przesłać obrazy kontenerów do rejestru Azure Container Registry (ACR), musisz mieć dostęp Microsoft.Authorization/roleAssignments/write. Można to osiągnąć, włączając administratora w rejestrze. Otwórz portal Azure, przejdź do zasobu usługi ACR / Ustawienia / Klucze dostępu, a następnie zaznacz pole wyboru administrator. Aby uzyskać więcej informacji, odwołaj się do Włącz użytkownika admina.

  3. Po wyświetleniu monitu wybierz subskrypcję i lokalizację, do których mają zostać wdrożone zasoby. Po wybraniu tych opcji zostanie wdrożony projekt .NET.NET Aspire.

    By default, a service can only be reached from inside the Azure Container Apps environment it is running in. Selecting a service here will also allow it to be reached from the Internet.
    ? Select which services to expose to the Internet webfrontend
    ? Select an Azure Subscription to use:  1. <YOUR SUBSCRIPTION>
    ? Select an Azure location to use: 1. <YOUR LOCATION>
    
    Packaging services (azd package)
    
    
    Provisioning Azure resources (azd provision)
    Provisioning Azure resources can take some time.
    
    Subscription: <YOUR SUBSCRIPTION>
    Location: <YOUR LOCATION>
    
      You can view detailed progress in the Azure Portal:
      <LINK TO DEPLOYMENT>
    
      (✓) Done: Resource group: <YOUR RESOURCE GROUP>
      (✓) Done: Container Registry: <ID>
      (✓) Done: Log Analytics workspace: <ID>
      (✓) Done: Container Apps Environment: <ID>
    
    SUCCESS: Your application was provisioned in Azure in 1 minute 13 seconds.
    You can view the resources created under the resource group <YOUR RESOURCE GROUP> in Azure Portal:
    <LINK TO RESOURCE GROUP OVERVIEW>
    
    Deploying services (azd deploy)
    
      (✓) Done: Deploying service apiservice
      - Endpoint: <YOUR UNIQUE apiservice APP>.azurecontainerapps.io/
    
      (✓) Done: Deploying service webfrontend
      - Endpoint: <YOUR UNIQUE webfrontend APP>.azurecontainerapps.io/
    
    Aspire Dashboard: <LINK TO DEPLOYED .NET ASPIRE DASHBOARD>
    
    SUCCESS: Your up workflow to provision and deploy to Azure completed in 3 minutes 50 seconds.
    

    Ostatnim wierszem danych wyjściowych polecenia azd jest link do portalu Azure, który zawiera wszystkie wdrożone zasoby Azure:

    Zrzut ekranu przedstawiający wdrożony zasób w portalu Azure.

Trzy kontenery są wdrażane w tej aplikacji:

  • webfrontend: zawiera kod z projektu internetowego w szablonie startowym.
  • apiservice: zawiera kod z projektu usługi interfejsu API w szablonie startowym.
  • cache: obraz kontenera Redis do zaopatrywania w pamięć podręczną dla front-endu.

Podobnie jak w przypadku programowania lokalnego konfiguracja parametrów połączenia została obsłużona automatycznie. W tym przypadku azd był odpowiedzialny za interpretowanie modelu aplikacji i tłumaczenie go na odpowiednie kroki wdrażania. Rozważmy na przykład parametry połączenia i zmienne odnajdywania usługi, które są wstrzykiwane do kontenera webfrontend, aby wiedzieć, jak nawiązać połączenie z pamięcią podręczną Redis i apiservice.

Zrzut ekranu przedstawiający zmienne środowiskowe w aplikacji kontenera webfrontend.

Aby uzyskać więcej informacji na temat sposobu, w jaki projekty .NET.NET Aspire obsługują parametry połączenia i lokalizowanie usług, zobacz omówienie orkiestracji .NET.NET Aspire.

Wdrażanie aktualizacji aplikacji

Po wykonaniu polecenia azd up bazowe zasoby Azure są aprowizowane, a obraz kontenera zostanie zbudowany i wdrożony w aplikacjach kontenerowych hostujących projekt .NET.NET Aspire. Zwykle po rozpoczęciu opracowywania i wdrożeniu Azure zasobów nie będzie konieczne aprowizowania zasobów Azure za każdym razem, gdy kod jest aktualizowany — dotyczy to szczególnie pętli wewnętrznej dewelopera.

Aby przyspieszyć wdrażanie zmian kodu, azd obsługuje wdrażanie aktualizacji kodu w obrazie kontenera. Odbywa się to przy użyciu polecenia azd deploy:

azd deploy
Deploying services (azd deploy)

  (✓) Done: Deploying service apiservice
  - Endpoint: <YOUR UNIQUE apiservice APP>.azurecontainerapps.io/

  (✓) Done: Deploying service webfrontend
  - Endpoint: <YOUR UNIQUE webfrontend APP>.azurecontainerapps.io/

Aspire Dashboard: <LINK TO DEPLOYED .NET ASPIRE DASHBOARD>

Nie trzeba wdrażać wszystkich usług za każdym razem. azd rozumie model projektu .NET.NET Aspire, można wdrożyć tylko jedną z usług określonych przy użyciu następującego polecenia:

azd deploy webfrontend

Aby uzyskać więcej informacji, zobacz Azure Developer CLI reference: azd deploy.

Wdrażanie aktualizacji infrastruktury

Za każdym razem, gdy struktura zależności w projekcie .NET.NET Aspire ulegnie zmianie, azd musi ponownie aprowizować bazowe zasoby Azure. Polecenie azd provision służy do stosowania tych zmian w infrastrukturze.

Aby zobaczyć to w akcji, zaktualizuj plik Program.cs w projekcie AppHost na następujący:

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

// Add the locations database.
var locationsdb = builder.AddPostgres("db").AddDatabase("locations");

// Add the locations database reference to the API service.
var apiservice = builder.AddProject<Projects.AspireSample_ApiService>("apiservice")
    .WithReference(locationsdb);

builder.AddProject<Projects.AspireSample_Web>("webfrontend")
    .WithReference(cache)
    .WithReference(apiservice);

builder.Build().Run();

Zapisz plik i wydaj następujące polecenie:

azd provision

Polecenie azd provision aktualizuje infrastrukturę, tworząc aplikację kontenera do hostowania bazy danych Postgres. Polecenie azd provision nie zaktualizowało parametrów połączenia dla kontenera apiservice. Aby parametry połączenia zostały zaktualizowane, aby wskazywały nowo aprowizowaną bazę danych Postgres, należy ponownie wywołać polecenie azd deploy. W razie wątpliwości użyj azd up do aprowizowania i wdrażania.

Czyszczenie zasobów

Pamiętaj, aby wyczyścić zasoby Azure utworzone podczas tego przewodnika. Ponieważ `azd` zna grupę zasobów, w której utworzył zasoby, można go użyć do wyłączenia środowiska za pomocą następującego polecenia:

azd down

Wykonanie poprzedniego polecenia może zająć trochę czasu, ale po zakończeniu grupy zasobów i wszystkich jej zasobów należy usunąć.

Deleting all resources and deployed code on Azure (azd down)
Local application code is not deleted when running 'azd down'.

  Resource group(s) to be deleted:

    • <YOUR RESOURCE GROUP>: <LINK TO RESOURCE GROUP OVERVIEW>

? Total resources to delete: 7, are you sure you want to continue? Yes
Deleting your resources can take some time.

  (✓) Done: Deleting resource group: <YOUR RESOURCE GROUP>

SUCCESS: Your application was removed from Azure in 9 minutes 59 seconds.

Generowanie Bicep na podstawie modelu projektu .NET.NET Aspire

Mimo że zespoły programistyczne mogą używać poleceń azd up (lub azd provision i azd deploy) zarówno do celów programistycznych, jak i produkcyjnych, niektóre zespoły mogą generować pliki Bicep, które mogą przeglądać i zarządzać w ramach kontroli wersji (umożliwia to również odwołowanie się do tych plików Bicep w ramach bardziej złożonego wdrożenia Azure).

azd obejmuje możliwość generowania danych wyjściowych z Bicep wykorzystywanego do provisioningu za pomocą następującego polecenia:

azd config set alpha.infraSynth on
azd infra synth

Po wykonaniu tego polecenia w przykładzie szablonu początkowego użytego w tym przewodniku w katalogu projektu AppHost zostaną utworzone następujące pliki:

  • infra/main.bicep: reprezentuje główny punkt wejścia dla wdrożenia.
  • infra/main.parameters.json: Wykorzystane jako parametry głównego Bicepu (przypisane do zmiennych środowiskowych zdefiniowanych w folderze .azure).
  • infra/resources.bicep: definiuje zasoby Azure wymagane do obsługi modelu projektu .NET Aspire.
  • AspireSample.Web/manifests/containerApp.tmpl.yaml: definicja aplikacji kontenera dla webfrontend.
  • AspireSample.ApiService/manifests/containerApp.tmpl.yaml: definicja aplikacji kontenera dla apiservice.

Plik infra\resources.bicep nie zawiera żadnej definicji aplikacji kontenera (z wyjątkiem aplikacji kontenera, które są zależnościami, takimi jak Redis i Postgres):

@description('The location used for all deployed resources')
param location string = resourceGroup().location

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

var resourceToken = uniqueString(resourceGroup().id)

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
  name: 'mi-${resourceToken}'
  location: location
  tags: tags
}

resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' = {
  name: replace('acr-${resourceToken}', '-', '')
  location: location
  sku: {
    name: 'Basic'
  }
  tags: tags
}

resource caeMiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(containerRegistry.id, managedIdentity.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d'))
  scope: containerRegistry
  properties: {
    principalId: managedIdentity.properties.principalId
    principalType: 'ServicePrincipal'
    roleDefinitionId:  subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
  }
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: 'law-${resourceToken}'
  location: location
  properties: {
    sku: {
      name: 'PerGB2018'
    }
  }
  tags: tags
}

resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' = {
  name: 'cae-${resourceToken}'
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalyticsWorkspace.properties.customerId
        sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
      }
    }
  }
  tags: tags
}

resource cache 'Microsoft.App/containerApps@2023-05-02-preview' = {
  name: 'cache'
  location: location
  properties: {
    environmentId: containerAppEnvironment.id
    configuration: {
      service: {
        type: 'redis'
      }
    }
    template: {
      containers: [
        {
          image: 'redis'
          name: 'redis'
        }
      ]
    }
  }
  tags: union(tags, {'aspire-resource-name': 'cache'})
}

resource locations 'Microsoft.App/containerApps@2023-05-02-preview' = {
  name: 'locations'
  location: location
  properties: {
    environmentId: containerAppEnvironment.id
    configuration: {
      service: {
        type: 'postgres'
      }
    }
    template: {
      containers: [
        {
          image: 'postgres'
          name: 'postgres'
        }
      ]
    }
  }
  tags: union(tags, {'aspire-resource-name': 'locations'})
}
output MANAGED_IDENTITY_CLIENT_ID string = managedIdentity.properties.clientId
output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.properties.loginServer
output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = managedIdentity.id
output AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = containerAppEnvironment.id
output AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = containerAppEnvironment.properties.defaultDomain

Aby uzyskać więcej informacji na temat automatyzowania wdrożeń do Azure, zobacz Co to jest Bicep?

Definicja aplikacji kontenera z projektów usługi .NET znajduje się odpowiednio w containerApp/tmpl.ya ml plików w katalogu manifests w każdym projekcie. Oto przykład z projektu webfrontend:

location: {{ .Env.AZURE_LOCATION }}
identity:
  type: UserAssigned
  userAssignedIdentities:
    ? "{{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}"
    : {}
properties:
  environmentId: {{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_ID }}
  configuration:
    activeRevisionsMode: single
    ingress:
      external: true
      targetPort: 8080
      transport: http
      allowInsecure: false
    registries:
    - server: {{ .Env.AZURE_CONTAINER_REGISTRY_ENDPOINT }}
      identity: {{ .Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID }}
  template:
    containers:
    - image: {{ .Env.SERVICE_WEBFRONTEND_IMAGE_NAME }}
      name: webfrontend
      env:
      - name: AZURE_CLIENT_ID
        value: {{ .Env.MANAGED_IDENTITY_CLIENT_ID }}
      - name: ConnectionStrings__cache
        value: {{ connectionString "cache" }}
      - name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES
        value: "true"
      - name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES
        value: "true"
      - name: services__apiservice__0
        value: http://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
      - name: services__apiservice__1
        value: https://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
tags:
  azd-service-name: webfrontend
  aspire-resource-name: webfrontend

Po wykonaniu polecenia azd infra synth, gdy azd provision i azd deploy są wywoływane, używają Bicep i pomocniczych wygenerowanych plików.

Ważny

Jeśli azd infra synth jest wywoływana ponownie, zastępuje wszystkie zmodyfikowane pliki świeżo wygenerowanymi i monituje o potwierdzenie przed wykonaniem tej czynności.

Środowiska izolowane na potrzeby debugowania

Ponieważ azd ułatwia aprowizację nowych środowisk, każdy członek zespołu może mieć izolowane środowisko hostowane w chmurze na potrzeby debugowania kodu w ustawieniu, które ściśle pasuje do środowiska produkcyjnego. W tym celu każdy członek zespołu powinien utworzyć własne środowisko przy użyciu następującego polecenia:

azd env new

Spowoduje to ponowne żądanie podania przez użytkownika informacji o subskrypcji i grupie zasobów, a kolejne wywołania azd up, azd provisioni azd deploy będą domyślnie używać tego nowego środowiska. Przełącznik --environment można zastosować do tych poleceń, aby przełączać się między środowiskami.

Czyszczenie zasobów

Uruchom następujące polecenie wiersza polecenia Azure, aby usunąć grupę zasobów, kiedy nie potrzebujesz już zasobów Azure utworzonych. Usunięcie grupy zasobów powoduje również usunięcie zawartych w niej zasobów.

az group delete --name <your-resource-group-name>

Aby uzyskać więcej informacji, zobacz Czyszczenie zasobów w Azure.