канареечное тестирование что это
Canary Releases
Что такое канареечный релиз?
Метод снижения риска внедрения новой версии программного обеспечения в “производственную среду”. Происходит путем плавного развертывания изменений для небольшой группы пользователей.
Термин «канареечный релиз» придуман по аналогии с тем, как шахтеры в угольных шахтах брали с собой канареек в клетках, чтобы обнаруживать опасный уровень угарного газа. Если в шахте скапливалось много угарного газа, то он убивал канарейку до того, как становился опасным для шахтеров, и они успевали спастись.
В чем основная суть метода?
Новый функционал или его обновлённая часть публикуется для ограниченной аудитории по мере готовности на продакшен окружение. Перед деплоем достаточно убедиться, что код не содержит синтаксических ошибок. Этот шаг может быть частью ci пайплаина. Первые пользователи, которые увидят изменения, могут быть разработчиками или тестировщиками. После проверки функционала, который уже находится в той среде, где с ним начнут взаимодействовать реальные пользователи, можно открыть доступ настоящим пользователям частично или полностью. В случае нахождения ошибок фичу можно моментально закрыть от пользователей и минимизировать потери (репутационные, финансовые).
Использовать предпродакшен среду, на которую сначала публикуются изменения, после этапа проверки и тестирования. Изменения попадают в продакшен среду, где еще раз проверяются на ошибки связанные с интеграцией, которые могли возникнуть из за неточности двух окружений.
Какие плюсы у канареечного релиза?
Какие накладные расходы для использования канареечных релизов?
Почему стоит использовать канареечные релизы?
Масштабирование, снижение количества ошибок, автоматизация ручной работы. При ускорении time to market и увеличении количества релизов ограничением становятся тестовые окружения, где в один момент времени может быть только одно изменение в тесте.
Фундаментальные проблемы нескольких предпродакшен окружений: при росте инфраструктуры и сложности приложения сложность поддержки тестовых окружений будет расти, увеличивая стоимость поддержки окружения и снижая частоту релизов. Тестовое окружение не может быть идентичным продакшен, а пользовательский трафик не может быть сопоставим.
Стратегии деплоя в Kubernetes: rolling, recreate, blue/green, canary, dark (A/B-тестирование)
Прим. перев.: Этот обзорный материал от Weaveworks знакомит с наиболее популярными стратегиями выката приложений и рассказывает о возможности реализации наиболее продвинутых из них с помощью Kubernetes-оператора Flagger. Он написан простым языком и содержит наглядные схемы, позволяющие разобраться в вопросе даже начинающим инженерам.
Схема взята из другого обзора стратегий выката, сделанного в Container Solutions
Одной из самых больших проблем при разработке cloud native-приложений сегодня является ускорение деплоя. При микросервисном подходе разработчики уже работают с полностью модульными приложениями и проектируют их, позволяя различным командам одновременно писать код и вносить изменения в приложение.
Более короткие и частые развертывания имеют следующие преимущества:
В этой публикации мы обсудим различные стратегии деплоя в Kubernetes, в том числе rolling-развертывания и более продвинутые методы, такие как канареечные (canary) выкаты и их разновидности.
Стратегии деплоя
Существует несколько различных типов стратегий развертывания, коими можно воспользоваться в зависимости от цели. Например, вам может потребоваться внести изменения в некое окружение для дальнейшего тестирования, или в подмножество пользователей/клиентов, или возникнет необходимость провести ограниченное тестирование на пользователях, прежде чем сделать некую функцию общедоступной.
Rolling (постепенный, «накатываемый» деплой)
Это стандартная стратегия развертывания в Kubernetes. Она постепенно, один за другим, заменяет pod’ы со старой версией приложения на pod’ы с новой версией — без простоя кластера.
Kubernetes дожидается готовности новых pod’ов к работе (проверяя их с помощью readiness-тестов), прежде чем приступить к сворачиванию старых. Если возникает проблема, подобное накатываемое обновление можно прервать, не останавливая всего кластера. В YAML-файле с описанием типа deployment’а новый образ заменяет собой старый образ:
Параметры накатываемого обновления можно уточнить в файле манифеста:
Recreate (повторное создание)
В этом простейшем типе развертывания старые pod’ы убиваются все разом и заменяются новыми:
Соответствующий манифест выглядит примерно так:
Blue/Green (сине-зеленые развертывания)
Стратегия сине-зеленого развертывания (иногда ее ещё называют red/black, т.е. красно-чёрной) предусматривает одновременное развертывание старой (зеленой) и новой (синей) версий приложения. После размещения обеих версий обычные пользователи получают доступ к зеленой, в то время как синяя доступна для QA-команды для автоматизации тестов через отдельный сервис или прямой проброс портов:
После того, как синяя (новая) версия была протестирована и был одобрен ее релиз, сервис переключается на неё, а зеленая (старая) сворачивается:
Canary (канареечные развертывания)
Канареечные выкаты похожи на сине-зеленые, но лучше управляются и используют прогрессивный поэтапный подход. К этому типу относятся несколько различных стратегий, включая «скрытые» запуски и А/В-тестирование.
Эта стратегия применяется, когда необходимо испытать некую новую функциональность, как правило, в бэкенде приложения. Суть подхода в том, чтобы создать два практически одинаковых сервера: один обслуживает почти всех пользователей, а другой, с новыми функциями, обслуживает лишь небольшую подгруппу пользователей, после чего результаты их работы сравниваются. Если все проходит без ошибок, новая версия постепенно выкатывается на всю инфраструктуру.
Хотя данную стратегию можно реализовать исключительно средствами Kubernetes, заменяя старые pod’ы на новые, гораздо удобнее и проще использовать service mesh вроде Istio.
Например, у вас может быть два различных манифеста в Git: обычный с тегом 0.1.0 и «канареечный» с тегом 0.2.0. Изменяя веса в манифесте виртуального шлюза Istio, можно управлять распределением трафика между этими двумя deployment’ами:
Пошаговое руководство по реализации канареечных развертываний с помощью Istio можно найти в материале GitOps Workflows with Istio. (Прим. перев.: Мы также переводили материал про канареечные выкаты в Istio здесь.)
Канареечные развертывания с Weaveworks Flagger
Weaveworks Flagger позволяет легко и эффективно управлять канареечными выкатами.
Flagger автоматизирует работу с ними. Он использует Istio или AWS App Mesh для маршрутизации и переключения трафика, а также метрики Prometheus для анализа результатов. Кроме того, анализ канареечных развертываний можно дополнить вебхуками для проведения приемочных (acceptance) тестов, нагрузочных и любых других типов проверок.
На основе deployment’а Kubernetes и, при необходимости, горизонтального масштабирования pod’ов (HPA), Flagger создает наборы из объектов (deployment’ы Kubernetes, сервисы ClusterIP и виртуальные сервисы Istio или App Mesh) для проведения анализа и реализации канареечных развертываний:
Реализуя контур управления (control loop), Flagger постепенно переключает трафик на канареечный сервер, параллельно измеряя ключевые показатели производительности, такие как доля успешных HTTP-запросов, средняя продолжительность запроса и здоровье pod’ов. Основываясь на анализе KPI (ключевых показателей эффективности), канареечная часть либо растет, либо сворачивается, и результаты анализа публикуются в Slack. Описание и демонстрацию этого процесса можно найти в материале Progressive Delivery for App Mesh.
Dark (скрытые) или А/В-развертывания
Скрытое развертывание — еще одна вариация канареечной стратегии (с ней, кстати, Flagger тоже может работать). Разница между скрытым и канареечным развертыванием состоит в том, что скрытые развертывания имеют дело с фронтендом, а не с бэкендом, как канареечные.
Другое название этих развертываний — А/В-тестирование. Вместо того, чтобы открыть доступ к новой функции всем пользователям, ее предлагают лишь ограниченной их части. Обычно эти пользователи не знают, что выступают тестерами-первопроходцами (отсюда и термин «скрытое развертывание»).
С помощью переключателей функциональности (feature toggles) и других инструментов можно следить за тем, как пользователи взаимодействуют с новой функцией, увлекает ли она их или они считают новый пользовательский интерфейс запутанным, и другими типами метрик.
Flagger и A/B-развертывания
Помимо маршрутизации с учётом весов, Flagger также может направлять на канареечный сервер трафик в зависимости от параметров HTTP. При А/В-тестировании можно использовать заголовки HTTP или файлы cookie для перенаправления определенного сегмента пользователей. Это особенно эффективно в случае frontend-приложений, требующих привязки сессии к серверу (session affinity). Дополнительную информацию можно найти в документации Flagger.
Автор выражает благодарность Stefan Prodan, инженеру Weaveworks (и создателю Flagger), за все эти потрясающие схемы деплоя.
Тестируем на проде: Canary Deployment
Канарейка — маленькая птица, которая постоянно поет. Эти птички чувствительны к метану и угарному газу. Даже от небольшой концентрации лишних газов в воздухе они теряют сознание или умирают. Золотоискатели и шахтеры брали птичек на добычу: пока канарейки поют, можно работать, если замолчали — в шахте газ и пора уходить. Шахтеры жертвовали маленькой птичкой, чтобы выбираться из шахт живыми.
Подобная практика нашла себя и в IT. Например, в стандартной задаче деплоя новой версии сервиса или приложения на продакшн с тестированием перед этим. Тестовое окружение может быть слишком дорогим, автоматизированные тесты не покрывают все, что хотелось бы, а не тестировать и жертвовать качеством рискованно. Как раз в таких случаях помогает подход Canary Deployment, когда немного настоящего продакшн-трафика пускается на новую версию. Подход помогает безопасно проверить новую версию на продакшн, жертвуя малым ради большой цели. Подробнее, как работает подход, чем полезен и как его реализовать, расскажет Андрей Маркелов (Andrey_V_Markelov), на примере реализации в компании Infobip.
Андрей Маркелов — ведущий инженер-программист в Infobip, уже 11 лет занимается разработкой приложений на Java в области финансов и телекоммуникаций. Разрабатывает Open Source продукты, активно участвует в Atlassian Community и пишет плагины для продуктов Atlassian. Евангелист Prometheus, Docker и Redis.
О компании Infobip
Это глобальная телекоммуникационная платформа, которая позволяет банкам, ретейлу, интернет-магазинам и транспортным компаниям отправлять сообщения своим клиентам с помощью SMS, push, писем и голосовых сообщений. В таком бизнесе важна стабильность и надежность, чтобы клиенты вовремя получали сообщения.
IT-инфраструктура Infobip в цифрах:
Релизы
Типичный релиз у нас проходит так. Например, есть сервисы A, B, C, D и E, каждый из них разрабатывается отдельной командой.
В какой-то момент команда сервиса А решает задеплоить новую версию, но команды сервисов B, C, D и E об этом не знают. Вариантов, как поступит команда сервиса А, два.
Проведет инкрементальный релиз: сначала заменит одну версию, а потом вторую.
Но есть второй вариант: команда найдет дополнительные мощности и машины, задеплоит новую версию, а потом переключит роутер, и версия начнет работать на продакшн.
В любом варианте после деплоя почти всегда возникают проблемы, даже если версия протестирована. Тестировать можно руками, можно автоматизированно, можно не тестировать — проблемы возникнут в любом случае. Самый простой и правильный способ их решить — откатиться назад на работающую версию. Уже потом можно разбираться с ущербом, с причинами и исправлять их.
Проблемы нам не нужны. Если клиенты обнаружат их быстрее нас, это ударит по репутации. Поэтому мы должны находить проблемы быстрее клиентов. Работая на опережение, мы минимизируем ущерб.
В то же время, мы хотим ускорить деплой, чтобы это происходило быстро, легко, само собой и без напряжения со стороны команды. Инженеров, DevOps-инженеров и программистов надо беречь — релиз новой версии это стресс. Команда это не расходный материал, мы стремимся рационально использовать человеческие ресурсы.
Проблемы деплоя
Клиентский трафик непредсказуем. Невозможно предсказать, когда клиентский трафик будет минимальным. Мы не знаем, где и когда клиенты начнут свои кампании — может, сегодня ночью в Индии, а завтра в Гонконге. С учетом большой разницы во времени, деплой даже в 2 часа ночи не гарантирует, что клиенты не пострадают.
Проблемы провайдеров. Мессенджеры и провайдеры — наши партнеры. Иногда у них бывают сбои, которые вызывают ошибки во время деплоя новых версий.
Распределенные команды. Команды, которые разрабатывают клиентскую часть и бэкенд, находятся в разных часовых поясах. Из-за этого они часто не могут договориться между собой.
Дата-центры нельзя повторить на стейдже. В одном дата-центре 200 стоек — повторить это в песочнице даже приблизительно не получится.
Даунтаймынедопустимы! У нас есть допустимый уровень доступности (Error Budget), когда мы работаем 99,99% времени, например, а оставшиеся проценты это «право на ошибку». Достичь 100% надежности невозможно, но важно постоянно следить за падениями и простоями.
Классические варианты решения
Писать код без багов. Когда я был молодым разработчиком, ко мне подходили менеджеры с просьбой провести релиз без багов, но это не всегда возможно.
Писать тесты. Тесты работают, но иногда совсем не так, как хочет бизнес. Зарабатывать деньги — это не задача тестов.
Тестировать на стейдже. За 3,5 года моей работы в Infobip я ни разу не видел, чтобы состояние стейджа хотя бы частично совпадало с продакшн.
Мы даже пытались развить эту идею: сначала у нас был стейдж, потом препродакшн, а потом препродакшн препродакшна. Но и это не помогло — они не совпадали даже по мощности. Со стейджем мы можем гарантировать базовую функциональность, но не знаем, как она будет работать при нагрузках.
Релиз делает тот, кто разрабатывал. Это хорошая практика: даже если кто-то меняет название комментария, сразу добавляет в продакшн. Это помогает развивать ответственность и не забывать о внесенных изменениях.
Дополнительные сложности тоже есть. Для разработчика это стресс — тратить много времени, чтобы все проверить вручную.
Согласованные релизы. Этот вариант обычно предлагает менеджмент: «Давайте договоримся, что каждый день будете тестировать и добавлять новые версии». Это не работает: всегда есть команда, которая ждет все остальных или наоборот.
Smoke-тесты
Еще один способ решить наши проблемы с деплоем. Рассмотрим, как работают smoke-тесты на предыдущем примере, когда команда A хочет задеплоить новую версию.
Сначала команда деплоит один инстанс на продакшн. Сообщениями в инстанс от моков имитируется реальный трафик, чтобы он совпадал с нормальным ежедневным трафиком. Если все хорошо, команда переключает новую версию на пользовательский трафик.
Второй вариант — деплоить с дополнительным железом. Команда тестирует его на продакшн, потом переключает, и все работает.
Canary-релизы
Из-за недостатков smoke-тестов мы начали использовать canary-релизы.
Практика, подобная тому, как шахтеры использовали канареек для индикации уровня газов, нашла себя и в IT. Мы пускаем немного настоящего продакшн-трафика на новую версию, при этом стараемся уложиться в Service Level Agreement (SLA). SLA — это наше «право на ошибку», которое мы можем использовать раз в год (или за какой-то другой промежуток времени). Если все будет хорошо, добавим больше трафика. Если нет — вернем предыдущие версии.
Реализация и нюансы
Как мы реализовали canary-релизы? Например, группа клиентов отправляет сообщения через наш сервис.
Деплой проходит так: убираем один узел из-под балансировщика (1), меняем версию (2) и отдельно пускаем немного трафика (3).
В целом, в группе будут счастливы все, даже если один пользователь будет недоволен. Если все хорошо — меняем все версии.
Покажу схематично, как это выглядит для микросервисов в большинстве случаев.
Есть Service Discovery и еще два сервиса: S1N1 и S2. Первый сервис (S1N1) оповещает Service Discovery, когда стартует, а Service Discovery его запоминает. Второй сервис с двумя узлами (S2N1 и S2N2) тоже оповещает Service Discovery при старте.
Второй сервис для первого работает как сервер. Первый запрашивает у Service Discovery информацию о своих серверах, а когда получает — ищет и проверяет их («health check»). Когда проверит, то отправит им сообщения.
Когда кто-то хочет задеплоить новую версию второго сервиса, он сообщает Service Discovery, что вторая нода будет canary-нодой: на нее будет отправляться меньше трафика, потому что сейчас пройдет деплой. Убираем canary-ноду из-под балансировщика и первый сервис не отправляет в нее трафик.
Меняем версию и Service Discovery знает, что вторая нода теперь canary — можно давать ей меньше нагрузки (5%). Если все хорошо, меняем версию, возвращаем нагрузки и работаем дальше.
Чтобы все это реализовать, нам нужны:
Балансировка
Это первое, о чем мы должны задуматься. Есть две стратегии балансировки.
Простейший вариант, когда одна нода всегда canary. Эта нода всегда получает меньше трафика и мы начинаем деплой с нее. В случае проблем мы сравним ее работу до деплоя и во время него. Например, если ошибок стало в 2 раза больше, значит и ущерб вырос в 2 раза.
Canary-нода задается в процессе деплоя. Когда деплой закончится и мы снимем с нее статус canary-ноды, баланс трафика восстановится. С меньшим количеством машин мы получим честное распределение.
Мониторинг
Краеугольный камень canary-релизов. Мы должны точно понимать, зачем мы это делаем и какие метрики хотим собирать.
Примеры метрик, которые мы собираем с наших сервисов.
Counter. Это некоторая возрастающая величина, например, количество ошибок. Эту метрику просто интерполировать и изучать график: вчера было 2 ошибки, а сегодня 500, значит, что-то пошло не так.
Количество ошибок в минуту или в секунду, это важнейший показатель, который можно вычислить используя Counter. Эти данные дают четкое представление о работе системы на дистанции. Рассмотрим на примере графика количества ошибок в секунду для двух версий продакшн-системы.
В первой версии было мало ошибок, возможно, не работал аудит. Во второй версии все намного хуже. Можно точно сказать, что есть проблемы, поэтому мы должны откатить эту версию.
Gauge. Метрики похожи на Counter, но мы записываем значения, которые могут как увеличиваться, так и уменьшаться. Например, время выполнения запросов или размер очереди.
На графике пример времени отклика (latency). По графику видно, что версии похожи, с ними можно работать. Но если приглядеться, то заметно, как меняется величина. Если время выполнения запросов увеличивается при добавлении пользователей, то сразу понятно, что есть проблемы — раньше такого не было.
Summary. Один из важнейших показателей для бизнеса — перцентили. Метрика показывает, что в 95% случаев наша система работает так, как мы хотим. Мы можем смириться, если где-то проблемы, потому что понимаем общую тенденцию, насколько все хорошо или плохо.
Инструменты
Prometheus. Хорошо себя проявил в Infobip. Он позволяет реализовать многомерные метрики, потому что используются лейблы.
Анализ версий
Есть несколько стратегий анализа версий.
Смотреть метрики только canary-ноды. Один из простейших вариантов: задеплоили новую версию и изучаем только работу. Но если инженер в это время начнет изучать логи, постоянно нервно перезагружая страницы, то это решение ничем не отличается от остальных.
Canary-нода сравнивается с любой другой нодой. Это сравнение с другими инстансами, которые работают на полном трафике. Например, если с маленьким трафиком дела обстоят хуже, или не лучше, чем на реальных инстансах, то что-то не так.
Canary-нода сравнивается с собой в прошлом. Ноды, выделенные для canary, можно сравнивать с историческими данными. Например, если неделю назад все было хорошо, то можем ориентироваться на эти данные, чтобы понять текущую ситуацию.
Автоматизация
Мы хотим освободить инженеров от ручного сравнения, поэтому важно реализовать автоматизацию. Процесс деплоя (deployment pipeline) обычно выглядит так:
На этом этапе мы реализуем автоматическое сравнение. Как оно может выглядеть и почему лучше, чем проверка после деплоя, рассмотрим на примере из Jenkins.
Это pipeline к Groovy.
Описание метрики. Посмотрим, как может выглядеть функция compare на примере DSL.
Допустим, мы сравниваем количество ошибок и хотим узнать количество ошибок в секунду за последние 5 минут.
У нас есть два значения: базовое и canary-ноды. Значение у canary-ноды — текущее. Базовое — baseValue — это значение любой другой не canary-ноды. Сравниваем значения между собой по формуле, которую ставим исходя из своего опыта и наблюдений. Если значение canaryValue плохое, то деплой не удался, и мы откатываемся.
Зачем это все нужно?
Человек не может проверить сотни и тысячи метрик, тем более сделать это быстро. Автоматическое сравнение помогает проверить все метрики и быстро оповещает о проблемах. Время оповещения критично: если что-то случилось за последние 2 секунды, то ущерб будет не такой большой, как если бы это произошло 15 минут назад. Пока кто-то заметит проблему, напишет в поддержку, а поддержка нам, чтобы откатить, можно потерять клиентов.
Если процесс прошел и все хорошо, мы деплоим все остальные ноды автоматически. В это время инженеры не делают ничего. Только когда они запускают canary, решают, какие метрики взять, сколько по времени делать сравнение, какую стратегию использовать.
Если возникли проблемы — автоматически откатываем canary-ноду, работаем на прошлых версиях и исправляем ошибки, которые нашли. По метрикам их легко найти и увидеть ущерб от новой версии.
Препятствия
Реализовать это, конечно, непросто. Прежде всего нужна общая система мониторинга. У инженеров свои метрики, у поддержки и аналитиков — другие, у бизнеса третьи. Общая система — это общий язык, на котором разговаривают бизнес и разработка.
Нужно проверить на практике стабильность метрик. Проверка помогает понять, какой минимальный набор метрик нужен, чтобы обеспечить качество.
Как этого достичь? Использовать canary-сервис не в момент деплоя. Добавляем на старой версии некий сервис, который в любой момент времени сможет взять любую выделенную ноду, уменьшить трафик без деплоя. После сравниваем: изучаем ошибки и ищем ту грань, когда мы достигаем качества.
Какую пользу мы получили от canary-релизов
Минимизировали процент ущерба от багов. Большинство ошибок деплоя происходит из-за несогласованности каких-то данных или приоритета. Таких ошибок стало намного меньше, потому что мы можем решить проблему в первые секунды.
Оптимизировали работу команд. У новичков есть «право на ошибку»: они могут деплоить в продакшн без страха ошибиться, появляется дополнительная инициатива, стимул работать. Если они что-то сломают, то это будет не критично, а ошибившегося не уволят.
Автоматизировали деплой. Это уже не ручной процесс, как раньше, а настоящий автоматизированный. Но он проходит дольше.
Выделили важные метрики. Вся компания, начиная от бизнеса и инженеров, понимает, что действительно важно в нашем продукте, какие метрики, например, отток и приток пользователей. Мы контролируем процесс: тестируем метрики, вводим новые, смотрим, как работают старые, чтобы строить систему, которая будет зарабатывать деньги производительнее.
У нас много классных практик и систем, которые нам помогают. Несмотря на это, мы стремимся быть профессионалами и делать свою работу качественно, вне зависимости от того, есть у нас система, которая нам поможет, или нет.
Инженерные подходы и практики — основной фокус конференции TechLead Conf. Если вы достигли успехов на пути к техническому совершенству и готовы рассказать, что вам в этом помогло, — подавайте заявку на доклад.
TechLead Conf пройдет 8 и 9 июня онлайн. Карантин не повод останавливать профессиональное общение, поэтому сейчас мы как раз тестируем новые форматы и к июню будем во всеоружии, чтобы конференция была именно конференцией — с вопросами, дискуссиями и нетворкингом.