APIが1人のユーザーに対してはうまく機能するものの、トラフィックが多いと機能不全に陥る場合、ロードテストが必要です。k6はそれを実行するための最もクリーンな方法の1つです。このガイドでは、k6とは何か、そのインストール方法、初めてのスクリプトの書き方、結果の読み取り方について説明し、ロードテストを通常のAPIパフォーマンステストルーチンの一部として扱えるようにします。また、詳細が重要な場合は公式のk6ドキュメントを参照しながら、CIにおけるk6が機能テストとどのように適合するかについても見ていきます。
k6とは?
k6は、現在Grafanaによって管理されているオープンソースのロードテストツールです。テストをJavaScriptファイルとして記述し、k6が高速なGoエンジンで実行し、シミュレートされたトラフィックでエンドポイントを叩きます。この分離は意図的なものです。ほとんどの開発者がすでに知っている言語でテストを作成しますが、ロードジェネレーター自体はコンパイルされたGoとして実行されるため、1台のマシンが処理能力を低下させることなく多くの仮想ユーザーを駆動できます。

k6は1つの仕事のために作られ、それを完璧にこなします。それは、持続的で再現性のある負荷を生成し、システムがどのように応答するかを測定することです。レイテンシのパーセンタイル、リクエストレート、エラーレートを報告し、それらの数値に基づいて合否ルールを設定できます。この焦点こそが重要です。k6はAPIクライアントでも、ドキュメンテーションツールでも、機能テストフレームワークでもありません。ロードエンジンなのです。
頻繁に目にする用語をいくつか紹介します。
- Virtual user (VU)(仮想ユーザー):スクリプトをループで実行するシミュレートされたユーザー。VUが多いほど、同時実行負荷が高くなります。
- Iteration(イテレーション):テスト関数を1回完全に実行すること。VUはイテレーションを連続して実行します。
- Stage(ステージ):負荷プロファイル内のステップで、時間の経過とともにVUを増減させるために使用されます。
- Threshold(閾値):メトリクスに対する合否ルール。例えば、「95パーセンタイルのレイテンシは500ms未満でなければならない」などです。
- Check(チェック):レスポンスに対する致命的ではないアサーション。例えば、「ステータスが200だった」などです。失敗したチェックはカウントされますが、テストは続行されます。
k6のインストール
k6は単一のバイナリとして提供されるため、インストールは短時間で完了します。Homebrewを使用しているmacOSの場合:
brew install k6
Chocolateyを使用しているWindowsの場合:
choco install k6
DebianまたはUbuntuの場合、Grafanaのaptリポジトリを追加してインストールします:
sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg \
--keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" \
| sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6
動作することを確認します:
k6 version
ローカルに何もインストールしたくない場合は、Dockerイメージも利用可能です。パッケージの詳細は時間の経過とともに変更されるため、現在のコマンドについてはドキュメントのインストールページを確認してください。
初めてのk6スクリプト
k6テストは、デフォルト関数を持つJavaScriptモジュールです。k6は、VUごとにイテレーションごとにその関数を1回呼び出します。以下は、1つのエンドポイントにアクセスし、レスポンスをチェックする最小限のスクリプトです:
import http from 'k6/http';
import { check, sleep } from 'k6';
export default function () {
const res = http.get('https://test-api.example.com/users');
check(res, {
'status is 200': (r) => r.status === 200,
'body is not empty': (r) => r.body.length > 0,
});
sleep(1);
}
これをscript.jsとして保存し、実行します:
k6 run script.js
デフォルトでは、k6は1つのVUで1つのイテレーションを実行します。sleep(1)は、イテレーション間に1秒のポーズを追加し、実際のユーザーがアクション間にポーズをとる様子を模倣します。sleepがない場合、各VUはネットワークが許す限り高速でループします。これは生の処理能力テストには役立ちますが、ユーザーの行動シミュレーションには非現実的です。
check()の呼び出しはソフトなアサーションです。失敗したチェックはサマリーに表示されますが、実行は停止しません。これは意図的なものです。高負荷下ではいくつかの障害が発生することを予想しており、どれだけ悪化するかを確認するためにテストが測定を続けることを望みます。
VU、ステージ、および閾値
最初のスクリプトは単一のユーザーを1回実行します。実際のロードテストは、APIを叩くユーザーの数と期間を制御することに関係します。これはエクスポートされたoptionsオブジェクトで設定します。
最も単純な形式では、固定数のVUと期間を設定します:
export const options = {
vus: 50,
duration: '30s',
};
これは50人の仮想ユーザーを30秒間実行します。より便利なのは、ステージから構築されたランププロファイルで、トラフィックの増加、維持、減少をシミュレートできます:
export const options = {
stages: [
{ duration: '1m', target: 100 }, // 100 VUまで増加
{ duration: '3m', target: 100 }, // 100 VUを維持
{ duration: '1m', target: 0 }, // 0 VUまで減少
],
thresholds: {
http_req_duration: ['p(95)<500'], // リクエストの95%が500ms未満
http_req_failed: ['rate<0.01'], // エラーが1%未満
},
};
閾値は、k6がCIでその価値を発揮する場所です。閾値が失敗した場合、k6はゼロ以外のコードで終了します。これは、パイプラインのステップが、設定したラインをレイテンシやエラーレートが超えたときにビルドを失敗させることができることを意味します。機能的なアサーションをコード化するのと同じ方法で、パフォーマンス予算をコードとしてエンコードしているのです。
一般的なロードプロファイルと、それぞれが答える質問の簡単な対応図:
| プロファイル | 目的 | 何がわかるか |
|---|---|---|
| スモーク | ごくわずかな負荷でスクリプトの実行を検証する | テスト自体が正しいことを確認する |
| ロード | 予想される通常のトラフィック | APIが日々持ちこたえるか |
| ストレス | 予想されるピークを越えて負荷をかける | どこで破綻し始めるか |
| スパイク | VUが急激に跳ね上がる | トラフィックの急増に耐えられるか |
| ソーク | 数時間にわたる中程度の負荷 | メモリリーク、ゆっくりとした劣化 |
これら5つすべてが必要なわけではありません。スモークとロードから始めましょう。通常の数値がわかったら、ストレスとスパイクを追加します。アプローチとそれらを支えるメトリクスのより広範な調査については、パフォーマンステストの基礎はk6だけでなく、すべてのツールに共通して当てはまります。
k6の結果を読む
実行が終了すると、k6はターミナルにサマリーを出力します。最も重要な行は次のとおりです:
- http_req_duration: 総リクエスト時間。平均、最小、最大、中央値、p90、p95として表示されます。p95とp99のパーセンタイルは、最も遅いユーザーが実際に経験する状況を示します。平均値は痛みを隠し、パーセンタイルがそれを表面化させます。
- http_req_failed: 失敗したリクエストの割合。VUが増加するにつれてこれがどのように変化するかを監視します。
- http_reqs: 総リクエスト数と1秒あたりのリクエスト数。これがスループットです。
- iterations: 完了した全パスの数とレート。
- vus および vus_max: アクティブな仮想ユーザー数とピーク時の仮想ユーザー数。
- checks:
check()アサーションの合格率。
平均ではなくパーセンタイルを読みましょう。平均応答時間が200msだと問題ないように聞こえますが、p99が4秒だと、100人に1人のユーザーが4秒待っていることになります。そのテール部分でユーザーは離れていきます。
ターミナルで目視する以上のことには、k6は結果を外部出力にストリーミングできます。JSONまたはCSVで書き込み、GrafanaダッシュボードやPrometheusと統合して、実行中のライブの視覚分析が可能です。この組み合わせ、k6とGrafanaは、ツールが「grafana k6」と呼ばれることが多い理由です。1回限りのテストではターミナルサマリーで十分ですが、継続的な監視には、メトリクスをグラフ化できる場所に送信しましょう。
k6とApidogの使い分け
k6はロードエンジンです。「システムは持続的なトラフィック下でどのように動作するか」という問いに答えます。APIが正しいデータを返すか、契約に合致しているか、すべてのエンドポイントで認証が正しく処理されるかといったことはチェックしません。これらは機能テストおよび契約テストの質問であり、別のツールが必要です。
この区別を明確に保つことが重要です。パイプラインには両方の種類のテストが必要であり、これらは競合しません。
| 関心事 | 最適な処理ツール | 何に答えるか |
|---|---|---|
| 持続的な重負荷、大規模なパーセンタイル | k6 | トラフィック下でも高速に保たれるか |
| 機能的な正確性、契約、認証 | Apidog | 正しいものを返すか |
| CIでのコミットごとのリグレッション | Apidog (apidog run) |
この変更がエンドポイントを破壊したか |
| CIでのパフォーマンス予算 | k6の閾値 | レイテンシやエラーがラインを超えたか |
Apidogは正確性の側面を扱います。APIを設計またはインポートし、ビジュアルアサーションを使用してテストシナリオを構築し、k6スクリプトを実行するのと同じように、apidog runを使用してCIで実行します。Apidog CLIガイドでは、これらの機能テストをパイプラインに組み込む方法を説明しています。Apidogには、簡単なチェックのための軽量なパフォーマンステスト機能も含まれており、ApidogでのAPIパフォーマンステストのチュートリアルで説明されていますが、k6クラスのロードジェネレーターではなく、その役割を目指しているわけではありません。
実用的なワークフローは次のようになります。コミットごとに、Apidogが機能テストと契約テストを実行し、APIが意図したとおりに機能していることを確認します。スケジュールまたはリリース前に、k6がステージング環境に対してロードプロファイルを実行し、APIがトラフィック下でも高速に維持されていることを確認します。正確性ゲートとパフォーマンスゲートを、それぞれのために構築されたツールで。
コミット前にエンジンを比較しているのであれば、k6はJMeter、Gatling、Locustと並びます。ロードテストツール比較とLocust代替比較では、スクリプト言語やスケールが選択を変える場合のトレードオフが示されています。
よくある質問
k6は無料ですか?
はい。k6はAGPLライセンス下のオープンソースであり、バイナリはハードウェアの制約を超えて仮想ユーザーに制限なくローカルで自由に実行できます。Grafanaはk6 Cloudも提供しており、大規模な分散テストの実行と結果の保存のための有料サービスですが、それを使用する必要はありません。コアツールでほとんどのチームに対応できます。まず他の無料オプションをスキャンしたい場合は、ロードテストツールの概要にそれぞれの提供内容がリストされています。
k6を使用するためにJavaScriptを知る必要がありますか?
深い専門知識ではなく、基本的なJavaScriptが必要です。ほとんどのk6スクリプトは、デフォルト関数、いくつかのhttp.getまたはhttp.post呼び出し、いくつかのチェック、およびオプションオブジェクトで構成されます。このガイドの例を読めるのであれば、動作するテストを作成できます。ビルドステップもフレームワークを学ぶ必要もなく、k6 APIだけです。
k6とApidogのパフォーマンステストにおける違いは何ですか?
k6は、持続的な重いトラフィックを駆動し、大規模なパーセンタイルを報告するために構築された専用のロードジェネレーターです。Apidogは、設計、機能テスト、契約テストに焦点を当てたAPIプラットフォームであり、簡単なチェックのための軽量なパフォーマンステスト機能を備えています。実際の負荷とCIパフォーマンス予算が必要な場合はk6を使用してください。正確性、契約検証、およびコミットごとの機能テストの実行にはApidogを使用してください。これらは異なる問題を解決し、うまく連携します。
k6をCI/CDで実行できますか?
はい、一般的なセットアップです。閾値が失敗するとk6はゼロ以外のコードで終了するため、あらゆるCIシステムがパフォーマンスリグレッション時にビルドを失敗させることができます。k6 run script.jsをパイプラインステップとして実行し、ステージング環境を指し、p95レイテンシとエラーレートの閾値を設定します。apidog runからの機能テストと組み合わせて、各コミットで正確性チェックと負荷チェックの両方を行うようにします。
まとめ
k6は、APIに実際の負荷をかけ、何が起こるかを測定するためのクリーンでスクリプト可能な方法を提供します。バイナリをインストールし、短いJavaScriptファイルを作成し、VUとステージを設定し、閾値を追加して、パーセンタイルを読み取ります。それが全体のループです。それぞれが異なる質問に答えるため、ロードテストは機能テストと分けて行い、両方をCIで実行して見落としがないようにしましょう。
その区分の正確性の側面については、Apidogを使用すると、APIを1か所で設計、テスト、モック、ドキュメント化し、その後apidog runでCIで機能テストを実行できます。k6のロード実行と契約レベルの確実性を組み合わせるためにApidogをダウンロードしてください。
