⚙️

UE LyraをAgonesで管理し,Docker Compes,Minikube,EKS環境で動作させる

2023/10/22に公開

要約

  • 前回の記事でLyraをLinux版のDedicated Serverとして稼働させた
  • Serverパッケージビルドし、コンテナ化、Agonesで管理し、Docker Compose,Minikube,EKS環境でそれぞれ動作させる
  • 構成やスクリプトはGitHubに配置

前回の記事

先にこちらの記事を参考にして頂くと前提知識が得られます。
https://zenn.dev/oniku2929/articles/7b255496b905f0

Agonesとは

端的に言いますと、ゲームサーバをKubernetes上で管理する機能を提供するOSSプロジェクトです。
こちらの記事が参考になります。
https://dev.classmethod.jp/articles/agones-on-eks/

公式doc
https://agones.dev/site/

GitHub
https://github.com/googleforgames/agones

Google Cloud blog
https://cloud.google.com/blog/ja/products/gcp/introducing-agones-open-source-multiplayer-dedicated-game-server-hosting-built-on-kubernetes

構成やスクリプトを設置したGitHubリポジトリ

https://github.com/oniku-2929/zenn_article_lyra_on_k8s
基本的に後述する、前提条件の環境変数が設定されている状態で使用される前提のものとなっています。
また、コマンドを手元で実行する場合は、該当リポジトリのバッチファイル等がお手元にある前提で、後述の手順は記載しています。

ソフトウェア情報

以下のソフトウェアが稼働する環境で動作確認しています。

OS

OS:Windows 10 Pro
バージョン:22H2

ソフトウェア

ソフトウェア名 バージョン 備考
Docker Desktop Docker Desktop 4.24.2 (124339) Engine Version 24.0.6 インストールページ
Terraform v1.5.7 Minikube,EKS環境構築時使用 インストールページ Chocolateyでインストールするのが楽
git version 2.37.3.windows.1 Minikube,EKS環境構築時使用インストールページ
Minikube v1.31.1 Minikube環境構築時使用インストールページ
aws CLI 2.11.11 EKS環境構築時使用インストールページ

動作前提条件の確認

後述の手順で動作するスクリプトは、以下の条件を満たしている事を前提としています。
まずはこれらの確認と対応を行います。

  • UE_ENGINE_ROOTという環境変数があらかじめ、エンジンのルートフォルダを指定した状態で設定されている
    • 例:
      set UE_ENGINE_ROOT          
      UE_ENGINE_ROOT=E:\\dev\\UnrealEngine5_2_0\\UnrealEngine
      
  • UE_ENGINE_ROOT直下にLyraStarterGameフォルダが配置されている

GitHub上で必要な権限を所有するPersonal access tokenを発行し、使用できる状態にする

後述する手順で、EpicがGitHub Container Registry(GHCR)上に配置しているエンジンのランタイム用コンテナイメージを使用します。
認証情報等の設定が必要な為、以下の設定作業を行います。

  • 前提としてこちらこちらに記載されているように、GitHubアカウントの連携設定が必要です。
  • こちらの手順に従い、GitHub上でPersonal access tokenを発行します
    • 必要な権限はread:packagesのみです。
    • 発行されたトークンは後の手順で使用します。
    • こちらに記載がある通り、2023/10現在はclassicトークンのみが対応しているようです。
  • docker login ghcr.ioコマンドを実行して、GHCRにログインします。
    • UsernameはGitHubのユーザー名,Passwordは先ほど発行したPersonal access tokenを入力します。

認証に成功すると,Login Succeededと表示されます。
こちらも参考になります

PATは期限が切れると、同じトークンが使用できなくなるため再発行の対応が必要です

Lyraの処理部分にAgones SDKを組み込み

Lyra自体の下準備として、AgonesのSDKを組み込みます。
これにより、LyraのゲームサーバがAgonesによって管理されるようになります。

AgonesのUnrealEngine用SDKの組み込みに関しては、公式のドキュメントページに記載があります。

まずはこちらの手順に従って、Lyraの実装内にAgonesのSDKを組み込みます。
具体的には、以下のような対応が必要です。

  • プラグインの追加処理
  • AgonesSDKの初期化処理の追加
    • LyraGameSession,LyraGameModeのどちらかの初期化処理に追加します。
  • Allocate,Shutdownの呼び出し処理追加

といった処理を追加します。

Linux Serverパッケージを作成する

SDKの組み込みが完了したら、Linux用のパッケージを作成します。
以下の手順を実行します。

  • container/make_package.bat Debugコマンドを実行します
    • 今回の例では、Linux ServerのDebug版パッケージを作成しています。
    • その他にも、Development,Shipping構成でのビルドが可能です。

上記の手順をエディタ上で手動で実行したい場合は、以下の手順を実行する事で同様の対応が可能です。

手動でLinux Serverパッケージを作成する手順
  • コンテンツ/SDK/デバイス管理「Linux」
  • バイナリコンフィギュレーション「Debug(デバッグ)」
  • ビルドターゲット「LyraServer」
    を選択した状態で「プロジェクトをパッケージ化」を実行します。
    自分の例では、(エンジンルート)/LyraStarterGame/Package/Debug/LinuxServerにパッケージを作成しています。

https://docs.unrealengine.com/5.3/ja/build-operations-cooking-packaging-deploying-and-running-projects-in-unreal-engine/

コンテナをビルドする

Linux Serverのパッケージ作成が完了したら、以下の手順に従って、コンテナをビルドします。

  • container/build.bat Debugを実行します
    • Debug構成でコンテナをビルドします。
    • その他にも、Development,Shipping構成でのビルドが可能です。

内部動作としては、ビルド用のディレクトリに作成したパッケージ関連のファイルを設定と一緒にコンテナ内に設置しています。

Docker Composeで動作確認を行う

前準備

  • Docker Desktopをインストールします。
    • docker composeコマンドが動作する必要があります・

動作確認

AgonesのSDKサイドカーコンテナはローカルでテスト動作させるための、--localオプションの機能を有しています。
https://agones.dev/site/docs/guides/client-sdks/local/
この機能を利用する事でローカル環境でも、Kuberntes環境無しの疑似動作確認が可能です。

この機能を使えば
まずはSDKサイドカーコンテナと自分達で動作させているサーバが通信できているか?
つまり
自分たちが組み込んだ処理が正しく動作しているか?
確認することができそうです。

Docker Composeでも、lyra-serverと一緒にsdkコンテナを起動しています。

compose.yaml
services:
  ~~~
  sdk:
  #ここの部分

というわけで、Docker Composeでこのまま2つのコンテナを起動して、動作確認を行いたい所ですが
このままでは動作しません。

なぜなら、AgonesのUnreal SDKはデフォルトではlocalhostで稼働しているAgonesのSDKサイドカーコンテナに接続する事を前提としている為です。
https://github.com/googleforgames/agones/blob/main/sdks/unreal/Agones/Source/Agones/Private/AgonesComponent.cpp#L68-L83

そこで、今回の例ではlocalモードで起動しているsdkのコンテナに接続する為に、コマンドラインによるコンフィグの上書きで接続先を変更するようにしています。
https://docs.unrealengine.com/5.3/ja/configuration-files-in-unreal-engine/#コマンドラインからコンフィギュレーションをオーバーライドする

AgonesComponent.h
UPROPERTY(EditAnywhere, Category = Agones, Config)
FString SDKHost = "localhost";
AgonesComponent.cpp
Request->SetURL(FString::Format(
    TEXT("http://{0}:{1}/{2}"), 
    {FStringFormatArg(SDKHost) ,FStringFormatArg(HttpPort), FStringFormatArg(Path)}
));
DefaultGame.ini
[/Script/Agones.AgonesComponent]
HttpPort=9358
HealthRateSeconds=10.0f
bDisableAutoConnect=true
SDKHost="localhost"

iniファイルでの接続先設定はlocalhostになっていますが、compose.yamlの以下の部分によって接続先をsdkコンテナに変更しています。

https://github.com/oniku-2929/zenn_article_lyra_on_k8s/blob/master/container/compose.yaml

compose.yaml
services:
  lyra-server:
    ~~~
    command: -log -ini:Game:[/Script/Agones.AgonesComponent]:SDKHost=sdk

この変更を行った上で、再度パッケージ作成、及びビルドを実行します。

  • container/make_package.bat Debugコマンドを実行します
  • container/build.bat Debugを実行します

最後に、以下のコマンドで起動用スクリプトを使用してコンテナを起動します。

  • container/up.bat Debugコマンドを実行します
    • Debug構成でコンテナを起動します。
    • その他にも、Development,Shipping構成での起動が可能です。

うまくLinuxサーバがsdkコンテナに接続できていれば、以下のようなログが出力されます。

sdk  | {"ctlConf":{"Address":"sdk","IsLocal":true,"LocalFile":"","Delay":0,"Timeout":0,"Test":"","TestSdkName":"","GRPCPort":9357,"HTTPPort":9358},"featureGates":"CountsAndLists=false\u0026CustomFasSyncInterval=true\u0026Example=false\u0026FleetAllocationOverflow=false\u0026PlayerAllocationFilter=false\u0026PlayerTracking=true\u0026PodHostname=true\u0026ResetMetricsOnDelete=true\u0026SplitControllerAndExtensions=true\u0026StateAllocationFilter=true","message":"Starting sdk sidecar","severity":"info","source":"main","time":"2023-09-13T14:51:41.8346737Z","version":"1.33.0"}
sdk  | {"grpcEndpoint":"sdk:9357","message":"Starting SDKServer grpc service...","severity":"info","source":"main","time":"2023-09-13T14:51:41.835595Z"}
sdk  | {"httpEndpoint":"sdk:9358","message":"Starting SDKServer grpc-gateway...","severity":"info","source":"main","time":"2023-09-13T14:51:42.8366761Z"}
sdk  | {"capacity":100,"message":"Setting Player Capacity","severity":"info","source":"*sdkserver.LocalSDKServer","time":"2023-09-13T14:51:46.2107055Z"}
sdk  | {"message":"Allocate request has been received!","severity":"info","source":"*sdkserver.LocalSDKServer","time":"2023-09-13T14:51:46.2107192Z"}
sdk  | {"message":"Gameserver update received","severity":"info","source":"*sdkserver.LocalSDKServer","time":"2023-09-13T14:51:46.2107651Z"}
sdk  | {"message":"Gameserver update received","severity":"info","source":"*sdkserver.LocalSDKServer","time":"2023-09-13T14:51:46.2107976Z"}
sdk  | {"message":"Health Ping Received!","severity":"info","source":"*sdkserver.LocalSDKServer","time":"2023-09-13T14:51:56.3450299Z"}
sdk  | {"message":"Health stream closed.","severity":"info","source":"*sdkserver.LocalSDKServer","time":"2023-09-13T14:51:56.3450603Z"}
...

ログから分かるようにsdkコンテナがAllocateのリクエストやPingを受け取っている事が確認できます。
SDKの組み込み処理は成功していそうです。

minikubeで動作確認を行う

Docker Composeを利用したローカルモードでの動作確認ができたら、次はminikubeを利用した動作確認を行ってみます。

ここでminikubeでの環境作成、Agonesのインストール、展開などの作業を1つずつ手作業で実行していっても良いのですが
Terraformの構成に落とし込んでいるので、基本的にはterraformコマンドの実行のみで環境構築が可能です。

今回は以下Providerの力をお借りしています。
https://registry.terraform.io/providers/scott-the-programmer/minikube/latest/docs

前準備

追加の前準備として、以下の作業を実行します。

  • Minikubeをインストールします
  • Terraformをインストールします

動作確認

  • minikubeに移動します

  • terraform initを実行します。

  • terraform applyを実行します。

    • 構成構築完了後minikube profile listを実行すると作成されたプロファイルに関する情報が確認できます。
      |-------------------------|-----------|---------|--------------|------|---------|---------|-------|--------|
      |         Profile         | VM Driver | Runtime |      IP      | Port | Version | Status  | Nodes | Active |
      |-------------------------|-----------|---------|--------------|------|---------|---------|-------|--------|
      | lyra-on-minikube-agones | hyperv    |         | 172.27.55.72 | 8443 | v1.27.3 | Running |     1 | *      |
      |-------------------------|-----------|---------|--------------|------|---------|---------|-------|--------|
      
  • クライアントから接続確認を行います。

    • ゲームサーバが起動したら、起動したGameServerのIPとポートを使用してクライアントから接続確認します
    • minikube/connect.batを実行すると、接続確認が行えます。
  • Grafanaにアクセスして、メトリクスを確認します。

    • 環境構築が完了すると、以下のメトリクスに関するドキュメントに記載されている手順を実行するのと同様の構成が作成されます。
    • Grafanaのダッシュボードにログインする場合は、以下のコマンドを実行します。
      kubectl port-forward deployments/grafana 3000 -n metrics
      
      この状態で、http://localhost:3000にアクセスするとGrafanaのダッシュボードにアクセスできます。
    • 上記URLにアクセスすると、ログイン画面が表示されます。
      ログイン用のパスワードは、環境構築完了後にgrafana_passwordとして出力されています。
      usernameにはadminを入力、passwordには上記のgrafana_passwordの値を入力します。
      パスワードを再度確認したい場合は、terraform output -raw grafana_passwordのコマンドを実行する事で確認できます。
    • Grafanaのメトリクスを確認すると、ゲームサーバの起動や削除のタイミングでメトリクスが変化している事が確認できます。

後片付け

minikubeの環境が必要なくなったら、以下の手順で環境を削除します。

  • minikubeに移動します。
  • terraform destroyで環境を削除します。

EKSで動作確認を行う

minikubeでも動作確認ができた!となれば、いよいよどこかのマネージドKubernetes環境で動作確認を行いたいと思いますよね!?👊
と、いうことで今回はEKSでも動作確認を行ってみます。

ここでもやはり偉大な巨人達の肩を借りて、既存のTerraform Providerで構成を作成しています。
以下Providerの力をお借りしています。
https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest

前準備

追加の前準備として、以下の手順を実行します。

  • AWS CLIをインストールします
    • aws sts get-caller-identityの実行と、各種Terraformを通じて作成するリソース関連操作が可能なIAM権限が必要です。

ECRのリポジトリを用意する

まず、EKSで使用するコンテナイメージをECRに格納する為、リポジトリを作成します。
以下の手順を実行します。

  • eks/images/に移動します
  • terraform initを実行します
  • terraform applyを実行します
    実行が完了すると、ECRのリポジトリが作成されます。
    確認したい場合は、以下のAWS CLIコマンドを実行します。
    aws ecr describe-repositories
確認コマンド出力例
{
    "repositories": [
        {
            "repositoryArn": "arn:aws:ecr:ap-northeast-1:***:repository/lyra-on-k8s-agones",
            "registryId": "***",
            "repositoryName": "lyra-on-k8s-agones",
            "repositoryUri": "***.dkr.ecr.ap-northeast-1.amazonaws.com/lyra-on-k8s-agones", 
            "createdAt": "2023-08-27T17:57:29+09:00",
            "imageTagMutability": "MUTABLE",
            "imageScanningConfiguration": {
                "scanOnPush": true
            },
            "encryptionConfiguration": {
                "encryptionType": "AES256"
            }
        }
    ]
}

ECRのリポジトリにコンテナイメージをプッシュする

上記手順でECRのリポジトリが作成できたら、コンテナイメージをプッシュします。
以下の手順を実行します。

  • eks\images\push_to_ecr.bat Debugコマンドを実行します。

EKSクラスタ等の環境を構築する

コンテナイメージのECRへの配置が完了したら、EKSクラスタ等の環境を構築します。
以下の手順を実行します。

  • eks/env/に移動します
  • terraform initを実行します
  • terraform applyを実行します
    実行が完了すると、EKSクラスタ等の環境が作成されます。
  • クライアントから接続確認を行います。
    • ゲームサーバが起動したら、起動したGameServerのIPとポートを使用してクライアントから接続確認します
    • eks/env/connect.batを実行すると、接続確認が行えます。

環境を削除する

EKS等の環境が必要なくなったら、以下の手順を実行し、環境を削除します。

  • eks/env/に移動します
  • terraform destroyを実行し、EKSクラスタ等の環境を削除します
  • eks/images/に移動します
  • terraform destroyを実行し、ECRリポジトリを削除します

所感

😂「構成が多くて動作確認メンドクサスギ・・」
😐👹「・・・」
😇💥👹 🙈🙉🙊

Discussion