この記事を書いている前日、MagicOnion勉強会で、MagicOnionをLinuxコンテナイメージにしてkubernetes上で動かして、NewRelicで監視する、というLTをしました。資料はこちらです。
LTということもあり、いきなり動いている様子をデモでお見せしたのですが、どうやって動かすんだろうという疑問をあったような気がします。そこで簡単にkubernetes上で動かす手順を紹介したいと思います。
一番のハードルはkubernetes環境の作成だと思います。AKS,EKS,GKEといったパブリッククラウドのマネージドkubernetesは各社が用意しているコマンドでインストールできますが、それなりにお金がかかります。ローカルにインストールするminikubeというものもありますが、それでも多少の面倒さはあります。そこで探していたら、Katacodaというサービスを見つけました。ブログ記事も出ているように、なんとブラウザ上で用意されたkubernetesの環境を操作できるというものです。というわけで今回はKatacodeを使ってMagicOnionのアプリをkubernetes上で動かしてみたいと思います。ただ、1つ制約があってgRPCのエンドポイントをインターネットに公開できないため、クライアント側も同じ環境上で動かす必要があります。
Katacodeはコースを作ることで、手順も込みで提示することができます。もう少し色々調べたら作り込もうと思いますが、まずはこちらの手順をみながら試してみてください。
まず私の作成したコース一覧のページにアクセスしてください。
このような画面になります。アカウント作成してログインすると履歴が残って便利ですが、作成せずとも利用できるようです。
kubernetes sandboxの下のStart Scenarioをクリックします。すると次の画面になります。

右下の黒い画面がターミナル、その上の白い画面がエディタとして使える画面です。まず、kubernetesを起動するコマンドを実行します。
launch.sh
しばらく待つとkubernetesd startedと表示されます。kubernetesのノード一覧を表示するコマンドを実行してみましょう。
kubectl get node
すると次のようにノード一覧が表示されます。ノードは1台だけのようです。
次にMagicOnionのアプリをデプロイして、外部からアクセスできるようにkubernetesのサービスを作ります。エディタを使うのでapp.yaml
という名前で空のファイルを作り、エディタ画面に表示されるのでダブルクリックで開きます。
エディタに次のkubernetesのオブジェクト定義をコピーペーストします。自動的に保存されます。
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: magiconion
spec:
replicas: 1
template:
metadata:
labels:
app: magiconion
spec:
containers:
- name: magiconion
image: tanakatakayoshi/magiconion-server-example:latest
ports:
- containerPort: 12345
---
apiVersion: v1
kind: Service
metadata:
name: magiconion-svc
spec:
ports:
- name: magiconion
port: 12345
selector:
app: magiconion
type: NodePort
ここで今から作るものを確認してみましょう。今定義したファイルにはdeploymentとserviceという2つのオブジェクトが存在しています。deploymentにはimageでtanakatakayoshi/magiconion-server-example:latest
を指定していますが、これが今から動かすコンテナイメージです。
このコンテナイメージの詳細はここに記載されています。
元となるソースコードはこちらで公開しています。
こんなよくわからないコンテナイメージ実行したくない!という場合は、いずれ自分で書いたソースコードをコンテナイメージにして実行する方法を紹介したいと思いますのでしばらくお待ちください。このコンテナはMagicOnionの単純なサーバーとそれに対応するクライアントのプロジェクトおよびそれらをビルドするDockerファイルから構成されています。
元に戻って、このdeploymentはimageに指定しているコンテナ1つから構成されるPodというkubernetesのオブジェクトを配置します。Podには複数のコンテナおよびvolumeと呼ばれるストレージを配置できますが、今定義したPodは1つのコンテナのみで構成されています。containerPort: 12345
というのは、このPodはポート12345番をコンテナ外に公開するという意味です。MagicOnionのサーバー側のコードでListenするポートと対応させます。
await MagicOnionHost.CreateDefaultBuilder()
.UseMagicOnion(new[] {
new ServerPort("0.0.0.0", 12345, ServerCredentials.Insecure) })
.RunConsoleAsync();
もう一つ作成したサービスというオブジェクトはPodへのアクセスを公開するためのオブジェクトです。(後述する理由で今回はこの環境外からアクセスできないのですが、)外部からアクセスするためのエンドポイントであり、1つのアプリが複数のPodで負荷分散している場合1にロードバランサになります。
ターミナル画面に戻って、今定義したオブジェクト定義を作成するコマンドを実行します。
kubectl create -f app.yaml
deploymentとserviceが作成されたと表示されます。deploymentによりPodが配置されるのですが、少し時間がかかるので完了を待ちます。kubectl get
コマンドは-w
オプションをつけると変化があると更新情報が表示されるようになります。これでPodの様子を確認します。
kubectl get po -w
次の画面のようにSTATUSがRunningになればOKです。
次にサービスの様子を確認します。
kubectl get svc
magiconion-svcというNAMEのサービスのCLUSTER-IPをメモしておきます。
さて、これで無事にMagicOnionのサーバー側のアプリがコンテナとしてkubernetes上で動きました。では接続したいところなのですが、Katacodeを使う上での制約が一つあります。HTTP(S)ではないTCPのトラフィックを外部から受け付ける方法がなさそう2ということです。先ほどの作成したサービスはNodePort
というタイプで、指定したポートでノードでアクセスすると、Podと通信できるというものです。しかしKatacodeのkubernetesではノードにアクセスできないためこの方法は使えません。
そこで、今kubernetesを動かしているサーバー上でMagicOnionのクライアントを動かすことにします。今動いているサーバーに対応したテストクライアントアプリを同じdocker repositoryで公開しているのでそれを使います。
ちょっと邪道ですが、kubernetesを動かしているサーバー上でdockerイメージを直接実行します。このクライアントはサーバーのホストをGRPC_HOST
という環境変数で外から渡すことができるように作っているので、先ほどメモしたCLUSTER-IPの値を指定した次のコマンドをターミナルで実行します。実際に動かす場合は10.99.143.216
を置き換えてください。
docker run --name client-demo -e GRPC_HOST=10.99.143.216 tanakatakayoshi/magiconion-server-example:client
すると一気にログが流れます。両方とも公開されているdockerイメージを使って、ログが流れているのを眺めるだけなのでいまいち動かした感がないかもしれませんがこれでMagicOnionのサーバーアプリをkubernetes上で動かすことができました。
もちろんminikubeをはじめ、通常のkubernetesで動かせば、kubernetes外からアクセスできて、Unityから繋ぐということもできます。Katacodeはkubernetesをお試しで動かすという用途ではすごくお手軽に使えていいと思います。今後も調べながらいろんなものを試せるコースを作ろうかなと思っています。
-
先ほどのdeployment定義の中の
replicas
に指定した数だけPodが生成されます。 ↩ -
調べた限りではなさそう。確実にないかどうかまではわからず。 https://www.katacoda.com/docs/scenarios/displaying-ports ↩