Le but de cette série d’articles est de présenter les principes de la technologie .NET Aspire, au travers de la mise en place d’une application « cloud native », que nous commencerons par définir.

Partie introductive, pour présenter les enjeux et les solutions apportées par .NET Aspire.

Partie codage, pour illustrer l’adaptation d’une application distribuée existante.

Suite de la partie codage, pour illustrer la découverte de services et ajouter un composant d’intégration.

Partie 4 :
Suite et fin, pour illustrer le déploiement de notre application distribuée.
Le code de la solution est disponible sur ce lien.
Nous abordons dans cet article la Partie 4.
Etape 6 : déploiements
Le modèle de déploiement par défaut de .NET Aspire dans Azure est de créer une Azure Container Apps.
Ce modèle permet ainsi d'exécuter des containers Docker utilisant :
- Les images construites pour les projets de la solution (pour nous, les services web et api),
- Les images externes (par exemple, un cache Redis).
Vous pouvez utiliser Visual Studio 2022, ou Azure Developper CLI (azd, cf https://learn.microsoft.com/fr-fr/azure/developer/azure-developer-cli/install-azd?tabs=winget-windows%2Cbrew-mac%2Cscript-linux&pivots=os-windows) pour réaliser ce déploiement.
Externalisation des points de terminaison
Avant de procéder au déploiement, nous devons adapter légèrement notre code afin que le point de terminaison du service web soit publique. En effet par défaut ces points sont privés, ce qui convient bien pour le service api, que l'on souhaite masquer.
Note :
Cela ne se remarque pas lorsque l'on fait les tests en local avec Visual Studio, car toutes les Urls sont en localhost, et donc accessibles en local !
Le code dans le projet AppHost doit donc être adapté ainsi :

Publication
Avec Visual Studio
La technique est classique, par un clic droit sur le projet AppHost et le choix « Publier » (ou “Publish”) :

L’étape suivante demande la sélection de l’abonnement Azure, la région de déploiement (où seront créés le groupe de ressources et les ressources) et le nom de l’environnement : celui-ci est utilisé pour le nommage des ressources Azure.
Par exemple :

Un profil de publication est alors généré par Visual Studio :

Une fois le profil créé, on lance le déploiement avec le bouton Publier (ou Publish) :

Lorsque le déploiement est terminé (après une dizaine de minutes !), la fenêtre affiche la liste des ressources créées, ainsi que les points de terminaison des services :

Nous constatons ainsi que :
- Le service api est déclaré en internal dans Azure Container Apps, donc avec une Url inaccessible de l’extérieur,
- Le service web a une Url publique.
Le nommage des ressources n’est pas totalement satisfaisant, nous corrigerons ce point dans le point « 3° Déploiement manuel des services » dans la suite de l’exemple.
Le log de déploiement décrit toutes les étapes internes :
…
29/11/2024 16:09:30: Info (✓) Done: Deploying service redis
29/11/2024 16:09:30: Info – Endpoint: https://redis.internal.whiteplant-9cee56b9.francecentral.azurecontainerapps.io/
29/11/2024 16:09:30: Info
29/11/2024 16:09:30: Info Deploying service weatherforecast-api
…
29/11/2024 16:12:12: Info (✓) Done: Deploying service weatherforecast-api
29/11/2024 16:12:12: Info – Endpoint: https://weatherforecast-api.internal.whiteplant-9cee56b9.francecentral.azurecontainerapps.io/
29/11/2024 16:12:12: Info
29/11/2024 16:12:12: Info Deploying service weatherforecast-web
…
29/11/2024 16:15:34: Info (✓) Done: Deploying service weatherforecast-web
29/11/2024 16:15:34: Info – Endpoint: https://weatherforecast-web.whiteplant-9cee56b9.francecentral.azurecontainerapps.io/
29/11/2024 16:15:34: Info
29/11/2024 16:15:34: Info Aspire Dashboard: https://aspire-dashboard.ext.whiteplant-9cee56b9.francecentral.azurecontainerapps.io
L’Url de lancement du Tableau de bord est également fournie.
Avec azd seul
Nous pouvons aussi déployer via l’outil en ligne de commande azd. Ce serait la technique à utiliser dans un pipeline CI/CD afin de déployer l’application sur Azure (cette technique est décrite ici ).
Les commandes doivent être saisies dans le terminal, à l’intérieur du répertoire du projet AppHost.
1° authentification sur le compte Azure
azd auth login
2° initiallisation du déploiement
azd init
Cette commande permet d’initialiser un déploiement d’application vers Azure.
La commande commence par demander la source du déploiement, nous sélectionnons ici le répertoire local :

Note :
La sélection d’un template permettrait de créer une application complète à partir d’un template de projet. La liste des templates disponibles est ici.
Note :
Si un environnement de déploiement existe déjà (par exemple suite à une publication avec Visual Studio), la commande à utiliser devient celle-ci :
azd provision -e deploy-aspire-azd-dev
L’outil détecte notre application .NET Aspire et demande la confirmation de déployer cette application vers une cible Azure Container Apps, que nous confirmons :

Il faut ensuite saisir le nom d’un environnement pour le nommage des ressources dans Azure :

Deux fichiers, azure.yaml, et next-steps.md, sont alors générés. Le fichier YAML est utilisé par azd pour le déploiement :

Pour personnaliser le nommage du groupe de ressources et des ressources elles-mêmes, le fichier next-steps.md précise une technique que l’on utilisera plus loin :

3° déploiement manuel des services
Comme indiqué par le fichier next-steps.md et la commande azd init, le déploiement vers Azure est lancé par cette commande :
azd up
Cette commande fait le provisionnement de l’infrastructure et déploie l’application dans Azure.
Note :
Si un environnement de déploiement existe déjà (par exemple suite à une publication avec Visual Studio), la commande à utiliser devient celle-ci :
azd up -e deploy-aspire-azd-dev
![]()
Le groupe de ressources et les ressources elles-mêmes sont alors créées dans Azure :
Note :
Chacune de ces tâches peut être réalisée indépendamment par les commandes suivantes :
azd provision
azd deploy
L’outil demande alors de renseigner l’abonnement Azure et la région:

Le déploiement des services s’effectue à la suite, et nous obtenons les Urls d’accès au Tableau de bord et au service web :

Note :
Il peut arriver que la création des ressources échoue avec l’erreur suivante :
![]()
Dans ce cas il est nécessaire de passer par chacune des commandes :
azd provision –no-state
azd deploy
4° déploiement de mises à jour
Si une mise à jour est faite dans le projet AppHost (ajout de projets, ajout de services externes), la commande azd provision permet de mettre à jour l’infrastructure pour Azure.
Si une mise à jour est faite dans le code d’un des projets (api ou web, dans notre exemple), la commande azd deploy permet de déployer la mise à jour vers Azure.
5° déploiement automatisé des services (CI/CD)
Les commandes azd (par exemple, provision, deploy) peuvent être utilisées dans GitHub Actions et Azure Pipelines pour tester le code sur des ressources Azure réelles et faciliter les déploiements.
Un exemple de pipeline pour Github est disponible ici.
Un exemple de pipeline pour Azure DevOps est disponible ici.
La documentation décrit un exemple de mise en place d’un pipeline CI/CD pour Azure DevOps : https://learn.microsoft.com/en-us/dotnet/aspire/deployment/azure/aca-deployment-github-actions?tabs=windows&pivots=azure-pipelines.
Cet exemple s’appuie sur la commande azd pipeline config –provider azdo.
Pour créer une Github Action, la commande serait azd pipeline config –provider github.
Tests dans Azure Container Apps
Accès au Tableau de bord
Dans Azure, l’accès au Tableau de Bord se fait via le portail, via les informations de la ressource Azure Container Apps Environment :

Il est alors possible de refaire les mêmes tests que précédemment, en accédant au point de terminaison (public) du service web.
Un problème existe par contre : notre code demandait 3 replicas (instances) pour le projet web, mais la configuration dans Azure est incorrecte :

Pour corriger cela, il faut passer par la modification des fichiers de déploiement (en Bicep, qui est le provider par défaut pour .NET Aspire).
Corrections des fichiers bicep de déploiement
Comme on a pu le constater dans le point « Publication – Avec Visual Studio », le nommage mis en place par défaut est assez peu explicite. Il peut même entrer en conflit avec des règles de nommage appliquées côté Azure (via des policies).
Pour corriger le nommage, ou appliquer toute autre correction (comme les replicas !), il est nécessaire de passer par une phase intermédiaire de génération des fichiers de déploiement. Le principe est décrit ici.
Nous lançons d’abord les commandes suivantes :
azd config set alpha.infraSynth on
azd infra synth
Les fichiers bicep sont alors générés en local et accessibles pour modification.

Correction du nombre de replicas
Pour corriger le nombre de replicas du service web, il suffit de corriger le fichier weatherforecast-web.tmpl.yaml qui contient cette ligne :
![]()
Nous passons donc la valeur à 3 pour appliquer la configuration souhaitée.
Pour effectuer la mise à jour du service dans Azure Container Apps, il suffit de lancer cette commande :
azd deploy
Après cette mise à jour la modification de nombre de replicas est appliquée :

Le Tableau de bord montre bien l’équilibrage de la charge sur les 3 instances du service web :

Corrections du nommage
Comme nous pouvons le constater dans le fichier infra\resources.bicep, le nommage des ressources utilise un préfixe pseudo-aléatoire, nommé ici resourceToken (cd ligne 10 ci-dessous):

On peut donc ici remplacer le code de la ligne 10, pour imposer un nommage plus adéquat (cf https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming), par exemple :
![]()
Suppression d’un déploiement
azd down permet de supprimer un déploiement afin de libérer les ressources :
azd down [-e <nom de l’environnement>]
La suppression est une étape relativement longue côté Azure :

En conclusion
Ceci termine notre vue globale des possibilités offerte par .NET Aspire.
.NET Aspire s’avère une technologie mature, « Production-ready », avec des templates de base, et des intégrations riches et robustes.
La technologie facilite la bonne mise en œuvre d’une application « cloud ready », car toutes les bonnes pratiques d’observabilité, de santé, et de résilience sont implémentées à tous les niveaux.
Dans le code du projet AppHost, il est possible de référencer des éléments externes existants, comme des images Docker, des services Azure, des fichiers (Dockerfile, bicep, …), et même des ressources AWS (cf le projet Github) !
Pour des besoins spécifiques (support de GCP ? ), vous pouvez aussi écrire vous-mêmes des packages d’intégration côté Hosting ou côté client, comme décrit dans la documentation (cf https://learn.microsoft.com/en-us/dotnet/aspire/extensibility/custom-hosting-integration?tabs=windows et https://learn.microsoft.com/en-us/dotnet/aspire/extensibility/custom-client-integration).
Il existe quand même quelques limitations :
- La version .Net minimale est la 8,
- Tous les services Azure ne sont pas supportés via les intégrations (mais le travail est en cours !),
- Il n’existe qu’un seul provider actuellement : Bicep,
- Les replicas sont partiellement supportés, ce qui nécessite une action manuelle dans les fichiers bicep (de même si un système de nommage plus adapté est requis).
Au final .NET Aspire constitue pour le Développeur Cloud aguerri ou débutant un chemin sûr pour bâtir des architectures distribuées aussi complexes que nécessaire. D’ailleurs Microsoft utilise lui-même en interne .NET Aspire pour ses propres besoins !

