Services, Routes, Consumers — базовые примитивы Kong
Service, Route и Consumer — три основных примитива Kong для маршрутизации запросов и управления доступом.
Проблема: Нужно абстрагироваться от конкретных URL бэкендов, чтобы легко менять их без изменения конфигурации маршрутизации.
Решение: Service в Kong — это представление upstream-сервиса, содержащее URL бэкенда.
# Базовое создание
curl -X POST http://localhost:8001/services \
--data "name=users-api" \
--data "url=http://users-service:8080"Параметры:
name — уникальное имя сервисаurl — полный URL бэкенда (протокол, хост, порт, опционально path)connect_timeout, write_timeout, read_timeout — таймауты (мс)retries — количество попыток подключенияПроблема: Бэкенд может отвечать медленно, нужно настроить таймауты.
Решение: Явное указание таймаутов при создании Service.
curl -X POST http://localhost:8001/services \
--data "name=slow-api" \
--data "url=http://slow-service:8080" \
--data "connect_timeout=5000" \
--data "write_timeout=10000" \
--data "read_timeout=30000" \
--data "retries=3"Значения по умолчанию:
connect_timeout: 60000 мсwrite_timeout: 60000 мсread_timeout: 60000 мсretries: 5Проблема: Бэкенд обслуживает несколько API по разным path.
Решение: Указание path в URL Service.
# Service будет проксировать на http://api.example.com/api/v1/*
curl -X POST http://localhost:8001/services \
--data "name=api-v1" \
--data "url=http://api.example.com/api/v1"Важно: Path из URL Service добавляется к path запроса. Если Routeсоответствия /users, а Service имеет URL http://backend/api, итоговый запрос будет на http://backend/api/users.
# Получение всех Services
curl http://localhost:8001/services
# Получение конкретного Service
curl http://localhost:8001/services/users-api
# Обновление Service
curl -X PATCH http://localhost:8001/services/users-api \
--data "read_timeout=60000"
# Удаление Service
curl -X DELETE http://localhost:8001/services/users-apiПроблема: Нужно маршрутизировать запросы на разные Services в зависимости от path, хоста, методов.
Решение: Route определяет условиясоответствия запроса и связывает его с Service.
Проблема: Нужно маршрутизировать запросы к /api/users на Service users-api.
Решение: Создание Route с указанием path.
# Вложенное создание (автоматически связывается с Service)
curl -X POST http://localhost:8001/services/users-api/routes \
--data "name=users-route" \
--data "paths[]=/api/users"Или создание с явным указанием service:
curl -X POST http://localhost:8001/routes \
--data "name=users-route" \
--data "paths[]=/api/users" \
--data "service.name=users-api"Kong поддерживает различные критериисоответствия:
# Точный path
curl -X POST http://localhost:8001/services/api/routes \
--data "paths[]=/api/users"
# Все запросы к /api/users/*
curl -X POST http://localhost:8001/services/api/routes \
--data "paths[]=/api/users/"
# Несколько paths
curl -X POST http://localhost:8001/services/api/routes \
--data "paths[]=/users" \
--data "paths[]=/profiles"Важно: Kong автоматически добавляет wildcard в конец path. Route с paths[]=/api/usersсоответствия:
/api/users/api/users/123/api/users/123/posts# Только GET и POST
curl -X POST http://localhost:8001/services/api/routes \
--data "paths[]=/api/users" \
--data "methods[]=GET" \
--data "methods[]=POST"# Match по хосту
curl -X POST http://localhost:8001/services/api/routes \
--data "hosts[]=api.example.com" \
--data "paths[]=/api"# Match по заголовку X-API-Version
curl -X POST http://localhost:8001/services/api/routes \
--data "paths[]=/api" \
--data "headers[]=x-api-version:v2"# Match по path + методу + хосту
curl -X POST http://localhost:8001/services/api/routes \
--data "name=users-v2-route" \
--data "paths[]=/api/users" \
--data "methods[]=GET" \
--data "methods[]=POST" \
--data "hosts[]=api.example.com"Проблема: Запрос можетсоответствия несколько Routes. Как Kong выбирает?
Решение: Kong использует алгоритм приоритизации на основе специфичности.
Факторы приоритета (от высшего к низшему):
Пример:
# Route 1: /api (приоритет ниже)
curl -X POST http://localhost:8001/services/api-v1/routes \
--data "paths[]=/api"
# Route 2: /api/users (приоритет выше)
curl -X POST http://localhost:8001/services/api-v2/routes \
--data "paths[]=/api/users"Запрос к /api/users/123 будет обработан Route 2 (более специфичный path).
Проблема: Нужно сложное условиесоответствия (например, path с определённым форматом ID).
Решение: Regex Routes с префиксом ~.
# Match /users/{uuid}
curl -X POST http://localhost:8001/services/users/routes \
--data "paths[]=~/users/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"Важно: Regex Routes имеют меньшую производительность. Используйте только когда нельзя обойтись обычными paths.
Проблема: Нужно распределить нагрузку между несколькими экземплярами сервиса.
Решение: Upstream — абстракция для группы Target'ов (серверов).
# Создание Upstream
curl -X POST http://localhost:8001/upstreams \
--data "name=users-upstream" \
--data "algorithm=round-robin"Алгоритмы балансировки:
round-robin — циклическое распределение (по умолчанию)least-connections — на сервер с наименьшим числом соединенийhash — хэширование по ключу (например, по IP клиента)# Добавление Target'ов
curl -X POST http://localhost:8001/upstreams/users-upstream/targets \
--data "target=users-1.example.com:8080" \
--data "weight=100"
curl -X POST http://localhost:8001/upstreams/users-upstream/targets \
--data "target=users-2.example.com:8080" \
--data "weight=100"
curl -X POST http://localhost:8001/upstreams/users-upstream/targets \
--data "target=users-3.example.com:8080" \
--data "weight=50" # Меньше трафикаПараметр weight: Определяет долю трафика. Target с weight=100 получит в 2 раза больше запросов, чем target с weight=50.
# Service указывает на Upstream по имени
curl -X POST http://localhost:8001/services \
--data "name=users-service" \
--data "url=http://users-upstream"Важно: URL Service должен совпадать с именем Upstream (без протокола и порта).
# Получение всех Target'ов
curl http://localhost:8001/upstreams/users-upstream/targets
# Удаление Target'а
curl -X DELETE http://localhost:8001/upstreams/users-upstream/targets/users-1.example.com:8080
# Установка веса в 0 (временное отключение)
curl -X PATCH http://localhost:8001/upstreams/users-upstream/targets/users-1.example.com:8080 \
--data "weight=0"Проблема: Нужно идентифицировать пользователей для аутентификации, авторизации и индивидуального rate limiting.
Решение: Consumer — представление пользователя или приложения в Kong.
# Базовое создание
curl -X POST http://localhost:8001/consumers \
--data "username=mobile-app"
# С кастомным ID
curl -X POST http://localhost:8001/consumers \
--data "username=web-app" \
--data "custom_id=web-app-123"Проблема: Consumer нужно аутентифицировать.
Решение: Добавление credentials (API-ключи, JWT, OAuth2).
# Создание API-ключа для Consumer
curl -X POST http://localhost:8001/consumers/mobile-app/key-auth \
--data "key=secret-key-123"# Создание JWT credentials
curl -X POST http://localhost:8001/consumers/mobile-app/jwt \
--data "algorithm=HS256" \
--data "key=mobile-app-key" \
--data "secret=my-secret"Проблема: Разные лимиты для разных потребителей (бесплатный vs премиум).
Решение: Применение плагина rate-limiting к Consumer.
# Бесплатный тариф — 100 запросов/час
curl -X POST http://localhost:8001/consumers/free-user/plugins \
--data "name=rate-limiting" \
--data "config.hour=100" \
--data "config.policy=redis"
# Премиум тариф — 10000 запросов/час
curl -X POST http://localhost:8001/consumers/premium-user/plugins \
--data "name=rate-limiting" \
--data "config.hour=10000" \
--data "config.policy=redis"Проблема: Нужно понять, как все компоненты работают вместе.
Решение: Пример полной конфигурации.
# 1. Создаём Upstream с Target'ами
curl -X POST http://localhost:8001/upstreams \
--data "name=api-upstream"
curl -X POST http://localhost:8001/upstreams/api-upstream/targets \
--data "target=api-1:8080" \
--data "weight=100"
curl -X POST http://localhost:8001/upstreams/api-upstream/targets \
--data "target=api-2:8080" \
--data "weight=100"
# 2. Создаём Service
curl -X POST http://localhost:8001/services \
--data "name=api-service" \
--data "url=http://api-upstream"
# 3. Создаём Route
curl -X POST http://localhost:8001/services/api-service/routes \
--data "name=api-route" \
--data "paths[]=/api" \
--data "methods[]=GET" \
--data "methods[]=POST"
# 4. Создаём Consumer
curl -X POST http://localhost:8001/consumers \
--data "username=my-app"
# 5. Добавляем API-ключ
curl -X POST http://localhost:8001/consumers/my-app/key-auth \
--data "key=my-secret-key"
# 6. Применяем плагин аутентификации к Route
curl -X POST http://localhost:8001/routes/api-route/plugins \
--data "name=key-auth"
# 7. Применяем rate limiting к Consumer
curl -X POST http://localhost:8001/consumers/my-app/plugins \
--data "name=rate-limiting" \
--data "config.minute=60"Схема работы:
Клиент → [Запрос с заголовком apikey: my-secret-key]
↓
Kong Gateway
↓
1. Match Route по path /api
↓
2. Проверка API-ключа (key-auth плагин)
↓
3. Проверка rate limit для Consumer 'my-app'
↓
4. Балансировка на api-1:8080 или api-2:8080
↓
Upstream Service
Проблема: Бэкенд должен знать оригинальный IP клиента, протокол, хост.
Решение: Kong добавляет заголовки к проксируемым запросам.
Kong автоматически добавляет:
| Заголовок | Значение |
|---|---|
X-Real-IP | IP клиента |
X-Forwarded-For | Цепочка IP (клиент + прокси) |
X-Forwarded-Proto | Оригинальный протокол (http/https) |
X-Forwarded-Host | Оригинальный хост |
X-Forwarded-Port | Оригинальный порт |
Host | Хост из Service URL |
Проблема: Нужно добавить кастомные заголовки.
Решение: Плагин request-transformer.
curl -X POST http://localhost:8001/services/api-service/plugins \
--data "name=request-transformer" \
--data "config.add.headers=X-Custom-Header:my-value" \
--data "config.remove.headers=X-Unwanted-Header"Проблема: Запрос не попадает на ожидаемый Service.
Решение:
# Проверка всех Routes
curl http://localhost:8001/routes
# Проверка конкретного Route
curl http://localhost:8001/routes/{name}
# Проверка приоритета Routes
curl http://localhost:8001/routes/{name}/plugins
# Тестирование с verbose
curl -v http://localhost:8000/api/usersПроблема: Kong не может подключиться к upstream.
Решение:
# Проверка доступности upstream
curl http://users-service:8080/health
# Проверка таймаутов Service
curl http://localhost:8001/services/users-api
# Увеличение таймаутов
curl -X PATCH http://localhost:8001/services/users-api \
--data "read_timeout=60000"Проблема: Rate limit превышен.
Решение:
# Проверка применённых плагинов
curl http://localhost:8001/routes/{name}/plugins
# Увеличение лимита
curl -X PATCH http://localhost:8001/routes/{name}/plugins/{plugin-id} \
--data "config.minute=120"Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.