Одна из наиболее важных задач при разделении системы на микросервисы - обеспечить надежный механизм их репликации и обнаружения и создать набор правил для маршрутизации входящих запросов к соответствующим контейнерам или сетевым узлам. Идеальная система также должна уметь отслеживать состояние доступности и исключать недоступные реплики из маршрутизации. В этой статье мы поговорим об использовании маршрутизатора Kong, который принимает на себя не только задачи умной маршрутизации, но и возможности по протоколированию и трансформации запросов, контролю доступа, мониторингу запросов, а также может быть расширен с использованием плагинов. Маршрутизатор Kong Gateway существует в свободном и коммерческом варианте, может быть запущен как самостоятельное приложение (например, через docker-контейнер kong), либо установлен в Kubernetes (в этом случае он представляется как специализированный Ingress-контроллер). Для управления Kong можно использовать как запросы к API, так и веб-интерфейсы Kong Manager или Konga. Многие расширения предустановлены в официальном контейнере, но они также могут быть найдены в Kong Plugin Hub. Мы с вами рассмотрим установку и настройку на примере простого приложения, состоящего из трех микросервисов (один из которых представляет публичный интерфейс без авторизации, для одного мы будем задавать сложные правила маршрутизации, а третий будет требовать обязательное использование токена для доступа к точкам подключения). Для начала составим топологию нашей системы и выделим микросервисы: сервис поиска местоположения и расширенной информации о городе по стране и названию (используется приложение Chercheville на Elixir , доступное на Docker Hub); сервис для получения информации из профиля авторизованного пользователя; сервис для выполнения авторизации и получения токена. Каждый сервис будет иметь собственную базу данных (или сторонний источник данных) и все взаимодействие между системами будет выполняться через шлюз API, который мы и будем настраивать с использованием Kong API Gateway. Kong использует для сохранения своей конфигурации базу данных PostgreSQL, либо может быть запущен с определением сервисов и привязок к json/yaml-файле. Мы будем рассматривать вариант запуска с базой данных. Для координации запуска будем использовать Docker Compose, который можно найти в официальном репозитории: https://github.com/Kong/docker-kong (путь /compose).  После выполнения первоначальных миграций базы данных запускается основной процесс, который начинает прослушать несколько TCP-портов: 8000/8443 - HTTP/HTTPS-трафик для маршрутизации к серверам; 8001/8444 - HTTP/HTTPS порты для отправки административных запросов (также используется веб-интерфейсом Konga для управления ресурсами); 8002/8445 - HTTP/HTTPS подключение к Kong Manager (веб-интерфейс), должен быть дополнительно разрешен и опубликован через docker-compose.yaml. Перед настройкой маршрутов нужно разобраться с используемыми терминами в Kong: Service - конфигурация backend-сервиса (протокол http/https, адрес хоста, порт, количество попыток подключения и таймауты, идентификатор клиентского сертификата при использовании https). К конфигурации сервиса могут быть подключены плагины для аудита/трансформации запросов, а также определены допустимые потребители (consumer). Route - правило маршрутизации входящих запросов, включает в себя перечисления связанных сервисов (может быть больше одного для отказоустойчивости) и группу фильтров (для http-протоколов) или набор правил для tcp-stream маршрутизации. К каждому маршруту может быть также добавлен плагин для обработки запросов. название домена (Hosts); префиксы пути (Paths); HTTP-методы (Methods); протоколы (http / https); проверка доменов для tcp-stream маршрутизации (SNI); источники запроса для tcp-stream (sources); получатели запроса для tcp-stream (destinations). Certificate - зарегистрированные клиентские сертификаты для подключения к https backend-сервисам (для каждого формируется уникальный id, который используется при конфигурации сервиса). Upstream - правило пересылки http/https трафика на один или несколько сервисов. После создания и настройки upstream появляется возможность добавить targets (ip/dns-адреса целевых серверов, порты и значение веса, которое влияет на вероятность выбора сервера при использовании хэш-правила none), а также Alert для отправки уведомлений администраторам по почте или в Slack при недоступности целевого сервера: Hash on - метод хэширования для выбора целевого сервиса из пула (может быть consumer, ip, cookie, header, none). В случае none используется последовательный выбор сервисов для равномерного распределения; Hash fallback - альтернативный метод хэширования, если основной не вернул результат (например, отсутствовал cookie или заголовок); Active Health Check - конфигурация проверки доступности (http-метод, путь, коды успешных и неуспешных ответов, количество попыток проверки, интервал проверки); Consumer - зарегистрированные авторизованные пользователи сервисов и метод их авторизации. Для Consumer определяется набор Credentials - это может быть Basic Auth (имя и пароль), API Key, Hash-based message authentication code (HMAC) - имя и секрет, OAuth2 (id и секрет приложения, redirect uri), JSON Web Token (JWT).  Для управления ресурсами можно использовать http-запросы к порту администрирования 8001 (или 8444 для https-запросов): http://ip:8001/services - просмотр списка/регистрация нового сервиса; http://ip:8001/routes - просмотр/создание маршрута; http://ip:8001/consumers - управление авторизованными пользователями; http://ip:8001/upstreams - изменение правил проксирования с проверкой доступности (upstream); http://ip:8001/certificates - управление клиентскими сертификатами; http://ip:8001 - просмотр информации о запущенном экземпляре kong. Для удобства доступа можно создать маршрут к admin api через основной порт (8000): И далее будет возможно получить доступ к сервису администрирования через http://localhost:8000/admin-api/. Наличие API для администрирования позволяет выполнить саморегистрацию сервиса и маршрута при запуске, но сейчас у нас доступ к api выполняется без авторизации, что нельзя назвать безопасным решением. Создадим новый consumer с APIKey и назначим его на доступ к маршруту api: Теперь доступ к API будет происходить только с использованием заголовка apikey: 6Y6fKCsFWWWSRMXGyUWs8g9q.  Кроме плагинов авторизации, можно добавить следующие расширения: session - отслеживание сессии между запросами (чаще всего с использованием cookie); bot detection - обнаружение активности ботов; cors - управление политикой cors; ip restriction - ограничение доступа по белым и черным спискам; acme - интеграция с letsencrypt для автоматического обновления сертификатов; rate limiting - ограничение количества запросов в секунду; response ratelimiting - ограничение количества ответов в секунду; request size limiting - ограничение размера запроса; proxy cache - кэширование ответа; pre function - запустить lua-функцию перед обработкой запроса; post function - запустить lua-функцию после обработки запроса; aws lambda - запустить внешнюю функцию с AWS при обработке правила; azure functions - запустить Azure-функцию при обработке правила; datadog - отправить метрики запросов в datadog; prometheus - отправить метрики по правилам в prometheus; zipkin - отправка меток по обработке правил для распределенной трассировки zipkin; request transformer - изменение запроса перед передачей на upstream-сервер; response transformer - изменение ответа upstream-сервера; correlation ID - отслеживание связи в цепочке пересылок; tcp/udp/http log - отправка информации о запросе и ответе на сервер журналирования через tcp/udp/http; file log - запись информации о запросе/ответе в файл; syslog - отправка запроса и ответа в системный процесс syslog; statsd - отправка статистики по обработке запроса в statsd; loggly - пересылка информации о запросе/ответе в loggly. При необходимости создания собственных расширений можно использовать Python Developent Kit. Для управления также можно установить konga для настройки всех ресурсов через веб-интерфейс: При выполнении первого подключения нужно будет сконфигурировать адрес Kong API и далее можно будет подключиться к https и выполнить аналогичные настройки через веб-интерфейс: Запустим теперь наш сервис для маршрутизации и выполним привязку его методов к префиксу /place. Для этого клонируем репозиторий и запустим docker compose up -d. После запуска будет необходимо выполнить импорт данных по странам: Для проверки доступности сервиса выполним запрос http://localhost:5000/cities/?q=Paris. Теперь выполним связывание сервиса и маршрута через konga: Здесь Host - внешний адрес сервера (альтернативно можно использовать DNS-имя во внутренней сети или через используемый Service Discovery, например Consul). Дальше необходимо настроить привязку сервиса к внешнему маршруту: Strip Path позволяет трансформировать адрес и убрать префикс /places при пересылке запроса. Теперь сервис будем доступен через адрес http://localhost:8000/places/ и можно будет выполнить запрос между микросервисами или от внешнего клиента через API Gateway. Следующим шагом выполним саморегистрацию сервиса авторизации в kong, который также будет управлять Consumer для доступа к сервису профиля: При регистрации сервиса profile необходимо добавить плагин key-auth для проверки токена при обращении к адресам profile. При авторизации будет добавлен заголовок X-Consumer-ID для хранения идентификатора, который соответствует представленному токену. Аналогично можно настроить удаление сервисов и маршрутов при завершении приложения. Таким образом с использованием API-шлюза Kong можно динамически изменять привязку маршрутов к экземплярам сервисов, а также решать типичные задачи контроля доступа и получения метрик по времени выполнения запросов. Всех, кому интересна тема микросервисов, хочу пригласить на бесплатный урок по теме: "Авторизация и аутентификация в микросервисной архитектуре". Регистрация доступна по ссылке ниже. Зарегистрироваться на вебинар  Flutter Developer@YandexPro, DevOps, IT Architect