Implementar Orleans no Azure Container Apps
Neste tutorial, irá aprender a implementar uma aplicação de carrinho de compras de exemplo Orleans no Azure Container Apps. Este tutorial expande a funcionalidade da aplicação do carrinho de compras de exemploOrleans, introduzida em Implementar Orleans no Serviço de Aplicações do Azure. A aplicação de exemplo adiciona a autenticação empresa-consumidor (B2C) do Azure Active Directory (AAD) e implementa no Azure Container Apps.
Irá aprender a implementar com GitHub Actions, as CLIs do .NET e do Azure e o Azure Bicep. Além disso, irá aprender a configurar a entrada HTTP da Aplicação de Contentor.
Neste tutorial, ficará a saber como:
- Implementar uma aplicação no Orleans Azure Container Apps
- Automatizar a implementação com o GitHub Actions e o Azure Bicep
- Configurar a entrada HTTP
Pré-requisitos
- Uma conta do GitHub
- Ler uma introdução a Orleans
- O SDK .NET 6
- CLI do Azure
- Um ambiente de desenvolvimento integrado do .NET (IDE)
- Não se sinta à vontade para utilizar o Visual Studio ou o Visual Studio Code
Executar a aplicação localmente
Para executar a aplicação localmente, fork the Azure Samples: Orleans shopping cart on Azure Container Apps repository and clone it to your local machine. Depois de clonada, abra a solução num IDE à sua escolha. Se estiver a utilizar o Visual Studio, clique com o botão direito do rato em Orleans. ShoppingCart.Silo project e selecione Definir Como Projeto de Arranque e, em seguida, execute a aplicação. Caso contrário, pode executar a aplicação com o seguinte comando da CLI de .NET:
dotnet run --project Silo\Orleans.ShoppingCart.Silo.csproj
Para obter mais informações, consulte Executar dotnet. Com a aplicação em execução, é-lhe apresentada uma página de destino que discute a funcionalidade da aplicação. No canto superior direito, verá um botão de início de sessão. Pode inscrever-se numa conta ou iniciar sessão se já tiver uma conta. Depois de iniciar sessão, pode navegar e pode testar as respetivas capacidades. Todas as funcionalidades da aplicação ao executar localmente dependem da persistência dentro da memória, do clustering local e utiliza o pacote NuGet Bogus para gerar produtos falsos. Pare a aplicação selecionando a opção Parar Depuração no Visual Studio ou premindo Ctrl+C na CLI .NET.
AAD B2C
Embora o ensino dos conceitos de autenticação esteja fora do âmbito deste tutorial, pode aprender a Criar um inquilino do Azure Active Directory B2C e, em seguida, pode Registar uma aplicação Web para a consumir. No caso desta aplicação de exemplo de carrinho de compras, o URL do Container Apps implementado resultante terá de ser registado no inquilino B2C. Para obter mais informações, veja ASP.NET Core autenticação e autorização do Blazor.
Importante
Após a implementação da Aplicação de Contentor, terá de registar o URL da aplicação no inquilino B2C. Na maioria dos cenários de produção, só terá de registar o URL da aplicação uma vez, uma vez que não deve ser alterado.
Para ajudar a visualizar como a aplicação está isolada no ambiente do Azure Container Apps, veja o seguinte diagrama:
No diagrama anterior, todo o tráfego de entrada para a aplicação é canalizado através de uma entrada HTTP segura. O ambiente do Azure Container Apps contém uma instância de aplicação e a instância da aplicação contém um anfitrião ASP.NET Core, que expõe a funcionalidade do Servidor Blazor e Orleans da aplicação.
Implementar no Azure Container Apps
Para implementar a aplicação no Azure Container Apps, o repositório utiliza GitHub Actions. Antes de esta implementação poder ocorrer, precisará de alguns recursos do Azure e terá de configurar corretamente o repositório do GitHub.
Antes de implementar a aplicação, tem de criar um Grupo de Recursos do Azure (ou pode optar por utilizar um existente). Para criar um novo Grupo de Recursos do Azure, utilize um dos seguintes artigos:
Tome nota do nome do grupo de recursos que escolher, precisará dele mais tarde para implementar a aplicação.
Criar um principal de serviço
Para automatizar a implementação da aplicação, terá de criar um principal de serviço. Esta é uma conta Microsoft que tem permissão para gerir recursos do Azure em seu nome.
az ad sp create-for-rbac --sdk-auth --role Contributor \
--name "<display-name>" --scopes /subscriptions/<your-subscription-id>
As credenciais JSON criadas terão um aspeto semelhante ao seguinte, mas com valores reais para o seu cliente, subscrição e 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 a saída do comando para a área de transferência e avance para o passo seguinte.
Criar um segredo do GitHub
O GitHub fornece um mecanismo para criar segredos encriptados. Os segredos que criar estão disponíveis para utilização em fluxos de trabalho GitHub Actions. Verá como GitHub Actions podem ser utilizadas para automatizar a implementação da aplicação, em conjunto com o AzureBicep.
Bicep é uma linguagem específica do domínio (DSL) que utiliza uma sintaxe declarativa para implementar recursos do Azure. Para obter mais informações, veja O que é o Bicep. Com a saída do passo Criar um principal de serviço , terá de criar um segredo do GitHub com o nome AZURE_CREDENTIALS
com as credenciais formatadas em JSON.
No repositório do GitHub, selecione Definições Segredos>>Criar um novo segredo. Introduza o nome AZURE_CREDENTIALS
e cole as credenciais JSON do passo anterior no campo Valor .
Para obter mais informações, consulte GitHub: Segredos Encriptados.
Preparar a implementação do Azure
A aplicação terá de ser empacotada para implementação.
Orleans.ShoppingCart.Silos
No projeto, definimos um Target
elemento que é executado após o Publish
passo. Isto irá zipar o diretório de publicação num ficheiro desilo.zip :
<Target Name="ZipPublishOutput" AfterTargets="Publish">
<Delete Files="$(ProjectDir)\..\silo.zip" />
<ZipDirectory SourceDirectory="$(PublishDir)" DestinationFile="$(ProjectDir)\..\silo.zip" />
</Target>
Existem várias formas de implementar uma aplicação .NET no Azure Container Apps. Neste tutorial, vai utilizar GitHub Actions, o Azure Bicep e as CLIs do .NET e do Azure. Considere o ficheiro ./github/workflows/deploy.yml na raiz do repositório do 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
O fluxo de trabalho do GitHub anterior:
- Publique a aplicação do carrinho de compras como um ficheiro zip com o comando dotnet publish .
- Inicie sessão no Azure com as credenciais do passo Criar um principal de serviço .
- Avalie o ficheiro acr.bicep e inicie um grupo de implementação com az deployment group create.
- Obtenha o servidor de início de sessão do Azure Container Registry (ACR) a partir do grupo de implementação.
- Inicie sessão no ACR com o segredo dos repositórios
AZURE_CREDENTIALS
. - Crie e publique a imagem de silo no ACR.
- Avalie o ficheiro main.bicep e inicie um grupo de implementação com az deployment group create.
- Implementar o silo
- Fim de sessão do Azure.
O fluxo de trabalho é acionado por um push para o ramo principal . Para obter mais informações, veja GitHub Actions e .NET.
Dica
Se encontrar problemas ao executar o fluxo de trabalho, poderá ter de verificar se o principal de serviço tem todos os espaços de nomes de fornecedor necessários registados. São necessários os seguintes espaços de nomes de fornecedor:
Microsoft.App
Microsoft.ContainerRegistry
Microsoft.Insights
Microsoft.OperationalInsights
Microsoft.Storage
Para obter mais informações, veja Resolver erros de registo do fornecedor de recursos.
O Azure impõe restrições de nomenclatura e convenções para recursos. Tem de atualizar os valores de ficheiro deploy.yml para o seguinte:
UNIQUE_APP_NAME
SILO_IMAGE_NAME
AZURE_RESOURCE_GROUP_NAME
AZURE_RESOURCE_GROUP_LOCATION
Defina estes valores para o nome exclusivo da aplicação e o nome e localização do grupo de recursos do Azure.
Para obter mais informações, veja Regras de nomenclatura e restrições para recursos do Azure.
Explorar os modelos do Bicep
Quando o az deployment group create
comando é executado, avaliará uma determinada referência de ficheiro .bicep . Este ficheiro contém informações declarativas que detalham os recursos do Azure que pretende implementar. Uma forma de pensar neste passo é que aprovisiona todos os recursos para implementação.
Importante
Se estiver a utilizar o Visual Studio Code, a experiência de criação do Bicep é melhorada ao utilizar a Extensão bicep.
O primeiro ficheiro Bicep que é avaliado é o ficheiro acr.bicep . Este ficheiro contém os detalhes do recurso do servidor de início de sessão do 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 ficheiro bicep produz o servidor de início de sessão do ACR e o nome correspondente. O ficheiro Bicep seguinte encontrado contém mais do que apenas um único resource
. Considere o ficheiro main.bicep composto principalmente por delegar module
definições:
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
O ficheiro Bicep anterior:
- Referencia um
existing
recurso do ACR, para obter mais informações, veja Azure Bicep: Recursos existentes. - Define um
module env
que delega para o ficheiro de definição environment.bicep . - Define um
module storageModule
que delega para o ficheiro de definição storage.bicep . - Declara vários partilhados
envVars
que são utilizados pelo módulo silo. - Define um
module siloModule
que delega para o ficheiro de definição container-app.bicep . - Produz o URL da ACA (isto pode potencialmente ser utilizado para atualizar o URI de redirecionamento de uma aplicação B2C existente).
O main.bicep delega vários outros ficheiros Bicep. O primeiro é o ficheiro 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 ficheiro bicep define os recursos do Azure Log Analytics e do Application Insights. O appInsights
recurso é um web
tipo e o logs
recurso é um PerGB2018
tipo. Tanto o appInsights
recurso como o logs
recurso são aprovisionados na localização do grupo de recursos. O appInsights
recurso está ligado ao logs
recurso através da WorkspaceResourceId
propriedade . Existem três saídas definidas neste bíceps, utilizadas posteriormente pelas Container Apps module
. Em seguida, vamos ver o ficheiro 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}'
O ficheiro Bicep anterior define o seguinte:
- Dois parâmetros para o nome do grupo de recursos e o nome da aplicação.
- A
resource storage
definição da conta de armazenamento. - Um único
output
que constrói a cadeia de ligação para a conta de armazenamento.
O último ficheiro Bicep é o ficheiro 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
A extensão do Visual Studio Code para Bicep acima mencionada inclui um visualizador. Todos estes ficheiros Bicep são visualizados da seguinte forma:
Resumo
À medida que atualiza o código fonte e push
muda para o main
ramo do repositório, o fluxo de trabalho deploy.yml será executado. Aprovisiona os recursos do Azure definidos nos ficheiros bicep e implementa a aplicação. As revisões são registadas automaticamente no seu Azure Container Registry.
Além do visualizador da extensão bicep, a página portal do Azure grupo de recursos teria um aspeto semelhante ao seguinte exemplo após o aprovisionamento e implementação da aplicação: