Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FastlyとTypeScriptで実現するカナリアリリース / yamagoya2020

FastlyとTypeScriptで実現するカナリアリリース / yamagoya2020

#yamagoya2020 で 2020/11/25 に登壇させていただいたセッションの資料です。

Sho Miyamoto

November 25, 2020
Tweet

More Decks by Sho Miyamoto

Other Decks in Technology

Transcript

  1. - 名前 Sho Miyamoto - 所属 日本経済新聞社 - 領域 -

    web - front-end - {client,server,edge}-side - GitHub https://github.com/shqld 自己紹介 2
  2. - 機能リリースが安全になる - 一度本番で確認してから全体へリリー ス、ということができる - QAテストが容易になる - 他部署・非エンジニアでも、スイッチを 切り替えるだけで検証できる

    15 Feature Toggles の利点 - 非常時の対応が素早い - 何かあればスイッチを切り戻すだけで デプロイせずに対応できる - 非機能要件の検証がしやすい - パフォーマンス施策の効果検証など
  3. - 新しい機能やページは基本的に ダークカナリアリリース - 実際に開発者が本番で確認してから 全てのユーザに展開 - 指定の日時に自動リリース - e.g.

    大統領選の始まる時間に合わせ て特設ページをリリース 18 Feature Toggles の用途 - マーケティング施策のA/Bテストを 行う - e.g. ペイウォール(有料登録動線)の 文言変更 - 技術的な施策の効果検証を行う - e.g. Dynamic Critical CSSを本番に反 映しても問題ないか検証、確認が取れ るまでは反映しない
  4. - JSONで管理 - defaultValue を決めて おく - A / B

    テストを行うときは candidates を定義 実際の Toggle 定義 19
  5. Default / Static - 既定値 - Toggle の定義時に人間が決定 - リリース用

    - 例 - 「このToggleはもうリリースできるのでオン」 Override / Dynamic - 上書き値 - 定義された条件から機械的に決定 - スケジュール用、セグメンテーション用 - 例 - 「11/25になったからオン」 - 「このユーザのセグメントが10%内だからオ ン」 24 Toggle の2つの側面
  6. - dynamic toggles の計算のため に別のサーバを必要としている - 運用・ケアが必要 - Toggles サーバにリクエストする

    ために VCL内で restart している - restart - static toggles の同期のために サービス側で5分おきにAPIへ ポーリングしている - メモリに暗黙的な状態が存 在する 28
  7. 旧基盤 (Nikkei-Flags) についての詳しい解説はFastlyの記事で How to solve anything in VCL, part

    3: authentication and feature flags at the edge https://www.fastly.com/blog/how-solve-anything-vcl-part-3-authentication-and- feature-flags-edge 30
  8. リプレースの要件・ゴール (1) 32 - インフラ - 状態や計算も全てVCLで完結 - 完全サーバーレス -

    転送量 - 各リクエスト毎に送られるデータはなるべく小さく - できるものは全て静的に解決しておく - 複雑性 - 暗黙的・非透過的な状態はなるべく排除 - 「いま何がメモリにあって何がどうなっているのか」という懸念がない
  9. - 運用性 - 更新反映が速い - 終了した・不要な toggle の分岐がコードに残らない - Toggleの定義

    - 定義が簡潔 - 個々の存在目的が明確 リプレースの要件・ゴール (2) 33
  10. - Toggleの種類は4つ - Release: (ダーク)カナリーリリース - Experiment: ダークローンチやA/Bテスト - Ops:

    状況に応じてインフラなどを切り替える - Permission 権限別に処理をスイッチ - → 本当に必要なのは Release と Experiment - それ以外はどちらも Longevity(寿命)が長く消しづらい - Opsはユースケースが限定的 で頻度が少ない - Permissionはアプリケーションの一部として 依存されてしまう可能性が高い Toggle 再考 36
  11. - 存在意義・目的が明確 - ある機能をスイッチ(オン /オフ)するだけ - → 値は True /

    False の2値のみ - 1つのToggleに複数の用途を持たせない - 寿命が短く疎結合 - 短い役目を終えたら すぐに消せる - コードから剥がしやすい - 存在が透過的 - Toggleの存在を前提としない - Toggleにアプリケーションの 実装が依存しない あるべき理想のToggle 37
  12. - エッジで dynamic toggles の計 算を行う - サーバレス、VCLで完結 - restart

    / polling も消えた - 最初から bereq に toggles が入っている - 各bereqごとに CDN へリクエスト して static toggles を取得 - 常に最新の toggles を同 期できる - 暗黙的な状態を持たない 41
  13. - Fastify の `req` オブジェクトに APIを生やす - TypeScriptで実装 - できるだけ型で縛れるように型推

    論多め - 返る値は必ずBoolean アプリケーション コード 43 (文字列の位置が下がっているのはVSCodeのプラグインの関係)
  14. デプロイフロー - Toggles を別のリポジトリの切り 出した - npmの`prepublishOnly` フックでデプロイが実行さ れる -

    npm publishとVCLのdeployが終 わったあとに Fastly API でソフト パージ - toggles 周りのVCLは VCL Snippets として作っており、本体 のVCLとは別軸・別レポでデプロ イが可能 44
  15. - JSで定義されたToggleを読んで、 dynamic toggles 用のVCLを生 成している - Scheduling - リクエストされた時間と定

    義ルールの時間を比較し てオンオフを決める - Segmentation - 何かしらのリクエストIDを 使いユーザのセグメントを 決定し定義ルールの範囲 と比較してオンオフを決め る 48
  16. - 上の定義から、下の dynamic toggles 用の条件分岐を生成し ている - セグメンテーションで同じユーザが 複数の Toggle

    で似たような判定 にならないように、条件範囲に random offset を含めている 49
  17. 60 ‘ xxx‘ で検索できる - 抽象化されているとtoggle がどこで使われているか追 えなくなる - toggle

    のキーは必ず ‘ ‘ で始まるように強制(それ以 外を弾いている) - string literal タイプなので キーを抽象化できない - ✖ get(‘ ‘ + name)
  18. - toggle を生成する関数を経由 - ここで name を string literal タイ

    プで受け取る - string literal の name を返す Toggle オブジェクトの型引数に 渡して保持 型の推論 61
  19. - 集めた toggles を Object.freeze で readonly に - typeof

    で型に変えた toggles の name を ユニオンとして取り出す 型の推論 (2) 62
  20. - (ダーク)カナリアリリースは便利 - リリースの安全性が高まる - Feature Toggles で実現できることが多い - デプロイとリリースのタイミングをずらすことで色々できる

    - 電子版では Feature Toggles を(結構)活用している - ダークカナリアリリース、スケジューリング、 A/Bテスト、... まとめ 64
  21. まとめ (2) - Feature Toggles の運用を見返してシンプルに - 何でもできてしまう toggles は禁止、制約を強めに

    - VCLを駆使すれば 外部のサーバは必要ない - VCL Snippets でデプロイフローも簡潔に - TypeScript でアプリケーションコードを安全に - 補完や検索、エラー検知も容易に 65
  22. - 人類にはまだ早い - 使わずに済むなら使わない方が良い - これを消したかった、というのも今回のリプレースの動機の大きな一つ - 中々解決できない問題は大体 restart 起因であることが多い(個人の経験上)

    - 様々なパターンを網羅的に知っておかないと思わぬ事故に繋がってしまう - 一度目のリクエストで( restartまでに)何が行われたのか - どんなHTTP ヘッダが付いてどう影響するのか - 次のリクエストでどうなるか ...etc. - もちろん必要なとき、有用なときはある - e.g. フレンドリーなエラーページに差し替えるとき VCL restart; 69