Привет, Хабр! Меня зовут Сергей Дербуш, я архитектор в компании «СмартАп Технолоджи».
Это третья часть из цикла статей о 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 % ежемесячного бюджета инфраструктуры.
Приглашаю в комментарии обсудить кейс и поделиться вашим опытом работы с архитектурой.