Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Quando uma implementação introduz um bug, precisa de uma forma de recuperar rapidamente. Este artigo mostra-lhe como recuperar de uma implementação deficiente numa aplicação de função Flex Consumption utilizando um processo de integração contínua e implementação contínua (CI/CD). Este processo inclui os seguintes métodos de recuperação:
| Método de recuperação | Velocidade | Quando utilizar | Descrição |
|---|---|---|---|
| Repetir a execução anterior bem-sucedida (reverter para trás) | Mais rápido | Existe uma versão boa conhecida, ou não existe alterações de dados ou estado entre versões | Selecione uma execução anterior e execute-a novamente, em seguida aguarde a compilação e a implementação. |
git revert e depois git push (avançar) |
Moderado | A correção é simples; caso contrário, o estado externo não pode ser revertido. | Identifica o commit que causou a falha, reverte-o e faz push. Depois, aguarda o mesmo tempo de build e de deploy. |
git commit um hotfix e depois git push (avançar) |
Mais lento | A causa raiz é conhecida e precisa de uma solução direcionada | Identificar a causa principal; criar, rever, testar e integrar uma correção; e depois esperar que a compilação e a implementação terminem. |
Estas estratégias recuperam tanto o código da tua função como as definições da app, por isso as alterações de configuração são recuperáveis com alterações no código.
Por que precisas de CI/CD para recuperar uma implementação
Quando implementa código na sua aplicação de plano Flex Consumption:
- O seu código é implementado sob a forma de um pacote ZIP para um contentor no armazenamento de blobs, que é montado no arranque.
- Cada implantação substitui o pacote atual.
- A plataforma não mantém qualquer histórico de revisões incorporado para preservar versões anteriores.
- A funcionalidade de slots de implantação não é suportada atualmente.
- As definições da aplicação são aplicadas separadamente através do portal Azure, CLI ou infrastructure-as-code (IaC), e a plataforma não consegue restaurá-las para um estado anterior.
Estes comportamentos de implementação limitam as suas opções para recuperar a sua aplicação do plano Flex Consumption de uma implementação deficiente.
O teu histórico Git e o processo CI/CD fornecem a única forma de acompanhar implementações de código num dado momento. Criar uma implementação que inclua tanto o código como a configuração permite-lhe recuperar de um lançamento problemático, apontando a execução seguinte para um commit válido conhecido.
Para mais informações sobre o modelo de implementação Flex Consumption, consulte plano Flex Consumption e Atualizações do site no plano Flex Consumption.
Pré-requisitos
Uma aplicação de funções existente implementada num plano Flex Consumption no Azure.
Código-fonte num repositório Git. Utilize tags do Git ou registe os SHAs dos commits de cada lançamento para que possa identificar rapidamente para que versão reverter.
Uma implementação configurada para a sua aplicação de funções:
Um fluxo de trabalho configurado com autenticação OIDC, conforme descrito em Continuous delivery, utilizando o GitHub Actions. O fluxo de trabalho deve usar
azure/login. A autenticação por perfil de publicação não suporta os comandosaz cliusados neste guia.
Prepare a sua implementação para gerir as definições da aplicação
Antes de poder efetuar uma reversão completa, tem de colocar as definições da aplicação em controlo de código-fonte e aplicá-las como parte da implantação. Embora esta abordagem permita recuperar tanto código como configuração numa única repetição, requer passos adicionais, como aplicar definições, esperar por reinicios e limpar valores não declarados.
Tip
Quando a sua implementação não inclui definições, só pode reverter o código implementado, mas não a configuração.
Esta secção detalha duas abordagens para gerir as definições da aplicação como parte da sua implementação:
| Approach | No fluxo de trabalho (CLI do Azure) | Na definição de serviço (Bicep) |
|---|---|---|
| Como funciona | Os passos de implementação aplicam definições de um ficheiro JSON usando az functionapp config appsettings, e depois removem definições não declaradas |
O modelo Bicep declara definições em siteConfig.appSettings; O ARM substitui toda a coleção durante a implementação |
| Complexidade | Moderado. ficheiro JSON mais passos adicionais de CLI no teu fluxo de trabalho | Mais alto. Requer conhecimento de Bicep |
| Deteção de deriva | No | Sim (what-if) |
| Melhor para | A começar, equipas pequenas | Infraestrutura complexa, multiambiente, preparada para produção |
Para informações mais gerais sobre as definições da aplicação, consulte a referência de definições da aplicação para o Funções do Azure.
Considerações sobre as definições da aplicação
Preste atenção a estas considerações ao trabalhar com a configuração programática das definições da aplicação.
Important
Não incluir todas as definições necessárias usando qualquer uma das abordagens pode quebrar a sua aplicação implementada.
Ambas as abordagens nesta secção tratam o seu ficheiro de definições como o estado completo desejado. Eles removem todas as definições da aplicação que não estejam declaradas no ficheiro a partir da aplicação em cada implementação. Inclua sempre todas as definições necessárias para evitar que a sua aplicação quebre.
Trate
app-settings.jsone as alterações ao modelo de ficheiro Bicep com o mesmo escrutínio que as alterações de código. Revise as alterações nas definições nos pull requests para detetar erros de configuração antes de chegarem à produção.Para uma segurança ótima, siga estas orientações para as suas ligações:
Use ligações de identidade gerida sempre que possível. Configure ligações com base na identidade para o armazenamento do anfitrião (
AzureWebJobsStorage), o armazenamento de implementação e as ligações de acionador/associação. Para obter mais informações, consulte Definir configurações de implantação.- Use referências ao Key Vault quando os segredos forem inevitáveis. A Key Vault guarda os seus segredos de forma segura. Em vez de armazenar segredos diretamente, pode usar uma referência para aceder de forma segura ao segredo necessário em tempo de execução. Para mais informações, consulte Utilizar referências do Key Vault.
Quando usas CI/CD, cada alteração nas definições da tua aplicação ou no teu código desencadeia uma atualização separada do site. Por defeito, este processo de implementação produz pelo menos duas atualizações do site: primeiro quando as definições são aplicadas e depois quando o código é implementado. Para implementações sem tempo de inatividade, utilize, em vez disso, uma estratégia de atualização progressiva, em que as instâncias são retiradas de serviço e substituídas em lotes. Para mais informações, consulte as atualizações do site no plano Flex Consumption.
Configurar as definições da app no fluxo de trabalho
Use estes passos básicos para adicionar um ficheiro de configuração de definições de aplicação à implementação do seu projeto:
Crie um ficheiro JSON no seu repositório, como em
infra/app-settings.json. Este ficheiro deve incluir todas as definições necessárias da aplicação num formato JSON que se assemelhe ao seguinte exemplo:[ { "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" } ]Na sua definição específica de implementação, adicione passos que apliquem as definições antes da implementação do código, com uma pausa de 30 segundos entre eles.
As secções seguintes fornecem exemplos específicos de implementação utilizando ambas as abordagens.
Exemplo: implementação de app-settings.json
Este exemplo de implementação mostra como configurar a sua implantação para incluir a configuração. Escolhe a aba que corresponde ao teu método CI/CD.
Adicione os passos seguintes ao job deploy do seu fluxo de trabalho. Adicione actions/checkout@v4 ao trabalho deploy para que infra/app-settings.json fique disponível e adicione RESOURCE_GROUP ao bloco env ao nível do fluxo de trabalho. Os passos aplicam primeiro as definições, esperam pelo reinício, implementam o código e depois limpam as definiçõ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 numa implementação em Bicep
Para implementações de IaC, gere as definições da aplicação diretamente no modelo Bicep. O Bicep substitui nativamente a coleção siteConfig.appSettings inteira em cada implementação, sem necessitar de uma etapa de limpeza separada. Também suporta deteção de deriva usando what-if.
Quando atualiza apenas a secção de definições da aplicação do ficheiro Bicep, todos os outros recursos do Azure permanecem inalterados durante a implementação. Este artigo não aborda a criação em Bicep do início ao fim. Para modelos completos de Flex Consumption, veja Funções do Azure infrastructure as code.
Aqui está o fragmento relevante do modelo Bicep (apenas 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 passos para implementar o modelo Bicep antes da implementação do código, com uma espera de 30 segundos pelo meio. A atualização das definições da aplicação com o Bicep é assíncrona. A aplicação reinicia para captar os novos valores, e a implementação de código durante o reinício 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 implementação
Reverter significa repetir uma corrida anterior bem-sucedida. Uma re-execução verifica o commit SHA original que desencadeou essa execução (não o branch HEAD atual), por isso reconstrói e implementa o código e o ficheiro de definições a partir desse momento. Não precisas de novos commits.
Para reverter uma implementação repetindo uma execução anterior bem-sucedida:
- Vai ao separador Ações no teu repositório do GitHub.
- Encontre a última execução de fluxo de trabalho bem-sucedida antes da má implementação.
- Selecionar Reexecutar todos os trabalhos.
- O fluxo de trabalho verifica o commit da execução, reconstrói, implementa o código e sincroniza as definições da app a partir desse
app-settings.jsoncommit.
O que a nova execução da reconstrução recria
A re-execução reconstrói o código a partir do commit antigo. Não reutiliza o artefacto binário original. Este comportamento significa:
- Com ficheiros de bloqueio de dependência fixados (
package-lock.json,requirements.txt, e assim sucessivamente), a saída é funcionalmente idêntica. - O tempo de construção é igual ao de uma implementação normal. Não é instantâneo.
- Dependências externas obtidas em tempo de compilação (NuGet, npm, pip) devem continuar disponíveis.
Considerações de reversão
Fixe os ficheiros de bloqueio de dependência (
package-lock.json,requirements.txt, ou versões bloqueadas.csproj) no controlo de versão. Os ficheiros de bloqueio fixados garantem que a reexecução de uma implantação produz uma compilação funcionalmente idêntica, independentemente do momento em que ocorra.A re-execução utiliza o workflow ou pipeline YAML do commit original. No entanto, os segredos e as variáveis do pipeline resolvem-se para os seus valores atuais no momento em que são reexecutados. Quando rodares os segredos entre a execução original e uma nova execução, será utilizado o novo valor do segredo.
Uma nova execução restaura a tua aplicação implementada para um estado conhecido como válido, mas não altera o teu histórico do Git. O teu HEAD de ramo ainda aponta para o commit quebrado.
O que executar novamente não restaura:
- Configuração de recursos do Azure gerida fora da sua implementação, incluindo planos de alojamento, redes e atribuições de identidade.
- Alterações de dados ou esquemas em serviços a jusante, como bases de dados, filas de mensagens e armazenamento.
- Valores secretos do Key Vault. Apenas as referências do Key Vault são mantidas no controlo do código-fonte. A rotação de segredos é uma operação do Key Vault.
Teste regularmente o seu processo de reversão. Não espere por um incidente de produção para descobrir que está avariado.
Corrigir o ramo após um rollback
Como a próxima execução acionada por push redistribui o commit quebrado, outros programadores que puxam o branch continuam a ver o código quebrado. Deve resolver esta situação com uma destas ações:
- Cria um commit hotfix que resolva o problema, que é essencialmente uma operação de roll forward.
- Execute um
git revertpara desfazer o commit quebrado criando um novo commit, que também é uma ação de roll forward. - Uma política de sucursal que impeça a fusão até resolver o problema.
Enquanto não concluíres uma destas ações, evita iniciar uma nova execução nessa ramificação. Para orientações de validação, consulte Validar antes da fusão.
Efetuar o avanço de uma implementação
Avançar significa enviar um novo commit para corrigir o problema. A implementação falhada mantém-se ativa até a correção ser implementada, por isso esta estratégia funciona melhor quando a aplicação tolera comportamentos degradados durante esse tempo.
Cria um commit de correção no teu ramo. Esta correção pode ser:
- Um hotfix que resolve diretamente o problema.
- Um
git revert <bad-commit-sha>que cria um novo commit que desfaz as alterações incorretas. Mesmo quegit revertreverta o código, trata-se de um avanço porque gera um novo commit e desencadeia uma nova implantação.
Se a correção também exigir alterações de configuração, atualize as definições da sua aplicação (dentro
app-settings.jsonou dentro do seu modelo Bicep) no mesmo commit.Empurra o compromisso. A sua implementação constrói e implementa automaticamente a correção.
Validar antes de fundir
Independentemente da sua estratégia de recuperação, valide e corrija os commits antes de os integrar no seu ramo de produção para evitar agravar o problema.
Estas recomendações aplicam-se tanto à progressão proativa como à correção da ramificação após uma reversão:
Utilize um ambiente de preparação: Como o plano Flex Consumption atualmente não suporta ranhuras de implementação, considere implementar antes numa aplicação separada num plano Flex Consumption para validar a correção antes de a intercalar na ramificação de produção.
Automatizar verificações de saúde: Adicione um passo pós-implementação que chame um endpoint de verificação de saúde na sua aplicação e verifique uma resposta positiva. Em caso de falhar, considere ativar uma repetição da corrida anterior bem-sucedida para reverter automaticamente o processo.
Monitorizar após a implementação: Configurar alertas Application Insights para deteção de regressão. A deteção precoce reduz o impacto de uma má implementação.