負荷テストツール K6 について調べてみた

Tatsuya Ikeda

2022.9.1

はじめに

K6 を初めて触ってから 7-8ヶ月くらいたったので、K6 のツール周りに関する情報紹介で
社内で発信した情報をまとめてみました。

k6 jslib

まず、K6 には k6 jslib という K6 の拡張ツール等があります。

https://jslib.k6.io/

NAMEVERSION(S)DOCS
k6-utils1.0.01.1.01.2.01.3.01.4.0https://k6.io/docs/javascript-api/jslib/utils
k6-summary0.0.1
jsonpath1.0.2https://github.com/grafana/k6-jslib-JSONPath
formdata0.0.10.0.2
form-urlencoded3.0.0
papaparse5.1.1https://www.papaparse.com/docs
ajv6.12.5https://ajv.js.org/api.html
httpx0.0.10.0.20.0.30.0.40.0.50.0.6https://k6.io/docs/javascript-api/jslib/httpx
expect0.0.40.0.5https://k6.io/docs/javascript-api/jslib/expect
k6chaijs4.3.4.04.3.4.1https://github.com/grafana/k6-jslib-k6chaijs
k6chaijs-contracts4.3.4.0https://github.com/grafana/k6-jslib-k6chaijs-contracts
url1.0.0
kahwah0.1.6https://www.npmjs.com/package/kahwah
aws0.1.00.3.00.4.0https://github.com/grafana/k6-jslib-aws
Available libs

K6 は Javascript を用いて負荷試験のテストを実施するのですが、Golang の内部で CMAScript 2015+(ES6+)を実行しています。

K6 は NodeJS でも、ブラウザーでもありません。
NodeJS によって提供される API に依存するパッケージ、たとえば os と fs モジュールは K6 では機能しません。

その為、データ加工などのモジュールを提供しているのがこれらです。

https://k6.io/docs/javascript-api/jslib/utils/

※ CMAScript 2015+(ES6+)に準拠しない記述を意識する必要はありません。

k6-jslib-aws が登場だが gcp 版はない

https://github.com/grafana/k6-jslib-aws

k6-jslib-aws では S3 の操作、SecretsManager からの値取得、V4 signatureの作成の機能があります。
ちょうど V4 signature が必要な認証があったので非常に助かりました。

実行結果出力のあれこれ

負荷テストでは、大体30分-1時間。または長期ではそれ以上の実行を実施することになります。
その為、途中でのログ消失はテストのやり直しが発生するので事前に対処をしたいところです。

下記のような方法をとって対策できます。

  • リアルタイムで inflaxdb にデータ転送を行う仕組み
    https://k6.io/docs/results-visualization/influxdb-+-grafana/
    inflaxdb を構築して out すれば良いですが、結構なデータ量になるので、volumeは大きめに設定するとよいです。
    CloudWatch や Datadog 等にも転送が可能ですが、費用と相談になると思います。
k6 run test.js --out influxdb=http://**.**.**.**:8086/k6
  • handleSummary でログをファイル出力する、k6-Sumarry と k6-reporter 基本は標準出力に吐かれてしまうが、終了処理前に処理を差し込めるのでこちらが安全です。
    https://github.com/grafana/k6/pull/1849
import {textSummary }from "https://jslib.k6.io/k6-summary/0.0.1/index.js";
import {htmlReport} from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
export function handleSummary(data) {
  return {
      stdout: textSummary(data, { indent: " ", enableColors: true }),
      "summary.html": htmlReport(data),
      'summary.json': JSON.stringify(data),
  }
}

k6-reporterの出力結果は下記のような形です。 (そんなに見やすくないのでおまけ程度)

中間集計を取得できる機能のプルリクエストがありましたがマージされていませんでした。

https://k6.io/docs/getting-started/results-output/

負荷試験の実装を簡略化

Swagger/OpenAPI 仕様から openapitools/openapi-generator-cli を使って K6 用の JavaScript を出力できます。

Interface 仕様として、正しく Swagger/OpenAPI が利用されていれば、負荷試験も楽になります。

https://k6.io/blog/load-testing-your-api-with-swagger-openapi-and-k6/

$ docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
    -i http://httpbin.test.loadimpact.com/spec.json \
    -g k6 \
    -o /local/k6-test/
    --skip-validate-spec
import http from 'k6/http';
import { group, check, sleep } from 'k6';

const BASE_URL = 'https://httpbin.org/';
const SLEEP_DURATION = 0.1;

export default function () {
  group('/absolute-redirect/{n}', () => {
    const n = 2;
    const url = BASE_URL + `/absolute-redirect/${n}`;
    // Request No. 1
    const request = http.get(url);
    sleep(SLEEP_DURATION);
  });
}

理想の負荷テスト環境に関して

社内の共有会で、私の考えるベストな負荷テスト環境の話をしました。

K6 は1つのインスタンスで30万リクエストかけられると謳っており、
他テストツールと比べて非常に高パフォーマンスらしいです。

それでも実際のところ、下記のような課題がありました。

  • 計測する負荷に対して、メモリ、CPU に余裕があるインスタンスが必要
    ・確かめなきゃならないから面倒(rps 100-200 の世界なら適当に大きめでいい)
    ・途中で限界が来たら計測がやり直しになってしまう
  • network capacity も見なければならない
    ・https://k6.io/docs/testing-guides/running-large-tests/
  • 計測時間と負荷量が大きくなるにつれ結果メトリクスが肥大化する
    ・Volume も必要
    ・metrics のレート変えられない(知らない)

その為、Kubernetes 上に K6 を apply して実行する環境の話をしました。
やっぱり Kubernetes 上でやりたいし、locast とかは hello world がそれになってる。

GKE Autopilot に載せるだけでメリットがあります。

  • リソース量は自動スケール
  • インスタンス料金も適正に
  • inflax + Grafana は適当に逃せばよい

K6-Operator

https://github.com/grafana/k6-operator

Kubernetes 上で K6 を動作させる CRD k6-operator の登場でこの環境の実現が容易になりました。
Configmap から JavaScript を投入しテストを実施する形です。

また、k6 Script が大規模なものになってきていても K6 自体は、test.js 群を archive 化して実行する機能も追加されているので、ファイル管理もシンプルにできます。

Archive Command

社内で試すのはまだ先になりそうですが、腰を据えてやれる機会があればやりたいです。

Pipeline に K6 を仕込むための Action が存在する

Github Action, CircleCI 自体もそれぞれ K6 の為のものが存在する為、 独自でコンテナを用意する必要はないです。軽い負荷や E2E に使うならこれで十分です。

https://github.com/grafana/k6-action
CircleCI Developer Hub – grafana/k6

上述の OpenAPICLient を使えば、Git push → Generate → E2E テストor 負荷テストまで自動化することもできそうです。
Swagger, アプリケーション、インフラまでの整合性確認が自動化しやすくなり、もちろんその結果は、Grafana や Datadog 等で視覚化できます。

Headless Browser を使ったブラウザテスト

https://k6.io/blog/announcing-xk6-browser-testing/

Web 画面のテストを行うときに利用できるヘッドレスブラウザです。
ユーザー アクション (ナビゲーション、マウスとキーボードのアクション、スクリーンショットの撮影)などの操作スクリプトを作成できます。

Playwright API 互換を目指しているようですが、K6 内での動きはそれと異なる場合があります。
これは K6 が Node.js の上で動いていないかつ、イベントループをサポートしていないためです。

ブラウザ操作から、test 用 js を作る k6 Browser Recorder

https://chrome.google.com/webstore/detail/k6-browser-recorder/phjdhndljphphehjpgbmpocddnnmdbda

こちらは Chrome の拡張として提供されています。ブラウザの操作から K6 のスクリプトを生成します。
生成されたスクリプトは k6.io のクラウドアカウントへアップロードされる為、k6.io への登録が必要です。

まとめ

いかがでしたでしょうか。
K6 を用いることで負荷試験のみならず、SRE の痒いところに手が届くかもしれないと思います。
負荷テストというと JMeter を用いることも多いかと思いますが、この記事が K6 を知るきっかけになれば幸いです。

また、K6 のTest Type は負荷テストの目的や、実施項目の理解の走り出しに良いドキュメントなので、読んでみるのをお勧めします。
https://k6.io/docs/test-types/introduction/

最後までお付き合いいただきありがとうございました。

ブログ一覧へ戻る

お気軽にお問い合わせください

SREの設計・技術支援から、
SRE運用内で使用する
ツールの導入など、
SRE全般についてご支援しています。

資料請求・お問い合わせ