Partager via


Déployer un projet de Aspire vers Azure Container Apps à l’aide du Azure Developer CLI (un guide détaillé)

Le Azure Developer CLI (azd) a été étendu pour prendre en charge le déploiement des projets Aspire. Utilisez ce guide pour suivre le processus de création et de déploiement d’un Aspire projet à Azure Container Apps à l’aide du Azure Developer CLI. Dans ce tutoriel, vous allez découvrir les concepts suivants :

  • Découvrez comment fonctionne l'intégration de azd avec les projets Aspire.
  • Approvisionner et déployer des ressources sur Azure pour un projet Aspire en utilisant azd
  • Générer l’infrastructure Bicep et d’autres fichiers de modèle à l’aide de azd

Prerequisites

Pour travailler avec Aspire, vous avez besoin des éléments suivants installés localement :

Pour plus d’informations, consultez Aspire configuration et outils, et Aspire SDK.

Vous devez également avoir Azure Developer CLIinstallé localement. Les options d’installation courantes sont les suivantes :

winget install microsoft.azd

Comment fonctionne l'intégration Azure Developer CLI

Le azd init flux de travail fournit une prise en charge personnalisée pour Aspire les projets. Le diagramme suivant illustre le fonctionnement conceptuel du flux et comment azd et Aspire sont intégrés :

Illustration du traitement interne de « azd » lors du déploiement du Aspire projet.

  1. Quand cible un projet , il démarre l'AppHost avec une commande spéciale (), qui produit le fichier manifeste .
  2. Le fichier manifeste est interrogé par la azd provision logique de sous-commande pour générer des fichiers Bicep en mémoire uniquement (par défaut).
  3. Après avoir généré les fichiers Bicep, un déploiement est déclenché à l’aide Azuredes API ARM ciblant l’abonnement et le groupe de ressources fournis précédemment.
  4. Une fois les ressources sous-jacentes Azure configurées, la azd deploy logique de sous-commande est exécutée qui utilise le même Aspire fichier manifeste.
  5. Dans le cadre du déploiement azd, un appel est lancé à dotnet publish à l'aide de la prise en charge intégrée de la publication de conteneurs pour générer des images de conteneur.
  6. Une fois que azd a construit les images de conteneur, il les pousse (push) vers le registre ACR qui a été créé pendant la phase d’approvisionnement.
  7. Enfin, une fois l’image conteneur dans ACR, azd met à jour la ressource à l’aide d’ARM pour commencer à utiliser la nouvelle version de l’image conteneur.

Note

azd vous permet également d'envoyer le Bicep généré dans un dossier infra de votre projet, pour en savoir plus, consultez la section Génération de Bicep à partir du modèle d’application Aspire.

Approvisionner et déployer une Aspire application de démarrage

Les étapes décrites dans cette section montrent comment créer une application de démarrage Aspire et gérer l’approvisionnement et le déploiement des ressources de l’application vers Azure, en utilisant azd.

Créer l’application Aspire de démarrage

Créez un nouveau projet Aspire en utilisant la commande dotnet new. Vous pouvez également créer le projet en utilisant Visual Studio.

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

Les commandes précédentes créent un projet Aspire basé sur le modèle aspire-starter qui inclut une dépendance au cache Redis. Il exécute le Aspire projet qui vérifie que tout fonctionne correctement.

Initialiser le modèle

  1. Ouvrez une nouvelle fenêtre de terminal et cd dans le répertoire de votre solution Aspire.

  2. Exécutez la commande azd init pour initialiser votre projet avec azd, qui inspecte la structure de répertoires local et détermine le type d’application.

    azd init
    

    Pour plus d’informations sur la commande azd init, consultez azd init.

  3. Sélectionnez Utiliser du code dans le répertoire actif lorsque azd vous êtes invité à utiliser trois options d’initialisation d’application.

    ? How do you want to initialize your app?  [Use arrows to move, type to filter]
    > Use code in the current directory
      Select a template
      Create a minimal project
    
  4. Après avoir analysé le répertoire, azd vous invite à confirmer qu’il a trouvé le projet Aspire approprié. Sélectionnez l’option Confirmer et continuer à initialiser mon application.

    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. Entrez un nom d’environnement, utilisé pour nommer les ressources provisionnée dans Azure et gérer différents environnements tels que dev et 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 génère un certain nombre de fichiers et les place dans le répertoire de travail. Ces fichiers sont les suivants :

  • azure.yaml: décrit les services de l’application, tels que Aspire projet AppHost, et les mappe aux ressources Azure.
  • .azure/config.json: fichier de configuration qui informe azd de quel est l'environnement actif actuel.
  • .azure/aspireazddev/.env: contient des remplacements spécifiques à l’environnement.

Le fichier azure.yaml contient le contenu suivant :

# 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

Nommage des ressources

Lorsque vous créez de nouvelles ressources Azure, il est important de respecter les exigences de nommage. Pour Azure Container Appscela, le nom doit comporter 2 à 32 caractères et se composer de lettres minuscules, de chiffres et de traits d’union. Le nom doit commencer par une lettre et se terminer par un caractère alphanumérique.

Pour plus d’informations, consultez règles et restrictions d’affectation de noms pour les Azure ressources.

Déploiement initial

  1. Pour déployer le Aspire projet, authentifiez-vous auprès d’AD Azure pour appeler les Azure API de gestion des ressources.

    azd auth login
    

    La commande précédente lance un navigateur pour authentifier la session de ligne de commande.

  2. Une fois authentifié, exécutez la commande suivante à partir du répertoire du projet AppHost pour approvisionner et déployer l’application.

    azd up
    

    Important

    Pour envoyer (push) des images conteneur à Azure Container Registry (ACR), vous devez avoir Microsoft.Authorization/roleAssignments/write accès. Pour ce faire, vous pouvez activer un utilisateur administrateur sur le Registre. Ouvrez le Azure portail, accédez à la ressource ACR / Paramètres / Clés d’accès, puis cochez la case Utilisateur administrateur . Pour plus d’informations, consultez Activer l’utilisateur administrateur.

  3. Lorsque vous y êtes invité, sélectionnez l’abonnement et l’emplacement où les ressources doivent être déployées. Une fois ces options sélectionnées, le Aspire projet sera déployé.

    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 Aspire DASHBOARD>
    
    SUCCESS: Your up workflow to provision and deploy to Azure completed in 3 minutes 50 seconds.
    

    La dernière ligne de sortie de la azd commande est un lien vers le Azure portail qui affiche toutes les Azure ressources déployées :

    Capture d’écran du Azure portail montrant les ressources déployées.

Trois conteneurs sont déployés dans cette application :

  • webfrontend: contient du code à partir du projet web dans le modèle de démarrage.
  • apiservice: contient du code du projet de service d’API dans le modèle de démarrage.
  • cache Redis: image conteneur permettant de fournir un cache au serveur frontal.

Tout comme dans le développement local, la configuration des chaînes de connexion a été gérée automatiquement. Dans ce cas, azd il a été chargé d’interpréter le modèle d’application et de le traduire en étapes de déploiement appropriées. Par exemple, considérez la chaîne de connexion et les variables de découverte de service qui sont injectées dans le webfrontend conteneur afin qu’elles sachent comment se connecter au Redis cache et apiservice.

Capture d’écran des variables d’environnement dans l’application conteneur webfrontend.

Pour plus d’informations sur la façon dont les projets Aspire gèrent les chaînes de connexion et la découverte de services, consultez Aspire Vue d’ensemble de l’orchestration.

Déployer des mises à jour d’application

Lorsque la azd up commande est exécutée, les ressources sous-jacentes Azure sont approvisionnées et une image conteneur est générée et déployée sur les applications conteneur hébergeant le Aspire projet. En règle générale, une fois que le développement est en cours et Azure que les ressources sont déployées, il n’est pas nécessaire de provisionner Azure des ressources chaque fois que le code est mis à jour, ce qui est particulièrement vrai pour la boucle interne du développeur.

Pour accélérer le déploiement des modifications de code, azd prend en charge le déploiement des mises à jour de code dans l’image conteneur. Pour ce faire, utilisez la azd deploy commande suivante :

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 Aspire DASHBOARD>

Il n’est pas nécessaire de déployer tous les services à chaque fois. azd comprend le Aspire modèle de projet, il est possible de déployer uniquement l’un des services spécifiés à l’aide de la commande suivante :

azd deploy webfrontend

Pour plus d’informations, consultez Azure Developer CLI référence : azd deploy.

Déployer des mises à jour d’infrastructure

Chaque fois que la structure de dépendances au sein d’un Aspire projet change, azd doit reprovisionner les ressources sous-jacentes Azure. La azd provision commande est utilisée pour appliquer ces modifications à l’infrastructure.

Pour voir cela en action, mettez à jour le AppHost.cs fichier dans le projet AppHost en procédant comme suit :

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

Enregistrez le fichier et émettez la commande suivante :

azd provision

La azd provision commande met à jour l’infrastructure en créant une application conteneur pour héberger la Postgres base de données. La azd provision commande n’a pas mis à jour les chaînes de connexion pour le apiservice conteneur. Pour que les chaînes de connexion soient mises à jour pour pointer vers la base de données nouvellement approvisionnée Postgres , la azd deploy commande doit être appelée à nouveau. En cas de doute, utilisez azd up pour l'approvisionnement et le déploiement.

Nettoyer les ressources

N’oubliez pas de nettoyer les Azure ressources que vous avez créées pendant cette procédure pas à pas. Étant donné que azd connaît le groupe de ressources dans lequel il a créé les ressources, il peut être utilisé pour démonter l’environnement en utilisant la commande suivante :

azd down

La commande précédente peut prendre un certain temps pour s’exécuter, mais une fois le groupe de ressources terminé et toutes ses ressources doivent être supprimées.

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.

Générer Bicep à partir du modèle de projet Aspire

Bien que les équipes de développement soient libres d’utiliser les commandes azd up (ou azd provision et azd deploy) pour leurs déploiements, à la fois pour des raisons de développement et de production, certaines équipes peuvent choisir de générer des fichiers Bicep qu’elles peuvent examiner et gérer dans le cadre du contrôle de version (cela permet également de référencer ces fichiers Bicep dans le cadre d’un déploiement plus complexe et plus vaste Azure).

Pour obtenir des conseils complets sur la personnalisation de l’infrastructure générée pour les scénarios de production, consultez Personnaliser AspireAzure les déploiements.

azd inclut la possibilité de générer le Bicep qu’il utilise pour le provisionnement via la commande suivante :

azd config set alpha.infraSynth on
azd infra gen

Une fois cette commande exécutée dans l’exemple de modèle de démarrage utilisé dans ce guide, les fichiers suivants sont créés dans le répertoire du projet AppHost :

  • infra/main.bicep : représente le point d’entrée principal du déploiement.
  • infra/main.parameters.json: utilisé comme paramètres pour le fichier Bicep principal (correspond aux variables d’environnement définies dans le dossier .azure).
  • infra/resources.bicep : définit les Azure ressources nécessaires pour prendre en charge le modèle de Aspire projet.
  • AspireSample.Web/manifests/containerApp.tmpl.yaml : définition de l’application conteneur pour webfrontend.
  • AspireSample.ApiService/manifests/containerApp.tmpl.yaml : définition de l’application conteneur pour apiservice.

Le fichier infra\resources.bicep ne contient aucune définition des applications de conteneurs elles-mêmes (à l'exception des applications de conteneurs qui sont des dépendances telles que Redis et 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

Pour plus d’informations sur l’utilisation de Bicep pour automatiser les déploiements, AzureQu’est-ce que Bicep ?

La définition des applications conteneur à partir des projets de .NET service est contenue dans les fichiers containerApp/tmpl.yaml dans le manifests répertoire de chaque projet respectivement. Voici un exemple du webfrontend projet :

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: APISERVICE_HTTP
        value: http://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
      - name: APISERVICE_HTTPS
        value: https://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
      - name: services__apiservice__http__0
        value: http://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
      - name: services__apiservice__https__0
        value: https://apiservice.internal.{{ .Env.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN }}
tags:
  azd-service-name: webfrontend
  aspire-resource-name: webfrontend

Après avoir exécuté la azd infra gen commande, quand azd provision et azd deploy sont appelés, ils utilisent bicep et prennent en charge les fichiers générés.

Important

S’il azd infra gen est appelé à nouveau, il remplace tous les fichiers modifiés par des fichiers générés à nouveau et vous invite à confirmer avant de le faire.

Environnements isolés pour le débogage

Étant donné qu’il azd est facile de provisionner de nouveaux environnements, il est possible que chaque membre de l’équipe dispose d’un environnement hébergé dans le cloud isolé pour le débogage du code dans un paramètre qui correspond étroitement à la production. Lorsque vous effectuez cette opération, chaque membre de l’équipe doit créer son propre environnement à l’aide de la commande suivante :

azd env new

Cela invite l’utilisateur à entrer à nouveau les informations d’abonnement et de groupe de ressources, et azd up les appels suivants azd provisionazd deployutilisent ce nouvel environnement par défaut. Le --environment commutateur peut être appliqué à ces commandes pour basculer entre les environnements.

Nettoyer les ressources

Exécutez la commande CLI Azure suivante pour supprimer le groupe de ressources lorsque vous n’avez plus besoin des ressources Azure que vous avez créées. La suppression du groupe de ressources supprime également les ressources contenues à l’intérieur de celui-ci.

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

Pour plus d’informations, consultez Nettoyer les ressources dans Azure.