この資料について
- GCPUG Shonan vol.7での発表資料です
自己紹介
- 武市融紀
- 株式会社ノハナ
- サーバーサイドエンジニア
- GCP Next 2016で弊社事例について発表してきました
ノハナ
- 株式会社ミクシィの社内公募制度による新規事業が子会社化
- 月一冊無料でフォトブックが作成できるアプリ
- 累計150万ユーザー
- 写真累計アップロード 1.5億枚
Parse.com
- 老舗Mobile向けBaaS
- REST APIによるデータのCRUD
- バックエンドのMongoDBに永続化
- ユーザー認証
- ファイルストレージ
- プッシュ通知送信機能
移行のきっかけ
- Parse.comの突然の終了宣告
- 来年1月までに移行を終えないとサービスが\(^o^)/オワル
- 終了宣言以前から移行の話は出ていた
- 月末に度々不安定になっていた
GCPを選んだ理由
- コストパフォーマンス
- GCE料金が利用期間に応じて勝手に割引される
- Cloud StorageがS3より安い
- Googleの長年の技術/ノウハウが投入されている
- Googleのクラウドへの投資額
- 成長が期待できる
- データ解析系サービスの拡充に期待
- 画像データの資産を活かしたい
移行の全貌
- DB
- MongoDB (Replica set)
- API Server
-
parse-server (node.js + express)
- iOS / Androidアプリ向けのエンドポイント
-
parse-server (node.js + express)
- CloudCode
- parse-serverのwebhookとして機能するサーバー (node.js + express)
- parse-serverでレコード作成/更新時にリクエストが飛んでくる
- 保存前のvalidationなどを行う
- Cloud Functionsのような機能
- 名前もそのまま"Cloud Function"
- Push通知送信機能
- 全ユーザに対する予約プッシュ機能
- 開封通知の集計
- 写真ファイルの移行
- 1.5億枚(平均1.5MB)の写真ファイルをParse.comのストレージから自社ストレージへ移行
DBとAPI serverの構成の検討
- 今回の移行はMongoDB一択
- データ移行ツールがMongoDBしかサポートされていない
- DBはGCEに置くしか無い
- 検討したAPI serverの構成
- GAE Standard Env
- GAE Flexible Env
- GKE
- GCE instance group
GAE Standard Envの場合
- GCEとはnetwork的に分断されている
- mongoにprivate IPでアクセスできない
- 出口IPが決まらない
- mongoへのアクセスをIPアドレスで制限できない...
- connection poolを作れない
- Socket APIだと毎回mongoとのconnectionを確立しにいくためオーバーヘッドが大きい
- SEのStatelessな設計は爆速スケールとのトレードオフなので仕方ない...
- connection poolingを行う別のserviceをFEで作ってgRPCで会話?
- オーバーエンジニアリング感が...
- Socket APIだと毎回mongoとのconnectionを確立しにいくためオーバーヘッドが大きい
- スケーラビリティの対価が大きすぎるため断念
GAE Flexible Envの場合
- 裏側はGCE with Docker
- Private IPでmongoと喋れる
- serverがstateを持てる
- まだGAじゃないので(ry
GKE
- Docker + コンテナオーケストレーション層
- API serverもMongoDBも載せてしまえる
- 習得時間掛けれなく断念
GCE instance group
- 1 instance group + 1 LBのシンプルな構成
- これになりました
MongoDB
MongoDBのinstance構成
- GCE + persistent SSD
- IOPS 15,000 & 240MB/s 出るのでRAID組む必要なかった
- replicaを各zoneに配置
柔軟なinstance size
- Custom instance typeのお陰でscale up (≠scale out)を細かな粒度で行える
- shardしなくて済んだ
- stopすればinstanceを作成し直すことなくサイズを変更できる
- 最初はオーバープロビジョニングして後々下げていく戦略が取れる
Live migration
- 本番DBで経験したが問題なし
- Operationsに表示されなければ本当に気が付かない
- Local SSDを持つinstanceではCPU使用率が大きく上昇した
- StackdriverのGCE MonitoringベースのCPU使用率が上昇しアラートが飛んだ
- 物理host間でSSDの中身コピーが走ってる?
- 実際に性能が低下したかどうかまでは確認できず
Disk snapshotによるバックアップ
- 1時間に1回backup replicaを切り離してdisk snapshotを作成
- 弊社の規模だと大体5分ぐらいで作成できる
- 500以上の差分があってもリストアのスピードが遅くはならない
- コストが低く抑えれる
- 単価はGCS相当 ($26/TB/mth) と安い
- 差分バックアップの実データ量で計算される
- 実際のデータ増分よりも差分バックアップのサイズは10倍程度大きい
- ブロック単位でのdiffを取ってる?
- snapshotはglobalにreplicateされる
- DBのregion移動の際に重宝
MongoDBのネットワーク構成
- Parse.comからの接続を受けるためPublic IPを振っている
- Public IPをfirewall ruleに登録
- 残念ながらタグでの指定は出来ない
- Public IPをfirewall ruleに登録
- Replica間の通信はPublic IPで行っている
- ドメイン名を元にReplica間で通信を行うため
- 通信はgoogleの域内で閉じておりワンホップでアクセスできる
- 課金対象にはなってしまう
- hostnameの書き換え
- DHCPでIPを取得するタイミングでhostnameを上書き
- set-hostnameに細工
API Server
API Serverの構成
- 1LB + 1instance group
- parse-serverとwebhook serverが同一instanceに同居
- 2LB + 2instance group構成だとlatency5倍ぐらいになり諦めた
- public LBだとmicroserviceライクなアーキテクチャは厳しい
- internal LBがGAになったら再度検討したい
- mongoへはprivate IPで接続
- /etc/hostsに追記
- mongoのreplica追加の際にはデプロイにより更新
- もう少しスマートにしたい...
- /etc/hostsに追記
- firewall
- LBのpublic IPからのport 80アクセスのみ許可
- Cloud Shellを使うためにGoogleの出口IPからのport22へのアクセスを許可
- Cloud Shellの出口IPレンジは限定されて欲しい...
プロビジョニング
- packerでimageを作成
- googlecompute builder
- NVMe向けimage familyはサポートしてない (PR出したがちっともMergeされない...)
- image familyには対応してない
- ansible provisioner
- GCE instacne上で実行するにはbuilderのoptionにuse_internal: trueを追加
- googlecompute builder
起動時間
-
systemd-analyze
での分析- systemd起動後はnetworkのonline待ちが5secと最長
- 平均20secほどで起動し終わるのでinstance groupのinitial delayは30secに設定
- systemd unitファイルにAfter=network.targetを指定
- onlineになったらserver processを起動するようにしている
デプロイ
- gcloud compute instance-groups recreate-instances
- rolling updateが早くGAになって欲しい...!
モニタリング
- Stackdriver agent
- CPU, mem, I/O など各種メトリクス
- process死活監視
- newrelicと併用
log周り
- Papertrail
- GCE上にElasticSearchを立てJSONを流している
- Stackdriver Loggingは最初にスキーマが決められてしまい柔軟性に欠ける...
instance group
- スケールしきい値はほぼデフォルトで運用
- CPU負荷をスケール基準
- Auto scalerの挙動が面白い
- 急激な負荷が来ると一気に10台ぐらい増えたりする
LB
- HTTPS load balancing
- TLSはLB終端
- セキュリティ要件次第ではinstance終端させた方が良い場合も
- health check
- parse-serverに専用のendpointを作成
- LBの作成がものすごく早い
- 本当に10secぐらいで作成が完了する
- ウォーミングアップ無しで1MQPS捌けちゃうらしい...
Push通知
GaurunをGCE上で動かしている
- GCE + instance group
- workerをスケールできるようにしている
- 間にCloud PubSubを挟んでいる
- 予約プッシュを送る際のpersistentなqueueとして利用
- Subscriberから受け取ったdevicetokenをgaurunに流している
GAE SEによる開封通知の受信
- 開封通知のような急激なトラフィックを捌くのにGAE SEは最適
- 爆速スケールの恩恵
- 開封データはDatastoreに保存
- BigQueryにexportして解析
写真の移行
写真の移行
- GCSを写真ストレージとして活用
- nearlineに移行することも検討
- オリジナルサイズの画像はフォトブック作成時しか使用されないため
- nearlineに移行することも検討
- Cloud PubSub
- SubscriberがParseのストレージから写真をDLしGCSにUL
移行した感想
GCEが洗練されている
- instanceの立ち上げが早い
- 開発時にストレスを感じない
- 8core & 500GB ($290/mth)で最高帯域が確保できる安心感
- Network: 16Gbps
- Disk: 15,000 IOPS & 240MB/s
- これだけ出れば大抵のケースでは十分
- Metadata serverの利便性
- 追加したssh keyが各instanceに反映される
- Regionを跨ぐKVSなのでconfig serverとして使える
-
?wait_for_change=true
による更新通知
-
- instance名を決められる
- 管理しやすい
- 自動的に割り振られるドメイン名でアクセスできる
- [instance-name].c.[project-id].internal
- IPをいちいち調べに行く必要が無く便利
開発者フレンドリー
- web consoleがサクサク動いてくれる
- loadingで待たされることなくストレスを感じない
- instance以外のリソースの作成も早いように感じる
- APIがきれいに設計されていてわかりやすい
- ドキュメントが充実している
- 知りたいことは大体公式ドキュメントに書いてあった
- 必要に応じてwhite paperや論文なども
要望
- IAM周りやその他サービスの拡充に期待
- AWSにあってGCPにない機能はまだまだ多い
- シンプルさや使い勝手の良さは維持して欲しい
まとめ
- 基本機能が洗練されておりスムーズな移行が実現できた
- パフォーマンスに関しての苦労は(今のところ)ない
- 謎技術に驚くことしばしば
- 欲しい機能が用意されておらず自分たちで作らないといけない部分もある