Recuperar-se de uma implantação de aplicativo do plano de Consumo Flexível incorreta

Quando uma implantação introduz um bug, você precisa de uma maneira de se recuperar rapidamente. Este artigo mostra como se recuperar de uma implantação incorreta em um aplicativo de funções de Consumo Flexível usando um processo de integração contínua e implantação contínua (CI/CD). Esse processo inclui estes métodos de recuperação:

Método de recuperação Velocidade Quando usar Descrição
Executar novamente a execução anterior bem-sucedida (reverter) Mais rápido Existe uma versão comprovadamente funcional, ou não há alterações de dados ou de estado entre as versões Selecione uma execução anterior e execute-a novamente e aguarde a compilação e a implantação.
git revert e, em seguida git push , (roll forward) Moderado A correção é simples, ou o estado externo não pode ser revertido. Identificar a confirmação com falha, revertê-la e fazer push. Em seguida, aguarde o mesmo tempo de compilação e implantação.
git commit um hotfix e, em seguida, git push (avançar) Mais lento A causa raiz é conhecida e precisa de uma correção direcionada Identificar a causa raiz; criar, revisar, testar e mesclar uma correção; e então aguardar a conclusão da compilação e da implantação.

Essas estratégias recuperam o código do aplicativo de funções e as configurações do aplicativo, de modo que as alterações de configuração podem ser recuperadas com alterações de código.

Por que você precisa de CI/CD para recuperar uma implantação

Ao implantar código em seu aplicativo do plano Flex Consumption:

  • Seu código é implantado como um pacote zip em um contêiner de armazenamento de blobs, que é montado na inicialização.
  • Cada implantação substitui o pacote atual.
  • A plataforma não mantém nenhum histórico de revisão interno para reter versões anteriores.
  • No momento, não há suporte para o recurso de slots de implantação .
  • As configurações de aplicativo são aplicadas separadamente por meio do portal Azure, da CLI ou da IaC (infraestrutura como código) e a plataforma não pode restaurá-las para um estado anterior.

Esses comportamentos de implantação limitam suas opções para recuperar seu aplicativo de plano de consumo flex de uma implantação incorreta.

O histórico do Git e o processo de CI/CD fornecem a única maneira de acompanhar implantações de código em um determinado ponto no tempo. Criar uma implantação que inclua código e configuração permite que você se recupere de um lançamento com problema apontando a próxima execução para um commit conhecido e estável.

Para obter mais informações sobre o modelo de implantação do Flex Consumption, consulte plano Flex Consumption e Atualizações do site no plano Flex Consumption.

Pré-requisitos

  • Um aplicativo de funções existente implantado em um plano de Consumo Flexível no Azure.

  • Código-fonte em um repositório Git. Use marcações do Git ou registre os SHAs dos commits de cada lançamento para que você possa identificar rapidamente para qual versão reverter.

  • Uma implantação configurada para seu aplicativo de funções:

    Um fluxo de trabalho configurado com a autenticação OIDC conforme descrito na entrega contínua usando GitHub Actions. O fluxo de trabalho deve usar azure/login. A autenticação por perfil de publicação não oferece suporte aos comandos az cli usados neste guia.

Preparar sua implantação para gerenciar as configurações do aplicativo

Antes de executar uma reversão completa, você deve colocar as configurações do aplicativo no controle do código-fonte e aplicá-las como parte da implantação. Embora essa abordagem permita que você recupere o código e a configuração em uma única nova execução, ela requer etapas extras, como aplicar configurações, aguardar reinicializações e limpar valores não declarados.

Dica

Quando sua implantação não inclui configurações, você só pode reverter o código implantado, mas não a configuração.

Esta seção detalha duas abordagens para gerenciar as configurações do aplicativo como parte de sua implantação:

Abordagem No fluxo de trabalho (CLI do Azure) Na definição de serviço (Bicep)
Como funciona As etapas de implantação aplicam as configurações de um arquivo JSON usando az functionapp config appsettingse, em seguida, removem configurações não declaradas O modelo Bicep define as configurações em siteConfig.appSettings; o ARM substitui toda a coleção durante a implantação
Complexidade Moderado. Arquivo JSON mais etapas extras da CLI em seu fluxo de trabalho Mais alto. Requer conhecimento de Bicep
Detecção de drift Não Sim (what-if)
Mais adequado para Introdução, equipes pequenas Infraestrutura complexa, com vários ambientes e pronta para produção

Para obter mais informações gerais sobre as configurações do aplicativo, consulte a referência de configurações de aplicativo para Azure Functions.

Considerações sobre configurações de aplicativo

Preste atenção a essas considerações ao trabalhar com a configuração programática das configurações do aplicativo.

Important

Deixar de incluir todas as configurações necessárias ao usar qualquer uma das abordagens pode fazer com que o app implantado pare de funcionar.

  • Ambas as abordagens nesta seção tratam o arquivo de configurações como o estado completo desejado. Eles removem as configurações de aplicativo não declaradas no arquivo do aplicativo em cada implantação. Inclua sempre todas as configurações necessárias para evitar quebrar seu aplicativo.

  • Trate app-settings.json e as alterações em modelos de arquivo do Bicep com o mesmo rigor que as alterações de código. Examine as alterações de configurações nas solicitações de pull para capturar erros de configuração antes que elas cheguem à produção.

  • Para obter a segurança ideal, siga estas diretrizes para suas conexões:

    • Use conexões de identidade gerenciada sempre que possível. Configure conexões baseadas em identidade para armazenamento de host (AzureWebJobsStorage), armazenamento de implantação e conexões de gatilho/vinculação. Para obter mais informações, consulte Definir configurações de implantação.

      • Use referências do Key Vault quando não for possível evitar segredos. Key Vault armazena seus segredos com segurança. Em vez de armazenar segredos diretamente, você pode usar uma referência para acessar com segurança o segredo necessário em runtime. Para obter mais informações, consulte Usar referências de Key Vault.
  • Quando você usa CI/CD, cada alteração nas configurações do aplicativo ou no código dispara uma atualização de site separada. Por padrão, esse processo de implantação produz pelo menos duas atualizações de site: primeiro quando as configurações são aplicadas e, em seguida, quando o código é implantado. Para implantações sem tempo de inatividade, use, em vez disso, uma estratégia de atualização contínua, em que as instâncias são drenadas e substituídas em lotes. Para obter mais informações, consulte Atualizações de Site no plano Flex Consumption.

Definir as configurações do aplicativo no fluxo de trabalho

Use estas etapas básicas para adicionar um arquivo de configuração de configurações de aplicativo à implantação do projeto:

  1. Crie um arquivo JSON em seu repositório, como em infra/app-settings.json. Esse arquivo deve incluir todas as configurações de aplicativo necessárias em um formato JSON semelhante ao exemplo a seguir:

    [
      {
        "name": "FUNCTIONS_EXTENSION_VERSION",
        "value": "~4"
      },
      {
        "name": "FUNCTIONS_WORKER_RUNTIME",
        "value": "dotnet-isolated"
      },
      {
        "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
        "value": "InstrumentationKey=00000000-..."
      },
      {
        "name": "AzureWebJobsStorage__blobServiceUri",
        "value": "https://mystorageaccount.blob.core.windows.net"
      },
      {
        "name": "AzureWebJobsStorage__queueServiceUri",
        "value": "https://mystorageaccount.queue.core.windows.net"
      },
      {
        "name": "AzureWebJobsStorage__tableServiceUri",
        "value": "https://mystorageaccount.table.core.windows.net"
      },
      {
        "name": "MyFeatureFlag",
        "value": "true"
      },
      {
        "name": "ServiceBus__fullyQualifiedNamespace",
        "value": "my-namespace.servicebus.windows.net"
      }
    ]
    
  2. Em sua definição de implantação específica, adicione etapas que aplicam as configurações antes da implantação de código ocorrer, com uma pausa de 30 segundos entre elas.

As seções a seguir fornecem exemplos de implantação específicos usando ambas as abordagens.

Exemplo: implantação de app-settings.json

Este exemplo de implantação mostra como configurar sua implantação para incluir a configuração. Escolha a aba que corresponde ao método de CI/CD.

Adicione as etapas a seguir ao job deploy em seu fluxo de trabalho. Adicione actions/checkout@v4 ao trabalho deploy para que infra/app-settings.json esteja disponível e adicione RESOURCE_GROUP ao bloco env no nível do fluxo de trabalho. As etapas aplicam as configurações primeiro, aguardam a reinicialização, implantam o código e limpam as configurações não declaradas.

  deploy:
    needs: build
    steps:
      - name: 'Checkout repository'
        uses: actions/checkout@v4

      - name: 'Download artifact from build job'
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.BUILD_ARTIFACT_NAME }}
          path: ./downloaded-artifact

      - name: 'Log in to Azure'
        uses: azure/login@v2
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

      - name: 'Apply app settings'
        run: |
          az functionapp config appsettings set \
            --name ${{ env.AZURE_FUNCTIONAPP_NAME }} \
            --resource-group ${{ env.RESOURCE_GROUP }} \
            --settings @infra/app-settings.json

      - name: 'Wait for settings restart'
        run: sleep 30

      - name: 'Deploy code'
        uses: Azure/functions-action@v1
        with:
          app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
          package: ./downloaded-artifact

      - name: 'Remove undeclared app settings'
        run: |
          DESIRED=$(jq -r '.[].name' infra/app-settings.json)
          CURRENT=$(az functionapp config appsettings list \
            --name ${{ env.AZURE_FUNCTIONAPP_NAME }} \
            --resource-group ${{ env.RESOURCE_GROUP }} \
            --query "[].name" -o tsv)
          TO_DELETE=""
          for setting in $CURRENT; do
            if ! echo "$DESIRED" | grep -qx "$setting"; then
              TO_DELETE="$TO_DELETE $setting"
            fi
          done
          if [ -n "$TO_DELETE" ]; then
            az functionapp config appsettings delete \
              --name ${{ env.AZURE_FUNCTIONAPP_NAME }} \
              --resource-group ${{ env.RESOURCE_GROUP }} \
              --setting-names $TO_DELETE
          fi

A azure/login@v2 etapa no fluxo de trabalho baseado em OIDC fornece a autenticação necessária para os az cli comandos.

Definir configurações em uma implantação de Bicep

Para implantações de IaC, gerencie as configurações do aplicativo diretamente no modelo de Bicep. O Bicep substitui de forma nativa a coleção siteConfig.appSettings inteira a cada implantação, sem precisar de uma etapa de limpeza separada. Ele também dá suporte à detecção de descompasso usando what-if.

Quando você atualiza apenas a seção de configurações do aplicativo do arquivo Bicep, todos os outros recursos Azure permanecem não modificados durante a implantação. Este artigo não aborda a criação em Bicep de ponta a ponta. Para obter modelos completos do Consumo Flexível, consulte Infraestrutura como código do Azure Functions.

Aqui está o fragmento relevante do modelo do Bicep (somente a parte appSettings):

siteConfig: {
  appSettings: [
    {
      name: 'MyFeatureFlag'
      value: 'true'
    }
    {
      name: 'ServiceBus__Connection'
      value: '@Microsoft.KeyVault(SecretUri=https://my-vault.vault.azure.net/secrets/sb-conn)'
    }
  ]
}

Adicione etapas para implantar o modelo de Bicep antes da implantação do código, com uma espera de 30 segundos no meio. Atualizar as configurações do aplicativo por meio de Bicep é assíncrono. O aplicativo é reiniciado para pegar os novos valores e a implantação de código durante a reinicialização pode falhar.

      - name: 'Deploy infrastructure'
        run: |
          az deployment group create \
            --resource-group ${{ env.RESOURCE_GROUP }} \
            --template-file infra/main.bicep \
            --parameters appName=${{ env.AZURE_FUNCTIONAPP_NAME }}

      - name: 'Wait for settings restart'
        run: sleep 30

      - name: 'Deploy code'
        uses: Azure/functions-action@v1
        with:
          app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }}
          package: ./downloaded-artifact

Reverter uma implantação

Reverter significa executar novamente uma execução anterior bem-sucedida. Uma nova execução verifica o SHA de commit original que disparou essa execução (não o HEAD da ramificação atual), para que ele recompile e implante o arquivo de código e configurações desse ponto no tempo. Você não precisa de novos commits.

Para reverter uma implantação, execute novamente uma execução anterior bem-sucedida:

  1. Vá para a guia Ações no repositório GitHub.
  2. Localize a última execução bem-sucedida do fluxo de trabalho antes da implantação incorreta.
  3. Selecione Executar novamente todos os trabalhos.
  4. O fluxo de trabalho faz checkout do commit daquela execução, recompila o código, implanta o código e sincroniza as configurações do aplicativo a partir do app-settings.json desse commit.

O que executa novamente as recompilações

A nova execução recria o código da confirmação antiga. Ele não reutiliza o artefato binário original. Esse comportamento significa:

  • Com arquivos de bloqueio de dependências fixos (package-lock.json, requirements.txt e assim por diante), a saída é funcionalmente idêntica.
  • O tempo de compilação é o mesmo que uma implantação normal. Não é instantâneo.
  • As dependências externas obtidas durante a compilação (NuGet, npm, pip) ainda devem estar disponíveis.

Considerações sobre reversão

  • Fixe os arquivos de bloqueio de dependência (package-lock.json, requirements.txt ou versões .csproj bloqueadas) no controle do código-fonte. Os arquivos de bloqueio fixados garantem que a nova execução de uma implantação produza um build funcionalmente idêntico, independentemente de quando a nova execução ocorrer.

  • Executar novamente usa o YAML do fluxo de trabalho ou do pipeline do commit original. No entanto, segredos e variáveis de pipeline resolvem para seus valores atuais no momento em que são executados novamente. Quando você rotaciona seus segredos entre a execução original e uma reexecução, o novo valor do segredo é usado.

  • Uma reexecução restaura sua aplicação implantada para um estado comprovadamente estável, mas não altera o histórico do Git. O HEAD da sua ramificação ainda aponta para o commit com problema.

  • O que não é restaurado ao executar novamente:

    • Configuração de recursos do Azure gerenciada fora da sua implantação, incluindo planos de hospedagem, rede e atribuições de identidade.
    • Alterações de dados ou esquema em serviços downstream, como bancos de dados, filas de mensagens e armazenamento.
    • Valores de segredo do Key Vault. Somente as referências ao Key Vault são mantidas no controle de versão. Rotacionar segredos é uma operação do Key Vault.
  • Teste o processo de reversão regularmente. Não espere por um incidente em produção para descobrir que algo está errado.

Corrigir a ramificação após uma reversão

Como a próxima execução disparada por push reimplanta o commit com erro, outros desenvolvedores, ao fazer pull da ramificação, ainda veem o código quebrado. Você deve corrigir essa situação com uma destas ações:

  • Crie um commit de hotfix que resolva o problema, que é essencialmente uma operação de avanço.
  • Execute um git revert para desfazer o commit com problema criando um novo commit, que também é uma ação de avanço.
  • Uma política de ramificação que impede a fusão até que você corrija o problema.

Até que você conclua uma dessas ações, evite acionar uma nova execução nessa ramificação. Para obter diretrizes de validação, consulte Validar antes da mesclagem.

Avançar uma implantação

Avançar significa enviar um novo commit por push para corrigir o problema. A implantação interrompida permanece ativa até que a correção seja implantada, portanto, essa estratégia funciona melhor quando o aplicativo pode tolerar comportamentos degradados durante esse tempo.

  1. Crie um commit de correção em sua ramificação. Essa correção pode ser:

    • Um hotfix que aborda diretamente o problema.
    • Um git revert <bad-commit-sha> que cria um novo commit que desfaz as alterações indesejadas. Embora git revert reverta o código, isso é um avanço porque produz um novo commit e aciona uma nova implantação.
  2. Se a correção também exigir alterações de configuração, atualize as configurações do app (seja em app-settings.json ou no seu modelo Bicep) no mesmo commit.

  3. Transmitir a confirmação Sua implantação compila e implanta a correção automaticamente.

Validar antes da mesclagem

Independentemente da sua estratégia de recuperação, valide e corrija os commits antes de mesclá-los na ramificação de produção para evitar agravar o problema.

Essas recomendações se aplicam independentemente de você estar avançando proativamente ou corrigindo a ramificação após uma reversão:

  • Use um ambiente de preparo: como o plano Consumo Flexível atualmente não oferece suporte a slots de implantação, considere implantar em um aplicativo separado do plano Consumo Flexível para validar a correção antes de mesclá-la à ramificação de produção.

  • Automatize as verificações de saúde: adicione uma etapa pós-implantação que faça uma chamada para um ponto de extremidade de verificação de saúde no seu aplicativo e confirme uma resposta positiva. Em caso de falha, considere acionar uma nova execução da execução anterior bem-sucedida para fazer a reversão automaticamente.

  • Monitorar após a implantação: configure alertas do Application Insights para detecção de regressão. A detecção antecipada reduz o impacto de uma implantação incorreta.