やっぱり AppEngine ja night #3で聞いた発表のメモです。
Scalingの設定について by @sinmetal さん
GAE の概要
-
GCPでは1プロジェクトに1アプリ作成できる
-
アプリ
の下にサービス
、その下にバージョン
- さらにその下にバージョニングされた
インスタンス
-
-
最初からブルー・グリーンデプロイの仕組みが提供されている
-
サービスごとにカスタムドメインも可能。
GAE のアーキテクチャ
スケーリングの概要をアーキテクチャ図から見る
-
GoogleFrontendはロードバランサ。
- 世界各国にある巨大なフロント部分。
-
AppEngine Frontend
にリクエストをさばく。
-
Pending Requests Queue にフロントエンドからのリクエストが貯まる
- そこから
AppServer
にリクエストが行く。-
AppServer
というレイヤーで自分が書いたGAEアプリケーションが動く - スケールするのはこの
AppServer
の部分.
-
- この
Queue
の状態でスケーリングが調整される
- そこから
スケーリング設定について
スライド
基本的に勝手にスケールする
- Automati Scaling
- デフォルト設定
- BasicScaling
- 最大数を事前に決めておくタイプ
- ManualScaling
- デプロイ時に指定した数のインスタンスが常時起動する
- 決め打ち設定
フロントエンド向けかバックエンド向けか
スライド
- フロントエンドとバックエンド用と大きく分かれる。
- フロントエンドはエンドユーザーのリクエストを受け取る系。
- バックエンドはバッチ処理などを担当する
-
Automatic
はフロントエンド向け -
Basic
,Manual
はバックエンド向け
Automatic Scaling の設定について
新しく追加された設定項目
target_cpu_utilization: 0.6 # default value
target_throughput_utilization: 0.6 # default value
max_instances: 5
min_instances: 0
- 最大インスタンス数の設定が追加
max_instances
- 最小インスタンス数の設定が追加
min_instances
- スライド
- ずっとたちあがりぱなしのインスタンス数
- 1インスタンスでどれくらいリクエストをさばくのかという設定が追加
target_throughput_utilization
- もともと
max_concurent_requests
という名前だった(?)
- CPU使用率がどれくらいで超えたらスケールするか、という設定が追加された。
target_cpu_utilization
既存の設定値について
min_idle_instances: 0
max_idle_instances: automatic # default value
min_pending_latency: 30ms # default value
max_pending_latency: automatic
max_concurrent_requests: 80
- レジデントインスタンスが削除された
- スライド
- もともと
レジデントインスタンス
というのがあった- 常に待機しているインスタンス
- スケールして増えるのが
ダイナミックインスタンス
- しかしレジデントが削除されたため、
ダイナミックインスタンス
のみになった
- レジデントインスタンスの削除に合わせて
min_idle_instances
の設定の意味が変わった。- スライド
- もともとはレジデントインスタンスの数を指定するものだった
-
ウォームアップリクエスト
が終わったタイミングで、指定した数を予約してくれる、という意味なった。
インスタンス数の設定について
-
min_insntace: 5
,min_idle_instane: 3
のとき- リクエストを処理するインスタンスが5つ
- warmup をすませたインスタンスは3つ予約されてプールされる
-
build instances
は計8つなので、その分課金される - 5つで処理してさばききれないと、のこりの3つがスッと入ってくる。
-
min idle instances
は warmup機能と必ず併用- ユーザーからのリクエストの前にwarmupリクエストが飛ばされる
min_idle_instances の動作についての推測
- ドキュメントに未記載なので確定情報ではない
- 動作を観察していると,
idle_instances
はずっと放置していると開放される動作になっているようだ
- 動作を観察していると,
pending latency について
スライド
min
, max
をそれぞれ指定する
-
Pending Requests Queue
で既存のインスタンスがたりないときに留まる時間。- 少なくとも待つ時間
-
Max Pending
は我慢できる最大時間。 - これを超えると、新しいインスタンスが立ち上がる。
-
より詳しい記事を Qiita に書いた
質疑応答
- Q: queue の設定と cpu の設定、どちらが優先されるか?
- A: デフォルトで設定された値がまず適応される。
課金額のこまかい調整したいときは、max insntace, cpu utilization を設定する。
基本デフォルトで automatic scaling で問題ないはず。
- Q: 起動に3sec かかるGAEアプリケーションがあるのだが、まったくリクエストこないときに大量のアクセスが来たらどうしよう?
- A: 瞬間的に大量のリクエストがくると、AppEngineはアホみたいに大量にインスタンスを立てるので、min instance, min idle instance の設定しておくのが安牌。
- Q: min_idle_instances, min_instance のそれぞれのメリットは?
- A: リクエストが来ないときに勝手に解放されるのが idle_instances。
ドキュメント未記載なので、これは推測だが AppEngine はアプリ側のリクエストの傾向を学習して、インスタンスのプール状況を変えている節がある。
たとえば毎日8時にアクセスが多くなるという傾向があるとき、AppEngine側はその時間でidleインスタンスを立ち上げている節がある。
なので、課金額に倒すのか、安定稼働に倒すのかで変わるだろうと思う。
安全可動ならmin_instances
で常時インスタンスを起動しておく。
- Q: 調整のコツは?
- A: 究極的にはデフォルトのパラメータで問題ないはず。
アプリ全体のアーキテクチャがAppEngineに寄せていればなおさら。
なので、課金額なのか安定稼働なのか、スピンアップの時間などで調整するくらいだと思う。
go.mercari.io/datastore を布教しにきました! by @vvakame さん
Datastore の種類について
- Datastore には
AppEngine
とCloud Datastore
用の2種類の口があいている。- AppEngine は StandardEnvironment からのアクセスに限定される。
- 昔からある
- Cloud Datastore は 任意のサーバーからアクセスできる。
- 新しくできた
- AppEngine は StandardEnvironment からのアクセスに限定される。
- Cloud Datastore 側がたまにトラブっていることがある。
- Datastore の RPCのエンドポイントが2系統に分かれている。
- AppEngine のほうは枯れているが、Cloudのほうがたまにリクエストが詰まってトラブっているようだ。
互換性
-
動作の互換性は AppEngine / Cloud Datastore どちらも同じ
- 裏の実装は同じ
- 知見や設計は9割以上使える。
-
よってラッパーを作った。
-
大体の機能は Client interface にある
-
FromContext
で AppEngine/CloudDS で分岐したものが返ってくる。
-
AppEngine との互換性について注意
-
datastore: ,flatten
タグの存在。- StructをGAEのDatastoreに合うよう書き換える。
-
Cloud Datastore はエンティティの入れ子が可能。
- スライド
- flatten タグを入れると、AppEngine と同じようにフラットにする。
安定しているか?
-
以下で本場可動実績あり
- メルカリアッテ
- メルカリKYCサービス(運用カスタマー向け)
- 技術書典のサイト
-
バグ
- 1件の報告あり
- 使用頻度から見て安定しているはず。
-
GCPUGのslackに常駐しているので、質問歓迎
- 作者なので、すべてを把握している
- 他人がつまずく箇所がわからない
- 質問がよく来る部分がわかれば、例やドキュメントを厚くすることができる
その他
- GitHub star くれるととても嬉しい
- コントリビューション歓迎
- ブログでの感想歓迎
- メルカリ社内では spanner が優勢になってきて datastore の立場が狭くなってきたとのこと
Java 8 ランタイム以降のサンドボックスと gVisor by @apstndb さん
共有インフラの課題。
- 悪意のあるユーザーのコードをいかに防ぐか
- 理論上はサンドボックスがないとAppEngineのような PaaS サービスを提供できない。
- GAE の従来のサンドボックスがなにか?というのは謎だった。
既存のサンドボックスには問題
- Dockerコンテナはリソースは隔離できるがカーネルを共有しているのでサンドボックスではない。
- seccomp なども事前にシステムコールを何使うか知ってないときつい。
- VMはサンドボックスとしては十分
- リソース利用効率は悪い
- サーバーレス向きではない。
gVisor as Serverless Sandbox
-
Sentry
- Linux システムコールのGo実装
- Sentry は 20万行のGo
- goroutine を駆使しており、Go言語のシステム言語的な側面が強く生かされているとのこと
- Linux システムコールのGo実装
-
gofer
- 9P(Plan9のプロトコル)プロトコル。
-
netstack
- Goで実装された、ユーザーランドで動くTCP/IP実装
- gVisor の動作(のごく一部)
- システムコールを ptrace / KVM でフックして Sentry にバイパス。
- ファイルアクセスとネットワークアクセス以外は、Sentryで処理している。
- ファイルアクセスする
- Gofer を使う
- ネットワーク
- netstack でTCP/IP処理。
- システムコールを ptrace / KVM でフックして Sentry にバイパス。
従来のGAE/Javaのサンドボックス
-
GAE/JavaのサンドボックスはGAEの不便さの象徴だった。
- しかしJava/8で大きく改善した
- java8コンテナが一番進化したサンドボックス
-
サンドボックス由来の制限がなくなった。
- urlfetch
- ローカルファイルアクセスの制限
- etc..
-
既存のGAE/JavaにはJRE由来のセキュリティ上の不具合があった
-
既存のサンドボックスでは不十分であると悟ったGoogleは新たに Go でサンドボックスを開発した → gVisor
-
よって gVisor は GAE/Java のサンドボックスの子孫である。
gVisor と OCIイメージ
FTL(faster than light)
OCI(open container initiative)
- gVisor サンドボックスであれば、OCIイメージが作れれば、GAEで動くはず。
- GAE/Node でFTLが動いている?
- FTLでOCIイメージをビルドしていると予想
- FTLはGoogle Cloud Registory にイメージ登録できる。
- gVisor/FTLが両方OCIイメージになっていることが重要。
- OCIを中心に新しいサンドボックスのアーキテクチャが作られた。
その他
- Flexible Env は gVisor で重要度が減った
- GAE/SEの未来は明るい
質疑応答
- Q: gVisor で GAE/Rust をつくれる?
- A: Sentry はすべてのシステムコールが実装されているわけではない。
Googleが実行するために十分だと判断したものしか追加されない。
よって Rust の実行に必要なシステムコールが足りない場合は難しい。
また、ソースコードのビルドラインはGoogleが許可したものしか動かせないだろう。
なので、その条件が満たされない限りはGAE/FEを使うことになるだろう。
※: コメント欄に補足をいただいたので、そちらもお読みください。
- Q: FTLをgoogle以外が使うか?
- A: ありえると考える。
これはdocker build
を使わずにdocker image
を作れる、ということを考えると割と汎用的。
ソースからイメージを作りたい、つまりPaaS的な処理はFTLを使うほうが楽。
GAEと同じ挙動をするものを作れるかもしれない。
感想
- gVisor について理解が非常に深まった