GAE Managed VM & Custom Runtimeについて

このエントリーはGoogle Cloud Platform Advent Calendar 2015の14日目です。

10月に入社しましてブログには初めて投稿します石井です。休日はJavaScriptやGoで趣味の開発を行っていたり、家に知人を集めてボードゲーム会をしてたりします。

さて、ALBERTはAWSメインの開発を行っているのですが、GCP (Google Cloud Platform) も最近盛り上がって来ている!という事で、新しい案件をGCPで構築してみることにしました。その際にGAE (Google AppEngine) 周りの調査を色々と行ったので、今回は特にManaged VMとCustom Runtimeについて紹介できればと思います。

GAE Managed VM, Custom Runtimeは簡単に言うと、GAEが裏で管理していたコンテナを触れることができるようになったり、自分で定義したDockerのコンテナをGAE上で動かすことがでるようになるものです。


GAE sandbox

予めGCPのコンソールから適当なプロジェクトを作成しておきます。

まずは基本のGAEプロジェクトから段階的にVM使うようにしてみます。
app.yamlとそこから呼び出してるmain.pyを作成、デプロイします。

$ gcloud preview app deploy app.yaml –promote
でデプロイします。

ブラウザでhttps://プロジェクト名.appspot.com/を見てみるとHello, World!が出ます。
ここまではよくあるsandboxのhello worldですね。


GAE Managed VM (MVM)

次に、このpythonアプリケーションをMVMに変更してみます。

さっきと比べ、app.yamlに
vm: true
manual_scaling: {instances: 1}

が追加されただけです。

MVMで重要なのはvm: trueの方で、これを追加するとMVMモードでアプリケーションが動作するようになります。
manual_scalingはスケーリング・負荷分散の設定値です。MVMはデフォルトで2つのインスタンスを立ち上げ分散するようになっているのですが、今回は特に必要ないので1つのインスタンスで処理するように設定しています。

先ほどと同じように
$ gcloud preview app deploy app.yaml –promote
でデプロイします。

MVMモードでVMを立ち上げているのでsandboxの時より少し時間が掛かるかと思います。気長に待って、先ほどと同じhttps://プロジェクト名.appspot.com/にアクセス。ちゃんと動作しているのが確認できます。また、GCEのコンソールへ移動すると今デプロイしたアプリケーション用のインスタンスが起動しているのが確認できると思います。sandboxで隠されていたインスタンスの中身があれこれ確認できるのですね。感激です。

注意する点として、MVMで立ち上がったインスタンスは新しいバージョンのアプリケーションがデプロイされても削除されず動き続けます。消したい場合はGAEコンソールから過去のバージョンを削除しないといけません。GCEから直接インスタンスを削除しても、しばらくするとオートスケーリングの設定により自動的にインスタンスが立ち上がってしまいます。このへん新しいバージョンのアプリケーションがデプロイされたら自動で消えるようにしたかったのですが調べてもよくわかりませんでした。何かご存じの方はご教授頂ければと思います。

さて、せっかく立ち上げたインスタンスですが、これだけじゃVMの何が嬉しいのかわからないのでちょっとアプリケーションをいじってみます。と言ってもsqliteでローカルのディスクへ書き込む簡単なものですが。
GAE sandboxだとfsへのアクセスができないのですが、vmにすればfsにも触れる用になるので、sqliteでローカルにDBファイルを作って読み書きすることも可能なはずです。

シンプルすぎるカウンター。
どうしようもないアプリケーションですがそこは気にせず、これを今までのようにデプロイするとアクセスのたびにカウンターがちゃんとインクリメントされているのが確認できます。
スクリーンショット 2015-12-14 13.02.37
何気ないアプリケーションですがGAEでローカルファイルへ書き込むことができるようになりました!

さて、MVMで立ち上がったインスタンスですが、GCEのインスタンスとして立ち上がっているのでもちろんSSH接続して中身を確認することができます。MVMで立ち上がったインスタンスはgoogle管理のインスタンスとなり、「途中で中身をいじって変更したまま動かし続ける」事はできませんが、弄ることだけはできます。試しにGCEインスタンスの一覧からsshボタンを押すと「ユーザー管理への切り替え」とダイアログが出てきて、変更は全て失われますと表示されます。
スクリーンショット 2015-12-14 13.05.07
何はともあれsshしてみるとそれらしいコンテナが動いているのが確認できますので、それに接続してみます。

コンテナの中に入れました!

最後はCtrl+p→Ctrl+qでコンテナから抜けます。豪快にexitするとコンテナが終了してアプリケーションが死んでしまうので気をつけてください。
いろいろと面白いものが見れましたね。ログインしたディレクトリにあったDockerfileが今まさにGAEで動いているコンテナのイメージファイルになります。


GAE MVM Custom Runtimes

実はこのDockerfileを自分で書いてグリグリするのもCustom Runtimeという形で公式にサポートされています。

GoogleCloudPlatform/appengine-nginx-hello
公式のサンプルではnginxを動かしています。これを真似てpythonのflaskを動かすコンテナを書いてみたのがこれです。以下はこれの説明です。
airtoxin/gae-mvm-custom-runtime-sample

nginxのyamlファイルを参考にしました。runtime: customとしてDockerfileを同梱するとそれを動かせるようになります。
handelrsのscript: dynamicは公式のマニュアルをどれだけ探しても出てこないのですが…おそらくリクエストをGAE側でハンドリングせず、サーバーに直接届けてくれるようなオプションかと思います。

で、動かすDockerfileですが、せっかくなのでpython3を動かしてみます。

こんな感じのDockerfileとpythonのスクリプトを用意して、doker runするとmain.pyでサーバーが起動するようにしてやります。

サーバーはflaskで立ててみます。sandboxだとdjangoかwebapp2くらいしか呼び出せず少々めんどくさかったのが、好きなライブラリを導入できるので軽量なライブラリでさっと書けるのがいいですね。
/へのルーティングはstatic/index.htmlを返すようにしていますので、これは適当に配置しておきます。/_ah/start/_ah/healthはGAEのライフサイクルイベントで、GAEが定期的にリクエストを送り、コンテナがreadyなのかhealthyなのかを確認するのでそれに応答するようにしています。healthの方はステータス200で何かメッセージを送ればよいようです。

あとはrequirements.txtに依存ライブラリを記述しておきます。これは先程のDockerfile内で、コンテナ内のpythonにインストールするようにしています。

ここまできたらデプロイはお馴染み
$ gcloud preview app deploy app.yaml –promote
ですね。
スクリーンショット 2015-12-14 14.45.48
来ました!勝手に定義したDockerfileがGAEで動いてます!


まとめ

GAE sandboxはVMの管理をGAEがやってくれる代わりにfsを触れないなどの制限がある。
そこでManaged VMにするとVMの管理をユーザーが行う必要がある代わりにそれらの制限を取っ払える。
さらにCustom RuntimeにするとVM自体をユーザーが定義したものを使用できる。

Custom RuntimeまでやるともはやGCEでやるのとほぼ同じ環境が手に入れられますね。スケーリング周りを引き続き面倒見てくれるので、この辺とリクエストのハンドリング周りの自由度で使い分ける感じでしょうか。


ryoji_ishii

システムソリューション部。 休日も何かしら開発したりしてます。JavaScript、Node.js、Python、Goなどなど。あとボドゲ。