Это третья часть из цикла статей о SSP (Supply‑Side Platform). В предыдущих статьях мы рассказывали о том, как поднимали систему и как боролись с проблемой несоответствия. В этой статье коснемся архитектуры и того, как от ее выбора зависит стоимость трафика.
На трафик уходило много денег, нужно было оптимизировать расходы
У клиента на AWS была развернута SSP система для предоставления рекламы на сайте.
Ежемесячные затраты на инфраструктуру составляли в среднем 25 000 $ в месяц (ежедневное использование от 750 до 900 $). Около 10 000 $ из этих ежемесячных расходов приходилось на стоимость сетевого трафика. Именно поэтому мы приняли решение взять в приоритет оптимизацию расходов на него.
Идея была в том чтобы приобрести выделенные сервера с безлимитным тарифом на исходящий трафик в любом стороннем дата-центре (ЦОД) и перенести наиболее затратный по трафику компонент системы на эти сервера. Важное примечание: указанный компонент был stateless, то есть не хранил у себя никаких постоянных данных. Далее планировалось настроить балансировщик нагрузки для распределения трафика между ЦОД и AWS. В ЦОД планировалось отправлять базовую часть (то есть, максимальный суточный пик + запас в 20 %) имеющегося трафика, а в AWS отправлять всплески трафика, так как там настроено автомасштабирование.
Выходом стала гибридная архитектура
Мы проанализировали две возможные стратегии внедрения гибридной инфраструктуры:
- Слабосвязанная инфраструктура (инфраструктура в ЦОД будет самодостаточной, то есть не будет зависеть от инфраструктуры в AWS) — в рамках этой стратегии рассматривали развертывание отдельных кластеров Kubernetes в AWS и ЦОД (с меньшими затратами на трафик), способные работать практически независимо (в нашем случае это означает наличие собственного кластера Aerospike, отдельного кластера NATS);
- Сильносвязанная инфраструктура (инфраструктура в ЦОД будет зависеть от компонентов в AWS) — на выделенные сервера в ЦОД развернуть часть SSP, которая генерирует много трафика и организовать для нее возможность использовать сервисы в AWS. Такие как NATS, Aerospike, Prometheus, AWS S3, AWS Kinesis Firehose, AWS OpenSearch.
Потратив некоторое время на анализ и исследование вышеуказанных стратегий мы получили общее представление о плюсах и минусах каждой, а самое главное — понимание необходимых ресурсов для их реализации. Для реализации обеих стратегий требовался VPN-канал между AWS и ЦОД. Именно подходы к реализации этого канала показались нам менее надежными и более усложненными в реализации слабосвязанной инфраструктуры. Поэтому мы решили, что реализация сильносвязанной инфраструктуры — более предпочтительный вариант.
Разработали два плана для перехода на новую архитектуру
Как упоминалось выше, основным требованием для реализации гибридной инфраструктуры является обеспечение надежного и безопасного канала связи между AWS и ЦОД, чтобы сервисы AWS были доступны для ЦОД. Для реализации этого коммуникационного уровня мы протестировали:
- Решения для подключения Kubernetes к Kubernetes на основе Submariner/Liqo;
- Классические решения для подключения VPN между ЦОД.
Решили двигаться последовательно и попробовать оба варианта, чтобы выбрать наиболее подходящий. То есть, приняли решение подготовить два последовательных плана в зависимости от результатов тестирования:
- «План A» — проверить решения для подключения Kubernetes к Kubernetes — если они соответствуют нашим потребностям и показывают хорошие результаты во время тестов, мы будем использовать этот вариант;
- «План Б» — в противном случае мы переключимся на решение для подключения на основе VPN.
В рамках «Плана A» мы развернули и протестировали два известных решения для подключения Kubernetes к Kubernetes, Submariner и Liqo. К сожалению, у них есть проблемы, которые блокируют их использование в нашем проекте.
Например:
- Submariner не работает с облачным сетевым подключаемым модулем CNI и требует, чтобы использовался один из других подключаемых модулей CNI. Это приводит к большому количеству пользовательских настроек в облачных рабочих узлах Kubernetes, и большинство этих настроек требуют дополнительных шагов для автоматизации. С другой стороны, Submariner предоставляет полнофункциональное межкластерное обнаружение сервисов (ServiceDiscovery), которое было бы весьма полезно для нашей реализации;
- Liqo работает с облачными плагинами CNI по умолчанию, и общий процесс установки намного проще, но он не имеет функции обнаружения сервисов (ServiceDiscovery). Как уже упоминалось, Liqo отлично работает с облачным плагином CNI по умолчанию, но имеет много проблем при использовании других плагинов CNI.
В результате нашего первоначального исследования решений для подключения Kubernetes к Kubernetes мы решили перейти к «Плану Б» — есть несколько решений VPN/Connectivity, которые мы могли бы реализовать в этом случае:
- Предоставляемое облаком VPN Site to Site — этот вариант хорошо работал в наших тестах (задержка ~ 2 мс, пропускная способность ~ 850 Мбит/с);
- Пользовательское решение Site-to-Site VPN (например, Wireguard или автономные службы IPsec).
Мы решили использовать облачное VPN Site-to-Site, так как у нас есть большой опыт использования этого подхода в нескольких других проектах.
Что мы сделали для запуска
- В системе уже использовался CloudFlare DNS+CDN в качестве DNS хостинга, включили дополнительную возможность для балансировки трафика для распределения трафика между ЦОД и AWS. Доли трафика распределяются в процентном соотношении, настройки можно менять по API;
- Описали и автоматизировали процесс добавления нового сервера на стороне хостинга;
- Подняли сервер с VPN Site-to-Site для взаимодействия с сервисами в облачном провайдере (Aerospike, Prometheus метрики, логирование, Kinesis Firehose, NATS);
- Так как масштабирование ресурсов в ЦОД достаточно долгий процесс, а количество имеющихся серверов не смогут стабильно обработать всплески трафика, то нам необходимо иметь возможность переводить долю трафика на ресурсы в AWS;
Добавили динамическое изменение по API распределения доли трафика между ЦОД и AWS в зависимости от входящего трафика (QPS) или использования аппаратных ресурсов на основе метрик (CPU и Memory) в Prometheus. Prometheus hook запускает Lambda функцию и на основании метрик функция обновляет настройки распределения доли трафика в CloudFlare. Также добавили алгоритм обнаружения аномалий, чтобы отслеживать неожиданные быстрые изменения показателей;
- Обновили информационные панели в Grafana с учетом гибридной архитектуры. Добавили возможность просматривать метрики для ЦОД и/или AWS;
- Обновили систему деплоя с учетом гибридной архитектуры (реализовали простенький аналог blue green deployment: обновляем одно окружение, затем переключаемся на него, затем обновляем другое окружение);
- В результате 2 месяцев эксплуатации гибридной архитектуры в производстве приблизительные расчеты показывают, что мы сэкономили от 50 до 60 % ежемесячного бюджета инфраструктуры.