TT Lab
はじめる
学ぶ 学習パス コース

負荷テスト

基準線を作る

TT Labで続きを見る

このラボは本物のVM上で動きます

この箱はPodではなく、KubeVirtが起動した仮想マシンです。Linuxカーネルが別に動き、systemdが実際にサービスを管理し、dockerは模倣ではなく本物のDockerエンジンです。docker runで起動したコンテナは実際にプロセスになり、docker execもdocker logsもそのまま動作します。

以前は、このラボはPodの中で動いていました。カーネルの権限をすべて下ろした箱なので、コンテナを起動するステップが塞がれていて、そのためイメージのアーカイブを直接展開してみるという回り道で学んでいました。もう回り道は必要ありません。

知っておくことが2つあります。

目標

実際のコンテナに負荷をかけて、RPS・p50・p95・p99・エラー率を取り出し、3回繰り返して、変動幅まで含めた再現可能なベースラインを/root/lt1/に作ります。

なぜ重要なのか

ベースラインがなければ、「遅くなった」という言葉は感想です。そしてベースラインは、数字だけでは足りません。同時実行数がいくつだったか、何件送ったか、いつ測ったかがなければ、来月に比較できないからです。指標を選ぶ基準も明確です。リクエスト10,000件のうち9,900件が50ms、100件が3,000msのとき、平均は79.5msで、実際に79.5msで応答を受けたリクエストは1件もありません。しかも、遅い100件が2倍悪化しても、平均は79.5 → 109.5msまでしか動きません。そのため、平均1つで判断せずに、p50・p95・p99を一緒に見て、最後には3回測って、変動幅より大きい差だけを「変化」と呼ぶことにします。

負荷ツールの出力の読み方

このイメージにはheyが入っています。出力には3つのセクションがあり、以降のステップはすべて、このセクションから値を読みます。

出力全体をそのまま保存してください。採点ツールが、あなたが書いた値を、この元データと再び突き合わせます。

ステップ

先にmkdir -p /root/lt1を実行しておいてください。

  1. 負荷対象のコンテナを起動します。名前: lt-web、ポート: ホスト127.0.0.1:8085 → コンテナ80、そしてcurl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8085/の結果が200である必要があります。\n 対象は応答時間に裾がある必要があります。ほとんどは速く、12件に1回ほど遅いサーバーをPythonで作って、python:3.12-alpineコンテナに入れてください。nginxで静的ファイルを返すと、1件が1msもかからず、平均とp95が同じ値になり、ステップ6で使う根拠がなくなります。
  2. スモーク実行の結果を/root/lt1/smoke.txtに保存します。総レスポンスが50件以上である必要があり、Requests/sec・Latency distribution・Status code distributionの3つのセクションが、すべてファイルにある必要があります。
  3. ウォームアップと本測定を分けます。/root/lt1/warmup.txt(ウォームアップ)と/root/lt1/run1.txt(本測定)をそれぞれ保存し、run1.txtの総レスポンスは200件以上である必要があります。
  4. /root/lt1/metrics.jsonに、5つのフィールドを書きます。rps、p50、p95、p99、error_rateです。最初の4つの値はrun1.txtから読んだ値そのまま(秒単位)、error_rateは2xx以外のレスポンス数 ÷ 全レスポンス数の比率(0–1)です。
  5. /root/lt1/errors.txtに3行を書きます。non2xx=(整数)、total=(整数)、rate=(パーセンテージ、小数第2位)です。最初の2つの値は、ステータスコード分布で数えた値と正確に同じである必要があります。
  6. /root/lt1/why.mdに、3行と説明を書きます。average_s=(run1.txtのAverage)、p95_s=(run1.txtの95%パーセンタイル)、ratio=(p95 ÷ 平均、小数第2位)です。そして、平均だけを見ると何を見逃すのかを、本文に、「平均」という単語を含めて説明してください。
  7. 同じ条件でもう2回測定して、/root/lt1/run2.txt、/root/lt1/run3.txtを作成し、/root/lt1/runs.csvにまとめます。形式は、1行目がヘッダーrun,rps,p95、続いてデータ行はちょうど3つ(1,<rps>,<p95>の形)、最後にspread=の行を置きます。spreadは、最大RPSから最小RPSを引いた値 ÷ 最小RPS × 100で、小数第1位までです。
  8. /root/lt1/baseline.jsonに、6つのフィールドを書きます。rps、p95、error_rate、concurrency、requests、measured_atです。rpsは3回の測定の中央値(真ん中の値)である必要があり、error_rateは0.01以下である必要があります(エラーが出ている状態の数字は、ベースラインになれません)。

参考

負荷対象のコンテナを起動する

負荷対象のコンテナを起動します。名前: lt-web、ポート: ホスト127.0.0.1:8085 → コンテナ80、そしてcurl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8085/の結果が200である必要があります。\n 対象は応答時間に裾がある必要があります。ほとんどは速く、12件に1回ほど遅いサーバーをPythonで作って、python:3.12-alpineコンテナに入れてください。nginxで静的ファイルを返すと、1件が1msもかからず、平均とp95が同じ値になり、ステップ6で使う根拠がなくなります。

名前は正確にlt-webで、ホスト127.0.0.1のポート8085をコンテナのポート80に接続する必要があります。ホスト側が1024未満だとバインドできないので、高いポートを使い、コンテナの内側はrootなので80をそのまま使ってもかまいません。対象は静的ファイルサーバーではなく、応答時間に裾があるサーバーである必要があります。そうしてこそ、ステップ6で平均とp95が分かれることを、自分の測定値で見られます。

スモーク実行でツールの出力を確認する

スモーク実行の結果を/root/lt1/smoke.txtに保存します。総レスポンスが50件以上である必要があり、Requests/sec・Latency distribution・Status code distributionの3つのセクションが、すべてファイルにある必要があります。

結果を/root/lt1/smoke.txtにそのまま保存します。サマリー・レイテンシ分布・ステータスコード分布の3つのセクションがすべて残る必要があるので、リダイレクトするときに一部だけを切り出してはいけません。最低50件以上を送ってください。

ウォームアップと本測定を分ける

ウォームアップと本測定を分けます。/root/lt1/warmup.txt(ウォームアップ)と/root/lt1/run1.txt(本測定)をそれぞれ保存し、run1.txtの総レスポンスは200件以上である必要があります。

warmup.txtとrun1.txtを別々に作ります。最初のリクエストは、キャッシュもコネクションもない状態を測るので、本測定に混ぜると分布が汚染されます。本測定は200件以上ないと、分布を見られません。

主要な指標5つをJSONにまとめる

/root/lt1/metrics.jsonに、5つのフィールドを書きます。rps、p50、p95、p99、error_rateです。最初の4つの値はrun1.txtから読んだ値そのまま(秒単位)、error_rateは2xx以外のレスポンス数 ÷ 全レスポンス数の比率(0–1)です。

/root/lt1/metrics.jsonの値は、run1.txtから読んだ値そのままである必要があります。でっち上げると、元データと突き合わせる過程で見つかります。エラー率は比率(0–1)で、ステータスコード分布から、2xx以外の件数を数えて求めます。

エラー率を手で計算する

/root/lt1/errors.txtに3行を書きます。non2xx=(整数)、total=(整数)、rate=(パーセンテージ、小数第2位)です。最初の2つの値は、ステータスコード分布で数えた値と正確に同じである必要があります。

/root/lt1/errors.txtに、non2xx / total / rateの3行を書きます。最初の2つの値は整数で正確に一致する必要があり、rateはパーセンテージです。ステータスコード分布のセクションの件数をすべて足すと、totalになります。

平均とp95の倍率を比較する

/root/lt1/why.mdに、3行と説明を書きます。average_s=(run1.txtのAverage)、p95_s=(run1.txtの95%パーセンタイル)、ratio=(p95 ÷ 平均、小数第2位)です。そして、平均だけを見ると何を見逃すのかを、本文に、「平均」という単語を含めて説明してください。

/root/lt1/why.mdに、average_s / p95_s / ratioの3行と、平均がなぜ足りないのかの説明を書きます。ratioは、p95を平均で割った値です。値はrun1.txtから読んでください。

3回の繰り返し測定と変動幅

同じ条件でもう2回測定して、/root/lt1/run2.txt、/root/lt1/run3.txtを作成し、/root/lt1/runs.csvにまとめます。形式は、1行目がヘッダーrun,rps,p95、続いてデータ行はちょうど3つ(1,<rps>,<p95>の形)、最後にspread=の行を置きます。spreadは、最大RPSから最小RPSを引いた値 ÷ 最小RPS × 100で、小数第1位までです。

同じ条件でrun2.txt、run3.txtをさらに作って、runs.csvにまとめます。変動幅は、最大と最小の差を最小で割ったパーセンテージです。この値より小さい差は、改善と呼べません。

ベースラインを確定する

/root/lt1/baseline.jsonに、6つのフィールドを書きます。rps、p95、error_rate、concurrency、requests、measured_atです。rpsは3回の測定の中央値(真ん中の値)である必要があり、error_rateは0.01以下である必要があります(エラーが出ている状態の数字は、ベースラインになれません)。

/root/lt1/baseline.jsonには、数字だけでなく、測定条件も一緒に入れて初めて、あとで比較できます。代表値は3回のうちの真ん中の値で、エラーが出ている状態の数字は、基準になれません。