Масштабирование игровых серверов в Kubernetes: почему стандартные Deployment не подходят и как Agones решает проблему сессионных нагрузок
Перенос серверной инфраструктуры в Kubernetes стал отраслевым стандартом для веб-приложений. Однако команды, запускающие в кластерах серверы для соревновательного мультиплеера (шутеров, королевских битв или сессионных стратегий), быстро упираются в ограничения базовой модели оркестратора. Механизмы управления подами (pod — наименьшая единица развертывания в Kubernetes из одного или нескольких контейнеров) и маршрутизации входящего трафика, созданные для сайтов и stateless API (сервисов без сохранения состояния между независимыми запросами), приводят к сбоям в сессионных играх.
Платформа с открытым исходным кодом Agones, созданная Google совместно с игровым издательством Ubisoft и развиваемая сообществом Google for Games, предлагает специализированную модель оркестрации выделенных игровых серверов (dedicated game servers) поверх Kubernetes, учитывая специфику протокола UDP, долгих сессий и прямого подключения игроков.
Архитектурный конфликт: почему стандартный Deployment ломает игры
В веб-разработке базовой сущностью служит Deployment — контроллер, поддерживающий заданное количество идентичных реплик сервиса. Если нагрузка падает, механизм масштабирования удаляет лишние поды; при релизе новой версии запускается плавное обновление (rolling update), поочередно заменяющее старые контейнеры новыми. Для веб-трафика это безопасно, так как сетевой балансировщик (Service) распределяет входящие HTTP-запросы по любым рабочим узлам.
В соревновательных сетевых играх физика взаимодействия принципиально иная:
- Непрерывное состояние в памяти (in-memory state). Сервер непрерывно рассчитывает физику мира, координаты персонажей, попадания и таймеры раундов с частотой 30–128 тактов в секунду (tick rate). Состояние матча находится исключительно в оперативной памяти конкретного процесса. Если Kubernetes решит завершить под в рамках масштабирования или обновления ноды, матч для всех участников мгновенно прервется.
- Сессии поверх UDP вместо независимых запросов. Игры передают данные по протоколу UDP (быстрому протоколу без накладных расходов на подтверждение доставки каждого пакета). В отличие от HTTP, здесь нет постоянного соединения, которое балансировщик мог бы прозрачно переключить на другой под: пакеты должны попадать ровно в один и тот же процесс операционной системы.
- Прямое сетевое подключение. Игроку не нужен виртуальный адрес балансировщика. Клиент должен соединяться напрямую с внешним IP-адресом конкретного серверного узла и портом, выделенным под его матч.
Стандартные контроллеры Kubernetes не знают, идет ли на сервере матч или он простаивает. Управление игровыми сессиями через стандартный Deployment неизбежно приводит к срыву матчей.
Анатомия Agones: кастомные ресурсы и жизненный цикл GameServer
Agones расширяет Kubernetes через пользовательские описания ресурсов (Custom Resource Definition, CRD). Ключевой сущностью платформы становится GameServer.
Каждый GameServer управляет одним игровым процессом. Рядом с контейнером игры Agones развертывает вспомогательный контейнер — сайдкар (sidecar). Сервер общается с сайдкаром через локальный SDK по протоколу gRPC или REST. Контейнер игры не должен занимать сетевые порты 8080, 9357 и 9358, зарезервированные сайдкаром под служебный API и метрики.
Жизненный цикл GameServer состоит из четырех фаз:
- Creating / Starting: инициализация контейнера, загрузка игровых карт и запуск бинарного файла.
- Ready: процесс готов принять игроков и уведомляет платформу вызовом
Ready()в SDK. - Allocated: сервер закреплен за начавшимся матчем. Как только матчмейкер резервирует сервер, Agones переводит его в статус
Allocated. С этого момента сервер неприкосновенен: автоматическое масштабирование никогда не удалит занятый под до конца игры. - Shutdown: раунд окончен, игроки отключились, сервер вызывает
Shutdown()и безопасно освобождает ресурсы.
Agones строго разделяет «здоровье» (health) и «готовность» (readiness). Сервер может быть исправен, слать сигналы Health(), но находиться в статусе Allocated, оставаясь недоступным для других игроков.
Маршрут игрока: интеграция с матчмейкингом
В Agones сетевой трафик разделен на управляющий контур (Control Plane) и игровой поток (Data Plane):
- Игровой клиент запрашивает матч в сервисе подбора соперников — матчмейкере (Matchmaker).
- Матчмейкер подбирает группу игроков и отправляет в API Kubernetes запрос на создание объекта
GameServerAllocation. - Контроллер Agones находит свободный сервер со статусом
Ready, атомарно переводит его в статусAllocatedи назначает внешний сетевой порт из разрешенного диапазона узла (например, порт7432на ноде с IP198.51.100.25). - Матчмейкер возвращает адрес
198.51.100.25:7432игровым клиентам. - Игроки подключаются напрямую к выделенному сокету по протоколу UDP без посредничества прокси и балансировщиков.
Управление пулом: Fleet и политики масштабирования
Запуск игрового сервера занимает от десятков секунд до пары минут. Чтобы игроки не ждали старта контейнеров, Agones объединяет серверы в абстракцию Fleet (флот). Флот поддерживает «теплый резерв» готовых серверов в статусе Ready.
Размером пула управляет контроллер FleetAutoscaler, поддерживающий две стратегии:
- Буферная политика (Buffer Policy): контроллер держит постоянный резерв свободных серверов (
Ready) сверх занятых (Allocated). Если буфер равен 5 серверам, а занято 15, Agones будет удерживать 20 экземпляров, восполняя буфер по мере старта новых матчей. - Вебхук-политика (Webhook Policy): контроллер обращается к внешнему HTTP-сервису, передавая объект
FleetAutoscaleReview. Сервис оценивает длину очереди игроков в матчмейкере и заранее заказывает необходимые мощности.
При размещении подов Agones поддерживает стратегию Packed: серверы плотно компонуются на минимальном числе физических узлов. Это позволяет механизму Cluster Autoscaler безопасно выключать полностью освободившиеся серверные ноды и экономить инфраструктурный бюджет.
Пошаговое развертывание: запуск флота в кластере
Развертывание игрового пула описано в официальных спецификациях Agones Documentation и Fleet Autoscaler.
Шаг 1. Системные требования
Перед началом убедитесь в наличии:
- Доступа к кластеру Kubernetes через утилиту
kubectl. - Открытого диапазона входящих портов UDP 7000–8000 в файрволе облачной сети.
- Установленного контроллера Agones в кластере.
Шаг 2. Запуск тестового флота
Примените официальный манифест тестового флота:
kubectl apply -f https://raw.githubusercontent.com/googleforgames/agones/release-1.60.0/examples/simple-game-server/fleet.yaml
Команда создаст две реплики простого игрового сервера на Go.
Шаг 3. Верификация состояния
Проверьте статус развернутых серверов:
kubectl get gameservers
Убедитесь, что серверы перешли в статус Ready и получили внешние адреса:
NAME STATE ADDRESS PORT NODE AGE
simple-game-server-4b5c6 Ready 198.51.100.25 7432 node-pool 25s
simple-game-server-8f2a1 Ready 198.51.100.26 7115 node-pool 25s
Отправьте тестовый UDP-пакет через nc -u 198.51.100.25 7432. Сервер немедленно вернет подтверждение ACK.
Шаг 4. Автомасштабирование пула
Создайте манифест fleet-autoscaler.yaml:
apiVersion: autoscaling.agones.dev/v1
kind: FleetAutoscaler
metadata:
name: simple-game-server-autoscaler
spec:
fleetName: simple-game-server
policy:
type: Buffer
buffer:
bufferSize: 2
minReplicas: 2
maxReplicas: 10
Примените конфигурацию командой kubectl apply -f fleet-autoscaler.yaml. Система начнет автоматически удерживать две готовые реплики в горячем резерве.
Чек-лист надежности перед продакшеном
Перед запуском боевого проекта проверьте ключевые параметры надежности:
- Сетевые порты: убедитесь, что приложение не занимает зарезервированные сайдкаром порты
8080,9357и9358. - Защита секретов: передавайте токены баз данных и ключи API через Kubernetes Secrets или HashiCorp Vault, избегая открытого текста в переменных окружения.
- Тест на эвикшен: сымитируйте дренаж узла (
kubectl drain) с сервером в статусеAllocated. Оркестратор обязан сохранять работающий под до завершения матча. - Задержка старта нод: закладывайте время инициализации виртуальной машины (2–3 минуты) в размер буфера свободных серверов флота.
- Бизнес-метрики: настраивайте оповещения по числу занятых серверов, сбоям аллокаций и длине очереди в матчмейкере, а не по усредненной утилизации CPU.
