Timee Product Team Blog

タイミー開発者ブログ

タイミーでProduction Readiness Checkをやってみたよ

はじめに

こんにちは!タイミーでPlatform Engineerをしている @MoneyForest です。

本記事では、タイミーで実施したProduction Readiness Checkの取り組みを紹介します。

Production Readiness Checkとは

プロダクションレディネスチェック(Production Readiness Check)とは、「サービスが本番環境で安定して運用できる状態にあるかどうかを評価」するプロセスのことです。

UberのSREの知見から書かれた書籍 プロダクションレディマイクロサービス には、以下のように書かれています。

Uberのすべてのマイクロサービスは、安定性、信頼性、スケーラビリティ、耐
障害性、パフォーマンス、監視、ドキュメント、大惨事(カタストロフィ)対応を備
えていなければならないという8つの原則を考え出しました。そして、サービスが安
定性、信頼性、スケーラビリティ、耐障害性、パフォーマンス、監視、ドキュメント、
大惨事対応を備えているとはどういうことかを定義する基準を考えていきました。大
切なのは、どの基準も定量化できるものにすることでした。そうすれば、マイクロサー
ビスの可用性が飛躍的に向上したという測定可能な結果が得られます。我々は、これ
らの基準を満たし、要件を備えたサービスを本番対応(プロダクションレディ)と表
現することにしました。

背景

株式会社タイミーはマイクロサービスを採用しておらず、主要事業であるスキマバイトサービス「タイミー」のアプリケーションは主に1つのRailsアプリケーションで構築されています。

モジュラモノリスという形でシステムのドメインとオーナーシップを論理的に分割してきました。

一方で直近は事業戦略、ガバナンス、クォータの観点から一部機能をサブシステムに分割する動きもあります。

つまり「マイクロサービスアーキテクチャほど頻繁にサービスは新規に立ち上がらないが、定期的にサービスは新規に立ち上がっている」という状態です。

なぜやるか

タイミーではマルチテナントのコンテナオーケストレーション基盤は存在せず、システム・サブシステムごとにECSクラスターを構築しています。

アプリケーションもRuby on Railsが採用されることが多いものの、言語およびフレームワークは都度選定されています。

また、サービス開発はアプリケーション、インフラ合わせてストリームアラインドチーム(Squad)のスクラム開発によって行われています。

上記の通り、現状ではゼロベースに近い状態から開発を行うため、信頼性などの様々な観点で注意すべき点が出てきます。

そのため、サブシステムや関連サービスのリリースに際して「本番環境で安定して運用できる状態にあるか」を評価点検する仕組みは一定の価値を発揮すると考えます。

タイミーのProduction Readiness Checklist

プロダクションレディマイクロサービス の内容をベースに、タイミーの技術選定に合わせ、より具体的な内容に落とし込み、チェックリストを作成しました。

書籍には以下の考慮がなされていますが、タイミーではクラウドインフラはAWS、オブザーバビリティツールはDatadog、と限られたものを活用しており、より具体的な記述になっているほうがチェックしやすいと判断しました。

テクノロジーはものすごい速さで動き、変化しています。私は可能な限り、
読者を既存のテクノロジーに縛り付けるようなことは書かないようにしました。たと
えば、すべてのマイクロサービスは、ロギングのためにKafkaを使うべきだとは言わ
ず、本番対応のロギングの重要な要素を説明し、実際にどのテクノロジーを選んで使
うかは読者に委ねるようにしました。

また、内容についてはClient-Server-Databaseの3層アーキテクチャを前提としています。

サーバレスアーキテクチャの場合は対象外です。

チェックの各項目は書籍を参考に以下の観点に分類しています。

観点 主なキーワード
安定性・信頼性 開発サイクル、デプロイパイプライン、依存関係処理、unhealthyなホストの検出、healthyなホストへのルーティング、グレースフルシャットダウン、APIバージョニング
スケーラビリティとパフォーマンス リソースの効率的な使い方、リソースの把握、キャパシティプランニング、依存関係のスケーリング、トラフィック管理、タスクの処理、スケーラブルなデータストレージ
耐障害性・大惨事対応 冗長化、一般的な大惨事と障害シナリオ、障害の検出と修正の方法、回復性テストの詳細、インシデントと機能停止の処理方法
監視 監視、構造化ロギング、ダッシュボード、アラートのトリアージ
ドキュメント・組織運営 サービスの適切なドキュメントの問題と、開発チームと技術組織全体でアーキテクチャと組織運営の理解

タイミーのProduction Readiness Checklistの詳細

実際のチェックリストの内容を観点ごとに紹介します。

1. 安定性・信頼性

  • コード管理
    • コードがGitHubリポジトリで適切に管理されている
    • 環境構築方法がdevcontainerやdocker-composeなどをベースに、環境差異が少なく導入工数が低い構成になっている
  • CI/CD
    • GitHub Flowによる開発の場合、以下のいずれかの設定が実装されている
      • CDの依存にCIのPass状態があること
      • ブランチ保護ルールの「Require branches to be up to date before merging」が有効化されていること
    • CIでコードの静的解析(Lintチェック)、セキュリティチェック、テストを実施している
    • 特別な理由がない限り、CI/CDパイプラインにGitHub Actionsを採用している
    • 各環境のCDパイプラインが自動化されている
    • CDの成功/失敗がSlackに通知される仕組みがある
  • インフラストラクチャ
    • AWSアカウントのサポートレベルがエンタープライズに設定されている
    • ALBのヘルスチェックにアプリケーションのヘルスチェックエンドポイントが使用されている
    • ECSでアプリケーションコンテナの依存関係にDatadog Agent、AWS for Fluent Bitが指定されており、アプリケーションコンテナが最後に立ち上がるよう依存関係が設定されている
  • アプリケーション設計
    • アプリケーションのAPIエンドポイントがバージョニング可能なURIパターンに設計されている
    • Deep Health Check パターンに基づいたヘルスチェックエンドポイントが実装されている
    • ECSのコンテナライフサイクルの仕様 を踏まえたグレースフルシャットダウンが実装されている
    • ALBのスティッキーセッションが無効でも正常に動作する設計になっている
    • ローリングデプロイにより新旧バージョンにトラフィックが分散しても問題ない設計になっている
    • アプリケーションがマルチスレッドで動作する場合、スレッドセーフになっている

2. スケーラビリティとパフォーマンス

  • オートスケーリング
    • ECSでCPUベースのオートスケーリングが設定されている
    • ECSでCPUスパイク時のオートスケーリングが設定されている
  • スケーラブルなデータストレージの選択
    • データベースにAurora MySQLのLTSバージョンを使用している
    • キャッシュにAmazon ElastiCache for Valkeyを採用している
  • パフォーマンステスト
    • 負荷テストが実施されており、想定されるトラフィック量に対する性能が検証されている

3. 耐障害性・大惨事対応

  • ロールバック
    • ECSでデプロイサーキットブレーカーが有効化されており、サービス更新失敗時に自動的にロールバックする仕組みがある
  • 可用性
    • Aurora MySQLで2台以上のリーダーインスタンスが配置されている
    • Auroraのサブネットグループに3AZを指定し、インスタンスが異なるAZに分散配置されている
    • Aurora MySQLの自動バックアップが有効化されており、ポイントインタイムリカバリ(PITR)による復元が可能になっている
    • Aurora MySQLのバックトラック機能が有効化されている
    • ElastiCacheレプリケーショングループでのマルチAZ化が有効化されている
  • 障害対応
    • SPOF(単一障害点)となりうる箇所が洗い出され、ドキュメント化されている
    • 想定される障害シナリオがRunbookとしてドキュメント化されている
    • 社内で定められたインシデント・障害対応フローに準じた障害対応手順が整備されている

4. 監視

  • ロギングとトレーシング
    • ALBのリクエストログがS3に保存され、日時でパーティショニングされており、Athenaでクエリ可能な状態になっている
    • ECSのサイドカーにDatadog Agent、AWS for Fluent Bitが設定されている
    • アプリケーションにDatadog APM Tracingが計装されている
    • ヘルスチェックエンドポイントで、正常時のログとTraceの出力が抑制されている
    • APM Tracingでリクエスト単位でTraceが出力され、最低でもDB、キャッシュ、外部サービスへのHTTPリクエストの単位でSpanを確認できる
    • アプリケーションのログが構造化されており、採用言語に応じてDatadogのドキュメントに準拠した実装がされている
    • ログとトレースの相関付けがされており、採用言語に応じてDatadogのドキュメントに準拠した実装がされている
    • アプリケーションがミドルウェアでリクエストログを出力するようになっている
    • リクエストごとに一意となるIDを生成または上流から受け取り、リクエストログとTraceに出力している
    • リクエストログを識別するためのフィールドが定義されている(Datadogでリクエストログ用のログインデックスに保存するため)
    • Sentryによるエラートラッキングが設定されている
  • データストア監視
    • Aurora MySQLのPerformance Insightsが有効化されている
    • Aurora MySQLで以下のパラメータが有効化されている
      • binlog_format = ROW
      • Datadog DBM 関連パラメータ
      • slow_query_log
      • long_query_time
      • innodb_print_all_deadlocks
      • performance_schema
  • ダッシュボードとアラート
    • Datadogにシステムメトリクスを監視できるダッシュボードが整備されている
    • Datadogにユーザー影響が発生した場合のモニタリングアラートが設定されている
      • Warning/Criticalの閾値が適切に定められている
      • オーナーチームが定義されている
      • Runbookへのリンクが添付されている
    • ビジネスメトリクス(ログインや課金の成功率など)を監視できるダッシュボードまたはウィジェットがある
    • モニタリングダッシュボードを定点観測するスキームがある

5. ドキュメント・組織運営

  • ドキュメンテーション
    • システムの概要説明とアーキテクチャ図が整備されている
    • システムの連絡先とコンタクト方法を記載したドキュメントがある
    • AWSやSaaSなど依存サービスのクォータが洗い出されており、クォータの引き上げ手順が整理されている
    • DBスキーマを元に最新のER図を生成する仕組みがある
    • GitHubリポジトリにREADMEが作成されている
    • READMEに以下が記載されている(リンクでも可)
      • リポジトリの概要
      • 環境構築手順
      • ディレクトリマップ
    • すべての依存サービス(関連社内サービス、外部SaaS)が洗い出され一覧化されている

まとめ

今回はProduction Readiness Checkの取り組みを紹介しました。

この取り組みはボトムアップ的に始めたものではありますが、全社的に当たり前のように行われるものにしていきたいです。

また書籍にはないですが、セキュリティやデータ連携もプロダクションレディの重要な要素になると思っているので、DREやセキュリティ部門と連携してチェックリストを拡充していきたいという思いもあります。

もっと知見を深めて、さらに楽しいエンジニアライフを送りたいと思います!またね〜