Bereitstellen von Orleans in Azure Container Apps
In diesem Tutorial erfahren Sie, wie Sie eine Orleans-Beispielanwendung für einen Warenkorb in Azure Container Apps bereitstellen. In diesem Tutorial wird die Funktionalität der Orleans-Beispiel-Warenkorb-App erweitert, die unter Bereitstellen von Orleans in Azure App Service eingeführt wurde. Die Beispiel-App fügt die Azure Active Directory (AAD) B2C-Authentifizierung (Business-to-Consumer) hinzu und wird in Azure Container Apps bereitgestellt.
Sie erfahren, wie Sie die Bereitstellung mithilfe von GitHub Actions, den .NET und Azure CLIs sowie Azure Bicep durchführen. Darüber hinaus erfahren Sie, wie Sie den HTTP-Eingang der Container-App konfigurieren.
In diesem Tutorial lernen Sie Folgendes:
- Bereitstellen einer Orleans-Anwendung in Azure Container Apps
- Automatisieren der Bereitstellung mit GitHub Actions und Azure Bicep
- Konfigurieren des HTTP-Eingangs
Voraussetzungen
- Ein GitHub-Konto
- Lesen einer Einführung in Orleans
- Das .NET 6 SDK
- Die Azure CLI
- In .NET integrierte Entwicklungsumgebung (Integrated Development Environment, IDE)
- Sie können Visual Studio oder Visual Studio Code verwenden.
Lokales Ausführen der App
Um die App lokal auszuführen, forken Sie das Repository Azure-Beispiele: Orleans-Warenkorb in Azure Container Apps, und klonen Sie es auf Ihren lokalen Computer. Öffnen Sie die Projektmappe nach dem Klonen in einer IDE Ihrer Wahl. Wenn Sie Visual Studio verwenden, klicken Sie mit der rechten Maustaste auf das Projekt Orleans.ShoppingCart.Silo, und wählen Sie Als Startprojekt festlegen aus. Führen Sie dann die App aus. Andernfalls können Sie die App mit dem folgenden .NET CLI-Befehl ausführen:
dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj
Weitere Informationen finden Sie unter dotnet run. Bei Ausführung der App wird ihnen eine Landing Page angezeigt, auf der die Funktionalität der App erläutert wird. In der oberen rechten Ecke wird eine Anmeldeschaltfläche angezeigt. Sie können sich für ein Konto registrieren bzw. sich anmelden, wenn Sie bereits über ein Konto verfügen. Nach der Anmeldung können Sie die App erkunden und die Funktionen ausprobieren. Bei lokaler Ausführung basiert die gesamte Funktionalität der App auf In-Memory-Persistenz und lokalem Clustering. Zum Generieren von Pseudoprodukten wird das Bogus NuGet-Paket verwendet. Beenden Sie die App durch Auswählen der Option Debuggen beenden in Visual Studio oder durch Drücken von STRG+C in der .NET CLI.
AAD B2C
Die Erläuterung der Authentifizierungskonzepte würde den Rahmen dieses Tutorials übersteigen, aber Sie erfahren mehr über das Erstellen eines Azure Active Directory B2C-Mandanten und können dann eine Web-App registrieren, um ihn zu nutzen. Im Fall dieser Warenkorb-Beispiel-App muss die resultierende bereitgestellte Container Apps-URL im B2C-Mandanten registriert werden. Weitere Informationen hierzu finden Sie unter ASP.NET Core-Blazor-Authentifizierung und -Autorisierung.
Wichtig
Nachdem Ihre Container-App bereitgestellt wurde, müssen Sie die App-URL im B2C-Mandanten registrieren. In den meisten Produktionsszenarien müssen Sie die URL der App nur einmal registrieren, da sie sich nicht ändern sollte.
Sehen Sie sich das folgende Diagramm an, in dem veranschaulicht wird, wie die App innerhalb der Azure Container Apps-Umgebung isoliert ist:
Im obigen Diagramm wird der gesamte eingehende Datenverkehr an die App über einen gesicherten HTTP-Eingang weitergeleitet. Die Azure Container Apps-Umgebung enthält eine App-Instanz, und die App-Instanz enthält einen ASP.NET Core-Host, der die Blazor Server- und Orleans-App-Funktionalität verfügbar macht.
Bereitstellen von Azure Container Apps
Um die App in Azure Container Apps bereitzustellen, verwendet das Repository GitHub Actions. Bevor diese Bereitstellung erfolgen kann, benötigen Sie einige Azure-Ressourcen, und Sie müssen das GitHub-Repository ordnungsgemäß konfigurieren.
Vor der Bereitstellung der App müssen Sie eine Azure-Ressourcengruppe erstellen (oder sie können eine vorhandene verwenden). Verwenden Sie einen der folgenden Artikel, um eine neue Azure-Ressourcengruppe zu erstellen:
Notieren Sie sich den von Ihnen ausgewählten Ressourcengruppennamen. Sie benötigen ihn später, um die App bereitzustellen.
Erstellen eines Dienstprinzipals
Um die Bereitstellung der App zu automatisieren, müssen Sie einen Dienstprinzipal erstellen. Hierbei handelt es sich um ein Microsoft-Konto, das über die Berechtigung zum Verwalten von Azure-Ressourcen in Ihrem Namen verfügt.
az ad sp create-for-rbac --sdk-auth --role Contributor \
--name "<display-name>" --scopes /subscriptions/<your-subscription-id>
Die erstellten JSON-Anmeldeinformationen sehen in etwa wie folgt aus, enthalten jedoch die tatsächlichen Werten für Ihren Client, Ihr Abonnement und Ihren Mandanten:
{
"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"
}
Kopieren Sie die Ausgabe des Befehls in die Zwischenablage, und fahren Sie mit dem nächsten Schritt fort.
Erstellen eines GitHub-Geheimnisses.
GitHub bietet einen Mechanismus zum Erstellen verschlüsselter Geheimnisse. Die von Ihnen erstellten Geheimnisse können in GitHub Actions-Workflows verwendet werden. Es wird gezeigt, wie die Bereitstellung der App mithilfe von GitHub Actions in Verbindung mit Azure Bicep automatisiert werden kann.
Bicep ist eine domänenspezifische Sprache (Domain-Specific Language, DSL), die eine deklarative Syntax zur Bereitstellung von Azure-Ressourcen verwendet. Weitere Informationen finden Sie unter Was ist Bicep? Mithilfe der Ausgabe aus dem Schritt Erstellen eines Dienstprinzipals müssen Sie ein GitHub-Geheimnis namens AZURE_CREDENTIALS
mit den JSON-formatierten Anmeldeinformationen erstellen.
Wählen Sie im GitHub-Repository Einstellungen>Geheimnisse>Neues Geheimnis erstellen aus. Geben Sie den Namen AZURE_CREDENTIALS
ein, und fügen Sie die JSON-Anmeldeinformationen aus dem vorherigen Schritt in das Feld Wert ein.
Weitere Informationen finden Sie unter GitHub: Verschlüsselte Geheimnisse.
Vorbereiten der Azure-Bereitstellung
Die App muss für die Bereitstellung gepackt werden. Im Projekt Orleans.ShoppingCart.Silos
definieren wir ein Target
-Element, das nach dem Publish
-Schritt ausgeführt wird. Dadurch wird das Veröffentlichungsverzeichnis in einer Datei silo.zip komprimiert:
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
Es gibt viele Möglichkeiten, eine .NET-App in Azure Container Apps bereitzustellen. In diesem Tutorial verwenden Sie GitHub Actions, Azure Bicep sowie die .NET und die Azure CLI. Betrachten Sie die Datei ./github/workflows/deploy.yml im Stammverzeichnis des GitHub-Repositorys:
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
Der vorherige GitHub-Workflow führt Folgendes aus:
- Veröffentlichen der Warenkorb-App mit dem Befehl dotnet publish als ZIP-Datei
- Anmelden bei Azure mit den Anmeldeinformationen aus dem Schritt Erstellen eines Dienstprinzipals
- Auswerten der Datei acr.bicep und Starten einer Bereitstellungsgruppe mit az deployment group create
- Abrufen des ACR-Anmeldeservers (Azure Container Registry) aus der Bereitstellungsgruppe
- Anmelden bei ACR mit dem Repositorygeheimnis
AZURE_CREDENTIALS
- Erstellen und Veröffentlichen des Siloimage in ACR
- Auswerten der Datei main.bicep und Starten einer Bereitstellungsgruppe mit az deployment group create
- Bereitstellen des Silos
- Abmelden von Azure
Der Workflow wird durch einen Push an den Mainbranch ausgelöst. Weitere Informationen finden Sie unter GitHub Actions und .NET.
Tipp
Wenn beim Ausführen des Workflows Probleme auftreten, müssen Sie möglicherweise überprüfen, ob für den Dienstprinzipal alle erforderlichen Anbieternamespaces registriert sind. Die folgenden Anbieternamespaces sind erforderlich:
Microsoft.App
Microsoft.ContainerRegistry
Microsoft.Insights
Microsoft.OperationalInsights
Microsoft.Storage
Weitere Informationen finden Sie unter Beheben von Fehlern bei der Registrierung von Ressourcenanbietern.
Azure erzwingt Namenseinschränkungen und -konventionen für Ressourcen. Sie müssen die Werte der Datei deploy.yml folgendermaßen aktualisieren:
UNIQUE_APP_NAME
SILO_IMAGE_NAME
AZURE_RESOURCE_GROUP_NAME
AZURE_RESOURCE_GROUP_LOCATION
Legen Sie diese Werte auf Ihren eindeutigen App-Namen und Ihren Azure-Ressourcengruppennamen und -standort fest.
Weitere Informationen finden Sie unter Benennungsregeln und -einschränkungen für Azure-Ressourcen.
Erkunden der Bicep-Vorlagen
Bei Ausführung des Befehls az deployment group create
wird ein bestimmter .bicep-Dateiverweis ausgewertet. Diese Datei enthält deklarative Informationen zu den Azure-Ressourcen, die Sie bereitstellen möchten. Diesen Schritt kann man sich beispielsweise so vorstellen, dass darin alle Ressourcen für die Bereitstellung bereitgestellt werden.
Wichtig
Wenn Sie Visual Studio Code verwenden, wird die Bicep-Erstellung durch die Bicep-Erweiterung verbessert.
Als erste Bicep-Datei wird die Datei acr.bicep ausgewertet. Diese Datei enthält die Ressourcendetails des ACR-Anmeldeservers (Azure Container Registry):
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
Diese Bicep-Datei gibt den ACR-Anmeldeserver und den entsprechenden Namen aus. Die nächste gefundene Bicep-Datei enthält mehr als nur eine einzelne resource
. Betrachten Sie die Datei main.bicep, die hauptsächlich aus delegierenden module
-Definitionen besteht:
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
Die vorherige Bicep-Datei:
- Verweist auf eine
existing
-ACR-Ressource. Weitere Informationen finden Sie unter Azure Bicep: Vorhandene Ressourcen. - Definiert eine
module env
, die an die Definitionsdatei environment.bicep delegiert. - Definiert ein
module storageModule
, das an die Definitionsdatei storage.bicep delegiert. - Deklariert mehrere freigegebene
envVars
, die vom Silomodul verwendet werden. - Definiert ein
module siloModule
, das an die Definitionsdatei container-app.bicep delegiert. - Gibt die ACA-URL aus. (Diese kann möglicherweise verwendet werden, um den Umleitungs-URI einer vorhandenen AAD B2C-App-Registrierung zu aktualisieren.)
Die Datei main.bicep delegiert an mehrere andere Bicep-Dateien. Die erste ist die Datei 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
Diese Bicep-Datei definiert die Azure Log Analytics- und Application Insights-Ressourcen. Die appInsights
-Ressource ist ein web
-Typ, und die logs
-Ressource ist ein PerGB2018
-Typ. Sowohl die appInsights
-Ressource als auch die logs
-Ressource werden am Standort der Ressourcengruppe bereitgestellt. Die appInsights
-Ressource ist über die WorkspaceResourceId
-Eigenschaft mit der logs
-Ressource verknüpft. In dieser Bicep-Datei sind drei Ausgaben definiert, die später vom Container Apps-module
verwendet werden. Als Nächstes sehen wir uns die Datei storage.bicep an:
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}'
Die vorangehende Bicep-Datei definiert Folgendes:
- Zwei Parameter für den Ressourcengruppennamen und den App-Namen.
- Die
resource storage
-Definition für das Speicherkonto. - Ein einzelnes
output
-Element, das die Verbindungszeichenfolge für das Speicherkonto erstellt.
Die letzte Bicep-Datei ist die Datei 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
Die oben genannte Visual Studio Code-Erweiterung für Bicep enthält eine Schnellansicht. All diese Bicep-Dateien werden wie folgt visualisiert:
Zusammenfassung
Wenn Sie den Quellcode aktualisieren und Änderungen per push
an den main
-Branch des Repositorys übertragen, wird der Deploy.yml-Workflow ausgeführt. Er stellt die in den Bicep-Dateien definierten Azure-Ressourcen und dann die Anwendung bereit. Revisionen werden automatisch in Ihrer Azure Container Registry-Instanz registriert.
Zusätzlich zur Schnellansicht der Bicep-Erweiterung sieht die Seite der Ressourcengruppe im Azure-Portal nach dem Bereitstellen der Anwendung in etwa wie folgendermaßen aus: