company_banner

Как мы делали облачный FaaS внутри Kubernetes и побеждали в Тинькофф-хакатоне


    Начиная с прошлого года у нас в компании начали организовывать хакатоны. Первое такое состязание прошло весьма успешно, о нем мы писали в статье. Второй хакатон прошел в феврале 2019 и был не менее успешным. О целях проведения последнего не так давно писал организатор.

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

    Задача нетривиальная и может быть решена множеством способов, в чем мы убедились на демонстрации финальных презентаций проектов участников. На хакатоне было 6 команд по 5 человек, у всех участников были хорошие проекты, но наша платформа оказалась наиболее конкурентоспособной. У нас получился очень интересный проект, о котором я хотел бы рассказать в данной статье.

    Наше решение – платформа на основе Serverless архитектуры внутри Kubernetes, которая сокращает время вывода новых фич на продакшн. Она позволяет аналитикам писать код в удобной для них среде и разворачивать его в прод без участия инженеров и разработчиков.

    Что такое скоринг


    В Tinkoff.ru, как и во многих современных компаниях, есть скоринг клиентов. Скоринг — это система оценки клиентов, в основе которой заложены статистические методы анализа данных.

    Например, клиент обращается к нам с просьбой выдать ему кредит, или открыть у нас счет ИП. Если мы планируем выдать ему кредит, то нужно оценить его платежеспособность, а если счёт ИП, то нужно быть уверенными что клиент не будет проводить мошеннические операции.

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

    Метод такой оценки может принимать самые разные данные на входе. А в какой-то момент мы можем добавить на вход новый параметр, который по результатам анализа на исторических данных повысит конверсию использования сервиса.

    У нас хранится множество данных о взаимоотношениях с клиентами, и объем этой информации непрерывно растет. Чтобы скоринг работал, для обработки данных нужны еще и правила (или математические модели), позволяющие быстро принять решение кому заявку одобрить, кому ответить отказом, а кому еще парочку продуктов предложить, оценив его потенциальную заинтересованность.

    Для поставленной задачи у нас уже используется специализированная система принятия решений IBM WebSphere ILOG JRules BRMS, которая, на основе заданных аналитиками, технологами и разработчиками правил решает, одобрить тот или иной банковский продукт клиенту или отказать.

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

    Поставленная задача


    Хакатон проводился 23 февраля. Участникам была предложена боевая задача: разработать систему принятия решений, которая должна была соответствовать ряду условий.

    Нам рассказали, как функционирует существующая система и какие сложности возникают при ее эксплуатации, а также какие бизнес-цели должна преследовать разрабатываемая платформа. У системы должен быть быстрый time-to-market разрабатываемых правил, чтобы рабочий код аналитиков попадал в продакшн как можно быстрее. А для входящего потока заявок время принятия решения должно стремиться к минимуму. Также разрабатываемая система должна иметь возможности cross-sell, чтобы давать клиенту возможность приобрести другие продукты компании в случае их одобрения с нашей стороны и потенциальной заинтересованности со стороны клиента.

    Понятно, что за одну ночь невозможно написать ready-to-release проект который непременно пойдет в продакшн, да и всю систему целиком охватить довольно сложно, поэтому нам было предложено реализовать хотя бы её часть. Был установлен ряд требований, которым должен удовлетворять прототип. Можно было попробовать как охватить все требования целиком, так и детально проработать отдельные разделы разрабатываемой платформы.

    Что касается технологий, то тут всем участникам была предоставлена полнейшая свобода выбора. Можно было использовать любые концепции и технологии: Data streaming, machine learning, event sourcing, big data и другие.

    Наше решение


    Проведя небольшой мозговой штурм мы решили, что для выполнения поставленной задачи идеально подойдет FaaS решение.

    Для данного решения необходимо было найти подходящий Serverless фреймворк для реализации правил разрабатываемой системы принятия решений. Так как в Тинькофф для управления инфраструктурой активно используется Kubernetes, мы рассмотрели несколько готовых решений на его основе, подробнее о нем я расскажу далее.

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

    1. Аналитик пишет скрипт, правило, или ML модель, основываясь на данных из хранилища. В рамках хакатона мы решили использовать Mongodb, но выбор системы хранения данных здесь не принципиален.
    2. После тестирования разработанных правил на исторических данных, аналитик заливает свой код в админку.
    3. С целью обеспечения версионирования весь код будет попадать в Git-репозитории.
    4. Через админку можно будет развернуть код в облаке как отдельный функциональный Serverless модуль.

    Исходные данные от клиентов должны проходить через специализированный Enrichment-сервис, предназначенный для обогащения первоначального запроса данными из хранилища. Важно было реализовать данный сервис таким образом, чтобы обеспечивалась работа с единым хранилищем (из которого аналитик берет данные при разработке правил), для поддержания единой структуры данных.

    Еще до хакатона мы определились с Serverless-фреймворком, который будем использовать. На сегодняшний день на рынке довольно много технологий реализующих данный подход. Наиболее популярными решениями в рамках Kubernetes архитектуры являются Fission, Open FaaS и Kubeless. Есть даже неплохая статья с их описанием и сравнительным анализом.

    Взвесив все плюсы и минусы мы остановили свой выбор на Fission. Данный Serverless-фреймворк довольно прост в управлении и удовлетворяет требованиям поставленной задачи.

    Для работы с Fission необходимо понимать две основные концепции: function и environment. Функцией (function) является кусок кода написанный на одном из языков для которого есть Fission-окружение (environment). Список реализованных в рамках данного фреймворка окружений включает в себя Python, JS, Go, JVM и множество других популярных языков и технологий.

    Также Fission способен выполнять функции, разбитые на несколько файлов, предварительно упакованные в архив. Работа Fission в кластере Kubernetes обеспечивается специализированными подами, управление которыми берет на себя сам фреймворк. Для осуществления взаимодействия с подами кластера, на каждую функцию необходимо назначить свой роут, и в который можно передавать GET параметры или request body в случае POST запроса.

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

    В предложенном нами решении отсутствует необходимость релиза правил, код легко разворачивается по одному нажатию кнопки. Так же управление инфраструктурой в Kubernetes позволяет не думать о нагрузке и масштабировании, подобные проблемы решаются «из коробки». А использование единого хранилища данных избавляет от необходимости сопоставления real-time данных с историческими, что упрощает работу аналитика.

    Что у нас получилось


    Так как на хакатон мы пришли с уже готовым решением (в наших фантазиях), нам осталось только преобразовать все наши мысли в строчки кода.

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

    Архитектура нашего проекта была следующей:


    На данной схеме указаны две точки входа, аналитик (основной пользователь нашей системы) и клиент.

    Процесс работы построен так. Аналитик разрабатывает функцию-правило и функцию обогащения данными для своей модели, сохраняет свой код в Git-репозиторий, и через приложение администратора разворачивает свою модель в облаке. Рассмотрим как развернутая функция будет вызываться и принимать решения по входящим заявкам от клиентов:

    1. Клиент заполняя форму на сайте, отправляет свой запрос на контроллер. На вход системы приходит заявка, по которой необходимо принять решение, и записывается в БД в своем первоначальном виде.
    2. Далее сырой запрос отправляется на обогащение, если в этом есть необходимость. Дополнить первоначальный запрос можно данными как от внешних сервисов так и из хранилища. Полученный обогащенный запрос также сохраняется в БД.
    3. Запускается функция аналитика, которая на вход принимает обогащенный запрос и отдает решение, которое также записывается в хранилище.

    В качестве хранилища в нашей системе мы решили использовать MongoDB в виду докуменоринтированного хранения данных в виде JSON документов, так как сервисы обогащения, включая исходный запрос, агрегировали все данные через REST-контроллеры.

    Итак, на реализацию платформы у нас в распоряжении были сутки. Мы довольно удачно распределили роли, каждый член команды имел свою зону ответственности в нашем проекте:

    1. Фронтенд-админки для работы аналитика, через которую он мог загружать правила из системы контроля версионирования написанных скриптов, выбирать варианты обогащения входных данных и править скрипты правил онлайн.
    2. Бэкенд-админки, включающий в себя REST API для фронта и интеграцию с VCS.
    3. Настройка инфраструктуры в Google Cloud и разработка сервиса обогащения исходных данных.
    4. Модуль интеграции приложения админки с Serverless-фреймворком для последующего деплоя правил.
    5. Скрипты правил для тестирования работоспособности всей системы и агрегация аналитики по входящим заявкам (принятым решениям) для финальной демонстрации.

    Начнем по порядку.

    Фронтенд у нас был написан на Angular 7 с использованием банковского UI Kit. Финальный вариант админки выглядел следующим образом:


    Так как времени было немного, мы постарались реализовать только ключевой функционал. Для деплоя функции в Kubernetes кластер необходимо было выбрать событие (сервис, для которого необходимо развернуть правило в облаке) и код код функции, реализующей логику принятия решения. По каждому развертыванию правила для выбранного сервиса мы писали лог этого события. В админке можно было видеть логи всех событий.

    Весь код функций хранился в удаленном Git-репозитории, который также необходимо было задавать в админке. Для версионирования кода все функции хранились в разных ветках репозитория. В админке также предусмотрена возможность внесения корректировок в написанные скрипты, чтобы перед деплоем функции в продакшн можно было не только проверить написанный код, но и внести необходимые правки.


    Помимо функций правил мы также реализовали возможность поэтапного обогащения исходных данных с помощью Enrichment-функций, код которых также представлял собой скрипты, в которых можно было ходить в хранилище данных, вызывать сторонние сервисы и выполнить предварительные расчеты. Для демонстрации нашего решения мы рассчитывали знак зодиака клиента, оставившего заявку, и определяли его мобильного оператора используя сторонний REST сервис.

    Бэкенд платформы был написан на Java и реализован как Spring Boot приложение. Для хранения данных админки мы изначально планировали использовать Postgres, но, в рамках хакатона, решили ограничиться простеньким H2, в целях экономии времени. На бэке была реализована интеграция с Bitbucket, для версионирования функций обогащения запросов и скриптов правил. Для интеграции с удаленными Git репозиториями использовалась библитека JGit, которая является своего рода оберткой над CLI командами, позволяющая исполнять любые git инструкции, используя удобный программный интерфейс. Так у нас было два отдельных репозитория, для функций обогащения и правил, а все скрипты разложены по директориям. Через UI можно было выбрать последний коммит скрипта произвольной ветки репозитория. При внесения правок в код через админку в удаленных репозиториях создавались коммиты измененного кода.

    Для реализации нашей идеи нам была необходима подходящая инфраструктура. Мы приняли решение развернуть наш Kubernetes кластер в облаке. Наш выбор остановился на Google Cloud Platform. Serverless-фреймворк Fission был установлен в кластере Kubernetes, который мы развернули в Gcloud. Первоначально сервис обогащения исходных данных был реализован отдельным Java-приложением обернутым в Pod внутри кластера k8s. Но после предварительной демонстрации нашего проекта в середине хакатона, нам порекомендовали сделать Enrichment сервис более гибким, чтобы предоставить возможность выбирать, как обогащать сырые данных входящих заявок. И нам ничего не оставалось, кроме как сделать сервис обогащения также Serverless.

    Для работы с Fission мы использовали Fission CLI, которую необходимо устанавливать поверх Kubernetes CLI. Деплой функций в k8s кластер довольно прост, необходимо лишь назначить для функции внутренний роут и ingress для разрешения входящего трафика, если необходим доступ вне кластера. Развертывание одной функции как правило занимает не более 10 секунд.

    Финальный показ проекта и подведение итогов


    Для демонстрации работы нашей системы мы разместили на удаленном сервере простенькую форму, на которой можно подать заявку на один из продуктов банка. Для запроса необходимо было ввести свои инициалы, дату рождения и номер телефона.

    Данные с клиентской формы уходили на контроллер, который параллельно отправлял заявки на все доступные правила, предварительно обогатив данные согласно заданным условиям, и сохранив их в общее хранилище. Всего у нас было развернуто три функции принимающие решение по входящим заявкам и 4 сервиса обогащения данными. После отправления заявки клиент получал наше решение:


    Клиент помимо отказа или одобрения также получал список других продуктов, запросы на которые мы отправляли параллельно. Так мы продемонстрировали возможность cross-sale в нашей платформе.

    Всего было доступно 3 выдуманных продукта банка:
    • Кредит.
    • Игрушка
    • Ипотека.

    На каждую услугу в ходе демонстрации мы развернули подготовленные функции и скрипты обогащения.

    Для каждого правила был необходим свой набор входных данных. Так, для одобрения ипотеки мы вычисляли знак зодиака клиента и связывали это с логикой лунного календаря. Для одобрения игрушки мы проверяли, что клиент достиг совершеннолетия, а для выдачи кредита мы отправляли запрос во внешний открытый сервис определения сотового оператора, и по нему принимали решение.

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

    Для сбора аналитики в режиме онлайн мы дополнительно развернули BI инструмент с открытым исходным кодом Metabase и прикрутили его к нашему хранилищу. Metabase позволяет строить экраны с аналитикой по интересующим нас данным, необходимо лишь прописать подключение к БД, выбрать таблицы (в нашем случае коллекции данных, так как мы использовали MongoDB), и указать интересующие нас поля.

    В результате у нас получился неплохой прототип платформы принятия решений, и на демонстрации каждый слушатель мог собственноручно проверить ее работоспособность. Интересное решение, готовый прототип и успешная демонстрация позволили нам победить, несмотря на сильную конкуренцию в лице других команд. Уверен, что по проекту каждой команды можно также написать интересную статью.
    Tinkoff.ru
    IT’s Tinkoff.ru — просто о сложном

    Похожие публикации

    Комментарии 2

    • НЛО прилетело и опубликовало эту надпись здесь
        +1

        Уже нет) разворачивали инфраструктуру в Google Cloud, а там все платно

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое