Slide 1

Slide 1 text

はじめまして

Slide 2

Slide 2 text

2 REALITY株式会社 エンジニア Oda Daisuke ● 主なお仕事 ○ DevOps改善の取り組み ○ グロース系の施策開発 ○ パフォーマンス改善

Slide 3

Slide 3 text

REALITYアプリのメンテナンスなしでの 機能リリースを実現する、Istio導入と B/Gデプロイ実現の取り組み REALITY株式会社 小田 大輔

Slide 4

Slide 4 text

おしながき 1. サービスのご紹介 2. サーバの機能リリースについて 3. なぜメンテナンスが必要だったか 4. BlueGreenデプロイメントによる解決 5. 導入の苦労 6. 得られた効果 7. 今後の課題・展望 8. まとめ 4

Slide 5

Slide 5 text

1. サービスのご紹介 2. サーバの機能リリースについて 3. なぜメンテナンスが必要だったか 4. BlueGreenデプロイメントによる解決 5. 導入の苦労 6. 得られた効果 7. 今後の課題・展望 8. まとめ 5

Slide 6

Slide 6 text

REALITYのご紹介 ● スマホひとつでアバター作成、ライブ配信などを楽しめるアプリ ● 12言語対応で63の地域で配信中 6

Slide 7

Slide 7 text

ユーザ数・DL数も成長中 7

Slide 8

Slide 8 text

リクエスト数もストレージも成長中 8

Slide 9

Slide 9 text

9

Slide 10

Slide 10 text

2. サーバの機能リリースについて 10

Slide 11

Slide 11 text

REALITYでは 毎週水曜日 14:00〜15:00 定期メンテナンスをしていました 11

Slide 12

Slide 12 text

1. 機能のリリース a. 中程度以上の機能はメンテナンス中にリリースすることが多い 2. インフラリソース調整 a. Google Kubernetes Engineクラスタのアップグレード b. CloudSQLのメンテナンスウィンドウなど 3. 運用系 a. 新規ガチャやワールドのリリース &動作確認 12 メンテナンス中に何をしている?

Slide 13

Slide 13 text

1. 機能のリリース a. 中程度以上の機能はメンテナンスにリリースすることが多い 2. インフラリソース調整 a. CloudSQLのメンテナンスウィンドウなど b. Google Kubernetes Engineクラスタのアップグレード i. サージアップグレード (同時更新台数)設定で、無停止更新も可能ではある 3. 運用系 a. 新規ガチャやワールドのリリース &動作確認 13 メンテナンス中に何をしている?

Slide 14

Slide 14 text

1. 機能のリリース a. 中程度以上の機能はメンテナンスにリリースすることが多い 2. インフラリソース調整 a. CloudSQLのメンテナンスウィンドウなど b. Google Kubernetes Engineクラスタのアップグレード 3. 運用系 a. 新規ガチャやワールドのリリース &動作確認 14 メンテナンス中に何をしている?

Slide 15

Slide 15 text

● ユーザ視点 ○ 1時間の間、全ての機能を利用できなくなる ○ アプリ利用中の場合は全ての操作が強制終了し、メンテナンス画面に飛ばされる ● 運営側視点 ○ 1時間ユーザがいなくなることによる売上の損失 ○ ユーザへのお知らせやチーム間の連携コストなど ○ 前日のメンテナンス作戦会議やメンテナンス直前の準備 MTGなど、シンプルに準備の時間がかかる 15 メンテナンスをすると何が起こるか

Slide 16

Slide 16 text

3. なぜメンテナンスが必要だったか 16

Slide 17

Slide 17 text

Q. なぜメンテナンスが必要だったか ● A1. メンテナンス中にしか新機能の動作確認ができなかった ○ 一部は開発者限定の動作確認モードを使えることができる ○ 全ての機能に限定公開モードを実装するのは現実的ではない ● A2. マイクロサービス間の生合成担保のため ○ 複数マイクロサービスを同時にリリースすることができない ○ 片方だけ先に出ると壊れてしまうような変更はメンテナンスでリリース ● A3. インフラリソースの更新で必要 ○ GKEクラスタのアップグレード ○ DBのアップグレードなど 17

Slide 18

Slide 18 text

Q. なぜメンテナンスが必要だったか ● A1. メンテナンス中にしか新機能の動作確認ができなかったから ○ 一部は開発者限定の動作確認モードを使えることができる ○ 全ての機能に限定公開モードを実装するのは現実的ではない ● A2. マイクロサービス間の整合性担保のため ○ 複数マイクロサービスを同時にリリースする仕組みがない。 ○ 片方だけ先に出ると壊れてしまうような変更はメンテナンスでリリース ● A3. インフラリソースの更新で必要 ○ GKEクラスタのアップグレード ○ DBのアップグレードなど 18

Slide 19

Slide 19 text

Q. なぜメンテナンスが必要だったか ● A1. メンテナンス中にしか新機能の動作確認ができなかったから ○ 一部は開発者限定の動作確認モードを使えることができる ○ 全ての機能に限定公開モードを実装するのは現実的ではない ● A2. マイクロサービス間の生合成担保のため ○ 複数マイクロサービスを同時にリリースすることができない ○ 片方だけ先に出ると壊れてしまうような変更はメンテナンスでリリース ● A3. インフラリソースの更新で必要 ○ GKEクラスタのアップグレード ○ DBのアップグレードなど 19

Slide 20

Slide 20 text

Q. なぜメンテナンスが必要だったか ● A1. メンテナンス中にしか新機能の動作確認ができなかったから 20 ↑こちらのテーマを重点的に話していきます

Slide 21

Slide 21 text

REALITYのサーバアーキテクチャ 21

Slide 22

Slide 22 text

REALITYのサーバアーキテクチャ 22

Slide 23

Slide 23 text

改善前のリリースフロー 23 画像引用 https://argo-cd.readthedocs.io ArgoCDで、更新のあるサーバーだけ新しいイメージの Podと入れ替える

Slide 24

Slide 24 text

改善前のリリースフロー 24 画像引用 https://argo-cd.readthedocs.io/en/stable/ ここでデプロイした瞬間、本番に反映される。 本番特有の問題が起きた際ユーザ影響が発生。

Slide 25

Slide 25 text

4. リリース時の問題点、 BlueGreenデプロイメントで 解決しました 25

Slide 26

Slide 26 text

理想とするBlueGreenデプロイメント.1 26 内部のユーザのみがアクセス可能 (Green環境) 通常のユーザのアクセス (Blue環境)

Slide 27

Slide 27 text

理想とするBlueGreenデプロイメント.2 27 一般ユーザのアクセスを Greenに移行

Slide 28

Slide 28 text

実現したい要件 ● 前提 ○ stable環境 = ユーザの目に触れる環境 ○ preview環境 = 動作確認で使う運営限定環境 28

Slide 29

Slide 29 text

実現したい要件 ● 前提 ○ stable環境 = ユーザの目に触れる環境 ○ preview環境 ● リリース対象マイクロサービスだけ、preview環境を適用できるように ● preview環境への接続は、可能な限り少ない手間で ● previewとstableの切り替えも同様、単純な手順で ● 事故が起きた時はすぐロールバックできるように 29

Slide 30

Slide 30 text

[構想編]どのような 構成でBlueGreen デプロイを実現するか ● デプロイメント部分 ● トラフィック制御部分 30

Slide 31

Slide 31 text

デプロイメント部分 ● 役割 ○ preview環境へのデプロイ ○ previewとstable環境の切り替え ● 今回は Argo Rollouts を採用 ○ ArgoCDとの親和性が高い ○ Web UI上でArgo Rolloutsの操作ができる 31

Slide 32

Slide 32 text

Argo Rollouts とは ● BlueGreenデプロイやカナリアリリースなどのプログレッシブデプロイをサポート している、Kubernetesのカスタムコントローラ ● 何ができるの? ○ k8sのDeploymentの仕組みを拡張してプログレッシブデプロイが行える ○ Deploymentの代替として動かすものです。 32

Slide 33

Slide 33 text

トラフィック制御部分 ● 役割 ○ 特定のリクエストヘッダなどに応じて、任意の環境へ接続先を振り分けるルータ ● k8sの場合、Istioを使うことが多い ● Google Kubernetes Engineでホストしているので、GCPが提供しているマ ネージドサービスメッシュであるAnthos Service Meshを採用 ○ 内部でIstioを利用 33

Slide 34

Slide 34 text

Kubernetes Service Istioとは ● Istioは、マイクロサービス同士の通信を一元管理・監視するためのツール ○ いわゆるサービスメッシュ ○ 各Podにプロキシコンテナ ● マイクロサービスの通信ルートやポリシーを制御 ○ 例えばBlueGreenのトラフィック制御にも使える 34 Service A Pod Service B Pod Istioプロキシ Istioプロキシ Istio コントロールプレーン Cloud Load Balancing 内部通信

Slide 35

Slide 35 text

どのように実装したか 35

Slide 36

Slide 36 text

Anthos Service Meshをインストール ● GCPのガイドに従い、GKEクラスタにAnthos Service Meshをインストール ○ 以降の細かい手順は割愛 36 参照 https://cloud.google.com/service-mesh/docs/unified-install/install-anthos-service-mesh?hl=ja#install_anthos_service_mesh

Slide 37

Slide 37 text

Istio IngressGatewayをインストール 37 ● IngressGatewayの役割 ○ 外部からのトラフィックを LB経由で受付 ○ VirtualServiceのルーティング設定をもとに送信先の Serviceなどを決定 ○ 主にL7(HTTPなど)でルーティング

Slide 38

Slide 38 text

Istio IngressGatewayをインストール ● セットアップについて ○ GCPの公式Docsに沿って、専用のnamespaceにBackendConfigやIngress一式を反映 ○ namespace作成時、istio-injection=enabledで作成することで、各サービスのPod作成時に サイドカーコンテナ(プロキシ)が自動で注入される。 38

Slide 39

Slide 39 text

preview環境作成の下準備 1. DeploymentをArgo Rolloutsに置き換える a. まずは一つのマイクロサービスに導入 39

Slide 40

Slide 40 text

1. 2. HorizontalPodAutoscalerの対象ワークロードを切り替え a. 先ほど作成したRolloutに書き換えます preview環境作成の下準備 40

Slide 41

Slide 41 text

preview環境の作成 Anthos Service Mesh関連リソース一式を作成 1. Preview環境用のServiceを作成 a. 実態はKubernetesのService 41

Slide 42

Slide 42 text

preview環境の作成 1. 2. VirtualService a. Istio の機能 b. Header-basedルーティングで 42 トラフィック制御を行う

Slide 43

Slide 43 text

previewとstableの切り替え Argo Rollouts標準のダッシュボードを導入してGUIでできるようにしました 43

Slide 44

Slide 44 text

トラフィック制御の実装 ● サーバ側 ○ Gatewayサーバから内部のサーバにリクエストする際、クライアントのリクエストヘッダを継承す るようにしました。 ■ 内部サービス間の通信でも継承 44

Slide 45

Slide 45 text

トラフィック制御の実装 ● アプリ側 ○ 社内専用アプリで、BlueGreenデプロイメント用のリク エストヘッダを自由に on/offできる仕組みを作りました 45

Slide 46

Slide 46 text

BlueGreenデプロイメントアーキテクチャ 46 2. 内部のユーザのみがアクセス可能 (最終的にこちらがstableになる) 1. 通常のユーザのアクセス

Slide 47

Slide 47 text

5. 導入の工夫と苦労話 47

Slide 48

Slide 48 text

[導入時の工夫] Kubernetesマニフェスト ● 多数のマイクロサービスがあるため、共通して参照できるようにkustomizeの componentとしてワークロード一式を定義しました ● 利用する際は、それをインポートしてサービス特有のlocal-configを少し書き換 えるだけで済むように 48

Slide 49

Slide 49 text

49 共通設定をインポート

Slide 50

Slide 50 text

[苦労話1] ヘッダの引き継ぎが大変でした ● Go言語で対応 ● リクエストでトラフィック制御用のヘッダを受け取り、その値によって参照する環境 (preview or stable)を切り替えていた ● 内部のサーバ間通信の際も、クライアントから受け取ったトラフィック制御用ヘッダ を流用。 50

Slide 51

Slide 51 text

実装当初起きた問題点 ● リクエスト途中でクライアントの接続が切れた際、処理中の内部リクエストが全て中断 されてしまった。 ○ 高頻度で発生した ○ 本来はこれで正しい ↓どんな問題が起こる? ● Write系の処理で不整合が起こる可能性がある ○ つまりクライアントがリクエスト途中で切断しても、裏側の処理は atomicに完了してほしい 51

Slide 52

Slide 52 text

なぜこの問題が起きていたのか 52

Slide 53

Slide 53 text

当初はこのように実装.1 Requestが来るたびにhttp.Request.Context経由でcontextを生成 ※つまりrequest scopeなContext 53

Slide 54

Slide 54 text

当初の実装.2 別サーバにリクエストするとき、自前のhttp.RoundTripper内で1.のcontextからトラ フィック制御ヘッダをrequest headerの設定 ※middlewareのようなイメージ 54

Slide 55

Slide 55 text

当初の実装.3 2.をcontext.WithTimeout(1のctx, {時間})でラップしてリクエスト。 55

Slide 56

Slide 56 text

context canceledが起きていた原因 1. 内部サービスへのリクエストはcontext.Contextを継承した context.WithTimeoutで行っていた 2. context.WithTimeoutは親のcontextを継承してしまう 3. http.Request.Contextがキャンセルされると、その子のcontext.WithTimeout を使ったリクエストもキャンセルされてしまう。   =context canceledの伝播 ※Istio導入前は、context.Background()でグローバルコンテキストを使っていた。こ の場合はcancelが発生しないので今まで問題はなかった。 56

Slide 57

Slide 57 text

context.Backgroundを元にすることで解決 ● なぜこれで解決するのか ○ context.WithTimeoutは、受け取ったcontextを継承する ○ context.Background()はcancelが発生しないので、Background()を元にcontextを生 成すればOK 57

Slide 58

Slide 58 text

最終的なコードの要約 58 1. Requestが来るたびにcontext.Background経由で、トラフィック制御用の 値を持ったrequest scopedなcontextを生成。 2. 別サーバへのリクエスト時、http.RoundTripper内で1.のcontextからトラ フィック制御ヘッダを取得し、request headerに設定

Slide 59

Slide 59 text

[苦労話2] Anthos Service Mesh(ASM)のログが爆発 ● 既存のリクエストログに加え、ASMのリクエストログも吐き出されており、ログデー タ量が2倍になったことでログ料金が増えた ● Cloud Loggingログルータの設定で、ASMのログをGCPに取り込まないように することで解決 59

Slide 60

Slide 60 text

6. BlueGreenデプロイメントの 導入により得られた効果 60

Slide 61

Slide 61 text

今までメンテナンスに依存していた 作業が、メンテナンス不要で できるように 61 この成果により、

Slide 62

Slide 62 text

メンテナンス回数が激減した 62

Slide 63

Slide 63 text

メンテナンス回数が激減した 63 ※0回になってない理由は後述

Slide 64

Slide 64 text

リリーススケジュールが柔軟に ● メンテナンスを待つ必要がなくなった ● メンテナンスを待たずして、任意のタイミングで以前より高速でリリースできるよう に 64

Slide 65

Slide 65 text

事故の予防がしやすくなった ● ユーザ影響のない環境(preview)が生まれたことにより、「preview環境で不具 合が起きたらリリースを中止する」という新たな選択肢が生まれた 65

Slide 66

Slide 66 text

既存のリリースの課題の大部分を改善する ことができました 66

Slide 67

Slide 67 text

7. 残された課題もあります 67

Slide 68

Slide 68 text

残された課題点もいくつかあります ● CloudSQLのアップグレードやスペック調整のタイミングでメンテナンスが必要に なる ● 外部APIとの連携はpreview環境と疎通できない場合がある ○ 例えばSNSログインや、グリーグループ共通の認証基盤など ○ 後者は調整可能ではある 68

Slide 69

Slide 69 text

まとめ ● 正攻法(サービスメッシュの導入)により大きな成果を得ることができた ○ REALITY流の工夫はありつつ、ユーザ & ビジネス双方で。 ○ できるだけ難しいことをしない。まずは凡事徹底。 ● BlueGreen以外にも応用できるものが生まれた ○ カナリアリリースなど ○ 開発体験向上にも流用する予定 69

Slide 70

Slide 70 text

70