Kubernetes Engine での専用ゲームサーバーの実行

サーバー アプリケーションをコンテナ イメージとしてパッケージ化することが主流になってきています。多くのゲーム会社は、コンテナを使用して VM の利用率を上げようとしています。また、コンテナが提供する独立した実行環境にも注目しています。しかし、関心は高いものの、何から始めればよいのかわからないというゲーム会社も少なくありません。本番環境の専用ゲームサーバーをデプロイするには、コンテナ オーケストレーション フレームワークの Kubernetes が最適です。

このチュートリアルでは、リアルタイム、セッション ベースのマルチプレーヤー型専用ゲームサーバーGoogle Kubernetes Engine 上で実行するための拡張可能なアーキテクチャについて説明します。このアーキテクチャでは、スケーリング マネージャー プロセスが必要に応じて仮想マシン インスタンスを自動的に開始または停止します。Kubernetes ノードのマシン構成はマネージド インスタンス グループによって自動的に処理されます。

このチュートリアルでは、説明と実装を簡単にするため、単純な構造のオンライン ゲームを使って説明を進めます。より複雑な構造が必要になる個所は、その都度、指摘していきます。

目標

  • Docker を使用して、人気のあるオープンソース専用ゲームサーバー(DGS)の OpenArena のコンテナ イメージを Linux 上に作成する。このコンテナ イメージには、必要な Linux 基本イメージ、バイナリ、ライブラリのみが含まれます。
  • 読み取り専用の永続ディスク ボリュームにアセットを保存し、実行時にコンテナにマウントする。
  • Kubernetes API と Google Cloud Platform API を使用して、基本的なスケジューラ プロセスを設定し、ノードのスケーリングをオンデマンドで行う。

料金

このチュートリアルでは、課金対象である以下の Google Cloud Platform コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。

始める前に

このチュートリアルは Linux または macOS 環境から実行します。

  1. GCP プロジェクトを選択または作成します。

    [リソースの管理] ページに移動

  2. プロジェクトに対して課金が有効になっていることを確認します。

    課金を有効にする方法について

  3. Compute Engine API を有効にします。

    APIを有効にする

  4. Cloud SDK をインストールして初期化します。

    : このチュートリアルでは Cloud Shell を使用できません。Cloud SDK をインストールする必要があります。

  5. kubectl をインストールします。これは、Kubernetes のコマンドライン インターフェースです。
    gcloud components install kubectl
  6. GitHub にあるチュートリアルのリポジトリのクローンを作成します。
    git clone https://github.com/GoogleCloudPlatform/gke-dedicated-game-server.git
    
  7. Docker をインストールします。

    このチュートリアルでは、root ユーザーとして Docker コマンドを実行しません。root 以外のユーザーが Docker を管理できるように、インストール後の処理を行ってください。
  8. (省略可)チュートリアルの最後にゲームサーバーへの接続をテストする場合は、OpenArena ゲーム クライアントをインストールします。ゲーム クライアントを実行するには、デスクトップ環境が必要です。このチュートリアルでは、Linux または macOS でのテスト方法について説明します。

アーキテクチャ

ゲーム ソリューションの概要

クラウド上のゲーム インフラストラクチャの概要ページでは、多くのオンライン ゲーム アーキテクチャに共通するコンポーネントの概要について説明しています。このチュートリアルでは、フロントエンド サービスとして Kubernetes DGS クラスタを実装し、バックエンド サービスとしてスケーリング マネージャを実装します。本番環境のゲーム インフラストラクチャには、これ以外に多くのフロントエンド サービスとバックエンド サービスが実装されていますが、このチュートリアルでは、これらのサービスについて説明しません。

このチュートリアルの設計上の制約

このチュートリアルでは、簡単で拡張可能なゲームサンプルを作成するため、次の制約を前提としています。

  • 対戦型のリアルタイム ゲームで、正式な DGS でゲームの状態をシミュレートします。
  • DGS は UDP 経由でクライアントと通信します。
  • 各 DGS プロセスで 1 つの対戦を実行します。
  • どの DGS プロセスでも、ほぼ同じ負荷が発生します。
  • 対戦には最大時間が設定されています。
  • DGS の起動時間は無視できるレベルで、専用のゲームサーバー プロセスを事前に開始しておく必要はありません。
  • ピーク後にスケールダウンするときに、費用節約のために対戦を早期に終了することはありません。プレーヤーのエクスペリエンスに影響を及ぼさないことを優先します。
  • DGS プロセスでエラーが発生し、続行不能な場合は、対戦状態が失われます。プレーヤーは、ゲーム クライアントから別の対戦に参加することになります。
  • DGS プロセスはディスクから静的アセットを読み込みますが、アセットへの書き込みは行いません。

これらの制約はゲーム業界で特殊のものではなく、実際の事例でも同様の制約がある場合があります。

GCP 作業環境の準備

gcloud コマンドを簡単に実行できるようにプロパティを設定します。これにより、コマンドを実行するたびに、プロパティのオプションを指定する必要がなくなります。

  1. [PROJECT_ID] にプロジェクト ID を指定して、デフォルトのプロジェクトを設定します。

    gcloud config set project [PROJECT_ID]

  2. [ZONE] に優先ゾーンを指定して、Compute Engine のデフォルト ゾーンを設定します。

    gcloud config set compute/zone [ZONE]

専用ゲームサーバーのコンテナ化

このチュートリアルでは、「GPL idTech3 テクノロジーに基づいてコミュニティが作り上げたデスマッチ FPS」といわれている OpenArena を使用します。このゲームの技術が登場してから 15 年以上になりますが、現在でも一般的な DGS パターンの優れた見本です。

  • サーバー バイナリは、ゲーム クライアントと同じコードベースからコンパイルされます。
  • サーバー バイナリには、サーバーがシミュレーションを実行するために必要なデータアセットしか含まれていません。
  • ゲームサーバーのコンテナ イメージは、サーバー プロセスの実行に必要な基本 OS コンテナ イメージに、バイナリ、ライブラリのみを追加したものです。
  • アセットは別のボリュームからマウントされます。

このアーキテクチャには多くのメリットがあります。バイナリのみが置換され、消費するディスク容量も少ないため、イメージの配布を迅速に行い、更新の負荷を軽減することができます。

コンテナ イメージの作成

Dockerfile に、ビルドするイメージを記述します。このチュートリアルの Dockerfile は、openarena/Dockerfile のリポジトリにあります。openarena/ ディレクトリから Docker の build コマンドを実行してコンテナ イメージを生成し、OpenArena サーバーのバージョン 0.8.8 というタグを付けます。

docker build -t openarena:0.8.8 .

アセット ディスクの生成

通常、ゲームのバイナリはアセットよりもかなり小さくなります。このため、バイナリのみを含むコンテナ イメージを作成することは理にかなっています。アセットは永続ディスクに配置し、DGS コンテナを実行する複数の VM インスタンスに接続できるようにします。このアーキテクチャでは、コスト面のメリットがあるだけでなく、すべての VM インスタンスにアセットを配布する必要がなくなります。

  1. gcloud を使用して、サイズの小さい Compute Engine VM インスタンスを作成します。

    gcloud compute instances create openarena-asset-builder \
        --machine-type f1-micro --image-family debian-9 \
        --image-project debian-cloud

  2. 永続ディスクを作成します。

    gcloud compute disks create openarena-assets --size=50GB \
        --type=pd-ssd --description="OpenArena data disk. \
        Mount read-only at /usr/share/games/openarena/baseoa/"

    永続ディスクはブートディスクと別にし、仮想マシンと一緒に削除されないように構成する必要があります。Kubernetes の persistentVolume 機能は、GKE で永続ディスクを扱うときに役に立ちます。Compute Engine では、これらの永続ディスクは、パーティション テーブルのない単一の ext4 ファイル システムにする必要があります。

  3. openarena-assets 永続ディスクを openarena-asset-builder VM インスタンスに接続します。

    gcloud compute instances attach-disk openarena-asset-builder \
        --disk openarena-assets

  4. 新しいディスクをフォーマットします。

    1. openarena-asset-builder VM インスタンスにログインして、ディスクをフォーマットします。

      gcloud compute ssh openarena-asset-builder

    2. 次のステップで使用する mkfs.ext4 コマンドは、ディスク上のすべてのデータを消去するコマンドであるため、openarena-assets ディスクのデバイス ID を必ず確認してください。このチュートリアルを最初から実行していて、新しいプロジェクトを使用している場合、ID は /dev/sdb です。lsblk コマンドを実行して、接続されているディスクとそのパーティションを確認します。

      sudo lsblk

      出力を見ると、端末 sdb には 2 つのディスクが接続しています。1 つは 10 GB の OS ディスク sda で、ここには 1 つのパーティション sda1 があります。もう 1 つは 50 GB の openarena-assets ディスクで、ここにはパーティションがありません。

      NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
      sda 8:0 0 10G 0 disk
      └─sda1 8:1 0 10G 0 part /
      sdb 8:16 0 50G 0 disk

    3. openarena-assets ディスクをフォーマットします。

      sudo mkfs.ext4 -m 0 -F -E \
          lazy_itable_init=0,lazy_journal_init=0,discard /dev/[DEVICE_ID]

  5. openarena-asset-builder VM インスタンスに OpenArena をインストールし、圧縮されたアセット アーカイブを openarena-assets 永続ディスクにコピーします。

    このゲームのアセットは .pk3 ファイルで、/usr/share/games/openarena/baseoa/ ディレクトリにあります。いくつかの作業を保存するため、インストールの前に以下の一連のコマンドを実行して、このディレクトリにアセット ディスクをマウントします。インストールを実行すると、すべての .pk3 ファイルがこのディスクに保存されます。前のステップで確認した端末 ID を使用してください。

    sudo mkdir -p /usr/share/games/openarena/baseoa/

    sudo mount -o discard,defaults /dev/[DEVICE_ID] \ /usr/share/games/openarena/baseoa/

    sudo apt-get update && sudo apt-get -y install openarena-server

  6. インスタンスを終了して削除します。

    exit

    gcloud compute instances delete openarena-asset-builder

    ディスクが Kubernetes の永続ボリュームとして使用できる状態になりました。

ゲーム開発のパイプラインの一部として永続ディスクを実装する場合は、適切なディレクトリ構造のすべてのアセット ファイルが永続ディスクに作成されるようにビルドシステムを構成します。この構成は、gcloud コマンドを実行する単純なスクリプトで行う場合もあれば、選択したビルドシステムに GCP 固有のプラグインで行う場合もあります。スループットを向上させながら障害リスクを管理できるように、永続ディスクの複数のコピーを作成して、これらのコピーに VM インスタンスをバランスよく接続することをおすすめします。

Kubernetes クラスタの設定

Kubernetes はオープンソースのコミュニティ プロジェクトで、オンプレミスを含むほとんどの環境で実行できます。

Kubernetes Engine に Kubernetes クラスタを作成する

このチュートリアルでは、n1-highcpu マシンタイプの標準の Kubernetes Engine クラスタを使用します。これは OpenArena の使用に適しています。

  1. game という名前でゲーム用の VPC ネットワークを作成します。

    gcloud compute networks create game

  2. OpenArena にファイアウォール ルールを作成します。

    gcloud compute firewall-rules create openarena-dgs --network game \
        --allow udp:27961-28061

  3. gcloud を使用して、4 個の仮想 CPU コアを持つ 3 ノードクラスタを作成し、それぞれのノードが game ネットワークを使用します。

    gcloud container clusters create openarena-cluster \
        --network game --num-nodes 3 --machine-type n1-highcpu-4 \
        --addons KubernetesDashboard

  4. クラスタを起動したら、適切な Kubernetes 認証情報でローカルシェルを設定し、新しいクラスタを制御します。

    gcloud container clusters get-credentials openarena-cluster

本番環境のクラスタでは、各マシンで実行する vCPU の数は主に次の 2 つの要因によって決まります。

  • 同時に実行する DGS ポッドの最大数。 Kubernetes クラスタプール内のノード数には制限があります(ただし、Kubernetes プロジェクトでは今後のリリースでこの上限を上げる予定です)。たとえば、仮想 CPU(vCPU)ごとに 1 つの DGS を実行する場合、n1-highcpu-2 マシンの 1,000 ノードクラスタで使用できる DGS ポッドの最大数は 2,000 個ですが、n1-highcpu-32 マシンの 1,000 ノードクラスタの場合、最大数は 32,000 ポッドになります。

  • VM インスタンスの粒度。 クラスタ内のリソースを増やしたり、減らしたりする場合、クラスタの作成時に選択したタイプの VM インスタンス単位で増減するのが最も簡単な方法です。32 個の vCPU よりも少ない容量を追加または削除する場合は、32 vCPU マシンを選択しないでください。

GKE でデフォルトで使用されるマネージド インスタンス グループ機能には、VM インスタンスの自動スケーリングと HTTP 負荷分散の機能が含まれています。ただし、Kubernetes クラスタの作成で使用したコマンドでは、--disable-addons HttpLoadBalancing,HorizontalPodAutoscaling フラグを使用して、これらの機能を無効にしました。

DGS は TCP ではなく UDP を使用してクライアントと通信するため、HTTP 負荷分散は不要です。オートスケーラーは CPU 使用率に基づいてインスタンス グループをスケーリングするため、DGS の負荷を正確に把握できない可能性があります。多くの DGS は、ゲームのシミュレーションを最適化するため、アイドル サイクルを消費するように設計されています。

結果として、多くのゲーム開発者は、このタイプのワークロードの要件に対応するため、DGS 対応のカスタム スケーリング マネージャー プロセスを実装しています。ただし、この場合もマネージド インスタンス グループは重要な役割を果たしています。デフォルトの GKE イメージ テンプレートには、必要な Kubernetes ソフトウェアがすべて含まれ、起動時にノードを自動的にマスターに登録します。

コンテナ イメージを GCP にアップロードする

Google では、Container Registry(gcr.io)に非公開 Docker イメージのストレージを提供しています。

  1. GKE クラスタに最も近い gcr.io リージョンを選択します。たとえば、米国の場合は us、ヨーロッパの場合は eu、アジアの場合は asia を選択します(ドキュメントをご覧ください)。また、リージョン情報をプロジェクト ID と一緒に環境変数の中で設定します。

    export GCR_REGION=[GCR_REGION] PROJECT_ID=[PROJECT_ID]

  2. コンテナ イメージに gcr.io レジストリ名でタグを付けます。

    docker tag openarena:0.8.8 \
        ${GCR_REGION}.gcr.io/${PROJECT_ID}/openarena:0.8.8

  3. コンテナ イメージをイメージ リポジトリにアップロードします。

    gcloud docker -- push \
        ${GCR_REGION}.gcr.io/${PROJECT_ID}/openarena:0.8.8

push が完了すると、コンテナ イメージが GKE クラスタ内で実行可能になります。後でポッド指定ファイルに入れる必要があるため、最終的なコンテナ イメージタグをメモしておきます。

Kubernetes でアセット ディスクを構成する

通常の DGS では、ゲームアセットへの書き込みを必要としないため、各 DGS ポッドに読み取り専用アセットを含む永続ディスクをマウントできます。この処理を行うには、Kubernetes の persistentVolume リソースと persistentVolumeClaim リソースを使用します。

  1. 前に作成したアセット ディスクにバインドする Kubernetes persistentVolume リソースの定義を含む asset-volume.yaml を適用します。

    kubectl apply -f openarena/k8s/asset-volume.yaml

  2. asset-volumeclaim.yaml を適用します。このファイルには Kubernetes persistentVolumeClaim リソースの定義が含まれています。これにより、ポッドがアセット ディスクをマウントできるようになります。

    kubectl apply -f openarena/k8s/asset-volumeclaim.yaml

    次のコマンドを実行して、ボリュームが Bound 状態であることを確認します。

    kubectl get persistentVolume

    予想される出力:

    NAME           CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                      STORAGECLASS   REASON    AGE
    asset.volume   50Gi       ROX           Retain          Bound     default/asset.disk.claim   assets                   3m

    同様に、クレームがバインド状態であることを確認します。

    kubectl get persistentVolumeClaim

    予想される出力:

    NAME               STATUS    VOLUME         CAPACITY   ACCESSMODES   STORAGECLASS   AGE
    asset.disk.claim   Bound     asset.volume   50Gi       ROX           assets         25s

DGS ポッドの構成

スケジューリング タスクとネットワーキング タスクは Kubernetes によって処理されるため、DGS コンテナの起動時間とシャットダウン時間は無視できます。したがって、このチュートリアルでは DGS インスタンスを必要に応じてスピンアップします。

各 DGS インスタンスは 1 回の対戦時間だけ持続します。対戦時間は OpenArena DGS サーバーの構成ファイルで制限されています。対戦が完了すると、コンテナが正常に終了します。プレーヤーが再度プレイしたい場合、別のゲームをリクエストすることになります。この設計は、ポッド ライフサイクルのさまざまな側面を簡略化するだけでなく、スケーリング マネージャのセクションで説明するように、自動スケーリング ポリシーの基礎となります。

このチュートリアルではゲーム クライアント コードのフォークや変更を行わないため、このフローは OpenArena とシームレスではありません。市販のゲームでは、別の対戦のリクエストは前回の対戦結果画面や読み込み時間の背後で実行され、ユーザーからは見えません。対戦間で新しいサーバー インスタンスに接続するコードは、ネットワークの問題やサーバーのクラッシュなどの予期せぬ状況でクライアントの再接続を処理する場合でも必要になるため、開発時間が余分にかかることはありません。

わかりやすくするために、このチュートリアルでは GKE ノードにデフォルトのネットワーク構成があるものとします。この構成では、各ノードにパブリック IP アドレスが割り当てられ、クライアント接続を許可します。

専用のゲームサーバー プロセスの管理

市販のゲームサーバーの場合、コンテナ内での DGS の実行に必要な DGS 以外の機能は、可能な限り DGS バイナリに直接統合しています。

ベスト プラクティスでは、DGS がマッチメーカーやスケーリング マネージャと直接通信を行わずに、その状態を Kubernetes API に公開します。外部プロセスは、サーバーに直接クエリを送信するのではなく、適切な Kubernetes エンドポイントから DGS の状態を読み取ります。Kubernetes API への直接アクセスの詳細については、Kubernetes のドキュメントをご覧ください。

有効期間が限定され、成功条件が定義されたコンテナ内で単一のプロセスを実行するのが Kubernetes ジョブのユースケースのように見えますが、実際にはジョブを使用する必要はありません。DGS プロセスはジョブの並列実行機能を必要としません。また、自動的に再起動することで成功を保証する必要もありません。通常、セッションベースの DGS がなんらかの理由で終了し、状態が失われた場合、プレーヤーは別の DGS に参加します。そのため、このユースケースでは個々の Kubernetes ポッドをスケジューリングするほうが適切です。

本番環境では、DGS ポッドは Kubernetes API を使用してマッチメーカーによって直接開始されます。このチュートリアルでは、DGS ポッドリソースを記述している YAML ファイルが openarena/k8s/openarena-pod.yaml のチュートリアル リポジトリに含まれています(このファイルは、人が読める形式になっています)。専用のゲームサーバー ポッドを構成する場合は、アセット ディスクが複数のポッドに読み取り専用でマウントできるように、ボリューム プロパティに注意する必要があります。

スケーリング マネージャーの設定

スケーリング マネージャーとは、GKE ノードとして使用される仮想マシンの数を、その時点の DGS 負荷に基づいてスケーリングする単純なプロセスです。スケーリングは、永続的に動作する一連のスクリプトを使用し、実行中の DGS ポッドの数とリクエストされた DGS ポッドの合計数を検査して、必要に応じてノードプールのサイズを変更します。スクリプトは、適切なライブラリと Cloud SDK を含む Docker コンテナ イメージにパッケージ化されています。Docker イメージは、次の手順で作成し、gcr.io に push できます。

  1. 必要に応じて、gcr.io GCR_REGION 値と PROJECT_ID をビルドと push スクリプトの環境変数に設定します。以前にコンテナ イメージをアップロードしたときに、すでにこの手順を実行している場合は、この手順をスキップできます。

    export REGION=[GCR_REGION] PROJECT_ID=[PROJECT_ID]

  2. スクリプト ディレクトリに移動します。

    cd scaling-manager

  3. ビルド スクリプトを実行して、すべてのコンテナ イメージをビルドし、gcr.io に push します。

    ./build-and-push.sh

  4. テキスト エディタで、scaling-manager/k8s/openarena-scaling-manager-deployment.yaml の Kubernetes デプロイ ファイルを開きます。

    スケーリング マネージャ スクリプトは、Kubernetes デプロイ内で実行されるように設計されているため、これらのプロセスは障害発生時に再起動します。

  5. 次の表のように、環境変数をデプロイの値で変更します。

    環境変数 デフォルト値
    REGION [GCR_REGION] 置換が必要。 gcr.io リポジトリのリージョン。
    PROJECT_ID [PROJECT_ID] 置換が必要。 プロジェクトの名前。
    GKE_BASE_INSTANCE_NAME gke-openarena-cluster-default-pool-[REPLACE_ME] 置換が必要。 GKE クラスタごとに異なる。[REPLACE_ME] の値を取得するには、gcloud compute instance-groups managed list コマンドを実行する。
    GCP_ZONE [ZONE] 置換が必要。 このチュートリアルの冒頭で指定した GCP ゾーンの名前。
    K8S_CLUSTER openarena-cluster Kubernetes クラスタの名前。

  6. 親ディレクトリに戻ります。

    cd ..

  7. Kubernetes クラスタにデプロイを追加します。

    kubectl apply \
        -f scaling-manager/k8s/openarena-scaling-manager-deployment.yaml

ノードのスケーリング方法

ノードのスケーリングを行うため、スケーリング マネージャが Kubernetes API を使用して現在のノードの使用状況を確認します。必要に応じて、マネージャは基盤となる仮想マシンを実行する Kubernetes Engine クラスタでマネージド インスタンス グループのサイズを変更します。

DGS ポッドに対するスケーリングの問題

DGS スケーリングの一般的な問題点は次のとおりです。

  • CPU とメモリ使用量の標準的な指標では、ゲームサーバー インスタンスのスケーリングに十分な情報を取得できない場合が少なくありません。
  • 既存のノードで最適化された DGS コンテナのスケジューリングには数秒かかります。このため、利用可能な未使用のノードバッファを維持する必要があります。ただし、ノードの追加には数分かかる場合があります。これは待機中のプレーヤーにとっては許容できないレイテンシです。
  • 多くのオートスケーラーはポッドのシャットダウンを正常に処理できません。削除するノードからポッドをドレインすることが重要です。対戦実行中のノードをシャットオフできないことも少なくありません。

このチュートリアルで提供しているスクリプトは基本的で、シンプルな設計ですが、ロジックを簡単に追加できます。一般的な DGS にはよく知られているパフォーマンス特性があり、これらを指標とすることで、VM インスタンスを追加または削除するタイミングを判断できます。一般的なスケーリング指標には、このチュートリアルで使用されている CPU あたりの DGS インスタンスの数や使用可能なプレーヤー スロットなどが含まれています。

スケールアップ

スケールアップについては、このチュートリアルで行う特別な処理は必要ありません。わかりやすくするために、このチュートリアルではポッドのプロパティ limitsrequests をポッドの YAML ファイル(openarena/k8s/openarena-pod.yaml)で設定し、各 DGS に約 1 個の vCPU を予約します。これは OpenArena に十分な値です。

クラスタは n1-highcpu インスタンス ファミリーで作成されているため、1 vCPU に対して 600 MB の固定率になります。vCPU あたり 1 個の DGS ポッドがスケジュールされている場合、メモリは十分な量といえます。したがって、クラスタ内のすべてのノードの CPU 数と比較して、クラスタ内のポッド数に基づいてスケールアップできます。この比率によって使用可能な残りのリソースが決まるため、値がしきい値を下回った場合にノードを追加できます。このチュートリアルでは、vCPU の 70% 以上がポッドに割り当てられている場合にノードが追加されます。

本番環境のオンライン ゲームのバックエンドでは、DGS の CPU、メモリ、ネットワークの使用状況を正確にプロファイリングし、limitsrequests のポッド プロパティを適切に設定することをおすすめします。多くのゲームでは、DGS シナリオごとに複数のポッドタイプを作成し、ゲームタイプ、特定のマップ、プレーヤー スロット数などの異なるプロファイルを設定するほうが理にかなっています。このような検討事項は、このチュートリアルの範囲外ですので、これ以上は触れません。

スケールダウン

スケールダウンは、スケールアップとは異なり、複数のステップから構成されるプロセスで、Kubernetes 対応のカスタム DGS スケーリング マネージャが実行される理由の 1 つになっています。このチュートリアルでは、scaling-manger.sh が以下のステップを自動的に処理します。

  1. 削除に適したノードを選択する。このチュートリアルでは、完全なカスタムゲームに対応する Kubernetes スケジューラを使用しないため、API によって返される順番でノードが選択されます。

  2. 選択したノードを Kubernetes で使用不可とマークする。これにより、ノードで追加のポッドが開始しないようにします。

  3. 選択したノードをマネージド インスタンス グループから、abandon-instance コマンドを使用して削除する。これにより、マネージド インスタンス グループがインスタンスの再作成を行いません。

また、node-stopper.sh スクリプトは、放棄されたスケジュール不可のノードをモニタリングし、DGS ポッドが存在しないことを確認します。ノード上ですべての対戦が終了してポッドが終了すると、スクリプトは VM インスタンスをシャットダウンします。

DGS ポッドの数をスケーリングする

本番環境の標準的なゲーム バックエンドでは、新しい DGS インスタンスを追加するタイミングがマッチメーカーによって制御されます。DGS ポッドは対戦終了時に終了するように構成されているため(前の設計上の制約を参照)、DGS ポッドの数を減らす明示的なアクションは必要ありません。新しい対戦を要求する十分な数のリクエストがマッチメーカー システムに送信されない場合、対戦終了後に、DGS ポッドは Kubernetes クラスタから自身を削除します。

セットアップのテスト

ここまでで、OpenArena コンテナ イメージを作成してコンテナ レジストリに push し、DGS Kubernetes クラスタを開始しました。さらに、ゲームのアセット ディスクを生成し、Kubernetes で使用できるように構成して、スケーリング マネージャのデプロイを開始しました。では、DGS ポッドを起動してみましょう。

新しい DGS インスタンスをリクエストする

本番環境の標準的なシステムでは、マッチメーカー プロセスが対戦相手を選択すると、Kubernetes API を使用してインスタンスを直接リクエストします。ここでは、チュートリアルの設定をテストすることが目的ですので、インスタンスを直接リクエストすることにします。

  1. テキスト エディタで openarena/k8s/openarena-pod.yaml を開き、実行するコンテナ イメージが指定されている行を探します。

  2. 値が openarena コンテナ イメージのタグに一致するように、docker tag コマンドを実行して変更します(前述の説明をご覧ください)。

  3. openarena-pod.yaml ファイルを指定して、kubectl apply コマンドを実行します。

    kubectl apply -f openarena/k8s/openarena-pod.yaml

  4. しばらく待ち、ポッドの状態を確認します。

    kubectl get pods

    出力は次のようになります。

    NAME             READY     STATUS    RESTARTS   AGE
    openarena.dgs    1/1       Running   0          25s

DGS に接続する

ポッドが起動したら、OpenArena クライアントを起動して、DGS に接続できることを確認します。

macOS または Linux デスクトップ:

export NODE_NAME=$(kubectl get pod openarena.dgs \
    -o jsonpath="{.spec.nodeName}")
export DGS_IP=$(gcloud compute instances list \
    --filter="name=( ${NODE_NAME} )" \
    --format='table[no-heading](EXTERNAL_IP)')
openarena +connect ${DGS_IP}

スケーリング マネージャのテスト

スケーリング マネージャは、DGS ポッドの数に基づいて Kubernetes クラスタ内の VM インスタンス数をスケーリングします。スケーリング マネージャをテストするには、一定の期間内に多くのポッドをリクエストし、ノードの数が適切に増加するかどうか確認する必要があります。ノードのスケールダウンを確認するには、サーバー構成ファイルで対戦時間に制限を定義する必要があります。openarena/single-match.cfg にあるチュートリアルのサーバー構成ファイルでは、対戦時間が 5 分に制限されています。このファイルは、デフォルトでチュートリアルの DGS ポッドで使用されます。次のスクリプトを実行してテストを行います。このスクリプトは、5 分間に一定の間隔で DGS ポッドを追加します。

./scaling-manager/tests/test-loader.sh

kubectl get nodes を定期的に実行することで、ノードのスケールアップとスケールダウンの回数を確認できます。

クリーンアップ

このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

プロジェクトの削除

課金を停止する最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

GKE クラスタの削除

プロジェクト全体を削除したくない場合は、次のコマンドを実行して GKE クラスタを削除します。

gcloud container clusters delete openarena-cluster

永続ディスクを削除する

永続ディスクを削除する手順は次のとおりです。

  1. GCP Console で、[Compute Engine のディスク] メニューに移動します。

    [Compute Engine のディスク] ページに移動

  2. 削除するディスクを選択します。

  3. ページ上部にある [削除] ボタンをクリックします。

次のステップ

このチュートリアルでは、専用のゲームサーバーをコンテナ内で実行し、ゲームの負荷に基づいて Kubernetes クラスタを自動スケーリングするベアボーン アーキテクチャを説明しました。基本的なクライアントサイド サポートをプログラミングすることで、セッション間でのシームレスなプレーヤーの移行など、多くの機能を追加できます。プレーヤーがグループを形成し、サーバー間でグループを移動できるようにするために、マッチメイキング サービスとは別にプラットフォーム サービスを作成することもできます。このサービスを使用してグループを作成し、グループ招待状の送信、受信、拒否を行ったり、プレーヤーのグループを専用のゲームサーバー インスタンスに送信することもできます。

また、よりインテリジェントなゲームを展開するため、DGS ポッドのノードを選択できる Kubernetes カスタム スケジューラがよく利用されています。ほとんどのゲームでは、ポッドをまとめて処理するカスタム スケジューラが必要になります。これにより、ピーク後にスケールダウンするときに、削除するノードの順序を簡単に決めることができます。

GCP で DGS を実行するためのガイド:

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...