この記事は
Speee Advent Calendar 2017の13日目です! ぼちぼち折り返しの時期ですね。
よければ購読お願いします。
前日は、@yt-tanabe の SpeeeKaigiのつくりかた(とエンジニアの文化について)でした。
今日は@Tei1988によるKubernetesでFactorioです。
この記事を読めば、Factorioのマルチプレイ用サーバをKubernetesで構築することができます。
そもそもFactorioって?
とある星に不時着したプレイヤーが、その星の資源を使ってロケットを作り、宇宙に飛ばして、助けを待つ、というストーリーのゲームです。
「資源を使ってロケットを作る」のですが、周りには鉄鉱石や銅鉱石といった原料しかないので、それらを精錬したり組み合わせたりして、歯車や電子基板といった、より複雑な部品を作っていきます。
ロケットを作るのに必要な部品は、大量に必要かつ多岐にわたるため手作業で作っていくのは不可能です。
そこで、工場を作って資材をベルトコンベアに流して、生産の自動化を行います。
工場をたくさん作って生産を自動化し、材料がどんどん組み合わされていってベルトコンベア上を流れていくのを眺めていると、謎の達成感を味わえます。
工場の稼働率を向上させたり、別の工場のために、工場の配置や資源の流し方を変えるのですが、プログラミングのリファクタリングに通じるものがあり、普段コードを触っている人はもちろん、触っていない人でもリファクタリングの重要性を認識できる良いゲームだと思います。
ことの始まり
Factorioはマルチプレイが可能です。みんなで協力して、ロケットを飛ばします。
社内でも既に何人か持っている人がおり、マルチプレイをしよう、という話になりました。
さて、マルチプレイができるようにしなければなりません。
せっかくなので、手順などを残すついでに、記事を書くことにしました。
マルチプレイにも方法が二種類あります。
-
誰か一人がサーバ役になって、他の人がそこへ接続する
-
ゲームサーバを構築する
1の方法は、構成が手軽なのですが、サーバ役の人は毎回必ず参加しなければならないなど、負担が大きそうでした。
そこで、今回は2の方法を選択しました。
ゲームサーバを構築する
Factorioは、グラフィック機能の無い、headlessなゲームサーバを用意してくれています。
さらに、立ち上げるだけでOKなDockerイメージも有志によってdtandersen/factorioに置かれています。
なので、今回はこのDockerイメージを利用させてもらうことにしました。
次は、どこにデプロイするかです。
最近、Speee DEVELOPER BLOGにI ❤️ Kubernetesという記事を書くぐらいKubernetesを気に入っているので、GKEにデプロイすることにしました。
以下に、デプロイまでの手順を記しておきます。
-
準備
手順の中でgcloud
やkubectl
といったコマンドを使います。
以下などを参考に、インストールしてください。-
gcloud
公式インストールガイドを参考に、インストールしてください。
MacOSの場合、brew cask install google-cloud-sdk
でもインストールできるようです。 -
kubectl
kubectlはKubernetesの管理ツールで、基本的にはこのツールを用いて作業を行います。
MacOSの場合
Homebrewを使って以下のコマンドで導入可能です。
brew install kubectl
WindowsやLinuxの場合
すみません。公式インストールガイドなどを参考にしてください
-
-
GCPのコンソールからプロジェクトを作成します。プロジェクト名やプロジェクトIDは任意のもので大丈夫です。
公式ガイド
-
Kubernetes Engineを有効にします。
左のメニューから、Kubernetes Engine > Kubernetes クラスタ を選びます。すると、 有効化するボタンが表示されるので、押します。
押すと、以下のような表示に切り替わります。
この画面で少し待つと、有効化が完了します。
-
クラスタを作ります。
有効化が完了したのち、再び左のメニューから、Kubernetes Engine > Kubernetes クラスタ を選びます。すると、このようが表示になるので、クラスタを作成してください。
立ち上げるノードのスペックですがg1-smallの1台で大丈夫です。
ディスク容量を10GBにすると、お安くなります。
プリエンプティブなノードにするとさらにお安くなります。 -
GCEでpd-factorioという名前で空のディスクを作ります。
セーブデータを永続化するために使います。左のメニューから、Compute Engine > ディスクを選択します。
以下のような表示になるので、ディスクを作成をクリックします。
-
静的アドレスを確保します。
外からFactorioのマルチプレイ用サーバに接続する際に使用します。左のメニューから、VPC ネットワーク > 外部 IP アドレスを選択します。
静的アドレスの予約をクリックし、以下のように入力します。
以下のように、外部IPアドレスにIPが新しく追加されれば、静的アドレスの確保も完了です。
追加したIPは、後で確保した静的IPとして使います。 -
gcloud
がGCPに接続できるようにします。
ターミナルに以下を入力してください。
gcloud auth application-default login
ブラウザで、Googleアカウントにログインを求められるので、プロジェクトを作ったアカウントでログインしてください。ログインできれば、gcloudの設定は完了です。
-
kubernetesがGKEに接続できるように認証情報を取得します。
左のメニューから、 Kubernetes Engine > Kubernetes クラスタを選択します。先ほど作成したクラスタの横の接続をクリックします。
出てきたコマンドをコピーし、ターミナルで実行します。
これで、KubernetesがGKEに接続できるようになりました。
-
いよいよデプロイです。
Kubernetesで使うためのサンプル設定ファイルを用意しました。
以下のコマンドを実行します。
1.wget https://raw.githubusercontent.com/Tei1988/k8s-factorio/vanilla/k8s.yml.sample
2.sed 's/<IP>/確保した静的IP/g' k8s.yml.sample > k8s.yml
3.kubectl create -f k8s.yml --save-config
これで、Factorioが立ち上がります。
※初回の立ち上げはDockerイメージのpullが必要になるため、少し待つ必要があります。
さて、実際に遊べるか、実際にFactorioを起動してマルチプレイをしてみましょう。
Factorioを起動したあと、メニューから マルチプレイ > サーバに接続 を選び、確保した静的IP:34197を入力します。
どうでしょう?ログインできました?
ちなみに、もしFactorioサーバが何かしらの原因で落ちてしまっても、Kubernetesの自動デプロイでPodを復帰させてくれるので、追加でなにか作業が発生することは基本的にありません。
おわりに
ただいま絶賛、Modsを入れて7人程でワイワイ遊んでいるのですが、鉱石の種類が増えたり必要な生産物の種類が増えて、工場がとても複雑になり、リファクタリングする楽しさも増しています。
ボイスチャットをしながらプレイすると捗ります。
IPを教えるだけですぐに入ってもらえるので、マルチプレイの勧誘もとても楽です。
では、良い工場ライフを。
明日は、「SlackStatus とGoogleCalendarの同期をしてみた」や、「非エンジニアが社内wikiにヒートマップを実装してみた話」などの記事を書いた、新しい技術に目がない @nagayamacho3 がサンタクロースの正体を暴くようです。お楽しみに
おまけ
Factorioの醍醐味の一つであるModsを導入してみます。
Modsを導入する
Factorioは、Modsを導入することでさらに楽しむことができます。
マルチプレイをしていたメンバーも、通常のFactorioでは満足できなくなっており、Modsを導入することにしました。
クライアント側は、ゲーム画面からModsの導入が可能です。入れたいModsをポチポチしていけば、導入が完了します。
一方でサーバ側は、特定のフォルダに直接Modsを入れていく方法になります。
Modsは、クライアント側のものと共通なので、クライアント側に入れたModsをコピーするのが手っ取り早いです。
今回は、DockerイメージにModsを追加することにしました。
また、設定ファイルもConfigMapではなく、イメージに含めることにしました。
Mods入りのDockerイメージの作成手順は以下です。
-
Tei1988/k8s-factorioのmodsブランチをcloneする。
-
files/mods以下に、Modsをコピーする。mod-list.jsonも忘れずに。
-
必要であれば、
files/config/
以下の設定も修正する。 -
docker build -t gcr.io/プロジェクトID/factorio:mods .
-
docker push gcr.io/プロジェクトID/factorio:mods
これで、Dockerイメージの作成は完了です。
次に、Kubernetesにデプロイする前に、セーブデータを削除します。
もし、前のセーブで続きをやりたい場合は、ローカルにセーブをコピーしたり、pd-factorioディスクをコピーするなどでバックアップをとってください。
pd-factorioディスクを作り直せば、セーブデータは消えます。
最後に、作ったDockerイメージをKubernetesにデプロイします。
以下のコマンドで、デプロイできると思います。
cat k8s.yml.sample | sed 's/<IP>/確保した静的IP/g' | sed 's/<ProjectName>/プロジェクトID/g' > k8s.yml
kubectl apply -f k8s.yml