Создание масштабируемого API на спотовых инстансах AWS

Всем привет! Меня зовут Кирилл, я CTO в Adapty. Большая часть нашей архитектуры находится на AWS, и сегодня я расскажу о том, как мы сократили расходы на сервера в 3 раза за счёт использования спотовых инстансов на продакшн окружении, а также о том, как настроить их автомасштабирование. Сначала будет обзор того, как это работает, а потом подробная инструкция для запуска.


Что такое спотовые инстансы?

Спотовые инстансы — это сервера других пользователей AWS, которые в данный момент простаивают, и они продают их с большой скидкой (Amazon пишет до 90%, по нашему опыту ~3x, варьируется в зависимости от региона, AZ и типа инстанса). Основное их отличие от обычных в том, что они могут выключиться в любой момент. Поэтому мы долгое время считали, что их нормально использовать для дев окружений, либо для задач по расчёту чего-то, с сохранением промежуточных результатов на S3 или в базу, но не для прода. Существуют сторонние решения, которые позволяют использовать споты на проде, но там для нашего кейса много костылей, поэтому мы не внедряли их. Подход, описанный в статье, работает полностью в рамках стандартного функционала AWS, без дополнительных скриптов, кронов и тд.

Далее приведу несколько скриншотов, которые показывают историю цен на спотовые инстансы.

m5.large в регионе eu-west-1 (Ireland). Цена преимущественно стабильна на протяжении 3 месяцев, в настоящий момент экономия 2.9x.

image

m5.large в регионе us-east-1 (N. Virginia). Цена постоянно меняется на протяжении 3 месяцев, в настоящий момент экономия от 2.3x до 2.8x в зависимости от зоны доступности.

image

t3.small в регионе us-east-1 (N. Virginia). Цена стабильна на протяжении 3 месяцев, в настоящий момент экономия 3.4x.

image


Архитектура сервиса

Базовая архитектура сервиса, о котором мы будем говорить в рамках данной статьи, изображена на диаграмме ниже.

image


Application Load Balancer → EC2 Target Group → Elastic Container Service

В качестве балансировщика используется Application Load Balancer (ALB), который отправляет запросы в EC2 Target Group (TG). TG отвечает за то, чтобы открыть на инстансах порты для ALB и связать их с портами контейнеров Elastic Container Service (ECS). ECS — это аналог Kubernetes в AWS, который занимается менеджментом Docker контейнеров.

На одном инстансе может быть несколько работающих контейнеров с одинаковыми портами, поэтому мы не можем задать их фиксировано. ECS сообщает TG, что он запускает новый таск (в терминологии Kubernetes это называется под), она делает проверку свободных портов на инстансе и назначает один из них для запускаемого таска. Также TG регулярно проверяет, работает ли инстанс и апи на нём с помощью health check, и если видит какие-то проблемы, то перестаёт передавать туда запросы.


EC2 Auto Scaling Groups + ECS Capacity Providers

В приведённой выше диаграмме не показан сервис EC2 Auto Scaling Groups (ASG). Из названия можно понять, что он отвечает за масштабирование инстансов. При этом до недавнего времени в AWS не было встроенной возможности управлять количеством запущенных машин из ECS. ECS позволял масштабировать количество тасков, например, по использованию CPU, RAM или количеству запросов. Но если таски занимали все свободные инстансы, то новые машины автоматически не поднимались.

Это изменилось с появлением ECS Capacity Providers (ECS CP). Теперь каждый сервис в ECS можно связать с ASG, и если таски не умещаются на работающих инстансах, то поднимутся новые (но в рамках установленных лимитов ASG). Это работает и в обратную сторону, если ECS CP видит простаивающие инстансы без тасков, то он даст команду ASG, чтобы она их выключила. У ECS CP есть возможность указать целевой процент загрузки инстансов, так, чтобы некоторое количество машин было всегда свободно для быстрого масштабирования тасков, расскажу об этом чуть позже.


EC2 Launch Templates

Последний сервис, о котором я расскажу, прежде чем перейти к подробному описанию создания данной инфраструктуры, — EC2 Launch Templates. Он позволяет создать шаблон, по которому будут запускаться все машины, чтобы не повторять это каждый раз с нуля. Тут можно выбрать тип запускаемой машины, группу безопасности, образ диска и много других параметров. Также можно указать пользовательские данные, которые будут залиты на все запускаемые инстансы. В пользовательских данных можно запускать скрипты, например, можно отредактировать содержимое файла конфигурации ECS агента.

Один из наиболее важных в рамках данной статьи параметром конфигурации — ECS_ENABLE_SPOT_INSTANCE_DRAINING=true. Если этот параметр включен, то как только ECS получает сигнал о том, что спотовый инстанс забирают, он переводит все таски, которые работают на нём в статус Draining. Никакие новые таски на этот инстанс назначаться не будут, если есть таски, которые прямо сейчас хотят выкатится на него, они отменяются. Запросы с балансировщика тоже перестают приходить. Уведомление об удалении инстанса приходит за 2 минуты до фактического события. Поэтому если ваш сервис не выполняет задач дольше 2 минут и не сохраняет ничего на диск, то вы можете использовать спотовые инстансы без потери данных.

По поводу диска — AWS недавно сделал возможным использование Elastic File System (EFS) вместе с ECS, с этой схемой даже диск не является преградой, но мы это не пробовали, так как в принципе нам диск не нужен для хранения состояния. По умолчанию после получения SIGINT (отправляется в момент перевода таска в статус Draining) все работающие задачи будут остановлены через 30 секунд, даже если они не успели выполниться, изменить это время можно с помощью параметра ECS_CONTAINER_STOP_TIMEOUT. Главное не выставлять его больше 2 минут для спотовых машин.


Создание сервиса

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


EC2 Launch Template

В данном сервисе создаётся конфигурация машин, которые будут использоваться. Управление шаблонами происходит в разделе EC2 → Instances → Launch templates.

Amazon machine image (AMI) — указываем образ диска, с которым будут запускаться все инстансы. Для ECS в большинстве случаев стоит использовать оптимизированный образ от Amazon. Он регулярно обновляется и содержит всё необходимое для работы ECS. Чтобы узнать актуальный ID образа, заходим на страницу Amazon ECS-optimized AMIs, выбираем используемый регион и копируем AMI ID для него. Например, для региона us-east-1 актуальный на момент написания статьи ID — ami-00c7c1cf5bdc913ed. Этот ID нужно вставить в пункт Specify a custom value.

Instance type — указываем тип инстанса. Выбираете тот, который лучше всего подходит для вашей задачи.

Key pair (login) — указываем сертификат, с помощью которого можно будет подключиться с инстансу по SSH, если это нужно.

Network settings — указываем параметры сети. Networking platform в большинстве случаев должна быть Virtual Private Cloud (VPC). Security groups — группы безопасности для ваших инстансов. Так как мы будем использовать балансировщик перед инстансами, то рекомендую указывать здесь группу, которая разрешает входящие соединения только с балансировщика. То есть у вас будет 2 группы безопасности, одна для балансировщика, которая разрешает входящие (inbound) соединения отовсюду по портам 80 (http) и 443 (https), а вторая для машин, которая разрешает входящие соединения по любым портам от группы балансировщика. Исходящие (outbound) соединения в обеих группах нужно открыть по TCP протоколу на все порты на все адреса. Можно ограничить порты и адреса для исходящих соединений, но тогда нужно постоянно мониторить, что вы не пытаетесь обратиться куда-то по закрытому порту.

Storage (volumes) — указываем параметры дисков для машин. Объём диска не может быть меньше того, что задан в AMI, для ECS Optimized — 30 GiB.

Advanced details — указываем дополнительные параметры.

Purchasing option — хотим ли мы покупать спотовые инстансы. Мы хотим, но здесь эту галочку отмечать не будем, настроим это в Auto Scaling Group, там больше опций.

IAM instance profile — указываем роль, с которой будут запускать инстансы. Для того, чтобы инстансы работали в ECS, им нужны права, которые обычно лежат в роли ecsInstanceRole. В некоторых случаях она может быть создана, если нет, то здесь инструкция о том, как это сделать. После создания указываем её в шаблоне.
Дальше идёт много параметров, в основном везде можно оставлять дефолтные значения, но у каждого из них понятное описание. Я всегда включаю параметры EBS-optimized instance и T2/T3 Unlimited, если используются burstable инстансы.

User data — указываем пользовательские данные. Мы будем редактировать файл /etc/ecs/ecs.config, в котором лежит конфигурация агента ECS.
Пример того, как может выглядеть user data:

#!/bin/bash
echo ECS_CLUSTER=DemoApiClusterProd >> /etc/ecs/ecs.config
echo ECS_ENABLE_SPOT_INSTANCE_DRAINING=true >> /etc/ecs/ecs.config
echo ECS_CONTAINER_STOP_TIMEOUT=1m >> /etc/ecs/ecs.config
echo ECS_ENGINE_AUTH_TYPE=docker >> /etc/ecs/ecs.config
echo "ECS_ENGINE_AUTH_DATA={\"registry.gitlab.com\":{\"username\":\"username\",\"password\":\"password\"}}" >> /etc/ecs/ecs.config

ECS_CLUSTER=DemoApiClusterProd — параметр указывает, что инстанс принадлежит кластеру с заданным именем, то есть этот кластер сможет размещать на этом сервере свои таски. Мы пока не создали кластер, но при создании будем использовать это имя.

ECS_ENABLE_SPOT_INSTANCE_DRAINING=true — параметр указывает, что при получении сигнала о выключении спотового инстанса, все таски на нём должны переводиться в статус Draining.

ECS_CONTAINER_STOP_TIMEOUT=1m — параметр указывает, что после получения сигнала SIGINT, у всех задач есть 1 минуты, прежде чем их убьют.

ECS_ENGINE_AUTH_TYPE=docker — параметр указывает, что в качестве механизма авторизации используется docker-схема

ECS_ENGINE_AUTH_DATA=... — параметры подключения к приватному container registry, где хранятся ваши Docker образы. Если он публичный, то ничего указывать не нужно.

В рамках данной статьи я буду использовать публичный образ из Docker Hub, поэтому указывать параметры ECS_ENGINE_AUTH_TYPE и ECS_ENGINE_AUTH_DATA не нужно.

Полезно знать: рекомендуется регулярно обновлять AMI, потому что в новых версиях обновляются версии Docker, Linux, ECS агента и др. Чтобы не забывать об этом, можно настроить уведомления о выходе новых версий. Вы можете получать уведомления на email и обновлять руками, а можете написать Lambda-функцию, которая будет автоматически создавать новую версию Launch Template с обновлённым AMI.


EC2 Auto Scaling Group

Auto Scaling Group отвечает за запуск и масштабирование инстансов. Управление группами происходит в разделе EC2 → Auto Scaling → Auto Scaling Groups.

Launch template — выбираем созданный на предыдущем шаге шаблон. Версию оставляем дефолтную.

Purchase options and instance types — указываем типы инстансов для кластера. Adhere to launch template использует тип инстанса из Launch Template. Combine purchase options and instance types позволяет гибко настраивать типы инстансов. Мы будем использовать его.

Optional On-Demand base — количество обычных, не спотовых инстансов, которые всегда будут работать.

On-Demand percentage above base — процентное соотношение обычных и спотовых инстансов, 50–50 будет распределять поровну, 20–80 на каждый обычный инстанс будет подниматься 4 спотовых. В рамках данного примера я укажу 50–50, но в реальности мы чаще всего делаем 20–80, в некоторых случаях 0–100.

Instance types — тут можно указать дополнительные типы инстансов, которые будут использоваться в кластере. Мы никогда не использовали, потому что я не очень понимаю смысл этой истории. Возможно дело в лимитах на конкретные типы инстансов, но они увеличиваются через поддержку легко. Если вы знаете применение, буду рад прочитать в комментариях)

image

Network — настройки сети, выбираете VPC и подсети для машин, в большинстве случаев стоит выбрать все доступные подсети.

Load balancing — настройки балансировщика, но мы это сделаем отдельно, здесь ничего не трогаем. Health checks также будут настроены позже.

Group size — указываем лимиты на количество машин в кластере и желаемое количество машин на старте. Количество машин в кластере никогда не станет меньше минимально указанного и больше максимального, даже если по метрикам должно произойти масштабирование.

Scaling policies — параметры масштабирование, но мы будем масштабировать, отталкиваясь от запущенных ECS тасков, поэтому настроим масштабирование позже.

Instance scale-in protection — защита инстансов от удаления при масштабировании вниз. Включаем, чтобы ASG не удалила машину, на которой есть работающие таски. Отключать защиту для инстансов, на которых нет тасков, будет ECS Capacity Provider.

Add tags — можно указать теги для инстансов (для этого должна стоять галочка Tag new instances). Рекомендую указать тег Name, тогда все инстансы, которые запускаются в рамках группы, будут одинаково называться, их удобно смотреть в консоли.

image

После создания группы откройте её и зайдите в раздел Advanced configurations, почему на этапе создания в консоли видны не все опции.

Termination policies — правила, которые учитываются при удалении инстансов. Они применяются по порядку. Мы обычно используем такие, как на картинке ниже. Сначала удаляются инстансы с наиболее старым Launch Template (например, если мы обновили AMI, у нас создалась новая версия, но все инстансы успели на неё перейти). Потом выбираются инстансы, которые ближе всего к следующему расчётному часу по биллингу. И дальше выбираются самые старые по дате запуска.

image

Полезно знать: для обновления всех машин в кластере, удобно использовать Instance Refresh. Если совместить это с Lambda-функцией из предыдущего шага, то у вас будет полностью автоматизированная система апдейта инстансов. Перед обновлением всех машин необходимо отключить instance scale-in protection для всех инстансов в группе. Не настройку в группе, а именно защиту с самих машин, это делается на вкладке Instance management.


Application Load Balancer и EC2 Target Group

Балансировщик создаётся в разделе EC2 → Load Balancing → Load Balancers. Мы будем использовать Application Load Balancer, сравнение разных типов балансировщиков можно прочитать на странице сервиса.

Listeners — имеет смысл сделать 80 и 443 порты и сделать редирект с 80 на 443 с позже помощью правил балансировщика.

Availability Zones — в большинстве случаем выбираем всем зоны доступности.

Configure Security Settings — здесь указывается SSL-сертификат для балансировщика, самый удобный вариант — сделать сертификат в ACM. Про различия Security Policy можно почитать в документации, можно оставлять выбранный по умолчанию ELBSecurityPolicy-2016-08. После создания балансировщика, вы увидите его DNS name, на который необходимо настроить CNAME для вашего домена. Например, так это выглядит в Cloudflare.

image

Security Group — создаём или выбираем группу безопасности для балансировщика, подробнее об этом писал чуть выше в разделе EC2 Launch Template → Network settings.

Target group — создаём группу, которая отвечает за роутинг запросов с балансировщика на машины и проверяет их доступность, чтобы заменить в случае проблем. Target type должен быть Instance, Protocol и Port любые, если вы используете HTTPS для общения между балансировщиком и инстансами, то на них надо загрузить сертификат. В рамках данного примера мы это делать не будем, просто оставим 80 порт.

Health checks — параметры проверки работоспособности сервиса. В настоящем сервисе это должен быть отдельный запрос, который реализует важные части бизнес-логики, в рамках данного примера я оставлю настройки по-умолчанию. Далее можно выбрать интервал запросов, таймаут, коды успешных ответов и др. В нашем примере укажем Success codes 200–399, потому что Docker образ, который будет использоваться, возвращает 304 код.

image

Register Targets — здесь выбираются машины для группы, но в нашем случае этим будет заниматься ECS, поэтому просто пропускаем этот шаг.

Полезно знать: на уровне балансировщика можно включить логи, которые будут сохраняться в S3 в определённом формате. Оттуда их можно экспортировать в сторонние сервисы для аналитики, а можно делать SQL-запросы прямо по данным в S3 с помощью Athena. Это удобно и работает без какого-то дополнительного кода. Также рекомендую настроить удаление логов из бакета S3 по истечение заданного периода времени.


ECS Task Definition

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

Launch type compatibility — выбираем EC2.

Task execution IAM role — выбириаем ecsTaskExecutionRole. С помощью неё пишутся логи, даётся доступ к секретным переменным и др.

В разделе Container Definitions нажимаем Add Container.

Image — ссылка на образ с кодом проекта, в рамках данного примера я буду использовать публичный образ с Docker Hub bitnami/node-example:0.0.1.

Memory Limits — лимиты по памяти для контейнера. Hard Limit — жёсткий лимит, если контейнер выйдет за указанное значение, то выполнится команда docker kill, контейнер сразу же умрёт. Soft Limit — мягкий лимит, контейнер может выйти за указанное значение, но при этом при размещение тасков на машины будет учитываться этот параметр. Например, если на машине 4 GiB оперативной памяти, а soft limit контейнера — 2048 MiB, то на этой машине может быть максимум 2 запущенных таска с этим контейнером. В реальности 4 GiB оперативной памяти — это чуть меньше, чем 4096 MiB, это можно посмотреть на вкладке ECS Instances в кластере. Soft limit не может быть больше hard limit. Важно понимать, что если в одном таске есть несколько контейнеров, то их лимиты суммируются.

Port mappings — в Host port указываем 0, это значит, что порт будет назначаться динамически, его будет отслеживать Target Group. Container Port — порт, на котором работает ваше приложение, часто задаётся в команде для исполнения, либо назначается в коде вашего приложения, Dockerfile и тд. Для нашего примера используем 3000, потому что он указан в Dockerfile используемого образа.

Health check — параметры проверки работоспособности контейнера, не путать с тем, который настроен в Target Group.

Environment — настройки окружения. CPU units — похоже на Memory limits, только про процессор. Каждое ядро процессора — 1024 юнитов, так что если на сервере двухъядерный процессор, и у контейнера стоит значение 512, то на одном сервере может быть запущено 4 таска с этим контейнером. CPU units всегда соответствуют количеству ядер, их не может быть чуть меньше как в случае с памятью.

Command — команда для запуска сервиса внутри контейнера, все параметры указываются через запятую. Это может быть gunicorn, npm и тд. Если не указано, то будет использовано значение директивы CMD из Dockerfile. Указываем npm,start.

Environment variables — переменные окружения контейнера. Это могут быть как просто текстовые данные, так и секретные переменные из Secrets Manager или Parameter Store.

Storage and Logging — здесь настроим логирование в CloudWatch Logs (сервис для логов от AWS). Для этого достаточно включить галочку Auto-configure CloudWatch Logs. После создания Task Definition автоматически создастся группа логов в CloudWatch. По умолчанию логи в ней хранятся бесконечно, рекомендую изменить Retention period с Never Expire на требуемый срок. Это делается в CloudWatch Log groups, надо кликнуть на текущий период и выбрать новый.

image


ECS Cluster и ECS Capacity Provider

Переходим в раздел ECS → Clusters, чтобы создать кластер. В качестве шаблона выбираем EC2 Linux + Networking.

Cluster name — очень важно, делаем здесь такое же имя, как указано в Launch Template в параметре ECS_CLUSTER, в нашем случае — DemoApiClusterProd. Отмечаем галочку Create an empty cluster. Опционально можно включить Container Insights, чтобы смотреть метрики по сервисам в CloudWatch. Если вы всё сделали правильно, то в разделе ECS Instances вы увидите машины, которые были созданы в Auto Scaling group.

image

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

Auto Scaling group — выбираем созданную ранее группу.

Managed scaling — включаем, чтобы провайдер мог масштабировать сервис.

Target capacity % — какой процент загрузки машин тасками нам нужен. Если указать 100%, то все машины всегда будет заняты работающими тасками. Если указать 50%, то половина машин всегда будут свободными. В таком случае, если случится резкий скачок в нагрузке, новые такси сразу попадут на свободные машины, без необходимости ждать развёртывания инстансов.

Managed termination protection — включаем, этот параметр разрешает провайдеру убирать защиту инстансов от удаления. Это происходит, когда на машине нет активных тасков и позволяет Target capacity %.


ECS Service и настройка масштабирования

Последний шаг:) Чтобы создать сервис, надо зайти в созданный ранее кластер на вкладку Services.

Launch type — надо кликнуть на Switch to capacity provider strategy и выбрать созданные ранее провайдер.

image

Task Definition — выбираем созданный раннее Task Definition и его ревизию.

Service name — чтобы не путаться, мы всегда указываем такой же, как Task Definition.

Service type — всегда Replica.

Number of tasks — желаемое количество активных тасков в сервисе. Этот параметр управляется масштабированием, но всё равно его надо указать.

Minimum healthy percent и Maximum percent — определяют поведение тасков при деплое. Значения по умолчанию 100 и 200, говорят о том, что в момент деплоя количество тасков увеличится в раза, а потом вернётся к желаемому. Если у вас работает 1 таск, min=0, а max=100, то тогда при деплое он будет убиваться, и после этого подниматься новый, то есть будет простой. Если работает 1 таск, min=50, max=150, то деплой вообще не случится, потому что он 1 таск нельзя разделить пополам или увеличить в полтора раза.

Deployment type — оставляем Rolling update.

Placement Templates — правила размещения тасков на машинах. По умолчанию стоит AZ Balanced Spread — это значит, кто каждый новый таск будет помещаться на новый инстанс до тех пор, пока не поднимутся машины во всех зонах доступности. Мы обычно делаем BinPack — CPU и Spread — AZ, при такой политике таски помещаются максимально плотно по на одну машину по CPU. При необходимости создания новой машины, она создаётся в новой зоне доступности.

image

Load balancer type — выбираем Application Load Balancer.

Service IAM role — выбираем ecsServiceRole.

Load balancer name — выбираем созданный ранее балансировщик.

Health check grace period — пауза перед выполнением проверок работоспособности после выкатки нового таска, мы обычно ставим 60 секунд.

Container to load balance — в пункте Target group name выбираем созданную ранее группу, и всё автоматически заполнится.

image

Service Auto Scaling — параметры масштабирования сервиса. Выбираем Configure Service Auto Scaling to adjust your service«s desired count. Задаём минимальное и максимально количество тасков при масштабировании.

IAM role for Service Auto Scaling — выбираем AWSServiceRoleForApplicationAutoScaling_ECSService.

Automatic task scaling policies — правила для масштабирования. Есть 2 типа:


  1. Target tracking — отслеживание целевой метрики (использование CPU/RAM или количество запросов на каждый таск). Например, мы хотим среднюю загрузку процессора была 85%, когда она станет выше, то новые таски будут добавляться до тех пор, пока она не придёт к целевому значению. Если загрузка ниже, то таски наоборот будут убираться, если не включена защита от масштабирования вниз (Disable scale-in).
  2. Step scaling — реакция на произвольное событие. Тут можно настроить реакцию на любое событие (CloudWatch Alarm), когда она будет происходить, можно добавить или убрать указанное количество тасков, либо же указать точное количество тасков.

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


Заключение

Если вы следовали инструкции и использовали тот же Docker образ, ваш сервис должен возвращать такую страницу.

image


  1. Мы создали шаблон, по которому запускаются все машины в сервисе. Мы также научились обновлять машины при изменении шаблона.
  2. Мы настроили обработку сигнала остановки спотового инстанса, поэтому в течение минуты после его получения все работающие таски убираются с машины, таким образом ничего не теряется и не прерывается.
  3. Мы подняли балансировщик, чтобы равномерно распределять нагрузку по машинам.
  4. Мы создали сервис, который работает на спотовых инстансах, за счёт этого сокращаются расходы на машины примерно в 3 раза.
  5. Мы настроили автомасштабирование в обе стороны, чтобы обрабатывать увеличение нагрузок, но в то же время не платить за простой.
  6. Мы используем Capacity Provider, чтобы приложение управляло инфраструктурой (машинами), а не наоборот.
  7. Мы молодцы.

Если у вас есть предсказуемые всплески нагрузки, например, вы рекламируетесь в большой email-рассылке, вы можете настроить масштабирование по расписанию.

Ещё можно делать масштабирование на основе данных из разных частей вашей системы. Например, у нас есть функционал рассылки индивидуальных промо-предложений пользователям мобильного приложения. Иногда кампания рассылается на 1М+ человек. После такой рассылки всегда наблюдается большой рост запросов к API, так как много пользователей одновременно заходят в приложение. Так что если мы видим, что в очереди на отправку промо-пушей их стало значительно больше стандартных показателей, мы сразу можем запустить несколько дополнительных машин и тасков, чтобы быть готовым к нагрузке.

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

Скоро будут статьи про то, как мы обрабатываем тысячи аналитических эвентов в секунду на преимущественно serverless стэке (с деньгами) и как устроен деплой сервисов с помощью GitLab CI и Terraform Cloud.

Подписывайтесь на нас, будет интересно!

© Habrahabr.ru