Прийшов час осідлати справжнього Буцефала🏇🏻Приборкай норовливого коня разом з Newxel🏇🏻Умови на сайті
×Закрыть

Масштабируем автоматизацию тестирования с помощью Kubernetes

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

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

Перед рассказом о нашем опыте использования Kubernetes хотел бы сказать пару слов о себе. Меня зовут Хурсевич Алексей, я занимаюсь автоматизацией и развертыванием инфраструктуры под эти цели уже около 8 лет. Данная статья будет полезна DevOps инженерам и автоматизаторам, перед которыми стоит задача создания масштабируемой и стабильной инфраструктуры для запуска автотестов.

Что уже есть на рынке по автоматизации тестирования

Существует множество популярных платных решений вроде BrowserStack, Sauce Labs и LambdaTest. Подобные кластеры браузеров и мобильных устройств для мануального и автоматизированного тестирования — хороший вариант для малого бизнеса, который не в состоянии инвестировать крупные суммы в покупку новых устройств. Благодаря этим сервисам вы получаете удаленный доступ к любому устройству за 150$. Однако для крупных предприятий, которые ежедневно проводят тысячи тестов, эти решения могут оказаться довольно дорогими. Не подойдут они и высокотехнологичным компаниям, которые используют для тестирования свои виртуальные сети (VPC).

На рынке также присутствует достаточно много open-source решений. Например, известный многим Selenium Grid или более новые решения, базирующиеся на технологии Docker — Selenoid или Zalenium. Так или иначе, все они предполагают покупку или аренду серверного оборудования и постоянную поддержку со стороны DevOps инженеров. Такие инвестиции оправданы в случае действительно больших объемов ежедневных запусков автоматизации.

Эффективное решение для нашей команды

Наша инфраструктура для автоматизации состоит из следующих компонентов:

  • Selenium Grid;
  • Jenkins;
  • Zebrunner (собственный репортинг-инструмент);
  • Sonar (для статического анализа кода);
  • OpenSTF (для удаленного управления мобильной фермой).

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

В 2018 мы увидели значительный рост популярности Kubernetes, многие современные сервисы использовали эту технологию. Так как у нас уже был набор Docker образов, мы без особых проблем смогли переехать в облако AWS и запустить все компоненты в контексте Kubernetes кластера.

Кластерная топология Kubernetes

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

В дополнение к фишкам master и worker node отмечу, что Kubernetes может быть развернут на различных инфраструктурах. Таким образом, кластеры можно легко разместить на личном оборудовании или у любого публичного облачного провайдера, например, Google, Amazon или Microsoft. Kubernetes предоставляет простое решение для создания кластерной сети, которая поддерживает связь с микросервисами через уровень абстракции услуг. При развертывании Kubernetes работает с такими объектами как Pods (аналог Docker-контейнера), Deployments, ReplicaSets и StatefulSets.

Основной челлендж

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

Сформулируем три критически важных вопроса:

  • Как сделать тестирование изолированным и стабильным?
  • Как все быстро настроить?
  • Как получить необходимую инфраструктуру по разумной цене?

Изоляция и стабильность

Сперва поговорим о качественной автоматизации для CI. Для нашего CI-пайплайна мы выбрали Jenkins по следующим причинам: это open-source, для него есть большое количество плагинов, беспрецедентная надежность при работе с различными пайплайнами для разработки и тестирования. Одним из ключевых нюансов при установке Jenkins является корректная подготовка новых worker образов.

Поэтому я настоятельно рекомендую использовать плагин Jenkins Kubernetes. Основная суть заключается в том, что он выполняет каждую новую задачу Jenkins в контексте нового Kubernetes pod и удаляет данный ресурс сразу по завершении задачи.

С помощью Jenkins Kubernetes плагина можно передавать разные докер-образы под разные типы Jenkins задач, например, образы окружений Android SDK или NodeJS. Более того, вы можете легко управлять ресурсами для различных задач, выделяя для них необходимое количество процессоров и мегабайт оперативной памяти. Подробные инструкции по настройке плагина доступны по этой ссылке.

Перейдем к кластеру Selenium в контексте Kubernetes. Если вы работали с обычной Selenium Grid под большой нагрузкой, возможно, вы замечали его периодическую нестабильность; скорее всего, вам приходилось регулярно его перезапускать. Новые тесты могут зависать из-за утечек памяти, что несомненно может стать болью для автоматизации. Команде Aerokube удалось выпустить гораздо более стабильную версию Selenium Grid под названием Selenoid. Основная идея в том, что каждый тест выполняется в отдельном Docker контейнере, а после завершения теста контейнеры удаляются.

В Aerokube Selenoid вы можете наблюдать за тестовой сессией через VNC — это весьма удобно при отладке автоматических тестов.

Aerokube предлагает платное решение Moon — это коммерческая имплементация Selenium. Moon использует Kubernetes для запуска браузеров. Идея практически такая же, как я описывал выше, но вместо Docker-контейнеров Moon работает с Kubernetes pods.

Важно отметить, что Kubernetes имеет набор официальных плагинов, которые помогают решать различные задачи. Среди них можно найти полезный Kubernetes Autoscaler, который позволяет горизонтально масштабировать ваш кластер при возрастании нагрузки. Для управления нагрузками плагин контролирует использование ресурсов инфраструктуры, автоматически увеличивая или уменьшая auto scaling группы.

Быстрое распределение

Предположим, что на начальном этапе у нас есть кластер из одного master и трех worker nodes. Там размещены Jenkins мастер и две реплики Moon.

Как только мы начинаем запускать автоматизацию, Jenkins пытается аллоцировать woker pods, а Moon в свою очередь запускает браузерные контейнеры. В какой-то момент Kubernetes Autoscaler получает сигнал о необходимости добавить в кластер дополнительные сервера для деплоймента всех новых pods. По итогу мы получаем горизонтальное масштабирование кластера и автоматическую аллокацию новых задач по серверам.

Рекомендации в документации Kubernetes делают упор на важность контролироля явного выделения ресурсов для pods. Вы просто задаете request / limits параметры для лимитирования CPU и Memory ресурсов. На рисунке ниже показан пример распределения ресурсов для Jenkins worker, браузера Moon и эмулятора Moon Android.

Еще одна интересная фича Kubernetes — это node селекторы. Проектные задачи могут требовать различные типы инстансов из AWS. Например, для запуска Android эмуляторов нам требуются bare-metal сервера с поддержкой технологии KVM, в то время как браузерные сессии мы можем запускать на обычных виртуальных машинах. Такое распределение достигается за счет простой инструкции nodeSelector, которая позволяет поместить очередной pod на необходимый тип сервера.

Экономия бюджета

Так что же с бюджетом? Наша компания смогла значительно сэкономить, используя автоматическое масштабирование Kubernetes и Amazon Spot Instances. Обычно автоматизация тестирования использует инфраструктуру не равномерно. Например, можно выполнять регрессионные тесты в течение нескольких часов ночью или уже прогонять полную регрессию в конце спринта. В противном случае загрузка инфраструктуры потребует 10-20% от полной мощности. С помощью этих инструментов можно повышать масштаб кластера только тогда, когда это необходимо, и не платить за неиспользуемые мощности. Благодаря Amazon Spot Instances, мы сэкономили практически 80% от цены за сервера. На диаграмме ниже показана реальная история экономии бюджета для одного из клиентов компании:

Итоги

Мы уже почти 2 года используем Kubernetes для менеджмента инфраструктуры для автоматизации. Мы ощутили значительное облегчение в поддержке кластера и увеличение показателей стабильности системы. Операционные затраты стали значительно ниже за счет разумного масштабирования и использования Amazon Spot instances. Технология Kubernetes становится мировым стандартом для оркестрации сложных мультимодульных приложений в контексте облачных провайдеров. Как вы видите из нашего примера — это вполне подходящее решение и для построения автоматизации.

LinkedIn

Похожие статьи

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

і напевно основне питання : нафіга то все ? яку проблему воно вам вирішує ?

Проблем решает несколько:
1. Масштабируемость (возможность раскатывать все на сотнях виртуалок)
2. Меньшие затраты (все скейлится / даунскейлится по необходимости твоей автоматизации)
3. Высокая стабильность работы (кубер их коробки дает достаточно много возможностей для контроля жизнеспособности твоих сервисов в кластере)

ви описали, те що отримали в кінці.
Але мені цікавить власне, що передувало цьому — якісь проблеми були у простішій зв’язці ?
і скільки тестів та як часто запускаєте ?

С ростом количества клиентов нам стало сложно администрировать кучу отдельных серверов, по итогу решили делать 1 большой кластер (аля SaaS решение) и разделять контексты под отдельных кастомеров. Запускаем в среднем от 80 до 100 тыс. тестов ежедневно в зависимости от фазы релиза.

от 80 до 100 тыс. тестов

це все UI тести ?

Да, это только e2e UI тесты mobile / web. API в несколько раз больше.

Тобто, у вас є кубер, у якому є дженкіс. Дженкіс запускає Moon, який також є у цьому ж кубері. Moon запускає браузер у цьому ж кластері ? правильно я все зрозумів

Почти, но не совсем. Цепочка следующая — ты запускаешь задачу на jenkins master (который крутится в кубере), он поднимает под эту задачу отдельный слейв в качестве кубернетес pod. Твои тесты уже по классике обращаются по http к moon (аналог selenium hub), он под каждую сессию стартует pod с соответствующим браузером / эмулятором.

ну власне, те що я описав — все у одному кластері.

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

і тести запускаються з цього слейва ?

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

а як розгортаєте це все ? є якийсь infrastructure-as-a-code ?

Jenkins Kubernetes plugin — plugins.jenkins.io/kubernetes, готовим различный имаджи, с подготовленной средой. Через лейблы задачи запускаются на тех или иных образах.

Как гонять ОДИН тест запуская много инстансов хрома в рандомном порядке в параллель? Например, сейчас стартануло два параллельных инстанса, через минуту еще 50, через десять минут один и т.д.

Я думаю это скорее задача тула для запуска тестов, нежели инфраструктуры для автоматизации. Инфраструктура просто должна вывозить количество потоков, которое от нее хотят интеграционные тесты.
Непосредственно твою задачу можно решать кучей различных способов, я в основном работал на Java TestNG, там это можно было обыграть через параметры аннотации @Test — invocationCount / threadPoolSize: testng.org/...​ion-main.html#annotations

А про что думаете про Selenoid, Moon?

Наверное не совсем понял вопрос, на текущий момент используем Aerokube Moon.

А для иос приложений искали какие-то варианты? Насколько я понимаю из схемы вы только Андроид тестируете таким образом

Пока в кубере iOS не гоняем, яблочные оси к сожалению плохо поддаются докеризации. А так под себя строим мобильные фермы, как то недавно я записывал интервью по этой теме: www.youtube.com/watch?v=NEnq-xpGp3E

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

Есть новости про zebrunner для js фреймворков?

До конца 2020 будет официальный релиз JS агента

Намного удобнее мейнтейнить EKS, чем ECS на спот фаргейт инстансах?

На самом деле мы даже EKS не используем, разворачиваем сами k8s кластер с помощью kops. Вероятно ECS требует меньше трудозатрат, но мы не нашли возможности запускать Android эмуляторы в этой инфраструктуре на bare metal машинах.

да, точно, вам BM нужен же, и вы даже EC2 не используете.

как мне показалось не так сложно развернуть мастер ноду, как правильно ее настроить, нужные драйверы для сети и правильный ingress, поэтому EKS с коробки (за 75$) чуть легче.

Подписаться на комментарии