Восстановление после плохого развертывания приложения плана потребления Flex

Когда развертывание приводит к появлению ошибки, нужен способ быстро восстановиться. В этой статье показано, как восстановить работу приложения-функции Flex Consumption после неудачного развертывания с помощью процесса непрерывной интеграции и непрерывного развертывания (CI/CD). Этот процесс включает следующие методы восстановления:

Метод восстановления Скорость Когда использовать Описание
Повторный запуск предыдущего успешно выполненного запуска (откат) Самый быстрый Существует известно исправная версия или между версиями нет изменений в данных или состоянии Выберите предыдущий запуск и повторно запустите его, а затем дождитесь сборки и развертывания.
git revert а затем git push (прокрутка вперёд) Умеренно Исправить это просто, либо внешнее состояние нельзя откатить Определите коммит, который всё сломал, откатите его и отправьте изменения в удалённый репозиторий. Дождитесь того же времени сборки и развертывания.
git commit оперативное исправление, а затем git push (roll forward) Самый медленный Первопричина известна и нуждается в целевом исправлении Выявите первопричину; создайте, проверьте, протестируйте и объедините исправление; затем дождитесь, пока сборка и развёртывание завершатся.

Эти стратегии восстанавливают код приложения-функции и параметры приложения, поэтому изменения конфигурации можно восстановить с помощью изменений кода.

Зачем нужен CI/CD, чтобы восстановить развертывание

При развертывании кода в приложении плана потребления Flex:

  • Ваш код развертывается в виде ZIP-пакета в контейнер хранилища BLOB-объектов, который монтируется при запуске.
  • Каждое развертывание перезаписывает текущий пакет.
  • Платформа не сохраняет встроенный журнал редакций для хранения предыдущих версий.
  • Функция слотов развертывания в настоящее время не поддерживается.
  • Параметры приложения применяются отдельно с помощью портала Azure, интерфейса командной строки или инфраструктуры как кода (IaC), а платформа не может восстановить их до предыдущего состояния.

Эти особенности развертывания ограничивают ваши возможности по восстановлению приложения в плане Flex Consumption после неудачного развертывания.

Журнал Git и процесс CI/CD предоставляют единственный способ отслеживания развертываний кода в определенный момент времени. Развертывание, включающее и код, и конфигурацию, позволяет восстановиться после неудачного релиза, направив следующий запуск на заведомо рабочий коммит.

Дополнительные сведения о модели развертывания Flex Consumption см. в статьях План Flex Consumption и Обновления сайта в плане Flex Consumption.

Необходимые условия

  • Существующее приложение-функция, развернутое в плане потребления Flex в Azure.

  • Исходный код в репозитории Git. Используйте теги Git или записывайте SHA коммитов для каждого релиза, чтобы можно было быстро определить, к какой версии выполнить откат.

  • Развертывание, настроенное для вашего приложения-функции:

    Рабочий процесс, настроенный с аутентификацией OIDC, как описано в Непрерывная доставка с использованием GitHub Actions. Рабочий процесс должен использовать azure/login. Аутентификация с использованием профиля публикации не поддерживает az cliкоманды, используемые в этом руководстве.

Подготовьте среду развертывания для управления параметрами приложения

Прежде чем выполнить полный откат, необходимо добавить параметры приложения в систему контроля версий и применить их в ходе развертывания. Хотя этот подход позволяет восстановить код и конфигурацию в одном повторном запуске, это требует дополнительных действий, таких как применение параметров, ожидание перезапусков и очистка необъявленных значений.

Tip

Если развертывание не включает параметры, можно откатить развернутый код, но не конфигурацию.

В этом разделе описаны два подхода к управлению параметрами приложения в рамках развертывания:

Approach В рабочем процессе (Azure CLI) В определении сервиса (Bicep)
Принцип работы Шаги развертывания применяют параметры из JSON-файла с помощью az functionapp config appsettings, а затем удаляют параметры, не объявленные в нем В шаблоне Bicep настройки задаются в siteConfig.appSettings; при развертывании ARM заменяет всю коллекцию
Сложность Умеренный. JSON-файл и дополнительные шаги интерфейса командной строки в рабочем процессе Выше. Требуется знание Bicep
Обнаружение смещения нет Да (what-if)
лучше всего подходит для Начало работы, небольшие команды Готовая к промышленной эксплуатации, мультисредовая, сложная инфраструктура

Дополнительные сведения о параметрах приложения см. в справочнике по параметрам приложений для Функции Azure.

Рекомендации по параметрам приложения

Обратите внимание на эти рекомендации при работе с программными настройками параметров приложения.

Important

Если при использовании любого из этих подходов не включить все необходимые параметры, это может нарушить работу развернутого приложения.

  • Оба подхода в этом разделе рассматривают файл параметров как полное требуемое состояние. Они удаляют все параметры приложения, не объявленные в файле из приложения в каждом развертывании. Всегда включать все необходимые параметры, чтобы избежать нарушения работы приложения.

  • Рассматривайте app-settings.json и изменения в шаблонах файлов Bicep с той же тщательностью, что и изменения кода. Проверяйте изменения параметров в запросах на включение изменений, чтобы выявить ошибки конфигурации до того, как они попадут в рабочую среду.

  • Чтобы обеспечить оптимальную безопасность, следуйте приведенным ниже рекомендациям для подключений:

    • Используйте подключения с управляемой идентичностью везде, где возможно. Настройте подключения на основе удостоверений для хранилища узла (AzureWebJobsStorage), хранилища развертывания, а также подключений триггеров и привязок. Дополнительные сведения см. в разделе "Настройка параметров развертывания".

      • Используйте ссылки на Key Vault, если невозможно обойтись без секретов. Key Vault безопасно хранит свои секреты. Вместо хранения секретов напрямую можно использовать ссылку для безопасного доступа к требуемому секрету во время выполнения. Дополнительные сведения см. в разделе Использование ссылок Key Vault.
  • При использовании CI/CD каждое изменение параметров приложения или кода активирует отдельное обновление сайта. По умолчанию этот процесс развертывания создает по крайней мере два обновления сайта: сначала при применении параметров, а затем при развертывании кода. Для развертываний без простоя вместо этого используйте стратегию поэтапного обновления, при которой экземпляры поэтапно выводятся из эксплуатации и заменяются партиями. Дополнительные сведения см. в статье Обновления сайтов в плане Flex Consumption.

Настройка параметров приложения в рабочем процессе

Чтобы добавить файл конфигурации параметров приложения в развертывание проекта, выполните следующие основные действия.

  1. Создайте JSON-файл в репозитории, например в infra/app-settings.json. Этот файл должен содержать все необходимые параметры приложения в формате JSON, который выглядит следующим образом:

    [
      {
        "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. В определении конкретного развертывания добавьте шаги, которые применяют параметры перед развертыванием кода, с 30-секундной приостановкой между ними.

В следующих разделах приведены конкретные примеры развертывания с помощью обоих подходов.

Пример: развертывание файла app-settings.json

В этом примере развертывания показано, как настроить развертывание для включения конфигурации. Выберите вкладку, соответствующую методу CI/CD.

Добавьте следующие шаги в задание deploy в вашем рабочем процессе. Добавьте actions/checkout@v4 к заданию deploy, чтобы infra/app-settings.json стал доступен, и добавьте RESOURCE_GROUP в блок env на уровне рабочего процесса. Сначала примените параметры, дождитесь перезапуска, разверните код, а затем очистите необъявленные параметры.

  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

Шаг azure/login@v2 в рабочем процессе на основе OIDC обеспечивает проверку подлинности, необходимую для az cli команд.

Задайте параметры в развертывании Bicep

Для развертываний IaC управляйте параметрами приложения непосредственно в шаблоне Bicep. Bicep изначально поддерживает полную замену всей коллекции siteConfig.appSettings при каждом развертывании без необходимости выполнять отдельный этап очистки. Он также поддерживает обнаружение смещения с помощью what-if.

При обновлении только раздела параметров приложения файла Bicep все остальные Azure ресурсы остаются не измененными во время развертывания. В этой статье не рассматривается создание Bicep-файлов от начала до конца. Полные шаблоны для модели потребления Flex см. в разделе Инфраструктура Функции Azure как код.

Вот соответствующий фрагмент шаблона Bicep (только часть appSettings):

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

Добавьте шаги для развертывания шаблона Bicep перед развертыванием кода с 30-секундным ожиданием между ними. Обновление параметров приложения с помощью Bicep асинхронно. Приложение перезапускается для получения новых значений, а развертывание кода во время перезапуска может завершиться ошибкой.

      - 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

Откатить развертывание

Откат означает повторный запуск предыдущего успешного запуска. Повторный запуск проверяет исходную фиксацию SHA , которая активировала выполнение (а не текущая ветвь HEAD), поэтому она перестраивает и развертывает файл кода и параметров с этого момента времени. Вам не нужны новые коммиты.

Чтобы выполнить откат развертывания, повторно выполнив предыдущий успешный запуск:

  1. Перейдите на вкладку "Действия" в репозитории GitHub.
  2. Найдите последний успешный рабочий процесс перед плохим развертыванием.
  3. Выберите "Повторно выполнить все задания".
  4. Рабочий процесс извлекает коммит этого запуска, пересобирает проект, развертывает код и синхронизирует настройки приложения из app-settings.json этого коммита.

Что происходит при повторной сборке

Повторный запуск пересобирает код из старого коммита. Он не использует исходный двоичный артефакт. Это означает:

  • При использовании закреплённых lock-файлов зависимостей (package-lock.json, requirements.txt и т. д.) результат функционально идентичен.
  • Время сборки совпадает с обычным развертыванием. Это не мгновенно.
  • Внешние зависимости, извлекаемые во время сборки (NuGet, npm, pip), по-прежнему должны быть доступны.

Соображения по откату

  • Закрепляйте файлы блокировки зависимостей (package-lock.json, requirements.txt или заблокированные версии .csproj) в системе контроля версий. Зафиксированные lock-файлы гарантируют, что повторный запуск развертывания приводит к созданию функционально идентичной сборки независимо от того, когда этот повторный запуск выполняется.

  • При повторном запуске используется YAML-файл рабочего процесса или конвейера из исходного коммита. Однако при повторном запуске секреты и переменные конвейера подставляются в своих актуальных значениях. Если вы меняете секреты между исходным запуском и повторным запуском, используется новое значение секрета.

  • Повторный запуск восстанавливает развернутое приложение до заведомо рабочего состояния, но не изменяет историю Git. HEAD вашей ветви по-прежнему указывает на повреждённый коммит.

  • Что не восстанавливается при повторном запуске:

    • Конфигурация ресурсов Azure, управляемая за пределами вашего развертывания, включая планы хостинга, сетевые настройки и назначения удостоверений.
    • Изменения данных или схемы в подчиненных службах, таких как базы данных, очереди сообщений и хранилище.
    • Значения секретов Key Vault В системе контроля версий хранятся только ссылки на Key Vault. Ротация секретов — это операция в Key Vault.
  • Регулярно тестируйте процесс отката. Не ждите, пока сбой в продакшене покажет, что что-то сломано.

Исправление ветви после отката

Поскольку следующий запуск, вызванный push'ем, повторно развёртывает сломанный коммит, другие разработчики, делающие pull этой ветки, по-прежнему видят неработающий код. Эту ситуацию необходимо исправить с помощью одного из следующих действий:

  • Создайте коммит с хотфиксом, устраняющий проблему; по сути, это операция roll forward.
  • Выполните git revert для отмены ошибочной фиксации путём создания новой фиксации, что также является операцией roll forward.
  • Политика ветки, запрещающая слияние до устранения проблемы.

Пока вы не выполните одно из этих действий, не запускайте новый прогон в этой ветке. Рекомендации по проверке см. в разделе "Проверка перед слиянием".

Перейти к следующему развертыванию

Продвижение вперёд означает публикацию нового коммита для устранения проблемы. Неработающее развертывание остается в режиме реального времени, пока не будет развернуто исправление, поэтому эта стратегия работает лучше, когда приложение может терпеть ухудшение поведения в течение этого времени.

  1. Создайте коммит с исправлением в вашей ветви. Это исправление может быть следующим:

    • Исправление, которое непосредственно устраняет проблему.
    • git revert <bad-commit-sha> — команда, которая создает новый коммит, отменяющий ошибочные изменения. Несмотря на то, что git revert откатывает код, это движение вперёд, потому что при этом создаётся новый коммит и запускается новое развёртывание.
  2. Если исправление также требует изменений конфигурации, обновите настройки приложения (либо в app-settings.json, либо в шаблоне Bicep) в рамках того же коммита.

  3. Отправьте коммит. Ваше развертывание автоматически собирает и развертывает исправление.

Проверка перед слиянием

Независимо от вашей стратегии восстановления проверяйте и исправляйте коммиты перед слиянием в ветвь production, чтобы не усугубить проблему.

Эти рекомендации применяются независимо от того, заранее ли вы выполняете продвижение вперёд или исправляете ветвь после отката:

  • Используйте промежуточную среду: так как план потребления Flex в настоящее время не поддерживает слоты развертывания, вместо этого рассмотрите возможность развертывания в отдельном приложении плана потребления Flex, чтобы проверить исправление перед слиянием с рабочей ветвью.

  • Автоматизация проверок работоспособности. Добавьте шаг postdeploy, который вызывает конечную точку проверки работоспособности в приложении и проверяет положительный ответ. При сбое рассмотрите возможность повторного запуска предыдущего успешного запуска для автоматического отката.

  • Мониторинг после развертывания: настройка оповещений Application Insights для обнаружения регрессии. Раннее обнаружение снижает влияние плохого развертывания.