🐕

Cloud Run に高トラフィックなシナリオの負荷試験をする際の参考書

2024/12/19に公開

🌟 はじめに

本記事は GCP(Google Cloud Platform) Advent Calendar 2024Jagu'e'r Advent Calendar 2024 の 19日目の記事になります。

私は普段、業務で広告配信システムの構築に携わっています。広告配信システムでは、高トラフィックなシナリオにおいても高速なレスポンスを求められることが多く、非常に高いパフォーマンス要件を満たす必要があります。
具体的には、10,000 QPS(リクエスト/秒) のトラフィックに対応し、100ミリ秒以内のレスポンスを実現することを目指しています。

今回、これらの要件を満たすために Cloud Run(内部実装は Go)を利用したシステムを構築し、負荷試験を行いました。本記事では、その負荷試験の過程で考慮したポイント、留意すべき点、そしてハマりがちな課題についてご紹介します。これから同様の検証を行う方々の参考になれば幸いです。

なお、本検証では以下の技術スタックを利用しています。

  • データベース: Spanner
    負荷試験の結果、Spanner を利用する上で工夫すべきポイントが見つかりました。こちらについては、別記事として詳しく解説する予定です。
  • 負荷試験ツール: k6(Compute Engine 上で実行)
    k6 を使った負荷試験についても、工夫すべき点がいくつかありました。これについても、別記事で取り上げる予定です。

※ スライドでの発表も行なっておりますので、そちらも是非参照してみて下さい。

https://speakerdeck.com/oyasumipants/cloud-run-degao-torahuitukunasinarionofu-he-shi-yan-wosuruji-nocan-kao-shu

それでは、Cloud Run を活用した高トラフィック対応の実装と負荷試験の詳細を見ていきましょう!

📖 対象読者

  • Cloud Run に興味がある、またはすでに活用している方
    (特に、高トラフィックなシステム構築に関心がある方)
  • 負荷試験の手法や注意点を学びたい方
  • GoogleCloud を活用し、システムのパフォーマンス向上を目指している人

🗣️ 負荷試験を始める前

負荷試験を始める際には、いきなり試験を行うのではなく、事前にしっかりと準備を行うことが重要です。今回の検証では、以下の点を重点的に進めました。

  • 達成したい条件の明確化
  • コストの概算
  • スペックの調整
  • 監視の準備

達成したい条件の明確化

負荷試験を効果的に進めるためには、明確な目標条件を設定することが重要です。曖昧な基準で試験を始めると、結果が評価しにくくなるだけでなく、試験環境の構築や改善の方向性も不明瞭になってしまいます。今回の検証では、いくつかの観点から達成したい条件を設定しました。

シナリオを決める

負荷試験を行う際、最初に重要なのはテストシナリオの設計です。今回は、以下の条件を想定して負荷試験を実施しました。

  1. 平均的に 10,000 QPS のリクエストを処理
    k6 の ramping(段階的負荷増加機能)を活用し、10,000 QPS までスケールアップするシナリオを構築しました。

  2. 1台のインスタンスで処理可能な QPS の限界値を測定
    Cloud Run の 1 インスタンスあたりのスループットを確認し、インスタンスのスペック調整に役立てました。

  3. スパイクシナリオへの対応
    平均的に 10,000 QPS のリクエストが来ている状態で、急に 30,000 QPS にスパイクするケースを想定しました。これに耐えられるかどうかを検証しました。

これらのシナリオ設計は、類似プロダクトにおける実際の QPS データを参考にしつつ、以下の基準を設定して決定しました。

  • スパイクは通常の平均リクエストの 2~3倍 に耐えられるように設計(最大スループットを基準に、十分な余裕を持たせた設計)

検証内容のまとめ

  • 1台のインスタンスが捌ける QPS の限界を測定
  • 平均 10,000 QPS を 1時間 維持できるか確認
  • スパイク 30,000 QPS に耐えられるか検証

さらに、上記以外にも詳細な負荷条件を検証するため、30件ほどの追加シナリオを設定してテストを実施しました。

SLI/SLOを決める

サービスレベル指標(SLI)とサービスレベル目標(SLO)を決めることで、負荷試験の成果を具体的に評価できるようにしました。今回の負荷試験では、以下を目標としました:

  • 目標 SLI/SLO: 「リクエストの99パーセンタイル応答時間が 100ミリ秒以下であること」

なお、サービスの可用性やエラーレートといった指標も本来設定すべきですが、今回の負荷試験は運用前のフェーズでの実施だったため、これらの指標は開発期間との兼ね合いで詳細を詰めませんでした。
その後、SRE チームを含めたエンジニア・ビジネスチームで、より具体的な指標を設定しました。

データについて

負荷試験を本番に近い形で実施するために、テストデータの充足とリクエスト内容の多様性に配慮しました。

  • テストデータの準備
    実際の運用データを模倣し、十分な量のテストデータを生成しました。
  • リクエストの種類を分散
    複数のリクエストパターンを用意し、k6 側でランダムに選択するように設定しました。これにより、特定のリクエストに偏らない負荷を再現しました。

コストがどれくらいかかるのか

負荷試験を実施する際には、試験そのものにかかるコストだけでなく、本番運用時のコストを見積もり、チームで共有することが重要です。試験後の運用計画を円滑に進めるため、今回は特に Cloud Run の課金形態 に注目し、見積もりを行いました。

CloudRun の課金形態

課金形態は以下のような表で表せます。
※ 表記がズレている可能性があります。詳しくはドキュメントを参照してください。

https://cloud.google.com/run/pricing?hl=ja

Cloud Run の料金は、以下の要素に基づいて計算されます。

  1. CPU 使用量
  • リクエスト処理中の CPU 使用に応じて課金。
  • オプションで "Always-on CPU"(リクエストがない間も CPU を動作させるモード)を有効化可能。
  1. メモリ使用量
  • 割り当てたメモリ量に応じて課金。
  1. リクエスト量
  • 処理したリクエストの数およびデータ転送量に基づいて課金。

"Always-on CPU" の判断基準

"Always-on CPU" の有無は、サービスの性質や利用状況に応じて慎重に検討する必要があります。

"Always-on CPU" を有効化しない場合

  • リクエスト処理中のみ CPU を使用するため、リクエストが少ない時間帯のコストが大幅に削減できます。
  • 一方で、インスタンスがスリープ状態になるため、次のリクエストを処理する際にわずかなレイテンシー(Cold Start)が発生します。

"Always-on CPU" を有効化する場合

  • 常時 CPU を動作させるため、Cold Start の問題が解消されます(新規にインスタンスを起動する際には Cold Start が発生します)。
  • ただし、リクエストが少ない時間帯でも CPU 使用料金が発生します。

今回の選定理由

今回の広告配信サービスでは、24時間フルタイムで稼働することを想定しているため、"Always-on CPU" を有効化しました。これにより、以下のような効果が期待されます

  • 高トラフィックを処理する際の Cold Start を防ぎ、安定したレスポンス性能を維持。
  • 広告配信の性質上、リクエストが途切れることなく続くため、常時動作する CPU のコスト効率が高い。

一方で、staging(stg)および開発(dev)環境ではリクエスト頻度が低いことから、"Always-on CPU" を有効化せず、リクエスト処理中のみ CPU を割り当てる設定にしています。これにより、開発環境のコストを最小限に抑えています。

コスト見積もりの共有

チーム内では、以下を踏まえてコストを共有しました。

  • 負荷試験中のコスト: 試験実施中にかかる Cloud Run、Spanner、k6 実行環境(Compute Engine)の費用を試算。
  • 本番運用時のコスト: 広告配信サービスで見込まれる CPU、メモリ、リクエスト量を基に試算。

これらを共有することで、負荷試験を効率的に実施しつつ、本番運用時の課題やコスト感を事前にチーム全体で把握することができました。

可視化(ダッシュボード)

負荷試験や運用において、システムの状態をリアルタイムで把握できるようにすることは非常に重要です。今回のプロジェクトでは、Datadog を監視サービスとして採用し、ダッシュボードを活用してシステムの状態を可視化しました。

ダッシュボードの設計

Datadog のダッシュボードは、Google Cloud Monitoring のメトリクス表示形式を参考に設計しています。これにより、Google Cloud Console を普段利用しているチームメンバーにも馴染みやすい構成となっています。以下は実際のダッシュボード例です。

このダッシュボードでは以下のポイントを重点的にモニタリングしています。

  • リクエスト数(QPS)
    負荷試験の際に重要となる、リクエストの増加やスパイクをリアルタイムで確認。
  • レスポンス時間(パーセンタイル値)
    目標 SLO(100ミリ秒以内)が達成されているかを監視。
  • エラー率
    負荷試験中やスパイク時のエラーレートを把握。

これらの指標をリアルタイムに確認することで、システムのパフォーマンスやボトルネックを素早く特定することが可能になりました。

APM・Trace の活用

さらに、Datadog の APM(Application Performance Monitoring) 機能と Trace 情報を活用し、以下のデータを収集しました。

  • 各リクエストの詳細な処理時間
    処理中の各ステップ(例:DB クエリや外部 API 呼び出し)の時間を計測。
  • ボトルネックの特定
    スパイク時に遅延やエラーが発生した場合、その原因となる箇所を特定。
  • トランザクションの追跡
    リクエストがシステム内をどのように流れているかを詳細に可視化。

これにより、負荷試験の結果を単なる数値として見るだけでなく、具体的な改善点を特定するための情報 を得ることができました。

チームへの共有

可視化されたデータはチーム全体で共有し、以下の用途に役立てました:

  • リアルタイムモニタリング: 負荷試験中に異常を検知し、即時対応。
  • 結果の振り返り: 試験後にダッシュボードや Trace を元に原因分析や改善計画を策定。
  • 知見の蓄積: 将来的な負荷試験や運用に活かせるデータとして保存。

これにより、負荷試験の成果がより分かりやすくなり、チーム全体での改善活動を効率的に進めることができました。

🔄 負荷試験中に考え、改善していったこと

ここからは、実際に負荷試験を行いながら気づき、改善していったポイントについて解説します。

4つのオートスケールのポイントを知る

CloudRun には大きく 4つのオートスケールのポイントがあります。
これらは何度も見たので、頭に入っています。それくらい重要です。

  1. 既存インスタンスの1分間の平均 CPU 使用率
  • Cloud Run は、既存インスタンスの平均 CPU 使用率を 60% に維持しようとします。
  • この設定はデフォルトですが、CPU 使用率が急増するとスケーリングのタイミングが遅れることがあるため、モニタリングが重要です。
  1. 同時実行数(Concurrency)
  • Cloud Run は、1分間の最大同時実行数と現在の同時実行数を比較してスケールを判断します。
  • Concurrency の設定値を適切に調整することで、インスタンスの数と効率を最適化できます。
  1. インスタンスの最大数
  • Cloud Run には「インスタンスの最大数」を設定するオプションがあります。
  • 負荷の急増(スパイク) に対応するために、最大数は余裕を持って設定する必要があります。
  • 一方で、コスト管理の観点からは無制限にスケールさせない工夫も必要です。
  1. インスタンスの最小数
  • スケーリングの 起動時間 を短縮するため、インスタンスの最小数を設定できます。
  • 最小数を0にしておくとコールドスタートが発生し、負荷試験では遅延が確認されることがありました。そのため、最小インスタンス数を1以上に設定することで、応答速度の安定性を向上させました。

これら4つのポイントを把握することで、Cloud Run のオートスケールの挙動を理解しやすくなります。特に負荷試験の中で以下のことを実感しました。

  • CPU 使用率 と Concurrency のバランスがシステムのパフォーマンスに直結する。
  • 最大/最小インスタンス数 の設定は、コストとスパイク対応のトレードオフ。

Cloud Run のオートスケールについての詳細はこちらをご参照ください。
https://cloud.google.com/run/docs/about-instance-autoscaling?hl=ja

平均 CPU 使用率と同時実行数を定める

Cloud Run のパフォーマンス最適化において、平均 CPU 使用率同時実行数(Concurrency) は密接に関連しています。そのため、これらの設定は並行して考える必要があります。

なぜ同時実行数を適切に設定する必要があるのか?

Cloud Run のドキュメントでは、同時実行数がシステムの挙動に与える影響を示す次の図と説明が掲載されています。

https://cloud.google.com/run/docs/about-concurrency?hl=ja#maximum_concurrent_requests_per_instance

この図からわかることは以下の2点です:

  1. 同時実行数が多すぎる場合
  • コンテナに過度な負荷がかかり、CPU 使用率が高い状態になるとパフォーマンスが低下します。
  1. 同時実行数が少なすぎる場合
  • コンテナへの負荷が分散しすぎて、必要以上にインスタンスが増えることでリソースが非効率になります。

Cloud Run は CPU 使用率 60% を維持するためにオートスケールを行いますが、適切な同時実行数を設定していないとスケールアウトのタイミングや挙動に影響が出ることがあります。

※ 補足:ドキュメントにもある通り、「指定された同時実行数は最大値であり、CPU 使用率がすでに高い場合、Cloud Run はインスタンスにそれほど多くのリクエストを送信しない」ため、調整が重要です。

どう設定すれば良いか?

この点については、Google の方の記事にある以下の手法を参考にしました。

https://zenn.dev/google_cloud_jp/articles/cloudrun-concurrency#cpu-負荷によってスケールする

手順:

  1. 同時実行数(Concurrency)を最大の 1000 に設定する。
  2. 負荷試験を行い、CPU 使用率が 60% に達するタイミングでの同時実行数を確認する。
  3. 確認した同時実行数を基準に、適切な同時実行数を設定する。

さらに検証を深める方法

私は別の手法として、インスタンスの最大数を 1 に設定し、オートスケールを無効化する方法も試しました。この状態で負荷を徐々に上げていき、CPU 使用率が 60% 程度で安定した際の同時実行数 を測定することで、必要な同時実行数を見極めることも出来るかなと思います。

まとめ

  • 同時実行数の適切な設定が重要
    過剰な同時実行数はコンテナの負荷を高め、パフォーマンス低下を引き起こします。一方で、少なすぎるとインスタンスの増加によるリソースの非効率が発生します。適切なバランスを見極めることが重要です。

  • 設定の具体的な手法
    同時実行数を一度最大の 1000 に設定し、負荷試験を行うことで CPU 使用率が 60% に達するタイミングでの同時実行数 を確認し、それを基準に設定を調整するのが有効です。

  • さらに深める方法
    最大インスタンス数を 1 に固定し、オートスケールを無効化して負荷試験を行うことで、CPU 使用率と同時実行数の関係を詳細に分析することも検討できます。

最大台数・最小台数を定める

Cloud Run の 最大台数最小台数 の設定は、スケーリングの挙動を制御する重要な要素です。負荷試験の結果をもとに、それぞれの設定について以下のポイントを考慮しました。

最大台数の設定

最大台数を大きめに設定しておくと、スケールアウトが迅速に行われるため一見安心ですが、以下の点に注意が必要です:

  1. スケールアウトの制御が難しい
    Cloud Run は 同時実行数平均 CPU 使用率 を基準にスケールアウトしますが、負荷がかかった際に 必要以上にインスタンスが増加 することがあります。

実際に負荷試験を行った際、CPU 使用率が 60% 未満にもかかわらず、スケールインがすぐに行われない挙動が観測されました。
※ Cloud Run のオートスケーリングの実装は追えないため、この点は断定できません。

  1. 最大台数を絞ることで過剰なスケールアウトを防ぐ

スケールアウトしすぎる場合、最大台数を制限することでコストの制御やリソースの無駄な増加を防ぐことができます。

補足:今回の検証時間ではスケールインの挙動を "完全には" 観測しきれませんでした。そのため、実際の運用シナリオに合わせて、最大台数の設定をテストすることをおすすめします。

※ Cloud Run の最大台数を 6台に設定することでこれ以上スケールさせないことを示す図

最小台数の設定

最小台数は 急な負荷 に対応するために重要です。Cloud Run は 1分間の平均 CPU 使用率同時実行数 に基づいてスケールアウトを判断しますが、ここに注意点があります。

  1. スケールアウトの遅延リスク
  • 最小台数を 0 に設定している場合、負荷が発生した際に コールドスタート が発生します。これにより、処理が間に合わないケースがあるため注意が必要です。
  • スケールの判定は「1分間の平均値」に基づいて行われるため、短時間に急激な負荷(スパイク)が来た場合、スケールアウトが間に合わず処理が遅延するリスクが高まります。
  1. 最小台数を 1 以上に設定する
  • 常に少なくとも1つのインスタンスを起動しておくことで、コールドスタートを防ぎ、急な負荷にもある程度耐えられる状態を維持できます。
  • 負荷試験を通じて、最小台数を適切に設定することで、応答速度の安定性を確保できました。

まとめ

  • 最大台数: 過剰なスケールアウトを防ぐため、適切な上限を設定する。
  • 最小台数: コールドスタートや急な負荷への遅延を防ぐため、必要数に設定することを検討する。

特に Cloud Run は「1分間の平均 CPU 使用率」や「同時実行数」に基づいてスケーリングするため、急激なスパイク負荷が想定される場合には、最小台数の設定 がパフォーマンスの安定性を左右する重要なポイントになります。

クォータを正しく確認する

負荷試験を行う際、Cloud Run のクォータ を正しく把握しておかないと、思わぬ制約に引っかかることがあります。今回の負荷試験では、想定していなかった以下2つのクォータに直面しました。他のクォータについては、以下の公式ドキュメントを参考にしてください。

https://cloud.google.com/run/quotas?hl=ja

1. CPU の大きさの制限

Cloud Run では、メインコンテナサイドカー を含めて、1インスタンスあたりの最大 vCPU 数が 8 に制限されています。

問題点:
負荷試験を通じて高トラフィックを捌くために 8vCPU 以上 を用意したかったのですが、Cloud Run の制約により制限内に収める必要がありました。
これにより、1インスタンスの性能を最適化しつつ、スケールアウトすることで要件を満たす方向に調整しました。

2. HTTP による制約

このクォータは見落としていた部分で、特に問題解決に時間を要しました。

Cloud Run には、HTTP/1.1 コンテナポートに対する 1秒あたりのインバウンドリクエスト数800 という制約があります。

発生した問題

  • 内部実装では HTTP 通信を利用しており、1インスタンスあたりの HTTP/1.1 のクォータ上限 800 rps に引っかかってしまいました。
  • この状態で 10,000 QPS を満たそうと試みましたが、クォータ制限により CPU 使用率が上昇せず、スループットが伸びない問題が発生しました。

※ リクエスト数は増加しているのに、200で返ってくる Response が固定されたことを示す図


解決策

  • Cloud Run のインスタンス内部で HTTP/2 以上 のプロトコルを受け付けるように修正しました。
  • HTTP/2 は 複数リクエストを1つの接続で処理 できるため、HTTP/1.1 のリクエスト上限を回避し、リソース効率が大幅に改善されました。

補足: HTTP/2 は高トラフィック処理において特に効果的です。クォータ上限に引っかかる場合、内部通信やクライアント側も含めて HTTP/2 をサポートするよう見直すと良いでしょう。

まとめ

  • CPU 制限: Cloud Run は 最大 8vCPU の制約があるため、スケールアウト設計を検討する。
  • HTTP 制限: HTTP/1.1 のリクエスト数上限 800 rps を考慮し、HTTP/2 以上のプロトコルを活用することで制約を回避する。

これらのクォータを事前に把握し、対策を講じることで、負荷試験をスムーズに進めることができました。

Support の方を頼る

負荷試験やシステム設計で問題に直面した際、Google Cloud Support を頼ることは非常に有効です。Google Cloud のコンソールから以下の手順でサポートへ連絡できます:

  • 手順:Google Cloud Console > Support > ケース

実際に困りごとが発生した際にこの サポートケース を活用したことで、問題解決が大きく促進されました。

サポートを活用するメリット

  1. Google Cloud 側でしか確認できない内部メトリクス
  • Cloud Run の挙動や制約に関して、外部ユーザーからは見えない内部メトリクスやリソース使用状況をサポート担当者から確認してもらえました。
  • 例えば、スケールアウトが期待通りに行われないケースで、CPU 使用率やリクエストの分散状況を具体的に教えてもらえたことがありました。
  1. 内部の実装やクォータ制約に関する情報
  • ドキュメントには記載されていない 内部の実装の仕様クォータの制約 について説明を受けたことで、問題の原因を特定しやすくなりました。
  1. 解決策と折り合いのポイントの明確化
  • サポートを通じて「どこまでが Cloud Run の仕様上避けられない制約か」「どの部分で最適化や折り合いをつける必要があるか」を明確にできた点は非常に良かったです。
  • 結果として、設計上の妥協点や改善策をチーム内で早期に決定することができました。

まとめ

問題解決のスピードを上げるためには、Google Cloud Support を積極的に活用することが有効です。サポートを通じて、以下の点が得られました:

  • 内部のメトリクスや仕様の確認
  • 制約の把握と最適な解決策の検討
  • チーム内での設計・最適化の判断

問題が発生した際には、「一人で悩まず、サポートを頼る」という選択肢を持つことが、円滑な問題解決への近道になります。

CPU・Memory の大きさの決定する

CPU に関しては負荷試験を進める中で大きさを変化させることで一番コスト効率が良い方法を探りました。クォータによる制約とサイドカーのエージェントにかかる料金を比較しながら、1インスタンスでメインコンテナの vCPU をより大きくするという方針に決めました。

Memory に関してはアプリケーションで使う(In)Mmeory を十分に計算しました。どれくらいのデータ量があるのかを計算し、それが十分に格納できる Memory 容量を計算します。Go は型によって bit 数が決まるため、特に Numeric 型など不要な大きさを確保しないように型から見直しました。

https://go.dev/ref/spec#Numeric_types

Startup CPU boost を使ってみる

Cloud Run に対するリクエストが 急増 した場合、オートスケールが追いつかないことがあります。その際に問題となるのが コールドスタート です。

コールドスタートとは?

Cloud Run は、新しくインスタンスが起動される際にコンテナイメージを読み込み、初期化処理が行われるため、一定の時間がかかります。これが コールドスタート と呼ばれる現象です。
負荷が急増すると、新しいインスタンスが起動されてもリクエストの処理に時間がかかり、遅延タイムアウト が発生するリスクがあります。

Startup CPU Boost でコールドスタートを改善

この問題に対応する方法として、Startup CPU Boost を利用しました。

Startup CPU Boost の仕組み

  • 新しいインスタンスが起動する際に、通常の CPU 割り当てに加えて 一時的に CPU リソースをブースト する機能です。
  • これにより、起動時間の短縮コールドスタート時のレスポンス改善 が期待できます。

効果

  • インスタンスが迅速に初期化されるため、急なリクエスト増加 に対しても安定して対応できる可能性が高まります。

詳しい解説記事

Startup CPU Boost については、以下の記事が詳しく解説しているので、併せて参考にしてみてください。

https://blog.g-gen.co.jp/entry/cloudrun-cpu-startup-boost

まとめ

  • Startup CPU Boost はコールドスタート対策として有効。
  • 急激なリクエスト増加に対して、インスタンスの起動時間を短縮し、スムーズなスケールアウトを実現する。

急な負荷に耐えるシステムを構築する際には、ぜひこの機能を活用することをおすすめします。

🏃‍♀️ 負荷試験を行った後

ここでは最終的な負荷試験の結果についてまとめます。

最終的な負荷試験の結果

1台で捌ける QPS の限界を知る

  • 結果: 4,500 QPS 程度 まで処理可能であることが分かりました。
  • 考察:
    • この結果から、インスタンス1台あたりの性能上限が明確になり、スケール設計のベースとして活用できました。

※ 1台より大きくスケールアウトさせず、QPS を高めて行ったことを示す図

10,000 QPS を定常的に受けられるか(1時間程度)

  • 結果: インスタンス 6台程度 で 10,000 QPS を安定して処理できました。
  • 考察:
    • Cloud Run のオートスケーリングが適切に機能し、CPU 使用率やリクエストの分散も問題なく処理されました。
    • 最大インスタンス数の設定 や 同時実行数 の調整が功を奏し、安定した負荷処理を確認しました。

※ 10,000 QPS を定常的に捌くことができている様子を表す図

30,000 QPS のスパイクに耐えられるか

  • 結果: 同じく インスタンス 10台程度 で 30,000 QPS の急激なスパイクにも耐えられることを確認しました。
  • 考察:
    • Cloud Run のオートスケーリングが迅速に機能し、コールドスタートの影響も
    • スパイク対策 としてインスタンスの最小数設定や HTTP/2 の導入が効果的でした。

※ 30,000 QPS のスパイクにも耐えることができている様子を表す図

まとめ

負荷試験を通じて、以下の結果が得られました。

  • 1台の QPS 限界:約 4,500QPS
  • 10,000 QPS の安定処理:6~8台程度で達成
  • 30,000 QPS のスパイク対応:10程度で耐えられることを確認

今回の検証で得られた結果から、Cloud Run を活用すれば高トラフィックシナリオやスパイクにも十分対応可能であることが分かりました。インスタンスのスケール設計や CPU・Memory の最適化、オートスケーリング設定の調整が性能改善のカギとなります。

負荷試験共有会

負荷試験の結果や進め方について、チーム全体に共有する場として 負荷試験共有会 を開催しました。主な目的と成果は以下の通りです。

  1. 負荷試験の理解を深める
  • 「負荷試験とは何か?」について、チーム間で なんとなく理解する 状態を作る。
  • 負荷試験の目的や進め方を共有し、チーム全体で基本的な認識を揃えました。
  1. コスト認識の共有
  • システムが負荷に応じてスケールすることで、運用コストが変動する ことをビジネスチーム(biz)やデータサイエンティスト陣(ds)にも理解してもらいました。
  • これにより、コストとパフォーマンスのトレードオフについての認識が高まりました。
  1. 開発チームへの実践共有
  • 実際に負荷をかける場面を共有し、どのように負荷試験を行っているか を開発チーム(dev)に把握してもらいました。
  • 負荷試験ツールや監視の流れを見てもらうことで、チーム内のノウハウを共有する良い機会となりました。
  1. ビジネス要件の擦り合わせ
  • チーム間でビジネス的な要件を擦り合わせる ことが、今回の共有会で最も効果的だった点です。
  • システム設計や性能要件について、ビジネスサイドの視点と開発チームの視点をすり合わせることで、より明確な要件定義ができました。

最も効果があったこと:ビジネス要件の擦り合わせ

共有会の中でも特に重要だったのが、チーム間でビジネス的な要件を擦り合わせる ことです。ビジネスチーム、SREチーム、開発チームの間で性能要件やコスト認識について意見交換を行い、ビジネス視点と技術視点のギャップを埋めることができました。

この成果については、下記の記事「SREとビジネスの話」でも詳しく記載していますので、参考にしてみてください。

https://zenn.dev/oyasumipants/articles/d2a2648bbc8bc5

まとめ

負荷試験共有会は、技術的な成果を共有するだけでなく、チーム全体の理解や連携を強化する場として大きな成果がありました。

  • チーム間の認識合わせ
  • ビジネス要件と技術要件の擦り合わせ
  • コストとシステムスケールのトレードオフの共有

これにより、ビジネスと技術の両面からパフォーマンス要件を明確にし、システム設計の方向性がより明確になりました。

🔥 課題に思っていること

ここからは課題に思っていることを記載します。

1. オートスケールに関する柔軟性

Cloud Run のオートスケーリングにおいて、CPU 使用率が 60% で固定されている点 は柔軟性に欠けると感じました。

  • 課題:
    オートスケールのしきい値がカスタマイズできないため、
    • 「特定の条件で 80% まで CPU を使い切りたい」
    • 「余裕を持って 50% でスケールアウトしたい」

など、ユースケースに応じた設定ができないのは少し不便でした。

2. サイドカーが CPU 使用率に影響する

Cloud Run では CPU 使用率 の判定に メインコンテナとサイドカーの CPU 使用 が合算されて計算されます。

  • 問題点:
    サイドカーが CPU リソースを多く使用する場合、
    • メインコンテナの CPU 使用率が低くても、合計の CPU 使用率が 60% を超えている と判定されてしまう可能性があります。
    • これによって、本来はスケールアウトが不要な状況でも、新たなインスタンスが起動されてしまうことがありました。

3. 可視化の課題

Cloud Run のメトリクスでは、メインコンテナとサイドカーの CPU 使用率を個別に表示する方法 が見つかりませんでした。

  • 現状の問題:
    • CPU 使用率の合算値は Cloud Monitoring などで確認できますが、
      メインコンテナサイドカー の CPU 使用率がそれぞれどの程度かを確認する方法が分かりませんでした。
    • これができないと、どちらがボトルネックになっているのか を正確に把握するのが難しくなります。
  • 今後の課題:
    • メインコンテナとサイドカーの CPU 使用率を個別に可視化し、
      オートスケールの挙動をより精緻にチューニングできる環境 を整えることが必要だと感じました。
    • もし Cloud Monitoring や他の監視ツールで実現できる方法がある場合は、さらに調査を進めたいです。

🎄 最後に

いかがだったでしょうか。
今回は 「Cloud Run に高トラフィックなシナリオの負荷試験を行う際の参考書」 というテーマで記事をまとめてみました。

負荷試験を通じて得た成果として、安定して高負荷を処理できるアプリケーション を構築できたことを嬉しく思います。同時に、これからこのアプリケーションが 継続的に運用され、さらなる改善が加えられていく ことを強く願っています。

今後の課題と展望

現状の結果に満足するだけでなく、まだまだ改善すべき点や課題が残っています。例えば、以下のようなポイントです:

  1. サイドカーの計測
  • メインコンテナとサイドカーのリソース使用状況を正確に把握し、オートスケールの最適化を進める。
  1. 継続的に負荷試験を実施するための CI パイプライン
  • 定期的な負荷試験を自動化し、性能の退化や問題の早期発見ができる環境を整える。
  1. 予測不可能なリクエスト増加やワークロードへの対応
  • 突発的なスパイクにも柔軟に対応できるよう、システムの監視強化やオートスケーリング設定をさらに最適化する。

これらを実現するためには、負荷試験の基盤強化アプリケーションのさらなる改善、そして Cloud Run に対する理解の深化 が不可欠だと考えています。引き続き取り組みを進め、成長を続けていければと思います。

本記事が、Cloud Run を使ってアプリケーションを構築し、負荷試験を行う方々の参考になれば幸いです。少しでもお役に立つことができたら嬉しいです。

それでは、良い Cloud Run ライフを! 🚀

Discussion