Wdrażanie w usłudze Orleans Azure Container Apps

Z tego samouczka dowiesz się, jak wdrożyć przykładową Orleans aplikację koszyka na zakupy w usłudze Azure Container Apps. Ten samouczek rozszerza funkcjonalność przykładowej Orleans aplikacji koszyka na zakupy wprowadzoną w artykule Wdrażanie Orleans w Azure App Service. Przykładowa aplikacja dodaje uwierzytelnianie do użytkownika (B2C) usługi Azure Active Directory (AAD) i wdraża je w usłudze Azure Container Apps.

Dowiesz się, jak wdrażać przy użyciu platformy GitHub Actions, interfejsów wiersza polecenia platformy .NET i platformy Azure oraz usługi Azure Bicep. Ponadto dowiesz się, jak skonfigurować ruch przychodzący HTTP aplikacji kontenera.

Ten samouczek zawiera informacje na temat wykonywania następujących czynności:

  • Wdrażanie aplikacji w Orleans usłudze Azure Container Apps
  • Automatyzowanie wdrażania przy użyciu GitHub Actions i usługi Azure Bicep
  • Konfigurowanie ruchu przychodzącego HTTP

Wymagania wstępne

Lokalne uruchamianie aplikacji

Aby uruchomić aplikację lokalnie, rozwidlenie przykładów platformy Azure: Orleans koszyka zakupów w repozytorium usługi Azure Container Apps i sklonuj ją na komputer lokalny. Po sklonowanym pliku otwórz rozwiązanie w wybranym środowisku IDE. Jeśli używasz programu Visual Studio, kliknij prawym przyciskiem myszy plik Orleans. Projekt ShoppingCart.Silo i wybierz pozycję Ustaw jako projekt startowy, a następnie uruchom aplikację. W przeciwnym razie możesz uruchomić aplikację przy użyciu następującego polecenia interfejsu wiersza polecenia platformy .NET:

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

Aby uzyskać więcej informacji, zobacz dotnet run. Po uruchomieniu aplikacji zostanie wyświetlona strona docelowa, na której omówiono funkcje aplikacji. W prawym górnym rogu zobaczysz przycisk logowania. Możesz utworzyć konto lub zalogować się, jeśli masz już konto. Po zalogowaniu możesz poruszać się po niej i możesz przetestować jego możliwości. Wszystkie funkcje aplikacji podczas uruchamiania lokalnie opierają się na trwałości w pamięci, klastrowaniu lokalnym i używa pakietu Bogus NuGet do generowania fałszywych produktów. Zatrzymaj aplikację, wybierając opcję Zatrzymaj debugowanie w programie Visual Studio lub naciskając klawisze Ctrl+C w interfejsie wiersza polecenia platformy .NET.

AAD B2C

Podczas nauki pojęć związanych z uwierzytelnianiem wykracza poza zakres tego samouczka, możesz dowiedzieć się, jak utworzyć dzierżawę usługi Azure Active Directory B2C, a następnie zarejestrować aplikację internetową , aby z niej korzystać. W przypadku tej przykładowej aplikacji koszyka zakupów wynikowy wdrożony adres URL usługi Container Apps będzie musiał zostać zarejestrowany w dzierżawie usługi B2C. Aby uzyskać więcej informacji, zobacz ASP.NET Core uwierzytelnianie i autoryzacja platformy Blazor.

Ważne

Po wdrożeniu aplikacji kontenera należy zarejestrować adres URL aplikacji w dzierżawie usługi B2C. W większości scenariuszy produkcyjnych wystarczy zarejestrować adres URL aplikacji tylko raz, ponieważ nie powinien się zmieniać.

Aby ułatwić wizualizację sposobu izolowania aplikacji w środowisku usługi Azure Container Apps, zobacz następujący diagram:

Ruch przychodzący HTTP usługi Azure Container Apps.

Na powyższym diagramie cały ruch przychodzący do aplikacji jest kierowany przez zabezpieczony ruch przychodzący HTTP. Środowisko usługi Azure Container Apps zawiera wystąpienie aplikacji, a wystąpienie aplikacji zawiera host ASP.NET Core, który uwidacznia funkcje serwera Blazor i Orleans aplikacji.

Wdrażanie w usłudze Azure Container Apps

Aby wdrożyć aplikację w usłudze Azure Container Apps, repozytorium korzysta z GitHub Actions. Przed wdrożeniem będzie potrzebnych kilka zasobów platformy Azure i należy poprawnie skonfigurować repozytorium GitHub.

Przed wdrożeniem aplikacji musisz utworzyć grupę zasobów platformy Azure (lub użyć istniejącej). Aby utworzyć nową grupę zasobów platformy Azure, użyj jednego z następujących artykułów:

Zanotuj wybraną nazwę grupy zasobów. Będzie ona potrzebna później, aby wdrożyć aplikację.

Tworzenie nazwy głównej usługi

Aby zautomatyzować wdrażanie aplikacji, należy utworzyć jednostkę usługi. Jest to konto Microsoft z uprawnieniami do zarządzania zasobami platformy Azure w Twoim imieniu.

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

Utworzone poświadczenia JSON będą wyglądać podobnie do następujących, ale z rzeczywistymi wartościami klienta, subskrypcji i dzierżawy:

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

Skopiuj dane wyjściowe polecenia do schowka i przejdź do następnego kroku.

Tworzenie wpisu tajnego usługi GitHub

Usługa GitHub udostępnia mechanizm tworzenia zaszyfrowanych wpisów tajnych. Utworzone wpisy tajne są dostępne do użycia w przepływach pracy GitHub Actions. Zobaczysz, jak można użyć GitHub Actions do zautomatyzowania wdrażania aplikacji w połączeniu z platformą Azure Bicep. Bicep to język specyficzny dla domeny (DSL), który używa składni deklaratywnej do wdrażania zasobów platformy Azure. Aby uzyskać więcej informacji, zobacz Co to jest Bicep. Korzystając z danych wyjściowych kroku Tworzenie jednostki usługi , należy utworzyć wpis tajny usługi GitHub o nazwie z AZURE_CREDENTIALS poświadczeniami w formacie JSON.

W repozytorium GitHub wybierz pozycję Ustawienia>Wpisy tajne>Utwórz nowy wpis tajny. Wprowadź nazwę AZURE_CREDENTIALS i wklej poświadczenia JSON z poprzedniego kroku w polu Wartość .

Repozytorium GitHub: wpisy tajne ustawień >

Aby uzyskać więcej informacji, zobacz GitHub: Zaszyfrowane wpisy tajne.

Przygotowanie do wdrożenia platformy Azure

Aplikacja musi zostać spakowana do wdrożenia. W projekcie Orleans.ShoppingCart.Silos definiujemy Target element uruchamiany po Publish kroku. Spowoduje to spakowanie katalogu publikowania w pliku silo.zip :

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

Istnieje wiele sposobów wdrażania aplikacji .NET w usłudze Azure Container Apps. W tym samouczku użyjesz GitHub Actions, usługi Azure Bicep oraz interfejsów wiersza polecenia platformy .NET i platformy Azure. Rozważ plik ./github/workflows/deploy.yml w katalogu głównym repozytorium GitHub:

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

Powyższy przepływ pracy usługi GitHub będzie:

  • Opublikuj aplikację koszyka zakupów jako plik zip przy użyciu polecenia dotnet publish .
  • Zaloguj się do platformy Azure przy użyciu poświadczeń z kroku Tworzenie jednostki usługi .
  • Oceń plik acr.bicep i uruchom grupę wdrożenia przy użyciu polecenia az deployment group create.
  • Pobierz serwer logowania Azure Container Registry (ACR) z grupy wdrażania.
  • Zaloguj się do usługi ACR przy użyciu wpisu tajnego repozytoriów AZURE_CREDENTIALS .
  • Skompiluj i opublikuj obraz silosu w usłudze ACR.
  • Oceń plik main.bicep i uruchom grupę wdrożenia przy użyciu polecenia az deployment group create.
  • Wdrażanie silosu
  • Wylogowywanie platformy Azure.

Przepływ pracy jest wyzwalany przez wypychanie do gałęzi głównej . Aby uzyskać więcej informacji, zobacz GitHub Actions i .NET.

Porada

Jeśli podczas uruchamiania przepływu pracy wystąpią problemy, może być konieczne sprawdzenie, czy jednostka usługi ma zarejestrowane wszystkie wymagane przestrzenie nazw dostawcy. Następujące przestrzenie nazw dostawcy są wymagane:

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

Aby uzyskać więcej informacji, zobacz Rozwiązywanie błędów dotyczących rejestracji dostawcy zasobów.

Platforma Azure nakłada ograniczenia i konwencje nazewnictwa zasobów. Należy zaktualizować wartości pliku deploy.yml dla następujących elementów:

  • UNIQUE_APP_NAME
  • SILO_IMAGE_NAME
  • AZURE_RESOURCE_GROUP_NAME
  • AZURE_RESOURCE_GROUP_LOCATION

Ustaw te wartości na unikatową nazwę aplikacji oraz nazwę i lokalizację grupy zasobów platformy Azure.

Aby uzyskać więcej informacji, zobacz Reguły nazewnictwa i ograniczenia dotyczące zasobów platformy Azure.

Eksplorowanie szablonów Bicep

Po uruchomieniu az deployment group create polecenia zostanie obliczone dane odwołanie do pliku bicep . Ten plik zawiera informacje deklaratywne, które zawierają szczegółowe informacje o zasobach platformy Azure, które chcesz wdrożyć. Jednym ze sposobów myślenia o tym kroku jest to, że aprowizuje wszystkie zasoby na potrzeby wdrożenia.

Ważne

Jeśli używasz Visual Studio Code, środowisko tworzenia Bicep zostanie ulepszone podczas korzystania z rozszerzenia Bicep.

Pierwszy oceniany plik Bicep to plik acr.bicep . Ten plik zawiera szczegóły zasobu serwera logowania Azure Container Registry (ACR):

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

Ten plik bicep zwraca serwer logowania usługi ACR i odpowiednią nazwę. Napotkany następny plik Bicep zawiera więcej niż tylko jeden plik resource. Rozważmy plik main.bicep składający się głównie z delegowania module definicji:

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

Powyższy plik Bicep:

  • existing Aby uzyskać więcej informacji, zobacz Azure Bicep: Existing resources (Dokumentacja usługi Azure Bicep: istniejące zasoby).
  • Definiuje element, który module env deleguje do pliku definicji environment.bicep .
  • Definiuje element, który module storageModule deleguje do pliku definicji storage.bicep .
  • Deklaruje kilka udostępnionych envVars elementów używanych przez moduł silosu.
  • Definiuje element, który module siloModule deleguje element do pliku definicji container-app.bicep .
  • Zwraca adres URL usługi ACA (może to być potencjalnie używane do aktualizowania identyfikatora URI przekierowania istniejącej rejestracji aplikacji usługi AAD B2C).

Main.bicep delegatów do kilku innych plików Bicep. Pierwszy to plik 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

Ten plik bicep definiuje zasoby usług Azure Log Analytics i Application Insights. Zasób appInsights jest typem web , a logs zasób jest typem PerGB2018 . appInsights Zarówno zasób, jak logs i zasób są aprowidowane w lokalizacji grupy zasobów. Zasób appInsights jest połączony z zasobem logsWorkspaceResourceId za pośrednictwem właściwości . W tym bicepie zdefiniowano trzy dane wyjściowe, które są później używane przez usługę Container Apps module. Następnie przyjrzyjmy się plikowi 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}'

Powyższy plik Bicep definiuje następujące elementy:

  • Dwa parametry nazwy grupy zasobów i nazwa aplikacji.
  • Definicja resource storage konta magazynu.
  • Pojedynczy element output tworzący parametry połączenia dla konta magazynu.

Ostatnim plikiem Bicep jest plik 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

Wyżej wymienione rozszerzenie Visual Studio Code dla Bicep zawiera wizualizator. Wszystkie te pliki Bicep są wizualizowane w następujący sposób:

Orleans: Przykładowa aplikacja koszyka zakupów Bicep provisioning visualizer rendering (Renderowanie wizualizatora aprowizacji koszyka na zakupy).

Podsumowanie

Po zaktualizowaniu kodu źródłowego i push zmianie main gałęzi repozytorium zostanie uruchomiony przepływ pracy deploy.yml . Aprowizuje ona zasoby platformy Azure zdefiniowane w plikach Bicep i wdraża aplikację. Poprawki są automatycznie rejestrowane w Azure Container Registry.

Oprócz wizualizatora z rozszerzenia Bicep strona grupy zasobów Azure Portal będzie wyglądać podobnie do poniższego przykładu po aprowizacji i wdrażaniu aplikacji:

Azure Portal: Orleans przykładowe zasoby aplikacji koszyka zakupów dla usługi Azure Container Apps.

Zobacz też