Автоскейлинг и canary-деплой на Azure Container Apps с KEDA и Dapr

Пиковые нагрузки и ручные выпуски версий съедают время команды и нервы заказчика. Мы настраиваем автоскейлинг и канареечный выпуск под ключ: приложение само добавляет ресурсы на пике и отдаёт новую версию части пользователей. Нагрузка распределяется ровно, откат занимает минуты, а ручное вмешательство больше не нужно.
Часто задаваемые вопросы

Почему Azure Container Apps теряет запросы при пике

Azure Container Apps масштабирует контейнеры по событиям и метрикам, но на резком пике трафика приложение всё равно начинает отдавать 5xx. Дело не в нехватке ресурсов, а в задержке управляющего контура: решение о добавлении реплик принимается медленнее, чем растёт нагрузка.

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

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

Так отказы при пике складываются из двух волн: сначала входной поток превышает текущую ёмкость до срабатывания автоскейлинга, затем часть запросов попадает на неготовые реплики. В метриках это 503 на входе, рост 95-го и 99-го процентиля времени ответа и обрывы соединений у части клиентов.

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

Что даёт автоскейлинг и канареечный выпуск

Канареечный выпуск держит две ревизии одновременно: на новую уходит 5-10% трафика, остальное обслуживает предыдущая. Долю ошибок и время ответа новой ревизии сравнивают с базовой в реальном времени — при выходе за порог трафик возвращается на проверенную ревизию за секунды. Простоя сервиса при этом нет: пользователь не видит ни перезапуска, ни обрывов соединений.

Масштабирование по событиям меняет профиль реакции на нагрузку. Реплики добавляются не по загрузке процессора, а по длине очереди и числу незакрытых сообщений, поэтому ночной всплеск разбирается на десятки секунд раньше, чем успел бы сработать порог по метрикам железа. В Azure Container Apps правила масштабирования и разбиение трафика между ревизиями описаны декларативно, так что поведение под нагрузкой воспроизводится на любом стенде, а не настраивается заново.

Отсюда — классы инцидентов, которые перестают доходить до пользователя:

  • деградация после релиза: откат секундами, без ручного вмешательства дежурного;
  • отказ одной зоны: реплики поднимаются в оставшихся, время восстановления — единицы секунд;
  • ночная очередь: ёмкость растёт вместе с ней и так же уходит вниз, когда поток спал.

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

Режимы масштабирования и стратегии выпуска версий

В Azure Container Apps масштабирование и выпуск версий опираются на один механизм — неизменяемые ревизии приложения. Каждая ревизия получает свою долю трафика, поэтому раскатка новой сборки и откат выполняются переключением весов, без пересборки и простоя. Мощность задаётся правилами: по загрузке процессора и памяти, по длине очереди, по расписанию — вплоть до масштабирования до нуля.

Вариант Когда подходит Ограничения
Фиксированное число реплик ровная нагрузка, внутренние сервисы пик не переживает, в простое ресурсы простаивают
Правила по метрике переменный трафик, разбор очередей реакция с задержкой, чувствительность к порогу, холодный старт
Расписание известные окна: рабочие часы, пакетные задания незапланированный всплеск вне окна не покрывает
Выпуск по доле трафика проверка версии на части пользователей обе версии живут одновременно: контракты сервисов и схема данных должны быть совместимы
Сине-зелёный выпуск критичный сервис, нужен мгновенный откат двойной запас ресурсов на время переключения

Общее ограничение: совместимость данных

Общее ограничение у всех стратегий — состояние. Пока трафик делится между версиями, изменения схемы обязаны быть обратно совместимыми: сначала добавляем поля и читаем оба формата, старые убираем только после полного переключения. Иначе откат вернёт код, который уже не понимает данные.

Как мы внедряем автоскейлинг: этапы работ

Порядок работ строится от измеренной нагрузки к правилам, а не наоборот: сначала снимаем профиль спроса в Azure Container Apps, затем фиксируем схему масштабирования и только потом включаем изменения в рабочем контуре. Расхождение между тестовым и рабочим поведением сервиса — обычный источник ложных срабатываний.

  1. Обследование нагрузки. Снимаем метрики за несколько недель: интенсивность запросов, длительность обработки, глубину очередей, потребление ресурсов на пиках. По ним выбираем триггер, отражающий реальный спрос, а не косвенный признак.
  2. Схема масштабирования. Разводим фронт, API и фоновые обработчики на независимо масштабируемые группы, задаём минимум и максимум реплик и разделяем окружения, чтобы разработка не конкурировала с продом за ёмкость.
  3. Настройка правил. Описываем триггеры KEDA — очередь, поток событий, расписание — и подбираем окна охлаждения с шагом наращивания, чтобы реплики не дёргались на коротких всплесках. Правила храним как код и проводим через ревью.
  4. Canary-деплой. Выводим версию на долю трафика, сравниваем долю ошибок и время ответа с базовой, откат настраиваем автоматическим по порогу.
  5. Приёмочные проверки. Прогоняем профиль нагрузки из первого шага со ступенчатыми пиками и отказом внешней зависимости: замеряем время выхода на пик, потолок реплик и время возврата.
  6. Передача в эксплуатацию. Отдаём конфигурацию в репозитории, дашборды по репликам и триггерам, алерты на упор в потолок и на отказы, регламент дежурства с типовыми сценариями.

Конфигурации, схемы и регламенты после внедрения

После вывода сервиса в продуктив у команды остаётся не только работающий контур, но и набор артефактов, по которым его можно менять без нас. Всё лежит в репозитории заказчика вместе с историей правок: изменение конфигурации проходит ревью и попадает в среду тем же путём, что и код, поэтому в Azure Container Apps не появляется настроек «руками через консоль». Ниже — что именно передаём.

  • Конфигурация масштабирования — правила и диапазон реплик по каждому сервису, пороги срабатывания по метрикам, поведение при простое и время прогрева перед приёмом нагрузки.
  • Схема сервисов — связи между компонентами, точки входа, очереди и внешние зависимости, с явной границей ответственности приложения и платформы.
  • Правила доступа — роли, удостоверения сервисов, сетевые ограничения и порядок выдачи прав новому компоненту или подрядчику.
  • Регламент выпуска — порядок канареечного выпуска: доля трафика на новую ревизию, метрики-критерии продвижения и условия автоматического возврата.
  • Инструкция по откату — пошаговый возврат на предыдущую ревизию, включая совместимость со схемой данных и проверки после отката.
  • Карта наблюдаемости — какие метрики, журналы и оповещения заведены, на какие пороги настроены и кто получает уведомление при срабатывании.
  • Памятка по окружениям — чем отличаются среды, где хранятся секреты и переменные, как добавить новую среду без правки шаблонов.

Кейс: пиковая нагрузка без ручного вмешательства

Сервис оформления заявок для корпоративных клиентов держал пик в конце рабочего дня и в начале отчётного периода: за час приходило столько же запросов, сколько за остальные сутки. Масштабирование было привязано к загрузке процессора, а она росла уже после того, как очередь на обработку переполнялась. На пике доля неуспешных запросов доходила до 8 %, отклик на 95-м процентиле растягивался до нескольких секунд, а дежурный инженер поднимал реплики вручную три-четыре раза за сутки.

Приложение перенесли в Azure Container Apps и перевели масштабирование на внешние метрики — длину очереди и число одновременных запросов вместо загрузки процессора. Порог подъёма задали с запасом, а гашение реплик — с задержкой, чтобы короткая просадка не снимала уже прогретые экземпляры.

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

После перевода дежурства стали плановыми — раз в неделю вместо трёх-четырёх вызовов в сутки. Доля неуспешных запросов снизилась с 8 % до 0,4 %, отклик на 95-м процентиле сократился втрое, пик обслуживается без участия инженера. Выкат на долю трафика оставили включённым: откат на предыдущую версию занимает минуты.

Чем автоскейлинг в Azure отличается от ручного

Ручное масштабирование держит заданное число реплик: платформа не смотрит на нагрузку, пока инженер не изменит значение сам. На ровном потоке это предсказуемо, но всплеск — рост очереди, задержки, отказы — закрывает только дежурный, а в часы затишья вы платите за простой ресурсов.

Масштабирование по расписанию снимает часть ручной работы: правило задаёт, сколько реплик держать в рабочие часы и сколько ночью. Это работает при повторяющемся профиле нагрузки и ломается на разовых акциях.

Вариант Когда подходит Ограничения
Ручное Ровный поток, отладка, редкие релизы Реакция только со стороны дежурного
По расписанию Повторяющиеся суточные и недельные пики Не видит внеплановый рост
Событийное Очереди, потоки запросов, пакетные задания Нужен верный порог и окно стабилизации
Комбинированное Предсказуемая база плюс всплески Сложнее настраивать, нужен нагрузочный тест

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

Комбинированная схема в Azure Container Apps закрывает оба сценария: расписание выводит базовый уровень к утреннему пику, событийный триггер добирает реплики под фактическую нагрузку. Мы сначала снимаем профиль нагрузки, затем подбираем пороги и подтверждаем их нагрузочным тестом — иначе правило выглядит рабочим, но не срабатывает там, где нужно.

Технические вопросы, которые задают перед стартом

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

Что будет с активными соединениями при выпуске новой версии?

Платформа поднимает новую ревизию рядом со старой и переводит на неё часть трафика. Старая гасится не сразу, а после того, как обработка активных запросов и соединений завершится, — обрывов на стороне клиента нет. Если проверки не прошли, вес трафика автоматически возвращается на предыдущую ревизию: автоматический откат настроен заранее, а не включается вручную в момент аварии.

Нужно ли переписывать приложение?

В большинстве случаев нет. Приложение собирается в тот же контейнер, что и раньше, а сверху добавляются декларативные правила: по какому событию масштабироваться, сколько ревизий держать, как распределять трафик. Точечные доработки нужны, только если сервис сам управляет соединениями с источником событий или держит состояние в памяти процесса.

Где верхняя граница масштабирования?

Задаётся явно: минимальное и максимальное число реплик плюс правило по метрике. Это защита от лавины — при всплеске нагрузка растёт предсказуемо до выставленного потолка, а не до исчерпания квоты. Мы подбираем границы по профилю нагрузки: сколько событий приходит в пике, как быстро обрабатывается одно, какой запас нужен на разогрев.

Что делать, если источник событий недоступен?

Разделяем два случая — недоступность источника и отставание очереди. Пороги вешаем на длину очереди, а не только на сами события, чтобы масштабирование реагировало на накопление. Поведение реплик при нулевой нагрузке тоже настраивается: уход в ноль или удержание минимума, если сервису нужен прогрев.

Обсудим задачу автоскейлинга и выпуска версий

Чтобы вернуться с оценкой и планом, а не с общими соображениями, нам нужен минимум входных данных от заказчика. Ниже — то, что спрашиваем на первом разговоре; обычно хватает получаса обсуждения и доступа к репозиторию с манифестами и конфигурацией платформы, включая Azure Container Apps.

  • Профиль нагрузки: суточный и недельный график, пиковые окна, доля фоновых и периодических задач, распределение запросов по операциям.
  • Схема сервисов: какие компоненты не хранят состояние, какие держат его сами, кто общается синхронно, а кто через очереди и события.
  • Текущие правила масштабирования и узкие места: как ведёт себя система при всплеске, сколько длится запуск нового экземпляра, что упирается в лимиты платформы.
  • Требования к выпуску версий: доля трафика на канареечный вариант, условия автоматического отката, допустимое окно частичной деградации.
  • Доступы и ограничения: среды, приватные сети, роли, политики безопасности и регламент изменений в проде.
  • Приёмка результата: какие метрики считаем целевыми и на каких сценариях проверяем — резкий всплеск, отказ экземпляра, откат на предыдущий релиз.

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

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    815
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139