Масштабирование и надёжность

Обновлено 5 мин чтения

Autoscaling: почему инфраструктура должна расти вместе с нагрузкой, а не заранее

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

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

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

Начать стоит с того, что именно ждёт клиент

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

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

Но и количество заданий не всегда равно объёму работы. Файл из нескольких строк и годовая выгрузка могут считаться одной задачей. Тогда нужно учитывать распределение длительности, размер работ и задержку самых старых заданий. Иначе средний показатель будет успокаивать команду, пока отдельные клиенты ждут недопустимо долго.

Новый экземпляр ещё должен начать приносить пользу

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

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

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

Добавили приложение — перегрузили базу

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

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

Отдельно проверьте, не скрывает ли защита от перегрузки сигнал для масштабирования. Если приложение заранее отклоняет лишние запросы и удерживает CPU низким, контроллер, ориентированный только на CPU, может не увидеть неудовлетворённый спрос. В разборе load shedding в Amazon Builders’ Library описана именно такая неприятная взаимосвязь.

Уменьшать мощность иногда труднее, чем увеличивать

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

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

Не стоит одинаково быстро реагировать на рост и кратковременное снижение нагрузки. Иначе процессы будут постоянно запускаться и останавливаться. Окна стабилизации и ограничение скорости уменьшения мощности помогают сгладить такие колебания; конкретные механизмы приведены, например, в документации Horizontal Pod Autoscaler.

Верхний предел — начало решения о сервисе

У автоматизации должны быть границы, а у достижения этих границ — понятное последствие. Если максимально допустимая мощность уже занята, новые работы не исчезнут. Их придётся ограничить, принять с честным сроком ожидания или отклонить до того, как клиенту обещан результат.

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

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

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

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

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