Agones探訪 on GKE#1

GCP

この記事について

GoogleとUbisoftにより開発されたオープンソースのゲームプラットフォームAgonesに関する理解を深めていく。

Agonesについて

Agonesにより、デベロッパーはFPSやMMOといったマルチプレイヤーゲームにおけるインフラまわりの課題をオフロードし、バックエンドのロジック開発にフォーカスできるようになる。

ゲーム開発におけるインフラまわりの課題

大規模なオンラインゲームにおけるバックエンドでは、真っ先に以下の項目が検討課題となるだろう。どちらもAgonesが解決する課題だ。

  • ホスティングとスケーラビリティ
  • ゲームサーバーのライフサイクル管理

ホスティングとスケーラビリティ

  • クラウドにデプロイすればサーバー調達のリードタイム不要
  • GKEの場合、クラスタにノードを15,000まで拡張可能
    allocatorの構成によってはマルチクラスタにもできるようだ。これにより、より大規模なゲームサーバーのスケールアウト・インにも対応可能。

ゲームサーバーのライフサイクル管理

クライアントの接続からゲームサーバーのデプロイ、終了といったライフサイクルをAgonesが担う。これにより開発者はゲームサーバーのロジックに専念できるようなる。

デプロイ

GKEのデプロイ

TerraformでGKEをさくっとデプロイする。

$ cat gke.tf

resource "google_service_account" "default" {
  account_id   = "service-account-id"
  display_name = "Service Account"
}

resource "google_container_cluster" "agones-cluster" {
  name     = "agones-gke-cluster"
  location = "asia-northeast1-b"

  remove_default_node_pool = true
  initial_node_count       = 1
}

resource "google_container_node_pool" "primary_preemptible_nodes" {
  name       = "agones-node-pool"
  location   = "asia-northeast1-b"
  cluster    = google_container_cluster.agones-cluster.name
  node_count = 1

  node_config {
    preemptible  = true
    machine_type = "e2-medium"
    disk_type ="pd-standard"

    # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
    service_account = google_service_account.default.email
    oauth_scopes    = [
      "https://www.googleapis.com/auth/cloud-platform"
    ]
  }
}

Agonesのデプロイ

現時点での最新版をデプロイする。

$ kubectl create namespace agones-system
$ kubectl apply --server-side -f https://raw.githubusercontent.com/googleforgames/agones/release-1.30.0/install/yaml/install.yaml

kubenetesデプロイメント

$kubectl get deployment --namespace agones-system
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
agones-allocator    3/3     3            3           46s
agones-controller   1/1     1            1           46s
agones-ping         2/2     2            2           46s

役割(ざっくり)

deployment 役割
allocator ゲームサーバーのプロビジョニング。 gRPCまたはRESTでリクエストを受ける。Mutal TLS(mTLS)によりクライアント・サーバー間で相互に正当性を確認するサーバーからもクライアントを検証することで、本来のサービスの提供先でない者からのゲームサーバーへの不正なアクセスを排除できる。(ブルートフォース攻撃対策)
controller ゲームサーバーの状態管理
ping pingテスト用サービス

サービス

$kubectl get service --namespace agones-system
NAME                               TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)            AGE
agones-allocator                   LoadBalancer   10.103.254.202   35.189..***.***   443:30029/TCP      10m
agones-allocator-metrics-service   ClusterIP      10.103.246.40    <none>           8080/TCP           10m
agones-controller-service          ClusterIP      10.103.241.84    <none>           443/TCP,8080/TCP   10m
agones-ping-http-service           LoadBalancer   10.103.240.106   35.200.***.***    80:32452/TCP       10m
agones-ping-udp-service            LoadBalancer   10.103.241.252   34.146.***.***   50000:32223/UDP    10m

Ingress

デフォルトのデプロイだとIngressは構成されない。クライアントはゲームサーバーのIPをallocatorを通じ入手する。

$kubectl get ingress --namespace agones-system
No resources found in agones-system namespace.

ping

# ping 35.200.***.***
PING 35.200.***.*** (35.200.***.***): 56 data bytes
64 bytes from 35.200.***.***: icmp_seq=0 ttl=105 time=6.474 ms
64 bytes from 35.200.***.***: icmp_seq=1 ttl=105 time=5.882 ms
64 bytes from 35.200.***.***: icmp_seq=2 ttl=105 time=6.201 ms

シークレット

オフィシャルリポジトリのinstall.yamlを使ったデプロイではyaml内のsecretリソースに埋め込まれた証明書がallocatorに適用される。

$kubectl get secret --namespace agones-system
NAME                  TYPE                DATA   AGE
agones-manual-cert    Opaque              2      8m24s
allocator-client-ca   Opaque              1      8m24s
allocator-tls         kubernetes.io/tls   2      8m24s
allocator-tls-ca      Opaque              1      8m24s

テストゲームサーバーのデプロイ

入力した文字をエコーするだけのシンプルなゲームサーバーをデプロイする。

kubectl create -f https://raw.githubusercontent.com/googleforgames/agones/release-1.30.0/examples/simple-game-server/gameserver.yaml

デプロイされたゲームサーバー。

$kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
simple-game-server-6dglq   2/2     Running   0          92s

カスタムリソース

gameserverはkubectlにカスタムリソースとしてkubectlにロードされていてkubectl上でgameserversオブジェクトとしてステータスを確認できる。

$kubectl get customresourcedefinitions |grep game
gameserverallocationpolicies.multicluster.agones.dev   2023-03-26T04:10:28Z
gameservers.agones.dev                                 2023-03-26T04:10:27Z

ほかにAgonesのカスタムリソースとしてはFleetがある。

ゲームサーバーのIP

ゲームサーバーにはGKEノードのIPが表示されている。
デフォルトのポートポリシーである"Dynamic"ではGKEノードで空いているポートが割り当てられる。

$kubectl get gameservers
NAME                       STATE   ADDRESS         PORT   NODE                                                  AGE
simple-game-server-6dglq   Ready   35.190.***.***   7513   gke-agones-gke-clust-agones-node-pool-13a521cf-xcgr   2m58s

ゲームサーバーの状態遷移

kubectl describe gameserver
~
Events:
  Type    Reason          Age   From                   Message
  ----    ------          ----  ----                   -------
  Normal  PortAllocation  26m   gameserver-controller  Port allocated
  Normal  Creating        26m   gameserver-controller  Pod simple-game-server-6dglq created
  Normal  Scheduled       26m   gameserver-controller  Address and port populated
  Normal  RequestReady    26m   gameserver-sidecar     SDK state change
  Normal  Ready           26m   gameserver-controller  SDK.Ready() complete

IPアドレスとポートが割り当てられたあとGameServerはReadyとなる。

ゲームサーバーのステータス遷移

GameServerのライフサイクルを通じ、以下のような経過を辿る。

  • Ready
  • Allocated
  • Shutdown

ゲームサーバーはマッチごとに作成され、マッチが終わると破棄されるスクラップ&ビルドのイメージ。

ゲームサーバーのグローバルIP

Agonesは遅延最小化のためクライアントをゲームサーバーへ直接接続させるアーキテクチャーとなっている。
AllocatorがGKEノードのグローバルIPにクライアントを接続させるということ。GKEならノードのスケールアウトにより利用者が増えてノードのポート枯渇にも容易に対応できる。

サンプルゲームサーバーへの接続

Agonesではゲームサーバーに直接接続する仕組みのため、ノードが一台のミニマム構成の場合はPODに割り当てられたノードIPの公開ポートへUDPで接続するとゲームサーバーに接続できる。

# nc -u 35.190.***.*** 7513
hi
ACK: hi
Don't echo me.
ACK: Don't echo me.

次回

Fleetとマルチクラスタの動きを確認し、Agonesの拡張性について理解していく。

タイトルとURLをコピーしました