Implementación de Orleans en Azure Container Apps
En este tutorial, aprenderá a implementar una aplicación de ejemplo de carro de la compra de Orleans en Azure Container Apps. En este tutorial se amplía la funcionalidad de la aplicación de ejemplo de carro de la compra de Orleans, introducida en Implementación de Orleans en Azure App Service. La aplicación de ejemplo agrega la autenticación de negocio a consumidor (B2C) de Azure Active Directory (AAD) y la implementa en Azure Container Apps.
Aprenderá a realiza la implementación con la funcionalidad Acciones de GitHub, las CLI de .NET y Azure y Azure Bicep. Además, aprenderá a configurar la entrada HTTP de la aplicación contenedora.
En este tutorial, aprenderá a:
- Implementación de una aplicación de Orleans en Azure Container Apps
- Automatización de la implementación mediante Acciones de GitHub y Azure Bicep
- Configurar la entrada HTTP.
Requisitos previos
- Una cuenta de GitHub
- Lea una introducción a Orleans.
- El SDK de .NET 6
- La CLI de Azure
- Un entorno de desarrollo integrado (IDE) de .NET
- No dude en usar Visual Studio o Visual Studio Code
Ejecución de la aplicación de forma local
Para ejecutar la aplicación localmente, bifurque el repositorio de Azure Samples: carro de la compra de Orleans en Azure Container Apps y clónelo en la máquina local. Una vez clonado, abra la solución en un IDE de su elección. Si usa Visual Studio, haga clic con el botón derecho en el proyecto Orleans.ShoppingCart.Silo y seleccione Establecer como proyecto de inicio y ejecute la aplicación. De lo contrario, puede ejecutar la aplicación mediante el siguiente comando de la CLI de .NET:
dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj
Para más información, vea Ejecución de dotnet. Con la aplicación en ejecución, se le presenta una página de aterrizaje que describe la funcionalidad de la aplicación. En la esquina superior derecha, verá un botón de inicio de sesión. Puede registrarse para obtener una cuenta o iniciar sesión si ya tiene una. Cuando haya iniciado sesión, puede recorrerla y probar sus funcionalidades libremente. Toda la funcionalidad de la aplicación cuando se ejecuta localmente se basa en la persistencia en memoria, la agrupación en clústeres locales y en el uso del paquete NuGet Bogus para generar productos falsos. Detenga la aplicación. Para ello, seleccione la opción Detener depuración en Visual Studio o presione Ctrl+C en la CLI de .NET.
AAD B2C
Aunque la enseñanza de los conceptos de autenticación está fuera del ámbito de este tutorial, puede aprender a crear un inquilino de Azure Active Directory B2C y, luego, puede registrar una aplicación web para consumirlo. En el caso de esta aplicación de ejemplo de carro de la compra, la dirección URL de Container Apps implementada resultante deberá registrarse en el inquilino de B2C. Para más información, consulte Autenticación y autorización de ASP.NET Core.
Importante
Una vez implementada la aplicación contenedora, deberá registrar la dirección URL de la aplicación en el inquilino de B2C. En la mayoría de los escenarios de producción, solo tendrá que registrar la dirección URL de la aplicación una vez, ya que lo normal es que no cambie.
Para ayudar a visualizar cómo la aplicación está aislada en el entorno de Azure Container Apps, consulte el diagrama siguiente:
En el diagrama anterior, todo el tráfico entrante a la aplicación se canaliza mediante una entrada HTTP segura. El entorno de Azure Container Apps contiene una instancia de aplicación y esta contiene un host de ASP.NET Core que expone la funcionalidad de la aplicación de Blazor Server y Orleans.
Implementación en Azure Container Apps
Para implementar la aplicación en Azure Container Apps, el repositorio usa Acciones de GitHub. Para poder realizar esta implementación, necesitará algunos recursos de Azure y deberá configurar correctamente el repositorio de GitHub.
Antes de implementar la aplicación, debe crear un grupo de recursos de Azure (o bien puede optar por usar uno existente). Para crear un nuevo grupo de recursos de Azure, use uno de los siguientes artículos:
Anote el nombre del grupo de recursos que elija, ya que lo necesitará más adelante para implementar la aplicación.
Creación de una entidad de servicio
Para automatizar la implementación de la aplicación, deberá crear una entidad de servicio. Se trata de una cuenta de Microsoft que tiene permiso para administrar los recursos de Azure en su nombre.
az ad sp create-for-rbac --sdk-auth --role Contributor \
--name "<display-name>" --scopes /subscriptions/<your-subscription-id>
Las credenciales JSON creadas tendrán un aspecto similar al siguiente, pero con valores reales para el cliente, la suscripción y el inquilino:
{
"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"
}
Copie el resultado del comando en el portapapeles y continúe con el paso siguiente.
Creación de un secreto de GitHub
GitHub proporciona un mecanismo para crear secretos cifrados. Los secretos que cree están disponibles para usarlos en flujos de trabajo de Acciones de GitHub. Verá cómo se pueden usar Acciones de GitHub para automatizar la implementación de la aplicación, junto con Azure Bicep.
Bicep es un lenguaje específico de dominio (DSL) que usa una sintaxis declarativa para implementar recursos de Azure. Para obtener más información, consulte ¿Qué es Bicep? Con el resultado del paso Crear una entidad de servicio, deberá crear un secreto de GitHub denominado AZURE_CREDENTIALS
con las credenciales con formato JSON.
En el repositorio de GitHub, seleccione Configuración>Secretos>Crear un nuevo secreto. Introduzca el nombre AZURE_CREDENTIALS
y pegue las credenciales JSON del paso anterior en el campo Valor.
Para más información, consulte GitHub: Secretos cifrados.
Preparación para la implementación de Azure
La aplicación tendrá que empaquetarse para la implementación. En el proyecto Orleans.ShoppingCart.Silos
, se define un elemento Target
que se ejecuta después del paso Publish
. Esto comprimirá el directorio publish en el archivo silo.zip:
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
Hay muchas maneras de implementar una aplicación .NET en Azure Container Apps. En este tutorial, se usarán Acciones de GitHub, Azure Bicep y las CLI de .NET y Azure. Considere el archivo ./github/workflows/deploy.yml en la raíz del repositorio de 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
El flujo de trabajo de GitHub anterior hará lo siguiente:
- Publicar la aplicación de carro de la compra como archivo ZIP mediante el comando dotnet publish.
- Iniciar sesión en Azure con las credenciales del paso Crear una entidad de servicio.
- Evalúe el archivo acr.bicep e inicie un grupo de implementación mediante az deployment group create.
- Obtenga el servidor de inicio de sesión de Azure Container Registry (ACR) del grupo de implementación.
- Inicie sesión en ACR mediante el secreto
AZURE_CREDENTIALS
de los de repositorios. - Compile y publique la imagen de silo en el ACR.
- Evaluar el archivo main.bicep e iniciar un grupo de implementación mediante az deployment group create.
- Implementación del silo
- Cierre sesión en Azure.
El flujo de trabajo se desencadena con una inserción en la rama main. Para más información, consulte Acciones de GitHub y .NET.
Sugerencia
Si tiene problemas al ejecutar el flujo de trabajo, es posible que tenga que comprobar que la entidad de servicio tiene registrados todos los espacios de nombres de proveedor necesarios. A continuación se detallan los espacio de nombres de proveedor necesarios:
Microsoft.App
Microsoft.ContainerRegistry
Microsoft.Insights
Microsoft.OperationalInsights
Microsoft.Storage
Para más información, consulte el artículo Resoluión de errores de registro del proveedor de recursos.
Azure impone restricciones de nomenclatura y convenciones para los recursos. Debe actualizar los valores del archivo deploy.yml para lo siguiente:
UNIQUE_APP_NAME
SILO_IMAGE_NAME
AZURE_RESOURCE_GROUP_NAME
AZURE_RESOURCE_GROUP_LOCATION
Establecer estos valores en el nombre de la aplicación único y el nombre y la ubicación del grupo de recursos de Azure.
Para más información, consulte Reglas y restricciones de nomenclatura para los recursos de Azure.
Exploración de las plantillas de Bicep
Cuando se ejecute el comando az deployment group create
, evaluará una referencia de archivo .bicep determinada. Este archivo contiene información declarativa que detalla los recursos de Azure que quiere implementar. Una manera de pensar en este paso es que aprovisiona todos los recursos para la implementación.
Importante
Si va a usar Visual Studio Code, la experiencia de creación de Bicep se mejora con la extensión de Bicep.
El primer archivo de Bicep que se evalúa es el archivo acr.bicep. Este archivo contiene los detalles del recurso de servidor de inicio de sesión de 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
Este archivo Bicep genera el servidor de inicio de sesión de ACR y el nombre correspondiente. El siguiente archivo de Bicep encontrado contiene más de un único objeto resource
. Considere el archivo main.bicep compuesto principalmente por definiciones de module
de delegación:
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
El archivo Bicep anterior:
- Hace referencia a un recurso de ACR
existing
. Para más información, consulte Recursos existentes en Azure Bicep. - Define un objeto
module env
que delega en el archivo de definición environment.bicep. - Define un objeto
module storageModule
que delega en el archivo de definición storage.bicep. - Declara varios objetos
envVars
compartidos que usa el módulo de silo. - Define un objeto
module siloModule
que delega en el archivo de definición de container-app.bicep. - Genera la dirección URL de ACA (esta podría usarse para actualizar un URI de redirección del registro de aplicación de AAD B2C existente).
El archivo main.bicep delega en otros archivos de Bicep. El primero es en el archivo 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
Este archivo de bicep define los recursos de Azure Log Analytics y Application Insights. El recurso appInsights
es un tipo web
y el recurso logs
es un tipo PerGB2018
. Tanto el recurso appInsights
como el recurso logs
se aprovisionan en la ubicación del grupo de recursos. El recurso appInsights
está vinculado al recurso logs
a través de la propiedad WorkspaceResourceId
. Hay tres resultados definidos en este Bicep, que más adelante usa el objeto module
de Container Apps. A continuación, echemos un vistazo al archivo 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}'
El archivo Bicep anterior define lo siguiente:
- Dos parámetros para el nombre del grupo de recursos y el nombre de la aplicación.
- La definición de
resource storage
de la cuenta de almacenamiento. - Un único objeto
output
que construye la cadena de conexión de la cuenta de almacenamiento.
El último archivo de Bicep es el archivo 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
La extensión de Visual Studio Code mencionada anteriormente para Bicep incluye un visualizador. Todos estos archivos Bicep se visualizan de la siguiente manera:
Resumen
A medida que actualice el código fuente y push
cambie a la rama main
del repositorio, se ejecutará el flujo de trabajo deploy.yml. Se aprovisionan los recursos de Azure definidos en los archivos de Bicep y se implementa la aplicación. Las revisiones se registran automáticamente en Azure Container Registry.
Además del visualizador de la extensión de Bicep, la página del grupo de recursos de Azure Portal tendría un aspecto similar al ejemplo siguiente después de aprovisionar e implementar la aplicación: