Partager via


Déployer Orleans sur Azure App Service

Dans ce tutoriel, vous découvrez comment déployer une application de panier Orleans sur Azure App Service. Le tutoriel vous guide à travers un exemple d’application qui prend en charge les fonctionnalités suivantes :

  • Panier : application de panier simple, qui utilise Orleans pour la prise en charge de son framework multiplateforme et ses fonctionnalités d’applications distribuées scalables.

    • Gestion des stocks : modifiez et/ou créez un stock de produits.
    • Inventaire du magasin : explorez les produits pouvant être achetés, et ajoutez-les à votre panier.
    • Panier : affichez un récapitulatif de tous les articles de votre panier, et gérez ces articles en supprimant ou en changeant la quantité de chaque élément.

Une fois que vous aurez une bonne compréhension de l’application et de ses fonctionnalités, vous découvrirez ensuite comment la déployer sur Azure App Service en utilisant GitHub Actions, les interfaces .NET CLI et Azure CLI ainsi qu’Azure Bicep. De plus, vous allez apprendre à configurer le réseau virtuel de l’application dans Azure.

Dans ce tutoriel, vous allez apprendre à :

  • Déployer une application Orleans sur Azure App Service
  • Automatiser le déploiement à l’aide de GitHub Actions et d’Azure Bicep
  • Configurer le réseau virtuel de l’application dans Azure

Prérequis

Exécutez l’application localement.

Pour exécuter l’application localement, effectuez une duplication (fork) du dépôt Exemples Azure : Cluster Orleans sur Azure App Service, puis clonez-le sur votre machine locale. Une fois le clonage effectué, ouvrez la solution dans l’IDE de votre choix. Si vous utilisez Visual Studio, cliquez avec le bouton droit sur le projet Orleans.ShoppingCart.Silo, sélectionnez Définir en tant que projet de démarrage, puis exécutez l’application. Sinon, vous pouvez exécuter l’application à l’aide de la commande .NET CLI suivante :

dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj

Pour plus d’informations, consultez dotnet run. Une fois l’application en cours d’exécution, vous pouvez naviguer et tester librement ses fonctionnalités. Toutes les fonctionnalités de l’application, quand elle s’exécute localement, reposent sur la persistance en mémoire et le clustering local. De plus, l’application utilise le package NuGet Bogus pour générer des produits fictifs. Arrêtez l’application en sélectionnant l’option Arrêter le débogage dans Visual Studio, ou en appuyant sur Ctrl+C dans l’interface .NET CLI.

Dans l’application de panier

Orleans est un framework fiable et scalable pour la génération d’applications distribuées. Pour ce tutoriel, vous allez déployer une application de panier simple générée à l’aide d’Orleans sur Azure App Service. L’application permet de gérer les stocks, d’ajouter et de supprimer des articles dans un panier et d’acheter les produits disponibles. Le client est généré à l’aide de Blazor avec un modèle d’hébergement de serveur. L’architecture de l’application est la suivante :

Orleans : Architecture de l’exemple d’application Panier.

Dans le diagramme précédent, le client est représenté par l’application Blazor côté serveur. Il est composé de plusieurs services qui consomment un grain Orleans correspondant. Chaque service est associé à un grain Orleans de la manière suivante :

  • InventoryService : consomme IInventoryGrain, où le stock est partitionné par catégorie de produit.
  • ProductService : consomme IProductGrain, où un seul produit est attaché à une seule instance de grain par Id.
  • ShoppingCartService : consomme IShoppingCartGrain, où un seul utilisateur n’a qu’une seule instance du panier, quels que soient les clients consommateurs.

La solution inclut trois projets :

  • Orleans.ShoppingCart.Abstractions : bibliothèque de classes qui définit les modèles et les interfaces de l’application.
  • Orleans.ShoppingCart.Grains : bibliothèque de classes qui définit les grains implémentant la logique métier de l’application.
  • Orleans.ShoppingCart.Silos : application Blazor côté serveur, qui héberge le silo Orleans.

Expérience utilisateur du client

L’application cliente correspondant au panier comporte plusieurs pages, chacune représentant une expérience utilisateur distincte. L’IU de l’application est générée à l’aide du package NuGet MudBlazor.

page d'accueil

Quelques phrases simples pour permettre à l’utilisateur de comprendre l’objectif de l’application, et ajouter du contexte à chaque élément du menu de navigation.

Orleans : Page d’accueil de l’exemple d’application Panier.

Page de stock du magasin

Page qui affiche tous les produits disponibles à l’achat. Vous pouvez ajouter des articles au panier à partir de cette page.

Orleans : Exemple d’application Panier, page de stock du magasin.

Page de panier vide

Si vous n’avez rien ajouté à votre panier, la page affiche un message indiquant que vous n’avez aucun article dans votre panier.

Orleans : Exemple d’application Panier, page de panier vide.

Articles ajoutés au panier depuis la page de stock du magasin

Quand vous ajoutez des articles à votre panier depuis la page de stock du magasin, l’application affiche un message indiquant que l’article a été ajouté au panier.

Orleans : Exemple d’application Panier, articles ajoutés au panier depuis la page de stock du magasin.

Page de gestion des produits

Un utilisateur peut gérer le stock à partir de cette page. Il est possible d’ajouter, de modifier et de supprimer des produits à partir de l’inventaire.

Orleans : Exemple d’application Panier, page de gestion des produits.

Boîte de dialogue de création de produit dans la page de gestion des produits

Quand un utilisateur clique sur le bouton Créer un produit, l’application affiche une boîte de dialogue qui permet à l’utilisateur de créer un produit.

Orleans : Exemple d’application Panier, boîte de dialogue de création de produit dans la page de gestion des produits.

Éléments de la page du panier

Quand des articles se trouvent dans votre panier, vous pouvez les voir, changer leur quantité, et même les supprimer du panier. L’utilisateur voit un récapitulatif des articles du panier ainsi que le coût total hors taxe.

Orleans : Exemple d’application Panier, éléments de la page du panier.

Important

Quand cette application s’exécute localement, dans un environnement de développement, elle utilise le clustering localhost, le stockage en mémoire et un silo local. Elle alimente également l’inventaire avec des données fictives générées automatiquement à l’aide du package NuGet Bogus. Tout cela est intentionnel et vise à présenter une démonstration des fonctionnalité.

Déployer sur Azure App Service

Une application Orleans classique se compose d’un cluster de processus serveur (silos) où se trouvent des grains ainsi qu’un ensemble de processus clients, généralement des serveurs web, qui reçoivent les requêtes externes, les transforment en appels de méthode de grain et retournent les résultats. Ainsi, la première chose à faire pour exécuter une application Orleans est de démarrer un cluster de silos. Pour les tests, un cluster peut se composer d’un seul silo.

Notes

Dans le cadre d’un déploiement en production fiable, vous avez besoin de plusieurs silos dans un cluster à des fins de tolérance de panne et de mise à l’échelle.

Avant de déployer l’application, vous devez créer un groupe de ressources Azure, ou choisir d’utiliser un groupe existant. Pour créer un groupe de ressources Azure, utilisez l’un des articles suivants :

Notez le nom du groupe de ressources que vous choisissez. Vous en aurez besoin plus tard pour déployer l’application.

Créer un principal du service

Pour automatiser le déploiement de l’application, vous devez créer un principal de service. Il s’agit d’un compte Microsoft qui dispose de l’autorisation nécessaire pour gérer les ressources Azure en votre nom.

az ad sp create-for-rbac --sdk-auth --role Contributor \
  --name "<display-name>"  --scopes /subscriptions/<your-subscription-id>

Les informations d’identification JSON créées ressemblent à ce qui suit, mais avec des valeurs réelles pour votre client, votre abonnement et votre locataire :

{
  "clientId": "<your client id>",
  "clientSecret": "<your client secret>",
  "subscriptionId": "<your subscription id>",
  "tenantId": "<your tenant id>",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com/",
  "resourceManagerEndpointUrl": "https://brazilus.management.azure.com",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com",
  "managementEndpointUrl": "https://management.core.windows.net"
}

Copiez la sortie de la commande dans votre Presse-papiers, puis passez à l’étape suivante.

Créer un secret GitHub

GitHub fournit un mécanisme de création de secrets chiffrés. Les secrets que vous créez peuvent être utilisés dans les workflows GitHub Actions. Vous allez voir comment GitHub Actions peut être utilisé pour automatiser le déploiement de l’application, conjointement avec Azure Bicep. Bicep est un langage dédié (DSL), qui utilise une syntaxe déclarative pour déployer les ressources Azure. Pour plus d’informations, consultez Qu’est-ce que Bicep. À l’aide de la sortie de l’étape Créer un principal de service, vous devez créer un secret GitHub nommé AZURE_CREDENTIALS avec les informations d’identification au format JSON.

Dans le dépôt GitHub, sélectionnez Paramètres>Secrets>Créer un secret. Entrez le nom AZURE_CREDENTIALS et collez les informations d’identification au format JSON de l’étape précédente dans le champ Valeur.

Dépôt GitHub : Paramètres > Secrets

Pour plus d’informations, consultez GitHub : Secrets chiffrés.

Préparer le déploiement Azure

L’application doit être packagée pour le déploiement. Dans le projet Orleans.ShoppingCart.Silos, nous définissons un élément Target qui s’exécute après l’étape Publish. Cela entraîne la compression du répertoire de publication dans un fichier silo.zip :

<Target Name="ZipPublishOutput" AfterTargets="Publish">
    <Delete Files="$(ProjectDir)\..\silo.zip" />
    <ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>

Il existe de nombreuses façons de déployer une application .NET sur Azure App Service. Dans ce tutoriel, vous allez utiliser GitHub Actions, Azure Bicep ainsi que les interfaces .NET CLI et Azure CLI. Prenons l’exemple du fichier ./github/workflows/deploy.yml situé à la racine du dépôt GitHub :

name: Deploy to Azure App Service

on:
  push:
    branches:
    - main

env:
  UNIQUE_APP_NAME: cartify
  AZURE_RESOURCE_GROUP_NAME: orleans-resourcegroup
  AZURE_RESOURCE_GROUP_LOCATION: centralus

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Setup .NET 6.0
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 6.0.x

    - name: .NET publish shopping cart app
      run: dotnet publish ./Silo/Orleans.ShoppingCart.Silo.csproj --configuration Release

    - name: Login to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}
    
    - name: Flex bicep
      run: |
        az deployment group create \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
          --template-file '.github/workflows/flex/main.bicep' \
          --parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }} \
            appName=${{ env.UNIQUE_APP_NAME }} \
          --debug

    - name: Webapp deploy
      run: |
        az webapp deploy --name ${{ env.UNIQUE_APP_NAME }} \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME  }} \
          --clean true --restart true \
          --type zip --src-path silo.zip --debug

Le workflow GitHub précédent va :

  • Publier l’application de panier sous forme de fichier zip, à l’aide de la commande dotnet publish.
  • Connectez-vous à Azure à l’aide des informations d’identification de l’étape Créer un principal de service.
  • Évaluer le fichier main.bicep et démarrer un groupe de déploiement à l’aide de la commande az deployment group create.
  • Déployer le fichier silo.zip sur Azure App Service à l’aide d’az webapp deploy.

Le workflow est déclenché par une poussée vers la branche main. Pour plus d’informations, consultez GitHub Actions et .NET.

Conseil

Si vous rencontrez des problèmes au moment de l’exécution du workflow, vous devrez peut-être vérifier que tous les espaces de noms de fournisseurs nécessaires sont inscrits pour le principal de service. Les espaces de noms de fournisseurs suivants sont obligatoires :

  • Microsoft.Web
  • Microsoft.Network
  • Microsoft.OperationalInsights
  • Microsoft.Insights
  • Microsoft.Storage

Pour plus d’informations, consultez Résoudre les erreurs d’inscription du fournisseur de ressources.

Azure impose des restrictions et des conventions de nommage pour les ressources. Vous devez mettre à jour les valeurs du fichier deploy.yml pour ce qui suit :

  • UNIQUE_APP_NAME
  • AZURE_RESOURCE_GROUP_NAME
  • AZURE_RESOURCE_GROUP_LOCATION

Affectez à ces valeurs le nom unique de votre application ainsi que le nom et l’emplacement de votre groupe de ressources Azure.

Pour plus d’informations, consultez les règles de nommage et les restrictions.

Explorer les modèles Bicep

Quand la commande az deployment group create est exécutée, elle évalue le fichier main.bicep. Ce fichier contient les ressources Azure à déployer. Vous pouvez vous représenter cette étape comme le provisionnement de toutes les ressources du déploiement.

Important

Si vous utilisez Visual Studio Code, l’expérience de création Bicep est améliorée quand vous utilisez l’extension Bicep.

Il existe de nombreux fichiers Bicep, chacun contenant des ressources ou des modules (collections de ressources). Le fichier main.bicep est le point d’entrée et se compose principalement de définitions de module :

param appName string
param location string = resourceGroup().location

module storageModule 'storage.bicep' = {
  name: 'orleansStorageModule'
  params: {
    name: '${appName}storage'
    location: location
  }
}

module logsModule 'logs-and-insights.bicep' = {
  name: 'orleansLogModule'
  params: {
    operationalInsightsName: '${appName}-logs'
    appInsightsName: '${appName}-insights'
    location: location
  }
}

resource vnet 'Microsoft.Network/virtualNetworks@2021-05-01' = {
  name: '${appName}-vnet'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '172.17.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'default'
        properties: {
          addressPrefix: '172.17.0.0/24'
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
        }
      }
    ]
  }
}

module siloModule 'app-service.bicep' = {
  name: 'orleansSiloModule'
  params: {
    appName: appName
    location: location
    vnetSubnetId: vnet.properties.subnets[0].id
    appInsightsConnectionString: logsModule.outputs.appInsightsConnectionString
    appInsightsInstrumentationKey: logsModule.outputs.appInsightsInstrumentationKey
    storageConnectionString: storageModule.outputs.connectionString
  }
}

Le fichier Bicep précédent définit ceci :

  • Deux paramètres pour le nom du groupe de ressources et le nom de l’application.
  • La définition de storageModule, qui définit le compte de stockage.
  • La définition de logsModule, qui définit les ressources Azure Log Analytics et Application Insights.
  • La ressource vnet, qui définit le réseau virtuel.
  • La définition de siloModule, qui définit Azure App Service.

Le réseau virtuel représente une resource très importante. La ressource vnet permet à Azure App Service de communiquer avec le cluster Orleans.

Chaque fois qu’un module est rencontré dans le fichier Bicep, il est évalué via un autre fichier Bicep qui contient les définitions de ressources. Le premier module rencontré est storageModule, qui est défini dans le fichier storage.bicep :

param name string
param location string

resource storage 'Microsoft.Storage/storageAccounts@2021-08-01' = {
  name: name
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

var key = listKeys(storage.name, storage.apiVersion).keys[0].value
var protocol = 'DefaultEndpointsProtocol=https'
var accountBits = 'AccountName=${storage.name};AccountKey=${key}'
var endpointSuffix = 'EndpointSuffix=${environment().suffixes.storage}'

output connectionString string = '${protocol};${accountBits};${endpointSuffix}'

Les fichiers Bicep acceptent des paramètres, qui sont déclarés à l’aide du mot clé param. De même, ils peuvent également déclarer des sorties à l’aide du mot clé output. La resource liée au stockage repose sur le type et la version Microsoft.Storage/storageAccounts@2021-08-01. Elle est provisionnée à l’emplacement du groupe de ressources, en tant que référence SKU StorageV2 et Standard_LRS. Le fichier Bicep lié au stockage définit sa chaîne de connexion sous la forme de output. connectionString est ensuite utilisé par le fichier Bicep lié au silo pour se connecter au compte de stockage.

Le fichier logs-and-insights.bicep définit ensuite les ressources Azure Log Analytics et Application Insights :

param operationalInsightsName string
param appInsightsName string
param location string

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: appInsightsName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logs.id
  }
}

resource logs 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
  name: operationalInsightsName
  location: location
  properties: {
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  }
}

output appInsightsInstrumentationKey string = appInsights.properties.InstrumentationKey
output appInsightsConnectionString string = appInsights.properties.ConnectionString

Ce fichier Bicep définit les ressources Azure Log Analytics et Application Insights. La ressource appInsights est de type web et la ressource logs est de type PerGB2018. La ressource appInsights et la ressource logs sont toutes deux provisionnées à l’emplacement du groupe de ressources. La ressource appInsights est liée à la ressource logs via la propriété WorkspaceResourceId. Il existe deux sorties définies dans ce fichier Bicep, et qui sont utilisées plus tard par le module App Service.

Enfin, le fichier app-service.bicep définit la ressource Azure App Service :

param appName string
param location string
param vnetSubnetId string
param appInsightsInstrumentationKey string
param appInsightsConnectionString string
param storageConnectionString string

resource appServicePlan 'Microsoft.Web/serverfarms@2021-03-01' = {
  name: '${appName}-plan'
  location: location
  kind: 'app'
  sku: {
    name: 'S1'
    capacity: 1
  }
}

resource appService 'Microsoft.Web/sites@2021-03-01' = {
  name: appName
  location: location
  kind: 'app'
  properties: {
    serverFarmId: appServicePlan.id
    virtualNetworkSubnetId: vnetSubnetId
    httpsOnly: true
    siteConfig: {
      vnetPrivatePortsCount: 2
      webSocketsEnabled: true
      netFrameworkVersion: 'v6.0'
      appSettings: [
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: appInsightsInstrumentationKey
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: appInsightsConnectionString
        }
        {
          name: 'ORLEANS_AZURE_STORAGE_CONNECTION_STRING'
          value: storageConnectionString
        }
      ]
      alwaysOn: true
    }
  }
}

resource appServiceConfig 'Microsoft.Web/sites/config@2021-03-01' = {
  name: '${appService.name}/metadata'
  properties: {
    CURRENT_STACK: 'dotnet'
  }
}

Ce fichier Bicep configure Azure App Service en tant qu’application .NET 6. La ressource appServicePlan et la ressource appService sont toutes deux provisionnées à l’emplacement du groupe de ressources. La ressource appService est configurée pour utiliser la référence SKU S1, avec une capacité définie à 1. De plus, la ressource est configurée pour utiliser le sous-réseau vnetSubnetId et le protocole HTTPS. Elle configure également la clé d’instrumentation appInsightsInstrumentationKey, la chaîne de connexion appInsightsConnectionString et la chaîne de connexion storageConnectionString. Ces informations sont utilisées par l’application Panier.

L’extension Visual Studio Code pour Bicep mentionnée ci-dessus comprend un visualiseur. Tous ces fichiers Bicep sont visualisés de la façon suivante :

Orleans : Rendu du visualiseur de provisionnement Bicep pour l’exemple d’application Panier.

Résumé

Quand vous mettez à jour le code source et que vous effectuez un push des changements apportés à la branche main du dépôt, le workflow deploy.yml s’exécute. Il provisionne les ressources définies dans les fichiers Bicep et déploie l’application. Vous pouvez développer l’application pour inclure de nouvelles fonctionnalités, par exemple l’authentification, ou pour permettre la prise en charge de plusieurs instances de l’application. L’objectif principal de ce workflow est de démontrer la capacité à provisionner et déployer des ressources en une seule étape.

En plus du visualiseur de l’extension Bicep, la page du groupe de ressources du portail Azure ressemble à l’exemple suivant après le provisionnement et le déploiement de l’application :

Portail Azure : Ressources de l’exemple d’application Panier Orleans.

Voir aussi