Delen via


Implementeren Orleans in Azure Container Apps

In deze zelfstudie leert u hoe u een voorbeeld Orleans van een winkelwagentoepassing implementeert in Azure Container Apps. Deze zelfstudie breidt de functionaliteit van de voorbeeld-winkelwagen-app Orleansuit, die is geïntroduceerd in Implementeren Orleans in Azure App Service. De voorbeeld-app voegt B2C-verificatie (Business-to-Consumer) van Azure Active Directory (AAD) toe en implementeert deze in Azure Container Apps.

U leert hoe u implementeert met behulp van GitHub Actions, de .NET- en Azure CLIs en Azure Bicep. Daarnaast leert u hoe u het HTTP-inkomend verkeer van de container-app configureert.

In deze zelfstudie leert u het volgende:

  • Een Orleans toepassing implementeren in Azure Container Apps
  • Implementatie automatiseren met behulp van GitHub Actions en Azure Bicep
  • Inkomend HTTP-verkeer configureren

Vereisten

De app lokaal uitvoeren

Als u de app lokaal wilt uitvoeren, forkt u de Azure Samples: Orleans -winkelwagen in de Azure Container Apps-opslagplaats en kloont u deze naar uw lokale computer. Nadat de oplossing is gekloond, opent u de oplossing in een IDE van uw keuze. Als u Visual Studio gebruikt, klikt u met de rechtermuisknop op de Orleans. Het project ShoppingCart.Silo en selecteer Instellen als opstartproject en voer vervolgens de app uit. Anders kunt u de app uitvoeren met behulp van de volgende .NET CLI-opdracht:

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

Zie dotnet run voor meer informatie. Als de app wordt uitgevoerd, krijgt u een landingspagina te zien waarop de functionaliteit van de app wordt besproken. In de rechterbovenhoek ziet u een aanmeldingsknop. U kunt zich registreren voor een account of u aanmelden als u al een account hebt. Nadat u bent aangemeld, kunt u navigeren en kunt u de mogelijkheden testen. Alle functionaliteit van de app bij lokaal uitvoeren is afhankelijk van persistentie in het geheugen, lokale clustering en het Bogus NuGet-pakket om nepproducten te genereren. Stop de app door de optie Foutopsporing stoppen te selecteren in Visual Studio of door op Ctrl+C te drukken in de .NET CLI.

AAD B2C

Terwijl u leert dat de concepten van verificatie buiten het bereik van deze zelfstudie vallen, kunt u leren hoe u een Azure Active Directory B2C-tenant maakt en vervolgens een web-app registreren om deze te gebruiken. In het geval van deze voorbeeld-app voor winkelwagentjes moet de resulterende geïmplementeerde Container Apps-URL worden geregistreerd in de B2C-tenant. Zie ASP.NET Core Blazor-verificatie en -autorisatie voor meer informatie.

Belangrijk

Nadat uw Container App is geïmplementeerd, moet u de URL van de app registreren in de B2C-tenant. In de meeste productiescenario's hoeft u de URL van de app slechts eenmaal te registreren, omdat deze niet mag worden gewijzigd.

Zie het volgende diagram om te visualiseren hoe de app wordt geïsoleerd in de Azure Container Apps-omgeving:

Inkomend HTTP-verkeer van Azure Container Apps.

In het voorgaande diagram wordt al het binnenkomende verkeer naar de app doorgestuurd via een beveiligd HTTP-inkomend verkeer. De Azure Container Apps-omgeving bevat een app-exemplaar en het app-exemplaar bevat een ASP.NET Core host, die de Blazor Server- en Orleans app-functionaliteit beschikbaar maakt.

Implementeren in Azure Container Apps

Voor het implementeren van de app in Azure Container Apps maakt de opslagplaats gebruik van GitHub Actions. Voordat deze implementatie kan worden uitgevoerd, hebt u enkele Azure-resources nodig en moet u de GitHub-opslagplaats correct configureren.

Voordat u de app implementeert, moet u een Azure-resourcegroep maken (of u kunt ervoor kiezen om een bestaande resourcegroep te gebruiken). Gebruik een van de volgende artikelen om een nieuwe Azure-resourcegroep te maken:

Noteer de naam van de resourcegroep die u kiest. U hebt deze later nodig om de app te implementeren.

Een service-principal maken

Als u de implementatie van de app wilt automatiseren, moet u een service-principal maken. Dit is een Microsoft-account dat is gemachtigd om Azure-resources namens u te beheren.

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

De gemaakte JSON-referenties zien er ongeveer als volgt uit, maar met werkelijke waarden voor uw client, abonnement en tenant:

{
  "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"
}

Kopieer de uitvoer van de opdracht naar het Klembord en ga verder met de volgende stap.

Een GitHub-geheim maken

GitHub biedt een mechanisme voor het maken van versleutelde geheimen. De geheimen die u maakt, zijn beschikbaar voor gebruik in GitHub Actions werkstromen. U gaat zien hoe GitHub Actions kunnen worden gebruikt om de implementatie van de app te automatiseren, in combinatie met Azure Bicep. Bicep is een domeinspecifieke taal (DSL) die een declaratieve syntaxis gebruikt om Azure-resources te implementeren. Zie Wat is Bicep voor meer informatie. Met behulp van de uitvoer van de stap Een service-principal maken, moet u een GitHub-geheim maken met de naam AZURE_CREDENTIALS met de referenties in JSON-indeling.

Selecteer in de GitHub-opslagplaats Instellingen>Geheimen>Een nieuw geheim maken. Voer de naam AZURE_CREDENTIALS in en plak de JSON-referenties uit de vorige stap in het veld Waarde .

GitHub-opslagplaats: instellingengeheimen >

Zie GitHub: Versleutelde geheimen voor meer informatie.

Voorbereiden op Azure-implementatie

De app moet worden verpakt voor implementatie. In het Orleans.ShoppingCart.Silos project definiëren we een Target element dat na de Publish stap wordt uitgevoerd. Hiermee wordt de publicatiemap gezipt in een silo.zip-bestand :

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

Er zijn veel manieren om een .NET-app te implementeren in Azure Container Apps. In deze zelfstudie gebruikt u GitHub Actions, Azure Bicep en de .NET- en Azure CLIs. Overweeg het bestand ./github/workflows/deploy.yml in de hoofdmap van de GitHub-opslagplaats:

name: Deploy to Azure Container Apps

on:
  push:
    branches:
    - main

env:
  UNIQUE_APP_NAME: orleanscart
  SILO_IMAGE_NAME: orleanscart-silo
  AZURE_RESOURCE_GROUP_NAME: orleans-resourcegroup
  AZURE_RESOURCE_GROUP_LOCATION: eastus

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 ACR Bicep
      run: |
        az deployment group create \
          --resource-group ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
          --template-file '.github/workflows/flex/acr.bicep' \
          --parameters location=${{ env.AZURE_RESOURCE_GROUP_LOCATION }}

    - name: Get ACR Login Server
      run: |
        ACR_NAME=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} -n acr \
        --query properties.outputs.acrName.value | tr -d '"')
        echo "ACR_NAME=$ACR_NAME" >> $GITHUB_ENV
        ACR_LOGIN_SERVER=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} -n acr \
        --query properties.outputs.acrLoginServer.value | tr -d '"')
        echo "ACR_LOGIN_SERVER=$ACR_LOGIN_SERVER" >> $GITHUB_ENV

    - name: Prepare Docker buildx
      uses: docker/setup-buildx-action@v1

    - name: Login to ACR
      run: |
        access_token=$(az account get-access-token --query accessToken -o tsv)
        refresh_token=$(curl https://${{ env.ACR_LOGIN_SERVER }}/oauth2/exchange -v \
        -d "grant_type=access_token&service=${{ env.ACR_LOGIN_SERVER }}&access_token=$access_token" | jq -r .refresh_token)
        # The null GUID 0000... tells the container registry that this is an ACR refresh token during the login flow
        docker login -u 00000000-0000-0000-0000-000000000000 \
        --password-stdin ${{ env.ACR_LOGIN_SERVER }} <<< "$refresh_token"

    - name: Build and push Silo image to registry
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: ${{ env.ACR_LOGIN_SERVER }}/${{ env.SILO_IMAGE_NAME }}:${{ github.sha }}
        file: Silo/Dockerfile

    - name: Flex ACA 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 }} \
            acrName=${{ env.ACR_NAME }} \
            repositoryImage=${{ env.ACR_LOGIN_SERVER }}/${{ env.SILO_IMAGE_NAME }}:${{ github.sha }} \
          --debug

    - name: Get Container App URL
      run: |
        ACA_URL=$(az deployment group show -g ${{ env.AZURE_RESOURCE_GROUP_NAME }} \
        -n main --query properties.outputs.acaUrl.value | tr -d '"')
        echo $ACA_URL

    - name: Logout of Azure
      run: az logout

De voorgaande GitHub-werkstroom:

  • Publiceer de winkelwagen-app als een zip-bestand met behulp van de dotnet-publicatieopdracht .
  • Meld u aan bij Azure met de referenties uit de stap Een service-principal maken .
  • Evalueer het bestand acr.bicep en start een implementatiegroep met az deployment group create.
  • Haal de Azure Container Registry -aanmeldingsserver (ACR) op uit de implementatiegroep.
  • Meld u aan bij ACR met behulp van het geheim van de opslagplaatsen AZURE_CREDENTIALS .
  • Bouw en publiceer de silo-installatiekopieën naar de ACR.
  • Evalueer het bestand main.bicep en start een implementatiegroep met az deployment group create.
  • De silo implementeren
  • Afmelden bij Azure.

De werkstroom wordt geactiveerd door een push naar de hoofdbranch . Zie GitHub Actions en .NET voor meer informatie.

Tip

Als u problemen ondervindt bij het uitvoeren van de werkstroom, moet u mogelijk controleren of voor de service-principal alle vereiste providernaamruimten zijn geregistreerd. De volgende providernaamruimten zijn vereist:

  • Microsoft.App
  • Microsoft.ContainerRegistry
  • Microsoft.Insights
  • Microsoft.OperationalInsights
  • Microsoft.Storage

Zie Fouten voor de registratie van resourceproviders oplossen voor meer informatie.

Azure legt naamgevingsbeperkingen en -conventies op voor resources. U moet de waarden voor het bestand deploy.yml bijwerken voor het volgende:

  • UNIQUE_APP_NAME
  • SILO_IMAGE_NAME
  • AZURE_RESOURCE_GROUP_NAME
  • AZURE_RESOURCE_GROUP_LOCATION

Stel deze waarden in op uw unieke app-naam en de naam en locatie van uw Azure-resourcegroep.

Zie Naamgevingsregels en -beperkingen voor Azure-resources voor meer informatie.

De Bicep-sjablonen verkennen

Wanneer de az deployment group create opdracht wordt uitgevoerd, wordt een bepaalde bicep-bestandsreferentie geëvalueerd. Dit bestand bevat declaratieve informatie over de Azure-resources die u wilt implementeren. Een manier om aan deze stap te denken, is dat hiermee alle resources voor implementatie worden geïmplementeerd.

Belangrijk

Als u Visual Studio Code gebruikt, wordt de Bicep-ontwerpervaring verbeterd wanneer u de Bicep-extensie gebruikt.

Het eerste Bicep-bestand dat wordt geëvalueerd, is het bestand acr.bicep . Dit bestand bevat de resourcegegevens van de Azure Container Registry (ACR)-aanmeldingsserver:

param location string = resourceGroup().location

resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' = {
  name: toLower('${uniqueString(resourceGroup().id)}acr')
  location: location
  sku: {
    name: 'Basic'
  }
  properties: {
    adminUserEnabled: true
  }
}

output acrLoginServer string = acr.properties.loginServer
output acrName string = acr.name

Dit bicep-bestand voert de ACR-aanmeldingsserver en de bijbehorende naam uit. Het volgende Bicep-bestand dat is aangetroffen, bevat meer dan slechts één resource. Bekijk het bestand main.bicep dat voornamelijk bestaat uit delegeren module van definities:

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

resource acr 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = {
  name: acrName
}

module env 'environment.bicep' = {
  name: 'containerAppEnvironment'
  params: {
    location: location
    operationalInsightsName: '${appName}-logs'
    appInsightsName: '${appName}-insights'
  }
}

var envVars = [
  {
    name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
    value: env.outputs.appInsightsInstrumentationKey
  }
  {
    name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
    value: env.outputs.appInsightsConnectionString
  }
  {
    name: 'ORLEANS_AZURE_STORAGE_CONNECTION_STRING'
    value: storageModule.outputs.connectionString
  }
  {
    name: 'ASPNETCORE_FORWARDEDHEADERS_ENABLED'
    value: 'true'
  }
]

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

module siloModule 'container-app.bicep' = {
  name: 'orleansSiloModule'
  params: {
    appName: appName
    location: location
    containerAppEnvironmentId: env.outputs.id
    repositoryImage: repositoryImage
    registry: acr.properties.loginServer
    registryPassword: acr.listCredentials().passwords[0].value
    registryUsername: acr.listCredentials().username
    envVars: envVars
  }
}

output acaUrl string = siloModule.outputs.acaUrl

Het voorgaande Bicep-bestand:

  • Verwijst naar een existing ACR-resource. Zie Azure Bicep: bestaande resources voor meer informatie.
  • Definieert een module env die wordt gedelegeerd aan het definitiebestand environment.bicep .
  • Definieert een module storageModule die wordt gedelegeerd naar het definitiebestand storage.bicep .
  • Declareert verschillende gedeelde envVars die worden gebruikt door de silomodule.
  • Definieert een module siloModule die wordt gedelegeerd naar het definitiebestand container-app.bicep .
  • Voert de ACA-URL uit (deze kan mogelijk worden gebruikt om de omleidings-URI van een bestaande AAD B2C-app-registratie bij te werken).

Main.bicep delegeert naar verschillende andere Bicep-bestanden. De eerste is het bestand environment.bicep :

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'
    }
  }
}

resource env 'Microsoft.App/managedEnvironments@2022-03-01' = {
  name: '${resourceGroup().name}env'
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logs.properties.customerId
        sharedKey: logs.listKeys().primarySharedKey
      }
    }
  }
}

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

Dit bicep-bestand definieert de Azure Log Analytics- en Application Insights-resources. De appInsights resource is een web type en de logs resource is een PerGB2018 type. Zowel de appInsights resource als de logs resource worden ingericht op de locatie van de resourcegroep. De appInsights resource is gekoppeld aan de logs resource via de WorkspaceResourceId eigenschap . Er zijn drie uitvoer gedefinieerd in deze bicep, die later wordt gebruikt door container-apps module. Laten we nu eens kijken naar het bestand 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}'

Het voorgaande Bicep-bestand definieert het volgende:

  • Twee parameters voor de naam van de resourcegroep en de naam van de app.
  • De resource storage definitie voor het opslagaccount.
  • Eén die output de connection string voor het opslagaccount maakt.

Het laatste Bicep-bestand is het bestand container-app.bicep :

param appName string
param location string
param containerAppEnvironmentId string
param repositoryImage string = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
param envVars array = []
param registry string
param registryUsername string
@secure()
param registryPassword string

resource containerApp 'Microsoft.App/containerApps@2022-03-01' = {
  name: appName
  location: location
  properties: {
    managedEnvironmentId: containerAppEnvironmentId
    configuration: {
      activeRevisionsMode: 'multiple'
      secrets: [
        {
          name: 'container-registry-password'
          value: registryPassword
        }
      ]
      registries: [
        {
          server: registry
          username: registryUsername
          passwordSecretRef: 'container-registry-password'
        }
      ]
      ingress: {
        external: true
        targetPort: 80
      }
    }
    template: {
      revisionSuffix: uniqueString(repositoryImage, appName)
      containers: [
        {
          image: repositoryImage
          name: appName
          env: envVars
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 1
      }
    }
  }
}

output acaUrl string = containerApp.properties.configuration.ingress.fqdn

De eerder genoemde Visual Studio Code-extensie voor Bicep bevat een visualizer. Al deze Bicep-bestanden worden als volgt gevisualiseerd:

Orleans: Voorbeeld-app voor winkelwagen bicep inrichting visualizer rendering.

Samenvatting

Wanneer u de broncode en push wijzigingen in de main vertakking van de opslagplaats bijwerkt, wordt de deploy.yml-werkstroom uitgevoerd. Het richt de Azure-resources in die zijn gedefinieerd in de Bicep-bestanden en implementeert de toepassing. Revisies worden automatisch geregistreerd in uw Azure Container Registry.

Naast de visualizer van de Bicep-extensie ziet de pagina Azure Portal resourcegroep er ongeveer uit als in het volgende voorbeeld na het inrichten en implementeren van de toepassing:

Azure Portal: Orleans voorbeeldappresources voor winkelwagen voor Azure Container Apps.

Zie ook