やっぱり AppEngine ja night #3 聴講録

[やっぱり AppEngine ja night #3](https://gaeja.connpass.com/event/90133/)で聞いた発表のメモです。

## Scalingの設定について by @sinmetal さん
[発表資料](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.p)

### GAE の概要
[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_40)

- GCPでは1プロジェクトに1アプリ作成できる
    - `アプリ`の下に`サービス`、その下に`バージョン`
    - さらにその下にバージョニングされた`インスタンス`
- 最初からブルー・グリーンデプロイの仕組みが提供されている

- サービスごとにカスタムドメインも可能。
    - [スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_8)

### GAE のアーキテクチャ
スケーリングの概要をアーキテクチャ図から見る

[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_22)

- **GoogleFrontend**はロードバランサ。
    - 世界各国にある巨大なフロント部分。
    - `AppEngine Frontend` にリクエストをさばく。
- **Pending Requests Queue** にフロントエンドからのリクエストが貯まる
    - そこから `AppServer` にリクエストが行く。
        - `AppServer` というレイヤーで自分が書いたGAEアプリケーションが動く
        - スケールするのはこの `AppServer` の部分.
    - この`Queue`の状態でスケーリングが調整される


### スケーリング設定について
[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g89aa0d3d3_0_1)
基本的に勝手にスケールする

- Automati Scaling
    - デフォルト設定
- BasicScaling
    - 最大数を事前に決めておくタイプ
- ManualScaling
    - デプロイ時に指定した数のインスタンスが常時起動する
    - 決め打ち設定

**フロントエンド向けかバックエンド向けか**
[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3c55c97dfa_0_3)

- フロントエンドとバックエンド用と大きく分かれる。
    - フロントエンドはエンドユーザーのリクエストを受け取る系。
    - バックエンドはバッチ処理などを担当する
- `Automatic` はフロントエンド向け
- `Basic`, `Manual` はバックエンド向け


### Automatic Scaling の設定について
[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_94)

#### 新しく追加された設定項目

```
target_cpu_utilization: 0.6 # default value
target_throughput_utilization: 0.6 # default value
max_instances: 5
min_instances: 0
```

- 最大インスタンス数の設定が追加
    - `max_instances`
- 最小インスタンス数の設定が追加
    - `min_instances` 
    - [スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_140)
    - ずっとたちあがりぱなしのインスタンス数
- 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
```

- レジデントインスタンスが削除された
    - [スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_124)
    - もともと`レジデントインスタンス`というのがあった
        - 常に待機しているインスタンス
    - スケールして増えるのが`ダイナミックインスタンス`
    - しかしレジデントが削除されたため、`ダイナミックインスタンス`のみになった
- レジデントインスタンスの削除に合わせて `min_idle_instances` の設定の意味が変わった。
    - [スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_153)
    - もともとはレジデントインスタンスの数を指定するものだった
    - `ウォームアップリクエスト`が終わったタイミングで、指定した数を予約してくれる、という意味なった。

### インスタンス数の設定について
- `min_insntace: 5`, `min_idle_instane: 3` のとき
    - リクエストを処理するインスタンスが５つ
    - warmup をすませたインスタンスは３つ予約されてプールされる
    - `build instances` は計8つなので、その分課金される
    - ５つで処理してさばききれないと、のこりの3つがスッと入ってくる。
- `min idle instances`  は warmup機能と必ず併用
    - ユーザーからのリクエストの前にwarmupリクエストが飛ばされる

#### min_idle_instances の動作についての推測
[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3c590e4bc1_3_12)

- ドキュメントに未記載なので確定情報ではない
    - 動作を観察していると, `idle_instances` はずっと放置していると開放される動作になっているようだ

### pending latency について
[スライド](https://docs.google.com/presentation/d/1jGfHJ6PeycVrwq8mbN1Evk1hQ-_GaXxlrIXM-Ti96dw/edit#slide=id.g3be15ddec3_0_117)
`min`, `max` をそれぞれ指定する

- `Pending Requests Queue` で既存のインスタンスがたりないときに留まる時間。
    - 少なくとも待つ時間
    - `Max Pending` は我慢できる最大時間。
    - これを超えると、新しいインスタンスが立ち上がる。

- より詳しい記事を Qiita に書いた
    - https://qiita.com/sinmetal/items/017e7aa395ff459fca7c

### 質疑応答
- 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 さん
[発表資料](https://speakerdeck.com/vvakame/datastore-is-pretty-good)
### Datastore の種類について
[スライド](https://speakerdeck.com/vvakame/datastore-is-pretty-good?slide=11)

- Datastore には `AppEngine` と `Cloud Datastore` 用の2種類の口があいている。
    - AppEngine は StandardEnvironment からのアクセスに限定される。
        - 昔からある
    - Cloud Datastore は 任意のサーバーからアクセスできる。
        - 新しくできた
- Cloud Datastore 側がたまにトラブっていることがある。
    - Datastore の RPCのエンドポイントが2系統に分かれている。
    - AppEngine のほうは枯れているが、Cloudのほうがたまにリクエストが詰まってトラブっているようだ。

### 互換性
- 動作の互換性は AppEngine / Cloud Datastore どちらも同じ
    - 裏の実装は同じ
    - 知見や設計は9割以上使える。

- よってラッパーを作った。
    - 新しいほう(Cloud Datastore API)に寄せた
    - [goon](https://github.com/mjibson/goon)ユーザーのために[boom](https://github.com/mercari/datastore/tree/master/boom)という似たものも用意した

- 大体の機能は [Client interface](https://github.com/mercari/datastore/blob/master/interfaces.go) にある
    - `FromContext` で AppEngine/CloudDS で分岐したものが返ってくる。

#### AppEngine との互換性について注意
[スライド](https://speakerdeck.com/vvakame/datastore-is-pretty-good?slide=21)

- `datastore: ,flatten` タグの存在。
    - StructをGAEのDatastoreに合うよう書き換える。

- Cloud Datastore はエンティティの入れ子が可能。
    - [スライド](https://speakerdeck.com/vvakame/datastore-is-pretty-good?slide=23)
    - flatten タグを入れると、AppEngine と同じようにフラットにする。

### 安定しているか？
- 以下で本場可動実績あり
    1. メルカリアッテ
    2. メルカリKYCサービス(運用カスタマー向け)
    3. 技術書典のサイト
- バグ
    - 1件の報告あり
    - 使用頻度から見て安定しているはず。

- GCPUGのslackに常駐しているので、質問歓迎
    - 作者なので、すべてを把握している
    - 他人がつまずく箇所がわからない
        - 質問がよく来る部分がわかれば、例やドキュメントを厚くすることができる

### その他
- GitHub star くれるととても嬉しい
- コントリビューション歓迎
- ブログでの感想歓迎
- メルカリ社内では spanner が優勢になってきて datastore の立場が狭くなってきたとのこと


----


## Java 8 ランタイム以降のサンドボックスと gVisor by @apstndb さん
[発表資料](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit)

### 共有インフラの課題。
[スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c5f37a3b1_0_40)

- 悪意のあるユーザーのコードをいかに防ぐか
- 理論上はサンドボックスがないとAppEngineのような PaaS サービスを提供できない。
    - GAE の従来のサンドボックスがなにか？というのは謎だった。

### 既存のサンドボックスには問題
[スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c5f37a3b1_0_68)

- Dockerコンテナはリソースは隔離できるがカーネルを共有しているのでサンドボックスではない。
- seccomp なども事前にシステムコールを何使うか知ってないときつい。
- VMはサンドボックスとしては十分
    - リソース利用効率は悪い
    - サーバーレス向きではない。

### gVisor as Serverless Sandbox
[スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c5f37a3b1_0_74)

- [Sentry](https://godoc.org/github.com/google/gvisor/pkg/sentry)
    - Linux システムコールのGo実装
        - Sentry は 20万行のGo
    - goroutine を駆使しており、Go言語のシステム言語的な側面が強く生かされているとのこと
- [gofer](https://godoc.org/github.com/google/gvisor/pkg/sentry/fs/gofer)
    - 9P(Plan9のプロトコル)プロトコル。 
- [netstack](https://github.com/google/netstack)
    - Goで実装された、ユーザーランドで動くTCP/IP実装

----

- gVisor の動作(のごく一部)
    - システムコールを ptrace / KVM でフックして Sentry にバイパス。
        - ファイルアクセスとネットワークアクセス以外は、Sentryで処理している。
    - ファイルアクセスする
        - Gofer を使う
    - ネットワーク
        - netstack でTCP/IP処理。

### 従来のGAE/Javaのサンドボックス
[スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c5f37a3b1_0_140)

- GAE/JavaのサンドボックスはGAEの不便さの象徴だった。
    - しかしJava/8で大きく改善した
    - java8コンテナが一番進化したサンドボックス
- サンドボックス由来の制限がなくなった。
    - urlfetch
    - ローカルファイルアクセスの制限
    - etc..

- 既存のGAE/JavaにはJRE由来のセキュリティ上の不具合があった
    - [スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c51f50e3b_0_92)
    - セキュリティホールを発見した会社がGAE/Javaのアーキテクチャを解析した
        - [スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c57fe955d_0_17)

- 既存のサンドボックスでは不十分であると悟ったGoogleは新たに Go でサンドボックスを開発した → gVisor
    - [スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c5f37a3b1_0_0)

- よって gVisor は GAE/Java のサンドボックスの子孫である。
    - [スライド](https://docs.google.com/presentation/d/1GKkv6GAelTwieGThqnX28f6dc7fXKwDPuypRzCYT_Zk/edit#slide=id.g3c57fe955d_0_43)

### gVisor と OCIイメージ
[FTL(faster than light)](https://github.com/GoogleCloudPlatform/runtimes-common/tree/master/ftl)
[OCI(open container initiative)](https://www.opencontainers.org/)

- 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 について理解が非常に深まった