2021年の技術的ふりかえり

年の瀬になったので、あらためて今年学んだ技術を振り返っていく。

クラウドゲーミングの開発

2021年はほぼ全てOOPartsのクラウドゲーミング (Black Game Streaming Engine v2 )の開発に費やした。 経緯は id:oliver0521 によるCEDECの発表の通りで、Windows Serverのコストが高すぎるのでなんとか改善できないだろうかという話からだった。

迫り来る絶望的状況からの脱却物語 / #CEDEC2021 - Speaker Deck

Windows Serverを捨ててLinux + Wineでやれたら素晴らしいなぁという発想は2019年からあったが、Wineでどれくらいゲームが動くのかも未知数なので踏み切れずにいた。また、Windows Server時代に使っていた映像配信のSaaSがLinuxに対応してなかったため、もしLinuxでやるなら配信基盤も自前で作る必要もあり、さすがに夢のまま終わりか…という気持ちで止まっていた。

しかし、ある日GUIアプリをコンテナ上で動かし、Webブラウザから操作できるneko というOSSを発見し、 これを参考にすれば配信基盤が作れるのでは?と思って空いた時間に研究開発を始めた。 そしてひとつのゲームタイトルがLinux + Wine + Dockerで動作し、WebRTC経由でブラウザから操作できるPoCが完成したので、これを社内に伝えたら良い反応が得られ本格的にWindows Serverベースからの移行プロジェクトが始まった。

動作するOSも変わって配信基盤も変わるなら、いっそ全部書き直そうと決意してバックエンドをほぼ全部新規開発した。 この内部の話はGo Conference 2021 Autumnで発表した。

Go Conferenceでクラウドゲーミングな発表をした - castaneaiのブログ

WebRTC / GStreamer

配信基盤を自前で作ることになり、WebRTCという技術を採用した。 Pion WebRTCを使ったので0からWebRTCを開発したわけではないが、ゲーム画面の映像・音声を生成する部分とP2P接続の確立(シグナリング)部分はWebRTCでは提供されてないため独自で書く必要がある。

まず、ゲーム画面の映像・音声を生成する部分はGStreamer という技術を採用した。これはSelkies というリモートデスクトップのOSSが内部で使っていたためそれを参考に配信のパイプラインを構築した。

次にシグナリングについて、当初はAyame というシグナリングサーバーを用いていたが、Cloud Nativeな環境で扱うにあたって直したい点があったので、Ayameのプロトコルだけ使わせていただきつつ、独自のシグナリングサーバーを開発した。

Ayame互換の WebRTC Signaling Server "ayu" を作った - castaneaiのブログ

Kubernetes

開発したクラウドゲーミング基盤を実サービスとして耐えうる作りにするにはインフラの基盤も重要だった。 Kubernetes、以前からなんとなく知ってたが、わかったようでいまいちわからなかった。そこであれこれ資料を漁るよりも実際にクラスターを立ててクラウドゲーミング基盤を乗せてみるしかない!と思い立ってクラウドゲーミングの一連のプレイが回るところまでとにかくがんばって試行錯誤した。 そしたら急に Kubernetesのこと…完全に理解したかもしれない… って思えるほど色々な概念が頭の中でつながって最高だった。こういうものは座学よりも実際にアプリを立てて触って壊したりして覚えるのが一番良いと実感できた例だった。

ゲームのセーブデータ領域を動的に作成するためにMount Propagation という機能を使ったらPodがTerminatingのまま残り続ける問題が発生してしまい、原因調査と周辺知識の学習にかなり時間がかかった。しかし、この問題のおかげでkubeletという存在を知り、Kubernetesの内部のコンポーネントの構造や流れが見えて楽しかった。

さらに、クラウドゲーミングのようなStateful Game Serverに適したAgones の採用も重要だった。以前から存在は知っていたものの実運用するとこのような課題があるのかという気付きが多くあった。詳しくは id:yu_suke1994 が発表してくれた。

なぜ我々はクラウドゲーミング基盤をKubernetesに移行したのか #CNDT2021|うなすけ|note

他にはKubernetes上でGPUを使ったゲームを提供するためにContainer with GPUな技術について学び、コンテナランタイムやLinuxのデバイス周りの知識がついた。このあたりの知見は id:Mitu217 が発表してくれた。

Running GPU-bound games on Kubernetes / #k8sjp - Speaker Deck

Kubernetesを学ぶにあたってローカル環境で高速なiterationが回せるのは重要だと考え、minikubeやkindの勉強もした。 ローカル環境とリモート環境(主にGKE)での差異をできるだけなくしつつ、お手軽さも失わないためにはどうすればいいかと試行錯誤をした。 結果としてkustomizeや仮想化技術について少し詳しくなった。

ローカルKubernetes環境のネットワークを攻略する

Wine

LinuxとWebRTCによるクラウドゲーミング基盤が実現可能とわかったのは良かったが、Wineでどれくらいゲームが動くのかという点に関しては不安が残っていた。 実際にOOPartsのゲームタイトルをいくつかWineで動かしてみると意外と多くのゲームが動いた…が、完璧ではなかった。

Wineが完璧ではない以上仕方ないと諦めかけたが、よく考えたらWineはOSSである。これはWine側を修正することだってできるのでは?と思い、Wineへのコントリビュートを始めた。bug trackerに検証結果を提供したり、ときにはパッチを送ってWine本体に取り込んでもらった。これで当初動かなかったゲームがいくつか動くようになった。

日本語圏のWine開発者というのはまだ少ないように思えたので、次のような記事を書いて今後の新しいContributionをやりやすくする運動もしている。

Wineに関してはまだまだ修正したい箇所があるので現在も進行形でパッチを書いている。 来年にはさらに多くのゲームが動くようにしていきたい。