Implantando e dimensionando um aplicativo ASP.NET Core nos Aplicativos de Contêiner do Azure

Os aplicativos implantados no Azure que experimentam alta demanda intermitente se beneficiam da escalabilidade para atender à demanda. Os aplicativos escalonáveis podem ser dimensionados para garantir a capacidade durante os picos de carga de trabalho e, em seguida, reduzir automaticamente quando o pico cai, o que pode reduzir os custos. O dimensionamento horizontal (escalar horizontalmente) significa adicionar novas instâncias de um recurso, como VMs ou réplicas de banco de dados. Este artigo demonstra como implantar um aplicativo ASP.NET Core horizontalmente escalonável para aplicativos de contêiner do Azure com a conclusão das seguintes tarefas:

  1. Configurar o projeto de exemplo
  2. Implantar o aplicativo nos Aplicativos de Contêiner do Azure
  3. Dimensionar e solucionar problemas do aplicativo
  4. Criar os serviços do Azure
  5. Conectar os serviços do Azure
  6. Configurar e reimplantar o aplicativo

Este artigo usa Razor Pages, mas a maior parte se aplica a outros aplicativos do ASP.NET Core.

Em alguns casos, os aplicativos básicos do ASP.NET Core são capazes de dimensionar sem considerações especiais. No entanto, aplicativos que utilizam determinados recursos de estrutura ou padrões de arquitetura exigem configurações extras, incluindo o seguinte:

  • envios de formulário seguro: Razor Pages, aplicativos MVC e API Web geralmente dependem de envios de formulário. Por padrão, esses aplicativos usam tokens de falsificação entre sites e serviços internos de proteção de dados para proteger solicitações. Quando implantados na nuvem, esses aplicativos precisam ser configurados para gerenciar as preocupações do serviço de proteção de dados em um local seguro e centralizado.

  • Circuitos SignalR: os aplicativos Blazor Server exigem o uso de um serviço do Azure SignalR centralizado para dimensionar com segurança. Esses serviços também utilizam os serviços de proteção de dados mencionados anteriormente.

  • Cache centralizado ou os serviços de gerenciamento de estado: aplicativos escalonáveis podem usar Cache do Azure para Redis a fim de fornecer cache distribuído. O Armazenamento do Azure pode ser necessário para armazenar o estado de estruturas como Microsoft Orleans, que pode ajudar a escrever aplicativos que gerenciam o estado em várias instâncias de aplicativo diferentes.

As etapas neste artigo demonstram como resolver corretamente as preocupações anteriores implantando um aplicativo escalonável nos Aplicativos de Contêiner do Azure. A maioria dos conceitos neste tutorial também se aplica ao dimensionamento de instâncias do Serviço de Aplicativo do Azure.

Configurar o projeto de exemplo

Use o aplicativo de exemplo do GitHub Explorer para acompanhar este tutorial. Clone o aplicativo do GitHub usando o seguinte comando:

git clone "https://github.com/dotnet/AspNetCore.Docs.Samples.git"

Navegue até a pasta /tutorials/scalable-razor-apps/start e abra ScalableRazor.csproj.

O aplicativo de exemplo usa um formulário de pesquisa para procurar repositórios do GitHub pelo nome. O formulário depende dos serviços internos de proteção de dados do ASP.NET Core para lidar com preocupações antifalsificação. Por padrão, quando o aplicativo é dimensionado horizontalmente nos Aplicativos de Contêiner, o serviço de proteção de dados gera uma exceção.

Testar o aplicativo

  1. Inicie o aplicativo no Visual Studio. O projeto inclui um arquivo do Docker, o que significa que a seta ao lado do botão de execução pode ser selecionada para iniciar o aplicativo usando uma configuração do Docker Desktop ou o servidor Web local do ASP.NET Core padrão.

Use o formulário de pesquisa para procurar repositórios do GitHub pelo nome.

A screenshot showing the GitHub Explorer app.

Implantar o aplicativo nos Aplicativos de Contêiner do Azure

O Visual Studio é usado para implantar o aplicativo nos Aplicativos de Contêiner do Azure. Os aplicativos de contêiner fornecem um serviço gerenciado projetado para simplificar a hospedagem de aplicativos e microsserviços em contêineres.

Observação

Muitos dos recursos criados para o aplicativo exigem um local. Para este aplicativo, a localização não é importante. Um aplicativo real deve selecionar um local mais próximo dos clientes. Talvez você queira selecionar um local próximo a você.

  1. No gerenciador de soluções do Visual Studio, clique com o botão direito do mouse no nó do projeto de nível superior e selecione Publicar.

  2. Na caixa de diálogo de publicação, selecione Azure como destino de implantação e selecione Avançar.

  3. Para o destino específico, selecione Aplicativos de Contêiner do Azure (Linux) e, em seguida, Avançar.

  4. Crie um aplicativo de contêiner no qual implantar. Selecione o ícone verde + para abrir uma nova caixa de diálogo e insira os seguintes valores:

    A screenshot showing Visual Studio deployment.

    • Nome do aplicativo de contêiner: deixe o valor padrão ou insira um nome.
    • Nome da assinatura: selecione a assinatura na qual implantar.
    • Grupo de recursos: selecione Novo e crie um grupo de recursos chamado msdocs-scalable-razor.
    • Ambiente de aplicativos de contêiner: selecione Novo para abrir a caixa de diálogo do ambiente de aplicativos de contêiner e insira os seguintes valores:
      • Nome do ambiente: mantenha o valor padrão.
      • Local: selecione um local próximo de você.
      • Workspace do Azure Log Analytics: selecione Novo para abrir a caixa de diálogo do workspace do Log Analytics.
        • Nome: deixe o valor padrão.
        • Local: selecione um local perto de você e, em seguida, Ok para fechar a caixa de diálogo.
      • Selecione Ok para fechar a caixa de diálogo do ambiente de aplicativos de contêiner.
    • Selecione Criar para fechar a caixa de diálogo de aplicativos de contêiner original. O Visual Studio cria o recurso de aplicativo de contêiner no Azure.
  5. Após o recurso ser criado, verifique se ele está selecionado na lista de aplicativos de contêiner e selecione Avançar.

  6. Você precisará criar um Registro de Contêiner do Azure para armazenar o artefato de imagem publicado para seu aplicativo. Selecione o ícone + verde na tela do registro de contêiner.

    A screenshot showing how to create a new container registry.

  7. Deixe os valores padrão e selecione Criar.

    A screenshot showing the values for a new container registry.

  8. Depois que o registro de contêiner for criado, verifique se ele está selecionado e, em seguida, selecione Concluir para fechar o fluxo de trabalho da caixa de diálogo e exibir um resumo do perfil de publicação.

    Se o Visual Studio solicitar que você habilite o usuário Administrador para acessar o contêiner do Docker publicado, selecione Sim.

  9. Selecione Publicar na parte superior direita do resumo do perfil de publicação para implantar o aplicativo no Azure.

Quando a implantação for concluída, o Visual Studio iniciará o navegador para exibir o aplicativo hospedado. Pesquise Microsoft no campo de formulário e uma lista de repositórios será exibida.

Dimensionar e solucionar problemas do aplicativo

No momento, o aplicativo está funcionando sem problemas, mas gostaríamos de dimensionar o aplicativo para mais instâncias em antecipação a grandes volumes de tráfego.

  1. No portal do Azure, pesquise o aplicativo de contêiner razorscaling-app-**** na barra de pesquisa de nível superior e selecione-o nos resultados.
  2. Na página de visão geral, selecione Dimensionar na navegação à esquerda e selecione + Editar e implantar.
  3. Na página de revisões, alterne para a guia Dimensionar.
  4. Defina as instâncias mínima e máxima como 4 e selecione Criar. Essa alteração de configuração garante que seu aplicativo seja dimensionado horizontalmente em quatro instâncias.

Navegue de volta para o aplicativo. Quando a página é carregada, a princípio aparece que tudo está funcionando corretamente. No entanto, quando um termo de pesquisa é inserido e enviado, pode ocorrer um erro. Se um erro não for exibido, envie o formulário várias vezes.

Solução de problemas do erro

Não é imediatamente evidente por que as solicitações de pesquisa estão falhando. As ferramentas do navegador indicam que uma resposta 400 Solicitação Inválida foi enviada de volta. No entanto, você pode usar os recursos de registro em log dos aplicativos de contêiner para diagnosticar erros que ocorrem em seu ambiente.

  1. Na página de visão geral do aplicativo de contêiner, selecione Logs na navegação à esquerda.

  2. Na página Logs, feche o pop-up que é aberto e navegue até a guia Tabelas.

  3. Expanda o item Logs Personalizados para revelar o nó ContainerAppConsoleLogs_CL. Esta tabela contém vários logs para o aplicativo de contêiner que podem ser consultados a fim de solucionar problemas.

    A screenshot showing the container app logs.

  4. No editor de consultas, redija uma consulta básica para pesquisar a tabela Logs ContainerAppConsoleLogs_CL em busca de exceções recentes, como o seguinte script:

    ContainerAppConsoleLogs_CL
    | where Log_s contains "exception"
    | sort by TimeGenerated desc
    | limit 500
    | project ContainerAppName_s, Log_s
    

    A consulta anterior pesquisa a tabela ContainerAppConsoleLogs_CL em busca de linhas que contenham a exceção de palavra. Os resultados são ordenados pelo tempo gerado, limitado a 500 resultados, e incluem apenas as colunas ContainerAppName_s e Log_s para facilitar a leitura dos resultados.

  5. Selecione Executar; uma lista de resultados é exibida. Leia os logs e observe que a maioria deles está relacionada a tokens antifalsificação e criptografia.

    A screenshot showing the logs query.

    Importante

    Os erros no aplicativo são causados pelos serviços de proteção de dados do .NET. Quando várias instâncias do aplicativo estão em execução, não há garantia de que a solicitação HTTP POST para enviar o formulário seja roteada para o mesmo contêiner que inicialmente carregou a página da solicitação HTTP GET. Se as solicitações forem tratadas por instâncias diferentes, os tokens antifalsificação não serão tratados corretamente e ocorrerá uma exceção.

    Nas etapas a seguir, esse problema é resolvido com a centralização das chaves de proteção de dados em um serviço de armazenamento do Azure e sua proteção com o Key Vault.

Criar os serviços do Azure

Para resolver os erros anteriores, os seguintes serviços são criados e conectados ao aplicativo:

  • Conta de Armazenamento do Azure: trata do armazenamento de dados nos Serviços de Proteção de Dados. Fornece um local centralizado para armazenar dados de chave conforme o aplicativo é dimensionado. As contas de armazenamento também podem ser usadas para armazenar documentos, dados de fila, compartilhamentos de arquivos e quase qualquer tipo de dados de blob.
  • Azure KeyVault: esse serviço armazena segredos de um aplicativo e é usado para ajudar a gerenciar questões de criptografia dos Serviços de Proteção de Dados.

Criar o serviço de conta de armazenamento

  1. Na barra de pesquisa do portal do Azure, insira Storage accounts e selecione o resultado correspondente.
  2. Na página de listagem Contas de Armazenamento, selecione + Criar.
  3. Na guia Informações Básicas, insira os seguintes valores:
    • Assinatura: selecione a mesma assinatura escolhida para o aplicativo de contêiner.
    • Grupo de Recursos: selecione o grupo de recursos msdocs-scalable-razor criado anteriormente.
    • Nome da conta de armazenamento: nomeie a conta scalablerazorstorageXXXX, em que os X são números aleatórios de sua escolha. Esse nome precisa ser exclusivo em todo o Azure.
    • Região: selecione a mesma região selecionada anteriormente.
  4. Deixe o restante dos valores em seu padrão e selecione Examinar. Depois que o Azure validar as entradas, selecione Criar.

O Azure provisiona a nova conta de armazenamento. Quando a tarefa for concluída, escolha Ir para o recurso a fim de exibir o novo serviço.

Criar o contêiner de armazenamento

Crie um contêiner para armazenar as chaves de proteção de dados do aplicativo.

  1. Na página de visão geral da nova conta de armazenamento, selecione Navegador de armazenamento à esquerda.
  2. Selecione Contêineres de Blob.
  3. Selecione + Adicionar contêiner para abrir o submenu Novo contêiner.
  4. Insira um nome de scalablerazorkeys, deixe o restante das configurações em seus padrões e selecione Criar.

Os novos contêineres aparecem na lista de páginas.

Criar o serviço do cofre de chaves

Crie um cofre de chaves para armazenar as chaves que protegem os dados no contêiner de armazenamento de blobs.

  1. Na barra de pesquisa do portal do Azure, insira Key Vault e selecione o resultado correspondente.
  2. Na página de listagem do cofre de chaves, selecione + Criar.
  3. Na guia Informações Básicas, insira os seguintes valores:
    • Assinatura: selecione a mesma assinatura que foi selecionada anteriormente.
    • Grupo de Recursos: selecione o grupo de recursos msdocs-scalable-razor criado anteriormente.
    • Nome do Key Vault: insira o nome scalablerazorvaultXXXX.
    • Região: selecione uma região próxima à sua localização.
  4. Deixe o restante das configurações com os padrões e selecione Examinar + criar. Aguarde até que o Azure valide suas configurações e selecione Criar.

O Azure provisiona o novo cofre de chaves. Quando a tarefa for concluída, escolha Ir para o recurso a fim de exibir o novo serviço.

Criar a chave

Crie uma chave secreta para proteger os dados na conta de armazenamento de blobs.

  1. Na página de visão geral principal do cofre de chaves, selecione Chaves na navegação à esquerda.
  2. Na página Criar uma chave, selecione + Gerar/Importar para abrir o submenu Criar uma chave.
  3. Insira razorkey no campo Nome. Deixe o restante das configurações em seus valores padrão e selecione Criar. Uma nova chave aparece na página da lista de chaves.

Conectar os Serviços do Azure

O Aplicativo de Contêiner requer uma conexão segura com a conta de armazenamento e os serviços do cofre de chaves para resolver os erros de proteção de dados e dimensionar corretamente. Os novos serviços são conectados juntos por meio das seguintes etapas:

Importante

As atribuições de função de segurança por meio do Conector de Serviço e outras ferramentas normalmente levam um minuto ou dois para serem propagadas e, em alguns casos raros, podem levar até oito minutos.

Conectar a conta de armazenamento

  1. No portal do Azure, navegue até a página de visão geral do Aplicativo de Contêiner.
  2. À esquerda, selecione Conector de serviço
  3. Na página Conector de Serviço, escolha + Criar para abrir o painel de submenu Conexão de Criação e insira os seguintes valores:
    • contêiner: selecione o Aplicativo de Contêiner criado anteriormente.
    • Tipo de serviço: escolha Armazenamento – Blob.
    • Assinatura: selecione a assinatura usada anteriormente.
    • Nome da conexão: deixe o valor padrão.
    • Conta de armazenamento: selecione a conta de armazenamento criado anteriormente.
    • Tipo de cliente: selecione .NET.
  4. Selecione Avançar: Autenticação a fim de avançar para a próxima etapa.
  5. Selecione Identidade gerenciada atribuída pelo sistema e escolha Avançar: Rede.
  6. Deixe as opções de rede padrão selecionadas e selecione Examinar + Criar.
  7. Depois que o Azure validar as configurações, selecione Criar.

O conector de serviço habilita uma identidade gerenciada atribuída pelo sistema no aplicativo de contêiner. Ele também atribui uma função de Colaborador de Dados de Blob de Armazenamento à identidade para poder executar operações de dados nos contêineres de armazenamento.

Conectar o cofre de chaves

  1. No portal do Azure, navegue até a página de visão geral do Aplicativo de Contêiner.
  2. À esquerda, selecione Conector de serviço.
  3. Na página Conector de Serviço, escolha + Criar para abrir o painel de submenu Conexão de Criação e insira os seguintes valores:
    • contêiner: selecione o aplicativo de contêiner criado anteriormente.
    • Tipo de serviço: escolha Key Vault.
    • Assinatura: selecione a assinatura usada anteriormente.
    • Nome da conexão: deixe o valor padrão.
    • Cofre de chaves: selecione o cofre de chaves criado anteriormente.
    • Tipo de cliente: selecione .NET.
  4. Selecione Avançar: Autenticação a fim de avançar para a próxima etapa.
  5. Selecione Identidade gerenciada atribuída pelo sistema e escolha Avançar: Rede.
  6. Deixe as opções de rede padrão selecionadas e selecione Examinar + Criar.
  7. Depois que o Azure validar as configurações, selecione Criar.

O conector de serviço atribui uma função à identidade para que ele possa executar operações de dados nas chaves do cofre de chaves.

Configurar e reimplantar o aplicativo

Os recursos necessários do Azure foram criados. Nesta seção, o código do aplicativo está configurado para usar os novos recursos.

  1. Instale os seguintes pacotes NuGet:

    • Azure.Identity: fornece classes para trabalhar com os serviços de gerenciamento de acesso e identidade do Azure.
    • Microsoft.Extensions.Azure: fornece métodos de extensão úteis para executar as principais configurações do Azure.
    • Azure.Extensions.AspNetCore.DataProtection.Blobs: permite armazenar chaves DataProtection do ASP.NET Core no Armazenamento de Blobs do Azure para que as chaves possam ser compartilhadas em várias instâncias de um aplicativo Web.
    • Azure.Extensions.AspNetCore.DataProtection.Keys: habilita a proteção de chaves inativas usando o recurso de Criptografia/Encapsulamento de Chaves do Azure Key Vault.
    dotnet add package Azure.Identity
    dotnet add package Microsoft.Extensions.Azure
    dotnet add package Azure.Extensions.AspNetCore.DataProtection.Blobs
    dotnet add package Azure.Extensions.AspNetCore.DataProtection.Keys
    
  2. Atualize Program.cs com o seguinte código realçado:

    using Azure.Identity;
    using Microsoft.AspNetCore.DataProtection;
    using Microsoft.Extensions.Azure;
    
    var builder = WebApplication.CreateBuilder(args);
    var BlobStorageUri = builder.Configuration["AzureURIs:BlobStorage"];
    var KeyVaultURI = builder.Configuration["AzureURIs:KeyVault"];
    
    builder.Services.AddRazorPages();
    builder.Services.AddHttpClient();
    builder.Services.AddServerSideBlazor();
    
    builder.Services.AddAzureClientsCore();
    
    builder.Services.AddDataProtection()
                    .PersistKeysToAzureBlobStorage(new Uri(BlobStorageUri),
                                                    new DefaultAzureCredential())
                    .ProtectKeysWithAzureKeyVault(new Uri(KeyVaultURI),
                                                    new DefaultAzureCredential());
    var app = builder.Build();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    
    app.MapRazorPages();
    
    app.Run();
    

As alterações anteriores permitem que o aplicativo gerencie a proteção de dados usando uma arquitetura centralizada e escalonável. DefaultAzureCredential descobre as configurações de identidade gerenciada habilitadas anteriormente quando o aplicativo é reimplantado.

Atualize os espaços reservados na seção AzureURIs do arquivo appsettings.json para incluir o seguinte:

  1. Substitua o espaço reservado <storage-account-name> pelo nome da conta de armazenamento scalablerazorstorageXXXX.

  2. Substitua o espaço reservado <container-name> pelo nome do contêiner de armazenamento scalablerazorkeys.

  3. Substitua o espaço reservado <key-vault-name> pelo nome do cofre de chaves scalablerazorvaultXXXX.

  4. Substitua o espaço reservado <key-name> no URI do cofre de chaves pelo nome razorkey criado anteriormente.

    {
      "GitHubURL": "https://api.github.com",
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "AzureURIs": {
        "BlobStorage": "https://<storage-account-name>.blob.core.windows.net/<container-name>/keys.xml",
        "KeyVault": "https://<key-vault-name>.vault.azure.net/keys/<key-name>/"
      }
    }
    

Reimplantar o aplicativo

O aplicativo agora está configurado corretamente para usar os serviços do Azure criados anteriormente. Reimplante o aplicativo para que as alterações de código sejam aplicadas.

  1. Clique com o botão direito do mouse no projeto, no Gerenciador de Soluções e selecione Publicar.
  2. Na exibição de resumo do perfil de publicação, selecione o botão Publicar no canto superior direito.

O Visual Studio reimplanta o aplicativo no ambiente de aplicativos de contêiner criado anteriormente. Quando os processos terminarem, o navegador será iniciado na home page do aplicativo.

Teste o aplicativo novamente pesquisando Microsoft no campo de pesquisa. A página agora deve recarregar com os resultados corretos sempre que você enviar.

Configurar funções para desenvolvimento local

O código e a configuração existentes do aplicativo também podem funcionar ao longo da execução local durante o desenvolvimento. A classe DefaultAzureCredential configurada anteriormente é capaz de coletar credenciais de ambiente local para se autenticar nos Serviços do Azure. Você precisará atribuir as mesmas funções à sua própria conta que foram atribuídas à identidade gerenciada do aplicativo para que a autenticação funcione. Essa deve ser a mesma conta que você usa para fazer logon no Visual Studio ou na CLI do Azure.

Entrar em seu ambiente de desenvolvimento local

Você precisará estar conectado à CLI do Azure, ao Visual Studio ou ao Azure PowerShell para que suas credenciais sejam coletadas pela DefaultAzureCredential.

az login

Atribuir funções à sua conta de desenvolvedor

  1. No portal do Azure, navegue até a conta de armazenamento scalablerazor**** que você criou.
  2. Selecione Controle de acesso (IAM) na navegação à esquerda.
  3. Escolha + Adicionar em Adicionar atribuição de função no menu suspenso.
  4. Na página Adicionar atribuição de função, pesquise Storage blob data contributor, selecione o resultado correspondente e selecione Avançar.
  5. Verifique se Usuário, grupo ou entidade de serviço está selecionado e escolha + Selecionar membros.
  6. No submenu Selecionar membros, pesquise sua própria conta usuário@domínio e selecione-a nos resultados.
  7. Escolha Avançar e selecione Examinar + atribuir. Depois que o Azure validar as configurações, selecione Examinar + atribuir novamente.

Como indicado anteriormente, as permissões de atribuição de função podem levar um minuto ou dois para serem propagadas ou, em casos raros, até oito minutos.

Repita as etapas anteriores a fim de atribuir uma função à sua conta para que ela possa acessar o serviço e o segredo do cofre de chaves.

  1. No portal do Azure, navegue até o cofre de chaves razorscalingkeys criado anteriormente.
  2. Selecione Controle de acesso (IAM) na navegação à esquerda.
  3. Escolha + Adicionar em Adicionar atribuição de função no menu suspenso.
  4. Na página Adicionar atribuição de função, pesquise Key Vault Crypto Service Encryption User, selecione o resultado correspondente e selecione Avançar.
  5. Verifique se Usuário, grupo ou entidade de serviço está selecionado e escolha + Selecionar membros.
  6. No submenu Selecionar membros, pesquise sua própria conta usuário@domínio e selecione-a nos resultados.
  7. Escolha Avançar e selecione Examinar + atribuir. Depois que o Azure validar as configurações, selecione Examinar + atribuir novamente.

Talvez seja necessário aguardar novamente a propagação dessa atribuição de função.

Em seguida, você pode retornar ao Visual Studio e executar o aplicativo localmente. O código deve continuar funcionando conforme o esperado. A DefaultAzureCredential usa suas credenciais existentes do Visual Studio ou da CLI do Azure.

Padrões de aplicativos da web confiáveis

Veja O padrão de aplicativo da Web confiável para.NET vídeos do YouTube e artigo para obter orientação sobre como criar um aplicativo ASP.NET Core moderno, confiável, de alto desempenho, testável, econômico e escalonável, seja do zero ou refatorando um existente aplicativo.