Agones (от др.-греч. agōn — «соревнование») позволяет развернуть кластер игрового сервера используя Kubernetes с возможностью Auto-Scaling. Этот open-source проект был создан в 2018 году, уже набрал 2500 звезд, был на Google I/O 2019, и на Хабре, к великому удивлению, еще не был упомянут. В топике описан краткий экскурс в архитектуру и инструкция по запуску тестового сервера на локальной машине. Если интересно, добро пожаловать под кат, вперед!
Описание проекта
Agones представляет собой Custom Resource (расширение Kubernetes API).
Проект в действительности требует большего внимания, так как позволяет запускать единичный игровой сервер (GameServer) или же целый "флот" серверов (Fleets) посредством конфигурационных yaml файлов, через Agones API. В свою очередь, каждый сервер дает оповещения о его жизненном цикле (GameServer lifecycles), описывая текущий статус (health checking, connection information). Сервера в кластере имеют возможность автоматического масштабирования (Fleet Autoscaling), которые интегрированы с базовыми возможностями Kubernetes. В дополнение, есть вывод статистики на панели (dashboard) с помощью Prometheus, Grafana или Stackdriver, экспортируются метрики посредством OpenCensus, что позволяет добавить собственный экспортер. Пример dashboard'a в Stackdriver:
Архитектура, основные элементы
Сам по себе Agones берет на себя задачу запуска, автоматического расширения и
Agones Kubernetes API делится на три основных пакета (packages), в каждом из которых находятся ресурсы: agones.dev (GameServer, GameServerSet, Fleet), allocation.agones.dev (GameServerAllocation), autoscaling.agones.dev (FleetAutoscaler). Как и в других ресурсах Kubernetes для их запуска используется yaml файлы.
Краткое описание каждого ресурса:
-
GameServer — создает некий шаблон, который позволяет использовать обычные Pod параметры, с некоторыми дополнениями, такие как hostPort и containerPort для игрового сервера. Agones SDK предоставляет дополнительный контейнер "помощник" (sidecar), с которым GameServer в процессе будет постоянно общаться
-
GameServerSet — структура данных для нескольких GameServer, очень схоже с отношением между Depoyment и ReplicaSet
-
Fleet — создает несколько готовых GameServer, используется GameServerAllocation для распределения ресурсов
-
GameServerAllocation — запрашивает GameServer из Fleet для использования и помечает, что он готов для использования игроками, благодаря этому GameServer не будет автоматически удален
-
FleetAutoscaler — автоматически расширяет или, наоборот, уменьшает количество серверов во Fleet
Диаграмма (отсюда) показывает жизненный цикл GameServer ресурса:
Фиолетовыми стрелками отмечена работа Agones SDK, красным — API пользователя, синим — контроллер игрового сервера, желтым — контроллер приложения.
Установка
В данном и последующих разделах используются команды с инструкции на официальном сайте, с некоторыми дополнениями. Рекомендуется использовать Kubernetes версии 1.12 (протестировано разработчиками). Для теста на локальном компьютере можно использовать minikube, который потребует kubectl и гипервизор (Hyper-V или VirtualBox) поддерживаемый операционной системой.
Для установки кластера и Agones необходимо запустить следующие команды:
minikube profile agones #создадим профиль под названием agones
minikube start --kubernetes-version v1.12.10 --vm-driver hyperv #virtualbox
minikube status #статус кластера для созданного профиля
kubectl create namespace agones-system #создадим пространство имен для agones
kubectl apply -f https://raw.githubusercontent.com/googleforgames/agones/release-1.0.0/install/yaml/install.yaml
Последняя команда скачивает конфигурационный файл Agones создающий Custom Resource Definitions (CRD) через Kubernetes API.
Запуск GameServer
Теперь можно запустить в кластере UDP сервер используя готовый тестовый сервер из примеров, который будет просто отвечать на посланный к нему запрос:
#создание GameServer ресурса
kubectl create -f https://raw.githubusercontent.com/googleforgames/agones/release-1.0.0/examples/simple-udp/gameserver.yaml
kubectl get gameservers #список всех GameServer
minikube ip #адрес для подключения к серверу
kubectl describe gameserver #параметры и статус каждого GameServer
kubectl get gs #более удобная команда, список всех GameServer
Для подтверждения того, что сервер работает можно использовать NetCat, для linux программа обычно идет в поставке с системой, для windows её нужно скачать, к примеру здесь. NetCat нужно запустить с параметром -u
(UDP запрос), указывая адрес minikube (лучше скопировать адрес с команды minikube ip
) и активный порт GameServer:
echo "hello" | nc -u $(minikube ip) 7331
Если после запуска команды в консоли появится ответ "ACK: hello", то сервер работает, его можно выключить следующей командой, которая инициализирует :
echo "EXIT" | nc -u $(minikube ip) 7331
Статус сервера проверяется командой kubectl describe gameserver
, он должен поменяться на Shutdown.
Вносим изменения в GameServer
Используя предыдущий пример изменим ответ сервера. Для начала скопируем репозиторий проекта:
git clone git@github.com:googleforgames/agones.git
В файле agones/examples/simple-udp/main.go поменяем строку 159 на
respond(conn, sender, "ACKNOWLEDGED: "+txt+"n")
Из корневой папки проекта запустим следующее, чтобы создать docker image и сохранить его в minikube. Для windows предварительно нужно запустить minikube docker-env | Invoke-Expression
, для linux eval $(minikube docker-env)
. Это позволит создавать docker images напрямую в minikube.
Создадим docker image:
docker build -t agones-go:modified -f .examplessimple-udpDockerfile .
Эта команда может занять некоторое время, так как весь репозиторий проекта будет копироваться в image. Этого можно избежать, если в директории оставить только папку sdks, файл main.go и Dockerfile.
Далее в examplessimple-udpgameserver.yaml изменим строку 28 на image: agones-go:modified
и создадим новый GameServer:
kubectl create -f .examplessimple-udpgameserver.yaml
Проверим изменения и выключим сервер:
echo "hello" | nc -u 172.17.113.72 7331
echo "EXIT" | nc -u 172.17.113.72 7331
Если после запуска команд в консоли появится ответ "ACKNOWLEDGED: hello", то внесенные изменения прошли успешно.
Запускаем сервер локально
Итерировать изменения для удобной разработки можно и без Kubernetes, используя только Agones SDK. Во время работы игрового сервера SDK общается через TCP с маленьким gRPC сервером, который Agones запускает в контейнере под тем же namespace. Такой контейнер в Kubernetes называется sidecar. Поэтому, для локальной разработки необходимо запустить процесс SDK. Для этого потребуется запустить его исходный файл с параметром -local
, который включает режим 'local mode'. Этот режим говорит процессу быть в пассивном режиме и никуда не подсоединяться, только лишь выводить логи в консоль, чтобы можно было видеть, что делает SDK во время работы игрового сервера.
Скачать последний agonessdk-server можно в релизах официального репозитория проекта. По умолчанию, после запуска SDK сервера создается болванка конфигурации GameServer, которая используется для GameServer() и WatchGameServer() SDK запросов. При запуске можно указать и собственный конфигурационный файл в формате yaml или json, для этого потребуется параметр -file
или его сокращенная версия -f
вместе с параметром -local
.
.sdk-server --local -f .examplessimple-udpgameserver.yaml
sdk-server : {"ctlConf":{"Address":"localhost","IsLocal":true,"LocalFile":".\examples\simple-udp\gameserver.yaml","Timeout":0,"Test":""},"grpcPor
t":59357,"httpPort":59358,"message":"Starting sdk sidecar","severity":"info","source":"main","time":"2019-09-29T12:45:59.8379817+02:00","version":"1.0.0"}
{"filePath":"C:\agones-release-1.0.0\examples\simple-udp\gameserver.yaml","message":"Reading GameServer
configuration","severity":"info","time":"2019-09-29T12:45:59.8479789+02:00"}
{"message":"Starting SDKServer grpc service...","severity":"info","source":"main","time":"2019-09-29T12:45:59.8529791+02:00"}
{"message":"Starting SDKServer grpc-gateway...","severity":"info","source":"main","time":"2019-09-29T12:46:00.1555756+02:00"}
Автор: AlexZ005