Привет, сообществу! Меня зовут Блинов Дмитрий и я отвечаю за инфраструктуру в нашем стартапе. Это моя первая статья и в ней я бы хотел рассказать про API Gateway KrakenD и про его наиболее интересные возможности.
API gateway – это единая сущность в архитектуре приложения, которая занимается оркестрацией запросов. Его основная функциональность заключается в создании единого API, который действует как агрегатор множества микросервисов в единый эндпоинт, автоматически выполняя за вас и ваше приложение тяжелую работу, такую, например, как: агрегирование, преобразование, фильтрацию, декодирование, регулирование, аутентификацию и авторизацию запросов.
В данной статье не затрагивается полный функционал и описание структуры конфигурации KrakenD, вы всегда можете с этим ознакомиться в документации и протестировать его в созданном примере от авторов сервиса в их playground, а также попробовать собрать конфигурацию в онлайн конструкторе. В этом материале описаны только ключевые функциональности, которые мы непосредственно используем в нашем приложении и посчитали, что интересно было бы о них рассказать. Поехали!
Единая точка входа
API gateway как единая точка взаимодействия различных клиентов и микросервисов через единый API, что позволяет не только балансировать, мониторить и делать трассировку запросов, но и привести весь API к единому стандарту, а также позволяет изменять его структуру без изменений в коде. Он также позволяет улучшить работу с сессиями пользователей и безопасность приложения, так-как скрывает внутреннюю топологию сервисов и позволяет управлять наполнением данных в запросах и ответах.
Агрегация и преобразование эндпоинтов
KrakenD способен не просто проксировать запросы к бэкенду, а полноценно манипулировать их наполнением. Так как в конфигурации шлюза полностью описана спецификация каждого эндпоинта, KrakenD может объединять тела ответов в один, а также удалять и редактировать поля в нем по заданным параметрам.
Например, для клиента приложения требуется собрать данные сразу из нескольких микросервисов. Обычно – это был бы запрос к основному сервису, который бы сам обратился за остальными данными к другим микросервисам, либо же это сразу несколько запросов к разным сервисам. Если к данной задаче подключить KrakenD то у нас появится отдельный эндпоинт, под которым шлюз сам сделает нужные запросы к сервисам, соберет их реквесты в один с нужными полями и отправит клиенту. Дополнительно, он также может добавить в тело ответа еще и статические данные, которым можно хранить непосредственно в контейнере шлюза, например, когда необходимо сделать mock-данные какого-либо сервиса.
Валидация JWT
JWT-токены – это популярный и современный подход к авторизации пользователей, но когда речь идет о микросервисном подходе ключевым блоком в архитектуре становится сервис авторизации. На него накладывается большая нагрузка, когда необходимо помимо авторизации еще и валидировать запросы к другим сервисам. Помочь ему со второй задачей также может KrakenD, хотя в авторизацию он тоже умеет. Получив доступ к JWK кодированном в base64 он может самостоятельно проверять авторизованы ли поступающие запросы к сервисам. Также есть функционал проверки источника JWK, но в примере ниже он отключен за невостребованностью, так-как источником является наш собственный микросервис.
Пример конфигурации KrakenD для валидации JWT:
{
"extra_config": {
"auth/validator": {
"alg": "HS512",
"kid": "sim2",
"jwk_url": "http://auth-service/getJWK",
"disable_jwk_security": true,
"cookie_key": "token"
}
}
}
Пример тела эндпоинта jwk_url получения JWK для KrakenD:
{
"keys": [
{
"kty": "oct",
"k": "YouSuperSecretJWKbase64",
"kid": "sim2",
"alg": "HS512"
}
]
}
Генерация конфигурации
Бесспорно, при большом количестве микросервисов растет и количество эндпоинтов, для которых еще и требуется спецификация. Конфигурация, с которой запускается KrakenD – это всего один файл, написанный, например, в формате JSON или YAML, поэтому итоговый конфиг может с легкостью вырасти в тысячи строк, превратившись в нечто, что невероятно сложно поддерживать. Для решения данной задачи в KrakenD существует Flexible-конфигурация, на основе Go Templates. Она позволяет рендерить итоговую конфигурацию шлюза по заданным параметрам и шаблонам, с применением переменных и уровнями абстракций в них, прямо как Helm Chart. Переменные можно передавать как через окружение, так и заранее указывать их в специальном файле под каждый контур (dev, uat, prod).
Доработка для генерации конфигурации
Так-как данное решение базируется на Go Templates то в нём есть один существенный недостаток для активно развивающегося приложения – это невозможность динамического добавления шаблонов в конфигурацию, например, передавая имя шаблона через переменную в цикле. Конфигурации эндпоинтов каждого микросервиса у нас хранится в директории шаблонов и периодически там появляются новые файлики. Чтобы эндпоинты из нового файла попали в итоговую конфигурацию их шаблон нужно было бы добавить в основную конфигурацию. Это было не удобно, поэтому придумали простое решение: до начала рендеринга find’ом мы проходимся по директории с шаблонами и собираем название всех найденных файлов по заданной регулярке и потом с помощью sed’а просто добавляем их в основную конфигурацию и запускаем рендеринг конфига. Так мы позволили разработчикам не переживать о том, как их новые эндпоинты необходимо применить.
Трассировка и мониторинг запросов
В процессе разработки любого приложения наступает неотъемлемый этап тестирования и отладки. KrakenD также может с этим помочь, из коробки он уже готов к интеграции с множеством популярных средств мониторинга и трассировки запросов.
В нашем кейсе мы используем KrakenD совместно с Jaeger для подробной трассировки запросов и анализа производительности в процессе разработки. Чтобы настроить интеграцию необходимо лишь в конфигурацию шлюза написать спецификацию подключения к нему и параметры экспорта запросов, например, включить туда только определенные запросы или какой-то процент от общего объема.
Пример спецификации для Jaeger:
{
"telemetry/opencensus": {
"sample_rate": 25,
"reporting_period": 5,
"enabled_layers": {
"backend": true,
"router": true,
"pipe": true
},
"exporters": {
"jaeger": {
"agent_endpoint": "http://jaeger.host:14268/api/traces",
"service_name": "krakend"
}
}
}
}
Дополнительно, так как KrakenD написан на Go и является Open Source решением, к нему можно написать собственный плагин для интеграции с какими-либо собственными приложениями.
Итог
Для нас KrakenD стал функциональным и гибким инструментом создания единого API, но для него приходится генерировать достаточно большую конфигурацию, прописывая для каждого эндпоинта множество необходимых настроек. Из-за большого количества параметров приходится тратить время на штудирование документации. Также достаточно обширный объем возможностей шлюза доступен только в Enterprise версии продукта, поэтому приходится придумывать собственные способы реализации подобных возможностей на базе Community версии. В целом нам нравится использование KrakenD в нашем приложении, учитывая, что на текущий момент мы не смогли найти Open Source продукт с подобными функциональными возможностями.
Комментарии (7)
PuerteMuerte
30.12.2023 08:27+1Дмитрий, разрешите покритиковать вашу статью (c) Для меня в принципе понятно, что у вас за инструмент, но непонятно главное - зачем он нужен? Похожая функциональность есть "из коробки" в любом облаке, будь-то AWS API Gateway или там Azure API Management. Чем ваша тулза отличается от дефолтных, чтобы был смысл добавлять ещё одно звено в тулчейн?
baldr
30.12.2023 08:27Ну, побродив по документации, я вижу что смысл в таком инструменте есть. Помимо того, что он помогает, частично, избавиться от фатального недостатка встроенных в облако сервисов, он еще и расширяем с помощью самописных плагинов. Есть интеграция с брокерами через AMQP, например, что тоже интересно. Их неуклюжее объяснение Backend-For-Frontend принципа мне не нравится, но, тем не менее, многие встроенные фичи довольно интересные.
Однако, к статье именно что вопросы - как он применяется и чем именно он выигрывает относительно чего-либо другого. В данный момент в статье больше описаны какие-то малоинтересные детали деплоя.
baldr
Дмитрий, разрешите покритиковать вашу статью.. Для меня из неё непонятно практически ничего. Всё что я отсюда понял - есть такой замечательный инструмент и он как-то вам помог что-то сделать. За деталями я пошел на офсайт и на самой первой странице документации картинка мне объяснила больше чем вся ваша статья.
Спасибо за сведения о новом инструменте, но я лично плюс статье поставить не могу. Минусы, впрочем, тоже не буду.
Crash13
Вероятно, Вы имели ввиду, что в статье "непонятно практически ВСЁ", а не "ничего"?
Просто для себя уточнить Вашу мысль задал вопрос.
baldr
Ок, "всё непонятно" и "не понятно ничего" - две грамматически более правильные формы, если вы к этому решили прицепиться.
Crash13
Я уточнял для себя вопрос, а не грамматические формы.
Хотел бы прицепиться, то не уточнял бы в своем вопросе, что это было для себя. Прочтите мой вопрос внимательно.
И, откуда в людях агрессия на уточняющие вопросы?...
На всякий случай, вопрос в этом сообщении был риторическим.