yoshikipom Tech Blog

GoReplayで検証環境へ本番環境のリクエストを復元する方法と懸念

やりたいこと

  • (1) 検証環境で本番環境へのリクエストを再現したい
  • (2) トラフィックミラーリングではなく、任意のタイミングで任意の流量で再現したい
  • (3) 本番環境の機密情報を検証環境に持ち込みたいくない
  • (4) 本番環境への影響・変更は最低限に留めたい
  • (5) 対象アプリケーションはECSで動作しているとする

GoReplayで実現できるか?

「やりたいこと」の(1)、(2)に対応できるか。 GoReplay(https://github.com/buger/goreplay) の gor コマンドには 入力元と出力先を指定する必要がある。 参考: https://github.com/buger/goreplay/wiki/The-Basics

ミラーリングするだけならば入力: HTTPトラフィック、出力 HTTPトラフィック とすることですぐさまリクエストをコピーして転送できる。

ローカルでテストした例。(左: リクエスト対象サーバ、中央: コピー先サーバ、右:実行したgorコマンド)
HOSTヘッダ以外は同様のものをコピー先サーバで受信できていることがわかる。

今回検討したいことは任意のタイミングでのリプレイなので、入力・出力は以下のようになる。 (本番環境) 入力: HTTPトラフィック、出力: ファイル (検証環境) 入力: ファイル、出力: HTTPトラフィック アーキテクチャは以下のようなイメージ。

GoReplayをも用いて検証環境でリプレイするイメージ

GoReplayのPRO版ならばS3に保存する機能がついている。これを使わない場合、他の手段でアプリケーションのコンテナからファイルをどこかに保存する必要がある(この記事では省略)。 参考: https://github.com/buger/goreplay/wiki/%5BPRO%5D-Using-S3-for-storing-and-replaying-traffic

リプレイ時の流量調整もコマンドで対応可能 (|200%部分)。

# Replay from file on 2x speed 
gor --input-file "requests.gor|200%" --output-http "staging.com"

参考: https://github.com/buger/goreplay/wiki/Saving-and-Replaying-from-file#:~:text=change%20line%20endings.-,Performance%20testing,-Currently%2C%20this%20functionality

基本的な機能はこれでカバーできそうである。

データの変換、フィルタリング

「やりたいこと」の(3)に対応できるか。 ミドルウェアビジネスロジックの注入が可能。 参考: https://github.com/buger/goreplay/wiki/Middleware ミドルウェアの実装はアプリケーション次第だが、変換ロジックに外部との通信などコストが高い処理があるとアプリケーションコンテナに負荷がかかってしまう。 ミラーリングの場合でも無視できないレベルの負荷がありそう。 GoReplay利用時のベンチマークの参考 -> https://blog.glidenote.com/blog/2016/12/16/goreplay/

この部分は機能面では実現はできるはずだが、ロジック次第ではパフォーマンスの考慮が必要。

本番環境への影響

「やりたいこと」の(4)に対応できるか。 GoReplayはコンテナ内ではアプリケーションへのリクエストをプロキシしているわけではなく、コンテナに来たHTTPリクエストを取得している。GoReplayに問題があってもアプリケーションは問題なく動く。 懸念点の一つ目は、前節でも挙げたパフォーマンスである。負荷試験を行い、必要があればインフラを増強する必要がある。 また、別の問題点として、アプリケーションのDocker Imageへの改修が必要なことである。結果として、アプリケーションが複雑化してしまったり、切り戻り処理にそのアプリケーションのデプロイが必要になる可能性がある。

この問題を完全に回避するなら AWSVPC トラフィックミラーリングを使って、GoReplayのキャプチャ用コンテナにリクエストを流すという方法が考えられそう。 https://aws.amazon.com/jp/blogs/news/new-vpc-traffic-mirroring/

そもそも別の手段でミラーリングするならGoReplayが不要とも考えられるが、以下の理由でこの構成もありかもしれない。

  • リプレイ側で使える機能がとても便利そう(流量制限、複数ファイルの結合、同じファイルをループして利用、ミドルウェアなど)
  • リプレイで使うファイルが独自形式

感想

多機能でドキュメントもしっかりしていて、よく考えられたツールという印象。大規模システムで使う場合はパフォーマンスやデータの要件など細かい点の検討が必要になるとは思う。