arrow_back

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

参加 ログイン

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

1時間 30分 クレジット: 7

GSP133

Google Cloud セルフペース ラボ

テクノロジーの利用に関して、サーバー アプリケーションをコンテナとしてパッケージ化することが急速に主流になってきています。ゲーム会社も例外ではありません。多くのゲーム会社が、コンテナを使って VM の使用率を向上させようとしています。また、コンテナで実現できる独立した実行環境を活用しようとしています。しかし、関心は高いものの、何から始めればよいのかわからないというゲーム会社もたくさんあります。

このラボでは、Google Kubernetes Engine 上で Kubernetes を使用して、セッション ベースのリアルタイム マルチプレーヤー型専用ゲームサーバーを実行するための拡張可能なアーキテクチャを使用する方法について説明します。このアーキテクチャでは、スケーリング マネージャー プロセスが必要に応じて仮想マシン インスタンスを自動的に起動または停止するように構成されます。Kubernetes ノードのマシン構成はマネージド インスタンス グループによって自動的に処理されます。このラボでは、シンプルな構造のオンライン ゲームを使って説明します。より複雑な構造にしたほうがわかりやすい場合や、複雑な構造にする必要がある場合は、その都度説明します。

目標

  • Docker を使用して、一般的なオープンソースの専用ゲームサーバー(DGS)のコンテナ イメージを Linux 上に作成します。このコンテナ イメージでは、バイナリと必要なライブラリのみが Linux のベースイメージに追加されます。

  • 独立した読み取り専用の永続ディスク ボリュームにアセットを格納し、実行時にコンテナにマウントします。

  • Kubernetes と Google Cloud API を使用して基本的なスケジューラ プロセスをセットアップおよび構成し、必要に応じてノードの起動や停止を行います。

ゲーム クライアントのダウンロードを開始する前に

このラボではゲームサーバーを作成します。また、サーバーをテストするためにゲーム クライアントに接続する必要があります。OpenArena ゲーム クライアントは、ローカルマシンにインストールできれば多くのオペレーティング システムで利用できます。現在使用しているマシンにゲーム クライアントをインストールできない場合は、ゲーム クライアントをインストールできるマシンを使用してこのラボを受講することを検討してください。ゲーム クライアントに接続して作業の検証を行うことは必須ではありません。その場合でも、このラボを受講すれば専用ゲームサーバーを作成する方法を確認できますが、実際に動作しているのを確認することはできません。

OpenArena ゲーム クライアントをパソコンにインストールして、ラボの最後にゲームサーバーへの接続をテストします。

http://openarena.wikia.com/wiki/Manual/Install

これには時間がかかります。ダウンロードしている間にラボを開始し、30 分ほど経ったら終了したかどうかを確認してください。その後、ゲーム クライアントをインストールします。

アーキテクチャの概要

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

68b111517057146c.png

建設的な制約

このラボでは、学習に適した、拡張の余地がある単純なサンプルを作成します。そのため、ゲームについて次の制約があることを前提とします。

  • リアルタイムの対戦型ゲームであり、信頼できる DGS でゲームの状態をシミュレートします。
  • DGS の通信には UDP を使用します。
  • DGS プロセスごとに 1 つの対戦を実行します。
  • どの DGS プロセスでも、ほぼ同じ量の負荷が発生します。
  • 対戦には時間の上限があります。
  • DGS の起動時間は無視できるレベルであり、専用ゲームサーバー プロセスを事前に準備しておく必要はありません。
  • できる限りカスタマー エクスペリエンスへの影響が発生しないようにします。
  • ピーク時が過ぎたら、VM インスタンス数をスケールダウンするために対戦を早期に終了するという対応は行いません。
  • ただし、専用ゲームサーバーのプロセスで問題が発生して続行できなくなった場合は、対戦の状態が失われ、新しい対戦が開始されるようにします。
  • DGS プロセスはディスクから静的アセットを読み込みますが、アセットへの書き込みは必要ありません。

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

設定と要件

Qwiklabs の設定

[ラボを開始] ボタンをクリックする前に

こちらの手順をお読みください。ラボの時間は記録されており、一時停止することはできません。[ラボを開始] をクリックするとスタートするタイマーは、Google Cloud のリソースを利用できる時間を示しています。

この Qwiklabs ハンズオンラボでは、シミュレーションやデモ環境ではなく、実際のクラウド環境を使ってご自身でラボのアクティビティを行うことができます。そのため、ラボの受講中に Google Cloud にログインおよびアクセスするための、新しい一時的な認証情報が提供されます。

必要なもの

このラボを完了するためには、下記が必要です。

  • 標準的なインターネット ブラウザ(Chrome を推奨)
  • ラボを完了するために十分な時間

注: すでに個人の Google Cloud アカウントやプロジェクトをお持ちの場合でも、ラボでは使用しないでください。

注: Chrome OS デバイスを使用している場合は、シークレット ウィンドウを開いてこのラボを実行してください。

ラボを開始して Google Cloud コンソールにログインする方法

  1. [ラボを開始] ボタンをクリックします。ラボの料金をお支払いいただく必要がある場合は、表示されるポップアップでお支払い方法を選択してください。 左側の [ラボの詳細] パネルには、以下が表示されます。

    • [Google コンソールを開く] ボタン
    • 残り時間
    • このラボで使用する必要がある一時的な認証情報
    • このラボを行うために必要なその他の情報(ある場合)
  2. [Google コンソールを開く] をクリックします。 ラボでリソースが起動し、別のタブで [ログイン] ページが表示されます。

    ヒント: タブをそれぞれ別のウィンドウで開き、並べて表示しておきましょう。

    注: [アカウントの選択] ダイアログが表示されたら、[別のアカウントを使用] をクリックします。
  3. 必要に応じて、[ラボの詳細] パネルから [ユーザー名] をコピーして [ログイン] ダイアログに貼り付けます。[次へ] をクリックします。

  4. [ラボの詳細] パネルから [パスワード] をコピーして [ようこそ] ダイアログに貼り付けます。[次へ] をクリックします。

    重要: 認証情報は左側のパネルに表示されたものを使用してください。Google Cloud Skills Boost の認証情報は使用しないでください。 注: このラボでご自身の Google Cloud アカウントを使用すると、追加料金が発生する場合があります。
  5. その後次のように進みます。

    • 利用規約に同意してください。
    • 一時的なアカウントなので、復元オプションや 2 要素認証プロセスは設定しないでください。
    • 無料トライアルには登録しないでください。

その後このタブで Cloud Console が開きます。

注: 左上にある [ナビゲーション メニュー] をクリックすると、Google Cloud のプロダクトやサービスのリストが含まれるメニューが表示されます。 ナビゲーション メニュー アイコン

Google Cloud Shell の有効化

Google Cloud Shell は、デベロッパー ツールと一緒に読み込まれる仮想マシンです。5 GB の永続ホーム ディレクトリが用意されており、Google Cloud で稼働します。Google Cloud Shell では、コマンドラインで GCP リソースにアクセスできます。

GCP Console の右上のツールバーにある [Cloud Shell をアクティブにする] ボタンをクリックします。

Cloud Shell アイコン

[続行] をクリックします。

cloudshell_continue

環境のプロビジョニングと接続には少し時間がかかります。接続すると、すでに認証されており、プロジェクトは PROJECT_ID に設定されています。例えば:

Cloud Shell 端末

gcloud は Google Cloud Platform のコマンドライン ツールです。このツールは、Cloud Shell にプリインストールされており、タブ補完がサポートされています。

次のコマンドを使用すると、有効なアカウント名を一覧表示できます。

gcloud auth list

出力:

ACTIVE: *
ACCOUNT: student-01-xxxxxxxxxxxx@qwiklabs.net
To set the active account, run:
    $ gcloud config set account `ACCOUNT`
	

次のコマンドを使用すると、プロジェクト ID を一覧表示できます。

gcloud config list project
	

出力:

[core]
project = <project_ID>
	

出力例:

[core]
project = qwiklabs-gcp-44776a13dea667a6
	

専用ゲームサーバーをコンテナ化する

このラボでは、OpenArena を使用します。これは、GPL の id Tech 3 技術をベースにコミュニティによって作成されたデスマッチ FPS です。このゲームで使用されている技術は 15 年以上前のものですが、現在でも一般的な DGS のパターンを説明するにはよい例です。

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

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

専用ゲームサーバー バイナリのコンテナ イメージを作成する

このラボでは、Cloud Shell は使用できません。Docker イメージを作成して使用できるようにするため、クライアントに GCP SDK をインストールして環境を用意する必要があります。

VM インスタンスを作成してラボのタスクを実行する

Google Cloud Console で、[Compute Engine] > [VM インスタンス] をクリックします。

[作成] をクリックします。

[ID と API へのアクセス] で、[すべての Cloud API に完全アクセス権を許可] を選択します。

[作成] をクリックします。

インスタンスがデプロイされたら、[SSH] ボタンをクリックします。このラボの残りのタスクは、この VM の SSH コンソールで実行されます。

タスクを確認するため [進捗状況を確認] をクリックします。

VM インスタンスを作成する

kubectl と Docker を VM にインストールする

VM で apt-get リポジトリを更新します。

sudo apt-get update

Kubernetes 用に gcloud ツールをインストールします。

sudo apt-get -y install kubectl

Docker の依存関係をインストールします。

sudo apt-get -y install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common

Docker の公式 GPG キーをインストールします。

curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -

ダウンロードした Docker キーの GPG フィンガープリントが想定値と一致することを確認します。

sudo apt-key fingerprint 0EBFCD88

出力に以下のフィンガープリントが表示されます。

pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

安定版の Docker リポジトリを追加します。

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")    $(lsb_release -cs) stable"

apt-get リポジトリを更新します。

sudo apt-get update

Docker-ce をインストールします。

sudo apt-get -y install docker-ce

root 以外のユーザーとして実行するよう Docker を構成します。

sudo usermod -aG docker $USER

SSH セッションを終了し、VM インスタンスの [SSH] ボタンをクリックして再接続します。

root 以外のユーザーで Docker を実行できることを確認します。

docker run hello-world

出力に次のようなメッセージが表示されます。

Hello from Docker!
This message shows that your installation appears to be working correctly.

ゲームサーバーのサンプルデモをダウンロードする

サンプルデモのクローンを作成します。

gsutil -m cp -r gs://spls/gsp133/gke-dedicated-game-server .

専用ゲームサーバー バイナリのコンテナ イメージを作成する

作業環境を用意する

Kubernetes Engine クラスタの場所に最も近い gcr.io リージョンを選択します(ドキュメントに記載されているように、米国の場合は us、ヨーロッパの場合は eu、アジアの場合は asia など)。

次のコマンド内の <PROJECT_ID> をプロジェクト ID に、<REGION> を gcr.io リージョンに置き換えます。

export GCR_REGION=<REGION> PROJECT_ID=<PROJECT_ID>
printf "$GCR_REGION \n$PROJECT_ID\n"

置き換え後のコマンドは次のようになります。

export GCR_REGION=us PROJECT_ID=qwiklabs-gcp-e5xxxxxxx4c61da8

新しいコンテナ イメージを生成する

まず、構築するイメージの情報を記述した Dockerfile を作成します。openarena/Dockerfile のリポジトリに、このラボの Debian ベースの Dockerfile があります。

デモ用の Docker ディレクトリに変更します。

cd gke-dedicated-game-server/openarena

次の Docker ビルドコマンドを実行してコンテナ イメージを生成し、タグを付けます。Google Kubernetes Engine で使用するたびに、Google Container Registrygcr.io)を使用します。

docker build -t \
${GCR_REGION}.gcr.io/${PROJECT_ID}/openarena:0.8.8 .

ビルド中に警告やエラーが表示される場合がありますが、コマンド終了時に「Successfully built」と「Successfully tagged」で始まる 2 つのメッセージが表示されていれば続行できます。

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

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

タスクを確認するため [進捗状況を確認] をクリックします。

新しいコンテナ イメージを作成する

アセット ディスクを生成する

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

以下の手順に沿って OpenArena アセット ディスクを作成します。

デフォルトのリージョンを設定し、環境変数にゾーン ID を保存します。

region=us-east1
zone_1=${region}-b
gcloud config set compute/region ${region}

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

gcloud compute instances create openarena-asset-builder \
   --machine-type f1-micro \
   --image-family debian-11 \
   --image-project debian-cloud \
   --zone ${zone_1}

適切なサイズの永続ディスクを作成して接続します。永続ディスクはブートディスクとは別に作成し、仮想マシンが削除されても削除されないように構成する必要があります。Kubernetes の PersistentVolume 機能は、Compute Engine のドキュメントに沿って初期化された永続ディスク(パーティション テーブルなしで単一の ext4 ファイル システムで構成される)と一緒に使用すると効果的です。

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

openarena-asset-builder インスタンスが完全に起動するまで待ち、起動したら永続ディスクを接続します。

gcloud compute instances attach-disk openarena-asset-builder \
   --disk openarena-assets --zone ${zone_1}

永続ディスクが接続されたら、openarena-asset-builder VM インスタンスに SSH 接続してこの新しい永続ディスクをフォーマットできます。

タスクを確認するため [進捗状況を確認] をクリックします。

アセット ディスクを生成する

SSH を使用してアセット ビルダー VM インスタンスに接続する

コンソールで、[Compute Engine] > [VM インスタンス] をクリックします。

openarena-asset-builder インスタンスの横にある [SSH] ボタンをクリックします。

永続ボリュームを準備するために使用する新しい SSH コンソールが開きます。

アセット ディスクをフォーマットし、構成する

新しいディスクはフォーマットされていません。使用する前にディスクをフォーマットしてマウントする必要があります。openarena-assets 永続ディスクを openarena-asset-builder VM インスタンスに接続します。

次のステップで使用する mkfs.ext4 コマンドは、ディスク上のすべてのデータを消去するコマンドです。そのため、openarena-assets ディスクのデバイス ID を必ず確認してください。このラボを最初から進めている場合、ID は /dev/sdb です。

lsblk コマンドを実行して接続されているディスクとそのパーティションを参照して確認します。

sudo lsblk

出力を見ると、パーティションが 1 つ(sda1)の 10 GB の OS ディスク sda と、デバイス sdb としてパーティションがない 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

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

sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb

openarena-asset-builder VM インスタンスに OpenArena をインストールし、圧縮されたアセット アーカイブを openarena-assets 永続ディスクにコピーします。このゲームのアセットは .pk3 ファイルで、/usr/share/games/openarena/baseoa/ ディレクトリにあります。

作業の一部を保存するには、インストールする前にアセット ディスクをこのディレクトリにマウントします。それにより、インストール プロセスで .pk3 のファイルがすべてディスクに保存されるようになります。

sudo mkdir -p /usr/share/games/openarena/baseoa/
sudo mount -o discard,defaults /dev/sdb \
    /usr/share/games/openarena/baseoa/
sudo apt-get update
sudo apt-get -y install openarena-server
sudo gsutil cp gs://qwiklabs-assets/single-match.cfg /usr/share/games/openarena/baseoa/single-match.cfg

インストールが完了したら、永続ボリュームのマウントを解除し、インスタンスをシャットダウンします。

sudo umount -f -l /usr/share/games/openarena/baseoa/
sudo shutdown -h now

SSH コンソールが応答しなくなりますが、これは想定された挙動です。

永続ディスクは Kubernetes で PersistentVolume として使用される準備ができ、インスタンスを安全に削除できます。

ラボのメイン VM インスタンスの SSH コンソールに戻り、先ほど設定した zone_1 変数の値を確認します。

echo $zone_1

予想される出力:

us-east1-b

この値が設定されておらず、何も返されない場合は、次のコマンドで設定できます。

region=us-east1
zone_1=${region}-b

openarena-asset-builder VM を削除します。

gcloud compute instances delete openarena-asset-builder --zone ${zone_1}

削除を確認するメッセージが表示されたら、「Y」と入力します。

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

Kubernetes クラスタを設定する

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

このラボでは、n1-standard マシンタイプによる標準的な Container Engine クラスタを使用します。これはデモの目的に適しています。本番環境では、OpenArena を使用する場合は n1-highcpu マシンタイプがより適しています。各マシンで実行する vCPU 数は、次の 2 つの要因に大きく影響されます。

  • 同時実行が予定されている DGS ポッドの最大数:
  • Kubernetes クラスタプールに含めることができるノード数には制限があります(ただし、Kubernetes プロジェクトでは今後のリリースでこの数値を増やす予定です)。たとえば、仮想 CPU(vCPU)1 つにつき DGS を 1 つ実行する場合、n1-highcpu-2 マシンの 1,000 ノードのクラスタで使用できる DGS ポッド数はわずか 2,000 個です。一方、n1-highcpu-32 マシンの 1,000 ノードのクラスタでは最大 32,000 個です。
  • VM インスタンスの粒度:
  • クラスタ内のリソースを増減する場合、クラスタの作成時に選択したタイプの VM インスタンス単位で行うのが最も簡単な方法です。

このラボでは、vCPU 数はノードごとに 2 個までに制限されており、それで十分です。

Cloud Shell で、ゲームクラスタ用のネットワークとファイアウォールのルールを作成します。

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

先ほど作成したメインの VM インスタンスの SSH コンソールを使用して、次のコマンドを実行します。

次の gcloud create コマンドを実行すると、それぞれに 4 個の仮想 CPU コア( --machine-type=n1-standard-2)を持つノード 3 個(--num-nodes 3)で構成されるクラスタが作成されます。

gcloud container clusters create openarena-cluster \
   --num-nodes 3 \
   --network game \
   --machine-type=n1-standard-2 \
   --zone=${zone_1}

クラスタが起動するまでに最長で 10 分ほどかかる場合があります。

タスクを確認するため [進捗状況を確認] をクリックします。

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

クラスタが起動したら、適切な Kubernetes 認証情報を使ってローカルの shell を設定し、新しいクラスタを制御します。

gcloud container clusters get-credentials openarena-cluster --zone ${zone_1}

Container Engine が使用するマネージド インスタンス グループ機能では、VM インスタンスの自動スケーリングによって使用状況に基づきプール内のノード数が増減されます。ただし、先ほど実行したコマンドで --disable-addons=HttpLoadBalancing,HorizontalPodAutoscaling フラグを使用したため、この機能が無効になっています。

多くのゲーム開発者は、DGS 対応のカスタム スケーリング マネージャー プロセスを実装してこのタイプのワークロードの要件に対応するのがよいと考えています。マネージド インスタンス グループは重要な機能を提供しています。デフォルトの Kubernetes Engine イメージ テンプレートには、必要な Kubernetes ソフトウェアがすべて含まれており、起動時にノードを自動的にマスターに登録します。

また、--disable-addons フラグによって HTTP 負荷分散が無効になりました。このクラスタで実行されるポッドでは、負荷分散は不要です。

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

一般的な DGS ではゲームアセットに対する書き込み権限は不要です。そのため、DGS ポッドごとに、読み取り専用のアセットを含む同じ永続ディスクをマウントできます。これを実現するには、まず、アセット ディスクの作成についてのセクションで説明されているようにアセット ディスクを作成します。これはすでに実行済みです。次に、Kubernetes に PersistentVolume を作成します。

このボリュームを Kubernetes DGS ポッドに含めるには、PersistentVolumeClaim リソースが必要です。このリソースの YAML ファイルは、ソリューションのリポジトリの openarena/k8s/ ディレクトリにあります。PersistentVolume を適用するとアセット ディスクが検出され、PersistentVolumeClaim によって DGS ポッドがディスクを読み取り専用でマウントできるようになります。

次のコマンドを実行して、PersistentVolumePersistentVolumeClaim を作成します。

kubectl apply -f k8s/asset-volume.yaml
kubectl apply -f 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 2     5s

タスクを確認するため [進捗状況を確認] をクリックします。

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

DGS ポッドを構成する

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

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

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

わかりやすくするため、このラボのソリューションでは、Container Engine ノードにデフォルトのネットワーク構成があり、各ノードにパブリック IP アドレスを割り当て、クライアント接続を許可していることを前提に説明します。

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

市販のゲームサーバーの場合、DGS を実行させる DGS 以外のすべての機能とコンテナは、できる限り DGS バイナリに直接統合されている必要があります。

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

Kubernetes のリソース定義

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

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

スケーリング マネージャーを設定する

スケーリング マネージャーはシンプルなプロセスです。現在の DGS 負荷に基づいて、Container Engine ノードとして使用される仮想マシン数をスケーリングします。実際には、スケーリングを実現するには、永続的に動作するシンプルな複数のスクリプトを使用し、実行中の DGS ポッドとリクエストされた DGS ポッドの合計数を調べ、必要に応じてノードプールのサイズを変更します。スクリプトは、適切なライブラリおよび Google Cloud SDK と一緒に Docker コンテナ イメージ内でパッケージ化されています。

これらのイメージを作成する Docker ファイルは、scaling_manager/ ディレクトリのラボのリポジトリにあります。複数の環境変数を構成したら、ビルドと push 用の shell スクリプトを使用して Docker イメージを作成し、gcr.io に push できます。

必要な環境変数を設定します。[GCR_REGION] を GCR region ("us"、 "eu"、 など) に、[PROJECT_ID] を Qwiklabs プロジェクト ID に変更します。

export GCR_REGION=[GCR_REGION]
export PROJECT_ID=[PROJECT_ID]

次のコマンドを使用して、構成をビルドし、push します。

cd ../scaling-manager
chmod +x build-and-push.sh
source ./build-and-push.sh

これらのスクリプトは、Kubernetes の Deployment 内で実行されるように設計されています。これにより、障害発生時にこれらのプロセスが再起動されます。

タスクを確認するため [進捗状況を確認] をクリックします。

スケーリング マネージャーを設定する

OpenArena スケーリング マネージャーのデプロイ ファイルを構成する

サンプル ソリューションの scaling_manager/k8s/openarena-scaling-manager-deployment.yaml ディレクトリに、Kubernetes の Deployment 用 YAML ファイルのサンプルが用意されています。このファイルはカスタマイズして、このファイルで構成するコンテナの環境変数がラボの OpenArena クラスタを説明する値を使用するようにする必要があります。

ベース インスタンス名を確認します。

gcloud compute instance-groups managed list

ベース インスタンス名をコピーします。出力の 4 つ目の列にあり、次のような内容です。

BASE_INSTANCE_NAME
gke-openarena-cluster-default-pool-1990bcc7

この次の一連のコマンドでは、角かっこの項目をすべて、角かっこごとラボの適切な値に置き換えます。例えば、 [ZONE] を 「us-east1-b」に置き替えます。[BASE_INSTANCE_ID] は、各ラボインスタンスごとに変わります。

export GKE_BASE_INSTANCE_NAME=[BASE_INSTANCE_NAME]
export GCP_ZONE=[ZONE]
printf "$GCR_REGION \n$PROJECT_ID \n$GKE_BASE_INSTANCE_NAME \n$GCP_ZONE \n"

次のコマンドを実行して、設定した変数を YAML デプロイ テンプレートに適用します。

sed -i "s/\[GCR_REGION\]/$GCR_REGION/g" k8s/openarena-scaling-manager-deployment.yaml
sed -i "s/\[PROJECT_ID\]/$PROJECT_ID/g" k8s/openarena-scaling-manager-deployment.yaml
sed -i "s/\[ZONE\]/$GCP_ZONE/g" k8s/openarena-scaling-manager-deployment.yaml
sed -i "s/\gke-openarena-cluster-default-pool-\[REPLACE_ME\]/$GKE_BASE_INSTANCE_NAME/g" k8s/openarena-scaling-manager-deployment.yaml

これらのコマンドを実行すると、ファイル内の環境変数の値のプレースホルダが更新されます。以下に正しい値を記載します。

置換するテキスト

備考

[GCR_REGION]

gcr.io リージョン(us、asia など)

置換が必要。gcr.io リポジトリのリージョン。

[PROJECT_ID]

Qwiklabs のプロジェクト ID。ラボの開始ページからコピーできます。

置換が必要。プロジェクトの名前。

[REPLACE_ME]

前の手順で特定した値です。末尾の 8 桁の一意の ID を置き換えます。

gke-openarena-cluster-default-pool-[REPLACE_ME]

置換が必要。Container Engine クラスタごとに異なります。gcloud compute instance-groups managed list コマンドの出力からこの値を取得できます。

[ZONE]

ラボの開始時に選択した GCP のゾーンに設定します。通常は us-east1-b です。

gcloud container clusters create コマンドで指定した GCP ゾーンの名前です。

次の環境変数の値はデフォルトのままにします。

K8S_CLUSTER

openarena-cluster

Kubernetes クラスタの名前。

次のコマンドを実行すると、Kubernetes クラスタに Deployment を追加できます。

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

kubectl を使用して Deployment を監視します。

kubectl get pods

3 個すべてのノードの準備ができたことが報告されるまで待ちます。

タスクを確認するため [進捗状況を確認] をクリックします。

Openarena スケーリング マネージャーのデプロイ ファイルを設定する

ノードをスケーリングする

懸念事項

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

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

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

スケールアップ

このソリューションでは、スケールアップを行うために特別な処理は不要です。マネージャー インスタンス グループでノード数を増やすだけで実現できます。わかりやすくするため、このソリューションでは Kubernetes の制限とリクエスト用のポッドのプロパティを使用して、各 DGS におおよそ vCPU 1 個 とメモリ 500 MB を「確保」します。n1-highcpu インスタンス ファミリーを使用してクラスタを作成しており、これは vCPU 1 個に対してメモリ 600 MB という固定の割合であるため、vCPU 1 個につき 1 個の DGS ポッドを予定している場合でもメモリは十分であると想定できます。そのため、クラスタ内の全ノードの CPU 数ではなく、クラスタ内のポッド数に基づいてスケーリングできます。この割合によって使用可能な残りのリソースが決まるため、値がしきい値を下回った場合にノードを追加できます。このソリューションでは、70% を超える vCPU がポッドに割り当てられている場合にノードが追加されます。

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

スケールダウン

スケールダウンはスケールアップとは異なり、複数のステップで構成されるプロセスであり、Kubernetes 対応のカスタム DGS スケーリング マネージャーを実行する主な理由の 1 つです。このラボでは、scaling_manger.sh で次のステップを処理します。

  • 削除対象の適切なノードが選択される必要があります。このラボでは、カスタムのゲームに完全に対応している Kubernetes スケジューラは使用しないため、API によって返された順にノードが選択されます。
  • cordon コマンドを使用すると、選択されたノードに Kubernetes で「unschedulable」とマークされます。これにより、ノードで追加のポッドが起動されなくなります。
  • abandon-instance コマンドを使用すると、選択されたノードがマネージド インスタンス グループから削除されます。これにより、マネージド インスタンス グループでインスタンスが再作成されなくなります。

また、node_stopper.sh スクリプトでは、スケジュールできない放棄されたノードを監視し、DGS ポッドが存在しないことを確認します。ノード上ですべての対戦が終了してポッドが正常に終了すると、スクリプトによって VM インスタンスがシャットダウンされます。

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

一般的な本番環境のゲームのバックエンドでは、新しい DGS インスタンスを追加するタイミングはマッチメーカーが制御します。対戦が完了すると DGS ポッドが正常に終了するように構成されているため(制約を確認してください)、DGS ポッド数をスケールダウンするために明示的に何かを行う必要はありません。プレーヤーから十分な数のリクエストがマッチメーカー システムに送信されず、新しい対戦が生成されない場合は、対戦が終了すると、DGS ポッド自身が徐々に Kubernetes クラスタから減っていき、実質的にポッド数がスケールダウンされます。

設定をテストする

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

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

一般的な本番環境のシステムでは、対戦に適したプレーヤーがいると、マッチメーカー プロセスが Kubernetes API を使用して直接インスタンスをリクエストします。このソリューションの設定をテストするために、シンプルな kubectl コマンドで openarena_pod.yaml ファイルを指定してインスタンスをリクエストできます。

まず、openarena/k8s/openarena-pod.yaml ファイルを更新し、コンテナ イメージの [GCR_REGION] と [PROJECT_ID] の値を置き換える必要があります。変数はすでに定義されているため、もう一度 sed を使用して実行できます。

cd ..
sed -i "s/\[GCR_REGION\]/$GCR_REGION/g" openarena/k8s/openarena-pod.yaml
sed -i "s/\[PROJECT_ID\]/$PROJECT_ID/g" openarena/k8s/openarena-pod.yaml

次のコマンドを実行して、新しいポッドの構成を適用します。

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

数秒経ったら、kubectl を使用してポッドのステータスを確認できます。

kubectl get pods

次の出力が表示されるまで kubectl の get pods コマンドを繰り返し実行します。

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

タスクを確認するため [進捗状況を確認] をクリックします。

セットアップのテストをする

次のコマンドは、ポッドの起動時にエラーが発生する場合にのみ、ポッドを削除し、マウントのロケーションを変更して再作成します。

kubectl delete pod openarena.dgs
sed -i "s/\/usr\/share\/games\/openarena\/baseoa/\/usr\/lib\/openarena-server\/baseoa/g"  openarena/k8s/openarena-pod.yaml
kubectl apply -f openarena/k8s/openarena-pod.yaml

DGS に接続する

ポッドが開始されたら、次のコマンドを実行することで、ポート 27461 でゲーム インスタンスに接続するために使用できるゲームサーバーの IP アドレスを特定できます。

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)')
printf "Node Name: $NODE_NAME \nNode IP  : $DGS_IP \nPort         : 27961\n"
printf " launch client with: \nopenarena +connect $DGS_IP +set net_port 27961\n"

ゲームがインストールされたら、お使いのパソコンで OpenArena クライアントを起動します。

[Multiplayer]、[Specify] の順に選択します。

直前に実行したコマンドの出力内容を使用して、サーバーの IP アドレスとポートを構成します。

[Connect] をクリックします。

OpenArena クライアントを閉じます。

スケーリング マネージャーをテストする

スケーリング マネージャーは DGS ポッド数に基づいて Kubernetes クラスタ内の VM インスタンス数をスケーリングします。そのため、テストを行う場合は、複数のポッドを一定期間リクエストし、ノード数が適切にスケーリングされることを確認すること必要があります。

ソリューションのリポジトリに、テストで使用できるスクリプトが用意されています。このスクリプトでは、5 分間にわたり、1 分につき 4 つの DGS ポッドが追加されます。

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

お使いの環境で、対戦の長さをサーバーの構成ファイルで適切な長さに設定し、最終的にポッドが終了してノードが再度スケールダウンされることを確認してください。このラボでは、サーバーの構成ファイルで対戦時間が 5 分に制限されており、例として使用できます。openarena/single-match.cfgrepo にあり、デフォルトで使用されます。

Google Cloud Platform Console を開き、[Kubernetes Engine]、[ワークロード] の順にクリックします。

openarena-dgs.sopenarena-dgs.2 から openarena-dgs.15)という一連のワークロードが開始されるのを確認できます。クラスタ内の vCPU 数に制限があるため、テストコンテナの多くは最初に「Unschedulable」というステータスのエラー状態で表示されます。各コンテナの開始時の負荷が減るため、後で起動されるゲームサーバー コンテナの一部は正常に開始されます。約 10 分後にすべてのコンテナが開始されます。

エラーが発生したインスタンスを調べると、エラーの原因が CPU リソース不足であることを確認できます。実行中のインスタンスのいずれかを調べると、それらのインスタンス上でゲームサーバーが初期化されていることを確認できます。

お疲れさまでした

これで、「Google Kubernetes Engine での専用ゲームサーバーの実行」が正常に完了しました。

bf1e2a23518ceceb.png Solutions_Kubernetes-125.png

クエストの終了

このセルフペース ラボは、Google Cloud ソリューション I: インフラストラクチャのスケーリングおよび Kubernetes ソリューションのクエストの一部です。クエストとは、学習パスを構成する一連のラボのことです。完了すると、その成果が認められて上のバッジが贈られます。バッジは公開して、オンライン レジュメやソーシャル メディア アカウントにリンクさせることができます。このラボを終えたら、クエストに登録して、すぐにクレジットを受け取れます。受講可能なその他の Qwiklabs のクエストもご覧ください

次のラボの受講

次のラボに進んでクエストを続けるか、以下のおすすめをご確認ください。

次のステップと詳細情報

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

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

Google Cloud Training & Certification

Google Cloud 技術を最大限に活用できるようになります。このクラスでは、必要な技術力とベスト プラクティスを習得し、継続的に学習することができます。トレーニングは基礎レベルから上級レベルまであり、オンデマンド、ライブ、仮想環境など、多忙なスケジュールに対応できるオプションが用意されています。認定資格を取得することで、Google Cloud の技術のスキルと知識を証明できます。

マニュアルの最終更新日: 2021 年 4 月 27 日
ラボの最終テスト日: 2021 年 4 月 27 日

Copyright 2020 Google LLC All rights reserved. Google および Google のロゴは Google LLC の商標です。その他すべての企業名および商品名はそれぞれ各社の商標または登録商標です。