- Расскажу о себе и несколько слов о проекте, которым я занимаюсь и в котором потребовались фиче-флаги (фф).
- Короткое овервью что такое фф, какую задачу они решают.
- Задача 1: деплоймент в разные среды. Как решили перегрузку ифнраструктурного слоя для облака и для онпрема.
- Задача 2: распределенная разработка. Как разрабатывали фичу в нескольких командах и активировали на проде.
- Задача 3: быстрые релизы. Как релизились с мастера и закрывали фф неготовую функциональность.
- Переключимся с нашего опыта на доступные в экосистеме решения. Рассмотрим, какие есть стандартные библиотеки и подходы.
- Задача 4: миграция кодовой базы на новую мажорную версию UI Kit. Как спасает фф, когда мастер развалился, а до релиза рукой подать.
- Задача 5: поставка трёх продуктов из единой кодовой базы. Какие плюсы и сложности приносят фф.
- Выводы. Какие фф рассмотрели, какие сложности и как добавить тот самый 1 фф, чтобы править всеми другими фф.
- Ссылка на материалы, обсуждение.
Хочу подать материал через сторителлинг и оттолкнуться от проблематики нашего пути длиной в последние 7 лет и те проблемы и решения, которые видели и решали.
Я люблю веб-разработку и хочу быть адвокатом для хороших практик веб-разработки
Тип цели: информационная/убеждающая — Показать конкретное решение конкретной задачи/кейса Помочь слушателям решить несколько «болей» в разработке через фиче-флаги.
Структура доклада: Сценарная Рассказ о развитии проекта, возникающих вызовах и способах решения.
Привет. Меня зовут Паша Востриков, я занимаюсь JS разработкой в Kaspersky. Делаю frontend, облачные сервисы на Node.js, self-hosted поставку, платформенные компоненты и библиотеки.
Показать сценарии применения фиче-флагов для упрощения разработки TODO: Сразу сделать пример кода
- Предыстория: Переход от UI на C++ к веб-приложению
- Команда: 7 человек
- Задача: Управлять корпоративной защитой из брайзера
- Решение: Full Stak JS
- Этап: Быстрый рост проекта: увеличение команды и скоупа работ (Задача 3: быстрые релизы)
- Команда: 5 групп разработки по 5 человек
- Задача: Поставлять фукнционал
- Этап: Выделение зон ответственности команд (Задача 2: распределенная разработка)
- Команда: 2 группы разработки 7 человек и 4 человека
- Задача: Сделать общую фичу, декомпозировав работы на 2 отдела разработки — управление (знают как управлять) и защиты (знают как защищать)
- Решение: сквозной фиче-флаг
- Этап: Выход на новые рынки, защита из облака (Задача 1: деплоймент в разные среды)
- Этап: Обновление технологий в долгоживущем продукте (Задача 4: миграция кодовой базы)
- Этап: Формирование экосистемы: готовность защищать от цветочного ларька (SMB) до компании, работающей на всех континентах (Enterprise) (Задача 5: поставка трех продуктов из единой кодовой базы) Пример: доставка: доставка еды, курьерская доставка дверь-дверь внутри города, междугородняя доставка габаритных грузов
Фиче-флаги — это настройки, которые позволяют не трогая программистов менять поведение программы, к примеру включать и выключать фичи.
Фиче-флаги — это разновидность данных, используемых в системе. Нечто между стейтом и конфигом приложения.
Фиче-флаги нужны для:
- A / B тестов
- Canary релизов
- Закрытия не готовой фичи в main ветке
Резюмируя, фиче-флаги нужны для включения и выключения функциональности при необходимости. А необходимости бывают разные.
Больше можно почитать на martinfowler.com.
-
Этот доклад про применения фиче-флагов в инженерных целях, не про a / b тесты, исследования и маркетинг.
-
Если есть возможность не ветвить реализации или написать сразу протестированную фичу без багов — сделайте это. Для всех остальных случае потребуются фиче-флаги.
Было: KSC MMC Стало: KSC Web Console
Команда становится больше, продукт больше, релизы становятся длиннее. Пока всё разработают и проверят. Даже авто-тесты, и их написание занимает много времени.
Но мы хотим релизиться часто. Мало того что часто, ритмично.
Вне зависимости от того готов ли функциональность, релиз должен выйти.
Итак, давайте решим следующую задачу.
Дано:
- Частые релизы по готовности фичи, но не реже чем X времени.
- Коротко живущие ветки: сделал атомарную таску — залей. Ни к чему эти PRы на 3 тысячи файлов и полгода работы.
Как этого достичь? Новая фича при разработке обарачивается в фиче-флаг. Он в main по-умолчанию выключен. При разработке, в автотестах, для ручного тестирования можно включить фиче-флаг для конкретного пользователя. Так даже Canary релиз на проде можно сделать:
Приложение росло и появилась необходимость делать отдельные части фичи разными командами. Архитектура поставки — микрофронтенды и микросервисы, но речь не об этом.
Следующим этапом потребовалась выкатка фичи, разработанной тремя отдельными командами. Разумеется, каждая команда релизится в удобное для себя время и фича включается в Cloud поставке по готовности.
Простейший способ — это выставление env переменных в соответствующих сервисах.
Но что если улучшить? Например, HostApp должен контролировать поведение фичи и распространять включение централизованно? Такое может потребоваться, например, если мы управляем фичей из пользовательского интерфейса.
{
"FEATURE_WELCOME_WIZARD_ENABLED": 1
}
const { featureRegistry } = require('@kaspersky/feature-registry')
const {
isServerFeatureEnabled,
isUserFeatureEnabled,
getFeatureFlags
} = featureRegistry.init(global.config.featureFlagConfigMapPath)
const isWelcomeWizardEnabled = await isServerFeatureEnabled({
featureName: 'WELCOME_WIZARD_ENABLED'
})
const { hostApp } = require('@kaspersky/feature-registry')
hostApp.isServerFeatureEnabled({
featureName: 'WELCOME_WIZARD_ENABLED'
})
Это runtime фиче-флаг, контролирующий поведение в разных частях распределенной системы.
Итак, новая задача, с которой мы с командой столкнулись, еще не зная ни о каких фиче-флагах, деплоймент нашего приложения в 2 разных среды: Cloud и Self-Hosted.
В первом случае это Cloud Native поставка в k8s кластер нашего Node.js кода и фронтенда, а во втором случае — раскатка в инфраструктуре заказчика.
Такой формат поставки очень типичен для многих веб-приложений:
- GitLab
- Confluence
- Sentry
- Kaspersky Security Center
Мы делали Kaspersky Security Center — решение для управления корпоративной защитой. Пропатчевать операционную систему одной кнопкой, мониторить и автоматически реагигировать, когда корпоративную сеть ломают снаружи или изнутри.
Соответственно одно и то же Node.js приложение должно работать принципиально в 2 средах, контейнеры использовать в self-hosted мы не могли — не все заказчики к этому были готовы.
Решение — наш первый инфраструктурный фиче-флаг.
.
└── src/
├── index.js
└── feature/
├── env-local/
│ └── feature.js
├── env-cloud/
│ └── feature.js
└── feature.common.js
const path = require('path')
const featureFilePath = path.resolve(
__dirname,
'feature',
global.config.targetFolder, // <---- environment implementation folder
'feature.js'
)
const { FeatureLogic } = require(featureFilePath)
FeatureLogic.init()
const { CommonFeatureLogic } = require('../feature.common.js')
class FeatureLogic extends CommonFeatureLogic () {
async init () {
return 'I am Cloud feature!'
}
}
Плюс на этапе сборки убрать избыточные для Cloud директории env-local.
Таким образом у нас еще нет централизованного управления фиче-флагами, но уже есть возможность управлять кодом для определенной поставки.
Это buildtime фиче-флаг.
Возвращаясь к продуктовым задачам. Мы разработали новую версию Дизайн-системы и нужно менять компонентную базу в живом продукте.
Разработкой продукта к этому моменту уже занимается 30 человек в нашем JS стриме и порядка 20 команд 2-4 разработчика в смежных отделах.
Задача поменять UI компоненты во фронте на 20 команд выглядит как «поменяйте крылья у летящего самолета».
Первый подход — глобальный фиче-флаг V6_UI_KIT_ENABLED. Начали катить на стейджинги и фиаско. На части микрофронтов взлетело, на части — нет. Виной тому и наши девелоперские ошибки, и edge кейсы и вообще не ошибается тот, кто ничего не делает. Не бойтесь ошибаться, главное делайте выводы.
Второй подход — быстро откатить фиче-флаг V6_UI_KIT_ENABLED. Осмыслить что пошло не так. Написать Smoke E2E тесты в добавок к написанным юнитам. Пока глобальный фиче-флаг, переключающий версию UI Kit, откатили, нужно предложить решение, которое разблокирует команды в отдельных сценариях. Добавляем фиче-флаг для перехода только отдельных разделов.
К этому моменту написаны Smoke тесты, подчищены всплывшие ошибки, идет раннее тестирование отдельных продуктовых разделов в разных командах. Мы готовы к следующему этапу — включение фиче-флага для отдельного микрофронта. Из 20 микрофронтендов 5 уже стабилизированы и включены в деплойменте по-умолчанию. Остальные включаются по мере тестирования.
Таким образом, мы перешли от глобального скозного фиче-флага к per-component флагам и без изменения кода может прыгать со старой реализации на новую и обратно, в случае появления проблем.
Слайд 45. Формирование экосистемы: создание нескольких продуктов из единой кодовой базы (Задача 5: поставка трех продуктов из единой кодовой базы)
Количество пользователей продукта растет и есть потребность из единой кодовой базы делать 3 поставки:
- Cloud (Public Cloud)
- Self-hosted
- Private-cloud
При этом, исходя из потребностей клиентов у нас 2 инфраструктуры: контейнеризованная и сервисы внутри ОС.
И три подмножества пользовательских сценариев: пересекающиеся процентов 80 и 20 процентов отличий на каждую поставку.
Инфраструктуру разруливаем buildtime фиче-флагом с начала моего доклада.
Пользовательские сценарии ветвим серверными фиче-флаги.
Новую функциональность тестируем per-user фиче-флагами.
Вроде бы все по полочкам, что может пойти не так?
Комбинационный взрыв, когда появляется простыня из десятков флагов и энв переменных и что относится к чему довольно сложно разобрать.
Тут на помощь приходят 2 довольно простых решения: сделать пресеты фиче-флагов для каждой из поставок + валидировать env-переменные builtime, чтобы не было угадайки а что куда выставить при разработке и тем более в проде.
Для этого отлично подошла библиотека envaild.
- Когда мы говорим про подходы, конечно начать можно с if и env переменных / запроса к бэкенду.
- Env переменные трансформируются в ConfigMap (json / yaml).
- А ConfigMap переходит в кеширующий сервис, который хранит настройки локально и умеет забирать их / принимать обновления с сервера.
- Последняя важная мастовая часть — это возможность применять фиче-флаг на группы: серверов / регионов / пользователей.
Когда мы говорим про библиотеки и сервисы:
- Конечно же нужно упомянуть Firebase и JS SDK
- Unleash
- featurevisor
- Конечно, многие облачные провайдеры предоставляют из коробки сервис для работы с фиче-флагами:
- AWS AppConfig
- Microsoft Azure App Configuration
- Google Cloud Firestore
Подводя итог, мы рассмотрели
- Фиче-флаг для Work in Progress кода. Позволяет выкатывать ранние canary релизы и заниматься отладкой неготовой фичи.
- Фиче-флаг для 2 команд разработки. Позволяет управлять функциональностью сквозь все части системы, в том числе при распределенном деплое.
- Применение фиче-флагов на отдельные группы пользователей или серверов для тестирования фичи.
- Разбитие одного общего фиче-флага на подгруппы для градуипрованного раскатывания нового фичи в большом приложении.
- Buildtime перегрузка подсистем. (Не фиче-флаг, но тоже полезно)
- добавить про таблицу истинности
- перерисовать картинку хореография vs оркестрация
- Общая структура: перейти на проблема -> визуализация решения -> код
- уйти от описания роадмапа жизни продукта к сценариям фиче-флагов о которых поговорим
- обратить внимание в начале докладе и в выводах: это один фиче-флаг и один ифчик, а сценарии использования разные
- раскрытие сценария «добавить фиче-флаг под каждый микрофронт» — в чем отличие от общего флага
- как удалять фиче-флаги
- фиче-флаг для 2 команд разработки
- нарисовать общую схему взаимодействия
- как работают дефолты и удаленное хранилище
- проблема: настройка пропала на сервисе / сервис упал / корпоративная сеть без доступа к интернету
- проблема: хождение к сервису на каждое обращение к фф, нужна синхронная работа для лучшей скорости
- добавить про кеши и удаленный формат работы
- отдельно осветить бэкэндовую и фронтовую часть: в моей реализации core — фф backend, на фронтенде вызов библиотеки и пуши на обновление
- как разделяются дефолты между пресетами
- реализация функций из примеров
- смена поколений Дизайн-системы
- как происходит смена?
- 2 npm пакета: shared зависимость
- отдельный слой постройки форм
- про тесты
- как протестировать всю комбинаторику в юнитах
- как протестировать в e2e: как пишем тесты с учетом включи фиче-флаг, выключи фиче-флаг
- что случается, когда недозакрыли функциональность
- стаднартные библиотеки и подходы
- добавить специфичную фукнциональность для JS
- добавить qr код в последнем файле
- 22 - кейс? до этого убрать user и тд
- 29 - можно показать конкретный кейс, можно рассказать, почему флаги сразу в микрофронт не прокидывается
- 32 - уход в сторону, можно убрать
- 39 - надо визуализировать
- 43 - объединяем - показать пресеты
- 45 - задача 1: Решение - что можешь посоветовать из опенсурса
- задача 3: не понял, причем тут фича флаги
- 49 - после обл провайдеров, может не подойти - почему может не подойти?
- разработали либу - нет.
- 52 - можно показать пример теста
- 53 - баги в удаленном сервисе. Удаление - не про тесты.
- код тестов