目次
久々の投稿となります。よっしーです。今回は少しニッチな話題をお送りしたいと思います。
ネットゲームではサーバインフラにパブリッククラウドサービスを使用することが多く、
各クラウドサービスベンダーも、ゲームインフラ構築のためのサポートサービスを提供し、
インフラ構築を容易し、ゲームに必要な機能の安定して得られるようになりました。
今回取り上げる “Open Match“ は Google Cloud がサポートするマルチプレーヤーに対応したゲームのマッチメイキングのフレームワークであり、同じく Google Cloud でサポートするゲームサーバーのホスティングとスケーリングの機能を提供する “agones“ と共に Kubernetes ベースでのゲームサーバー構築を実現できるよう設計されました。
Open Match とは?
Open Match は上述の通り、
「ゲーム マッチメーカーの構築を簡素化するオープンソースのマッチメイキング フレームワーク」
です。以下、Open Match のホームページからの概要の抜粋です。
仲人を構築するのは難しいです!高品質の試合を生成するためのコア ロジックを実装することに加えて、膨大な数のプレイヤー集団の処理、効率的な検索、大規模な試合生成ロジックの同時処理などの困難な問題の解決も含まれます。 Open Match フレームワークは、ゲーム開発者がプレイヤーを優れたゲームにマッチングさせるためのマッチメイキング ロジックに集中できるように、これらの問題を解決するコア サービスを提供します。
既製の構成ベースのマッチメイキング ソリューションと比較して、Open Match を使用すると、ゲーム開発者はゲーム固有の要件に対応できるカスタマイズされたマッチメイキングを簡単に構築できます。
(https://open-match.dev/site/docs/overview/ より抜粋)
そして、Open Match にはマッチングに必要なデータを保存し、検索できるよう Redis を使用してます。
今回、Open Match で使用する Redis を Memorystore Redis に移行しますが、外部 Redis の使用は
「Open Match Version 1.8」以上の使用が必要になります。
Open Match のインストール
Google Cloud の Kubernetes エンジンである GKE に Open Match をインストールすると、標準で Redis の Pod がデプロイされます。
GKE クラスターの設定
まず、Memorystore Redis インスタンスと直接接続するためには GKE クラスターは
「VPC ネイティブのトラフィック ルーティング」を「有効」
であることが必要です。
しかし、「GKE バージョン 1.21.0-gke.1500」 以前に作成されたクラスターは「VPC ネイティブ」ではなく、
「ルートベース」のクラスタ ネットワーク モードがデフォルトとなっていたため、「ルートベース」で作成されたクラスターは「VPC ネイティブ」でのクラスター再作成 (!) が必要になりますが、これにはネットワークパフォーマンスは低下する懸念はありますが、回避策があります!後ほどご紹介します。
今回使用した GKE クラスターには Open Match システムの Pod 起動用と、Open Match で使用する Redis 用にそれぞれノードプールを作成し、それぞれのノードプール配下のノード GCE に Open Match の Pod がデプロイされるように、以下のメタデータを設定しています。
・open-match-pool
・om-redis-pool2
そして、Open Match の system pod の kubernetes ネームスペースとして “open-match” を使用します。
$ kubectl get ns | grep open-match
open-match Active 74d
Open Match のデプロイ
また、 Open Match は Open Match のチュートリアルに記載されている「Helm を使用してインストールする」によりインストールを実行しました。(今回使用した helm コマンドは下記)
$ helm dependency update <om-root>/open-match/install/helm/open-match
$ helm install open-match --namespace open-match <om-root>/open-match/install/helm/open-match \
-f <om-root>/open-match/install/helm/open-match/values.yaml \
--set open-match-customize.enabled=true \
--set open-match-customize.evaluator.enabled=true \
--set open-match-override.enabled=true
上記コマンドによりインストールされた Pod は以下になります。
$ kubectl get pod -n open-match -o wide
NAME READY STATUS NODE
open-match-backend-84bff77765-qczd7 1/1 Running open-match-pool
open-match-evaluator-69db5469f4-zqb92 1/1 Running open-match-pool
open-match-frontend-78f97c6887-4cpps 1/1 Running open-match-pool
open-match-frontend-78f97c6887-hk28m 1/1 Running open-match-pool
open-match-frontend-78f97c6887-wnrzr 1/1 Running open-match-pool
open-match-query-64f44cdb5c-4kmhn 1/1 Running open-match-pool
open-match-query-64f44cdb5c-pxpdj 1/1 Running open-match-pool
open-match-query-64f44cdb5c-wgsnh 1/1 Running open-match-pool
open-match-redis-master-0 2/2 Running om-redis-pool2
open-match-swaggerui-8cf7b87cc-2nmgr 1/1 Running open-match-pool
open-match-synchronizer-79b648dd6c-fjn8g 1/1 Running open-match-pool
(一部抜粋)
Open Match システムに関する Pod は open-match-pool に、Open Match の Redis は om-redis-pool2 の ノード GCE にデプロイされていることがわかります。
Open Match の Redis を Memorystore redis に移行
Open Match に標準でデプロイされる Redis も性能的には問題ないと思われますが、やはり、安定したゲームの品質を保つためには、安定した性能と冗長化および、メンテナンスを実施しやすいクラウドサービスベンダーが提供する Redis サービスを導入することがおすすめです。
Google Cloud には Google Cloud が提供する “Memorystore Redis” サービスがあります。
Memorystore Redis に Open Match 用の Redis インスタンスを作成し、GKE の Open Match システムから使用できるよう設定しましょう。
Memorystore Redis インスタンスの作成
Google Cloud コンソールの “Memorystore” → “Reids” → “インスタンスを作成” を選択
- インスタンスの名前を入力
- ティアを選択
「スタンダード」を選択。容量はレプリカを使用する場合は最小 5 GB。
- レプリカの設定、VPC の選択
- 接続の設定
「ダイレクト ピアリング」を選択
- セキュリティの設定
「AUTH」を有効にします
「インスタンスを作成」をクリックし、インスタンスを作成します。
作成後、Google Cloud コンソールの作成されたインスタンスページから
「プライマリ エンドポイント IP アドレス」
「AUTH 文字列」
を入手します。
プライマリ エンドポイント IP アドレス : 10.16.42.204
AUTH 文字列 : 7eb37f44-42c3-476b-99cf-xxxxxxxxxxxx
Open Match の再デプロイ
GKE に既に Open Match がデプロイされている場合は、Open Match をuninstall します。
$ helm uninstall open-match --namespace open-match
Memorystore Redis インスタンスに接続する Open Match システムをデプロイするには下記のコマンドを実行します。
$ helm dependency update <om-root>/open-match/install/helm/open-match
$ helm install open-match --namespace open-match <om-root>/open-match/install/helm/open-match \
-f <om-root>/open-match/install/helm/open-match/values.yaml \
--set open-match-customize.enabled=true \
--set open-match-customize.evaluator.enabled=true \
--set open-match-override.enabled=true \
--set open-match-core.redis.enabled=false \
--set open-match-core.redis.hostname="default:7eb37f44-42c3-476b-99cf-xxxxxxxxxxxx@10.16.42.204" \
--set open-match-core.redis.port=6379
ここでのポイントは新たに追加されたオプションになります。
--set open-match-core.redis.enabled=false
Open Match 標準の Redis を disable にします。
--set open-match-core.redis.hostname="default:7eb37f44-42c3-476b-99cf-xxxxxxxxxxxx@10.16.42.204"
Memorystore Redis インスタンスへのアクセス情報
User ID : 「default」 で固定になります。
Password : Memorystore Redis インスタンスの「AUTH 文字列」を指定
Host : Memorystore Redis インスタンスの「プライマリ エンドポイント IP アドレス」を指定
--set open-match-core.redis.port=6379
Memorystore Redis インスタンスで使用するポート番号を指定。デフォルト値は「6379」
デプロイ完了後、Pod の確認をすると、
$ kubectl get pod -n open-match -o wide
NAME READY STATUS NODE
open-match-backend-84bff77765-v77l2 1/1 Running open-match-pool
open-match-evaluator-69db5469f4-9rh8g 1/1 Running open-match-pool
open-match-frontend-78f97c6887-c4sxp 1/1 Running open-match-pool
open-match-frontend-78f97c6887-dwksp 1/1 Running open-match-pool
open-match-frontend-78f97c6887-wfq4n 1/1 Running open-match-pool
open-match-query-64f44cdb5c-2d6nd 1/1 Running open-match-pool
open-match-query-64f44cdb5c-hj6h5 1/1 Running open-match-pool
open-match-query-64f44cdb5c-nrgg2 1/1 Running open-match-pool
open-match-swaggerui-8cf7b87cc-42cml 1/1 Running open-match-pool
open-match-synchronizer-79b648dd6c-65jn4 1/1 Running open-match-pool
(一部抜粋)
Open Match の Redis の Pod はデプロイされず、 om-redis-pool2 の ノード GCE に何もデプロイされていることがわかります。つまり、om-redis-pool2 のノードプールは削除可能となりました。
実際にMemorystore Redis インスタンスが使用されているは、「redis-cli コマンド」等でインスタンス内のデータを確認ください。
Tips : GKE の VPC ネイティブが「無効」だった場合の回避策
GKE クラスターと Memorystore インスタンスは「VPC Peering」が必要なネットワーク上にそれぞれ存在するため、GKE クラスターの iptables に Memorystore インスタンスに接続するための設定を追加する必要があります。
まず、github リポジトリ「k8s-custom-iptables」のクローンを作成します。
$ git clone https://github.com/bowei/k8s-custom-iptables.git
$ cd k8s-custom-iptables/
この「k8s-custom-iptables」Pod は操作が必要なノードにデプロイする必要があるため、
今回は「open-match-pool」ノードプール配下のノード GCE 内にデプロイされるようにする必要があります。
上記の「GKE クラスターの設定」項で説明した通り、Open Match システムの Pod が「open-match-pool」ノードプールにデプロイされるようにするための「テイント」が設定されているため、そのテイント値を k8s-custom-iptables ディレクトリ配下の 「daemon.yaml」ファイルを編集し、下記の設定を追加します。
spec:
...
template:
metadata:
...
spec:
tolerations:
- key: "open-match.dev/open-match-pool"
operator: "Equal"
value: "true"
effect: "NoExecute"
また、iptables で操作する IP アドレス範囲を指定するために、Memorystore Redis の接続で使用する IP 範囲を確認します。
IP 範囲 : 10.16.42.192/28
IP 範囲を確認後、下記のコマンドで 「k8s-custom-iptables」Pod のデプロイを実行
$ TARGETS="10.16.42.192/28" ./install.sh
デプロイ実行後、設定を確認
$ kubectl get pods -n open-match
NAME READY STATUS RESTARTS AGE
k8s-custom-iptables-2vmrm 1/1 Running 0 31s
k8s-custom-iptables-6nzfn 1/1 Running 0 31s
$ kubectl describe configmap/k8s-custom-iptables -n open-match
Name: k8s-custom-iptables
Namespace: open-match
Labels: <none>
Annotations: <none>
Data
====
nat.rules:
----
10.16.42.192/28
BinaryData
====
Events: <none>
これで Open Match システム Pod から Memorystore Redis インスタンスに接続可能になりました!
k8s-custom-iptables の Pod という一種の NAT を経由するため、「VPC ダイレクト」接続よりネットワークパフォーマンスの低下は発生すると思われます。
まとめ
今回はニッチな話題を書いてみました。
ニッチな話題はインターネット上に解決策が公開されている可能性が低く、真に解決策必要なエンジニアは自力で解決するしか手が無くなります。
本投稿もそんな「真に解決策が必要なエンジニア」に届くように!