Delen via


Een .NET Aspire-project implementeren in Azure Container Apps met behulp van de Azure Developer CLI (uitgebreide handleiding)

De Azure Developer CLI (azd) is uitgebreid ter ondersteuning van de implementatie van .NET.NET Aspire projecten. Gebruik deze handleiding om het proces van het maken en implementeren van een .NET Aspire-project te doorlopen voor Azure Container Apps met behulp van de Azure Developer CLI. In deze zelfstudie leert u de volgende concepten:

  • Ontdek hoe azd integratie werkt met .NET.NET Aspire projecten
  • Resources inrichten en implementeren op Azure voor een .NET Aspire project met behulp van azd
  • Bicep-infrastructuur en andere sjabloonbestanden genereren met behulp van azd

Voorwaarden

Als u met .NET.NET Aspirewilt werken, hebt u het volgende lokaal geïnstalleerd:

Zie .NET.NET Aspire setup en hulpprogramma'sen .NET.NET Aspire SDK-voor meer informatie.

U moet de Azure Developer CLIook lokaal geïnstalleerd hebben. Algemene installatieopties zijn onder andere:

winget install microsoft.azd

Hoe Azure Developer CLI integratie werkt

De azd init werkstroom biedt aangepaste ondersteuning voor .NET.NET Aspire projecten. In het volgende diagram ziet u hoe deze stroom conceptueel werkt en hoe azd en .NET.NET Aspire zijn geïntegreerd:

Afbeelding van interne verwerking van 'azd' bij het implementeren van .NET.NET Aspire project.

  1. Wanneer azd zich op een .NET.NET Aspire project richt, wordt AppHost met een speciale opdracht (dotnet run --project AppHost.csproj --output-path manifest.json --publisher manifest) gestart, waarmee het Aspiremanifestbestandtot stand wordt gebracht.
  2. Het manifestbestand wordt door de azd provision-subcommando-logica onderzocht om Bicep-bestanden alleen in het geheugen te genereren (standaard).
  3. Nadat u de Bicep-bestanden hebt gegenereerd, wordt een implementatie geactiveerd met behulp van de ARM-API's van Azuredie gericht zijn op het abonnement en de resourcegroep die u eerder hebt opgegeven.
  4. Zodra de onderliggende Azure resources zijn geconfigureerd, wordt de azd deploy subopdrachtlogica uitgevoerd die gebruikmaakt van hetzelfde Aspire manifestbestand.
  5. Als onderdeel van de implementatie azd een aanroep doet naar dotnet publish met behulp van de ingebouwde ondersteuning voor containerpublicaties van .NETom containerinstallatiekopieën te genereren.
  6. Zodra azd de containerafbeeldingen heeft gemaakt, pusht het deze naar het ACR-register dat tijdens de inrichtingsfase is gemaakt.
  7. Ten slotte, wanneer de containerimage in ACR staat, werkt azd de resource bij met ARM om de nieuwe versie van de containerimage te gebruiken.

Notitie

azd kunt u ook de gegenereerde Bicep uitvoeren naar een infra map in uw project, waarover u meer kunt lezen in de sectie Bicep genereren vanuit .NET.NET Aspire app-model.

Een .NET.NET Aspire starter-app inrichten en implementeren

De stappen in deze sectie laten zien hoe u een .NET Aspire app kunt maken en hoe u de app-resources in Azure kunt inrichten en implementeren met behulp van azd.

De .NET.NET Aspire starter-app maken

Maak een nieuw .NET.NET Aspire project met behulp van de opdracht dotnet new. U kunt het project ook maken met behulp van Visual Studio.

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

Met de vorige opdrachten maakt u een nieuw .NET.NET Aspire project op basis van de aspire-starter-sjabloon die een afhankelijkheid van Redis cache bevat. Het voert het .NET.NET Aspire project uit, waarmee wordt gecontroleerd of alles correct werkt.

De sjabloon initialiseren

  1. Open een nieuw terminalvenster, en gebruik cd in de -apphost--projectmap van je .NET-.NET Aspire-oplossing.

  2. Voer de opdracht azd init uit om uw project te initialiseren met azd, waarmee de lokale mapstructuur wordt gecontroleerd en het type app wordt bepaald.

    azd init
    

    Zie azd initvoor meer informatie over de opdracht .

  3. Selecteer Code gebruiken in de huidige map wanneer azd u om twee initialisatieopties voor apps vraagt.

    ? 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. Nadat u de map hebt gescand, wordt azd aan u gevraagd om te bevestigen dat het juiste .NET.NET AspireAppHost--project is gevonden. Selecteer de optie Bevestigen en ga verder met het initialiseren van mijn app optie.

    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. Voer een omgevingsnaam in die wordt gebruikt om ingerichte resources in Azure een naam te geven en verschillende omgevingen zoals dev en prodte beheren.

    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 genereert een aantal bestanden en plaatst deze in de werkmap. Deze bestanden zijn:

  • azure.yaml-: beschrijft de services van de app, zoals .NET Aspire AppHost-project, en wijst deze toe aan Azure resources.
  • .azure/config.json: configuratiebestand dat azd informeert wat de huidige actieve omgeving is.
  • .azure/aspireazddev/.env: Bevat omgevingsspecifieke overschrijvingen.

Het bestand azure.yaml bevat de volgende inhoud:

# 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

Naamgeving van bronnen

Wanneer u nieuwe Azure resources maakt, is het belangrijk om de naamgevingsvereisten te volgen. Voor Azure Container Appsmoet de naam 2-32 tekens lang zijn en bestaan uit kleine letters, cijfers en afbreekstreepjes. De naam moet beginnen met een letter en eindigen met een alfanumerieke teken.

Zie Naamgevingsregels en -beperkingen voor Azure resourcesvoor meer informatie.

Eerste implementatie

  1. Als u het .NET Aspire-project wilt implementeren, moet u zich verifiëren bij Azure AD om de Azure resourcebeheer-API's aan te roepen.

    azd auth login
    

    Met de vorige opdracht wordt een browser gestart om de opdrachtregelsessie te verifiëren.

  2. Voer na verificatie de volgende opdracht uit vanuit de AppHost projectmap om de toepassing in te richten en te implementeren.

    azd up
    

    Belangrijk

    Als u containerafbeeldingen naar de Azure Container Registry (ACR) wilt uploaden, moet u Microsoft.Authorization/roleAssignments/write toegang hebben. Dit kan worden bereikt door een Admin-gebruiker in te schakelen in het register. Open de Azure-portal, ga naar de ACR-resource/Instellingen/Toegangssleutels en schakel vervolgens het selectievakje Gebruiker met beheerdersrechten in. Zie Gebruiker met beheerdersrechten inschakelenvoor meer informatie.

  3. Wanneer u hierom wordt gevraagd, selecteert u het abonnement en de locatie waarop de resources moeten worden geïmplementeerd. Zodra deze opties zijn geselecteerd, wordt het .NET.NET Aspire project geïmplementeerd.

    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.
    

    De laatste regel uitvoer van de opdracht azd is een koppeling naar de Azure Portal waarin alle Azure resources worden weergegeven die zijn geïmplementeerd:

    Schermopname van Azure Portal met geïmplementeerde resources.

Er worden drie containers geïmplementeerd in deze toepassing:

  • webfrontend: bevat code van het webproject in de starterssjabloon.
  • apiservice: bevat code uit het API-serviceproject in de starterssjabloon.
  • cache: De Redis containerafbeelding voorziet een cache voor de front-end.

Net als bij lokale ontwikkeling wordt de configuratie van verbindingsreeksen automatisch afgehandeld. In dit geval was azd verantwoordelijk voor het interpreteren van het toepassingsmodel en het vertalen ervan naar de juiste implementatiestappen. Denk bijvoorbeeld aan de verbindingsreeks- en servicedetectievariabelen die zijn opgenomen in de webfrontend-container, zodat deze weet hoe verbinding moet worden gemaakt met de Redis-cache en apiservice.

een schermopname van omgevingsvariabelen in de container-app webfrontend.

Zie .NETvoor meer informatie over hoe .NET Aspire projecten verbindingsreeksen en servicedetectie afhandelen.

Toepassingsupdates implementeren

Wanneer de azd up opdracht wordt uitgevoerd, worden de onderliggende Azure resources ingericht en wordt er een containerinstallatiekopie gemaakt en geïmplementeerd voor de container-apps die als host fungeren voor het .NET.NET Aspire project. Wanneer de ontwikkeling wordt uitgevoerd en Azure resources worden geïmplementeerd, is het niet nodig om Azure resources in te richten telkens wanneer code wordt bijgewerkt. Dit geldt met name voor de binnenste lus van de ontwikkelaar.

Om de implementatie van codewijzigingen te versnellen, biedt azd ondersteuning voor het implementeren van code-updates in de containerinstallatiekopieën. Dit gebeurt met behulp van de opdracht 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>

Het is niet nodig om elke keer alle services te implementeren. azd het .NET.NET Aspire projectmodel begrijpt, is het mogelijk om slechts één van de services te implementeren die zijn opgegeven met behulp van de volgende opdracht:

azd deploy webfrontend

Voor meer informatie, zie Azure Developer CLI naslaginformatie: azd deploy.

Infrastructuurupdates implementeren

Wanneer de afhankelijkheidsstructuur binnen een .NET.NET Aspire project verandert, moet azd de onderliggende Azure resources opnieuw inrichten. De opdracht azd provision wordt gebruikt om deze wijzigingen toe te passen op de infrastructuur.

Als u dit in actie wilt zien, werkt u het Program.cs-bestand in het AppHost-project bij naar het volgende:

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

Sla het bestand op en voer de volgende opdracht uit:

azd provision

Met de opdracht azd provision wordt de infrastructuur bijgewerkt door een container-app te maken om de Postgres-database te hosten. De azd provision opdracht heeft de verbindingsreeksen voor de apiservice container niet bijgewerkt. Als u verbindingsreeksen wilt laten bijwerken zodat deze verwijzen naar de zojuist ingerichte Postgres database, moet de opdracht azd deploy opnieuw worden aangeroepen. Wanneer u twijfelt, gebruikt u azd up om zowel de inrichting als de implementatie uit te voeren.

Resources opschonen

Vergeet niet om de Azure resources op te schonen die u tijdens deze handleiding hebt aangemaakt. Omdat azd de resourcegroep kent waarin het de resources heeft gemaakt, kan het worden gebruikt om de omgeving uit te schakelen met behulp van de volgende opdracht:

azd down

Het uitvoeren van de vorige opdracht kan enige tijd duren, maar wanneer deze is voltooid, zouden de resourcegroep en alle bijbehorende resources verwijderd moeten zijn.

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.

Bicep genereren van .NET.NET Aspire projectmodel

Hoewel ontwikkelteams gratis azd up opdrachten (of azd provision en azd deploy) kunnen gebruiken voor hun implementaties, zowel voor ontwikkelings- als productiedoeleinden, kunnen sommige teams kiezen voor het genereren van Bicep-bestanden die ze kunnen controleren en beheren als onderdeel van versiebeheer (hierdoor kunnen deze Bicep-bestanden ook worden verwezen als onderdeel van een grotere complexere Azure implementatie).

azd bevat de mogelijkheid om de Bicep uit te voeren die wordt gebruikt voor levering via de volgende opdracht:

azd config set alpha.infraSynth on
azd infra synth

Nadat deze opdracht is uitgevoerd in het voorbeeld van de starterssjabloon die in deze handleiding wordt gebruikt, worden de volgende bestanden gemaakt in de AppHost projectmap:

  • infra/main.bicep: vertegenwoordigt het belangrijkste toegangspunt voor de implementatie.
  • infra/main.parameters.json: Wordt gebruikt als de parameters voor de hoofd-Bicep (komt overeen met omgevingsvariabelen die zijn gedefinieerd in de .azure map).
  • infra/resources.bicep: definieert de Azure resources die nodig zijn om het .NET Aspire projectmodel te ondersteunen.
  • AspireSample.Web/manifests/containerApp.tmpl.yaml: de definitie van de container-app voor webfrontend.
  • AspireSample.ApiService/manifests/containerApp.tmpl.yaml: de definitie van de container-app voor apiservice.

Het bestand infra\resources.bicep bevat geen definitie van de container-apps zelf (met uitzondering van container-apps die afhankelijkheden zijn, zoals Redis en 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

Voor meer informatie over het gebruik van Bicep om implementaties naar Azure te automatiseren, zie Wat is Bicep?

De definitie van de container-apps uit de .NET-serviceprojecten bevindt zich in de bestanden containerApp/tmpl.yaml in de map manifests in elk project. Hier volgt een voorbeeld uit het webfrontend project:

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

Na het uitvoeren van de azd infra synth opdracht, maken azd provision en azd deploy gebruik van de Bicep-bestanden en ondersteunende gegenereerde bestanden wanneer ze worden aangeroepen.

Belangrijk

Als azd infra synth opnieuw wordt aangeroepen, worden alle gewijzigde bestanden vervangen door nieuw gegenereerde bestanden en wordt u om bevestiging gevraagd voordat u dit doet.

Geïsoleerde omgevingen voor foutopsporing

Omdat azd het eenvoudig maakt om nieuwe omgevingen in te richten, is het mogelijk dat elk teamlid een geïsoleerde in de cloud gehoste omgeving heeft voor foutopsporingscode in een instelling die nauw overeenkomt met de productie. Wanneer u dit doet, moet elk teamlid een eigen omgeving maken met behulp van de volgende opdracht:

azd env new

Hiermee wordt de gebruiker opnieuw gevraagd om informatie over abonnementen en resourcegroepen, en zullen de volgende aanroepen azd up, azd provisionen azd deploy deze nieuwe omgeving standaard gebruiken. De --environment-switch kan worden toegepast op deze opdrachten om tussen omgevingen te schakelen.

Resources opschonen

Voer de volgende Azure CLI-opdracht uit om de resourcegroep te verwijderen wanneer u de Azure resources die u hebt gemaakt niet meer nodig hebt. Als u de resourcegroep verwijdert, worden ook de resources in de resourcegroep verwijderd.

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

Zie Resources opschonen in Azurevoor meer informatie.