🎃

【負荷テスト】k6-operatorをk3d上で試してみる!!

2023/10/28に公開

※ 個人ブログを閉鎖するので個人ブログに書いていたものを転載

k6-operatorでKubernetes上に分散負荷テスト環境を構築

この記事では、公式ドキュメントに基づいて、Kubernetes上で分散負荷テストを行うためのk6-operatorを設定していきます。

前提条件

  • リクエスト先はホストPCのDocker-composeで動かしているnginx
  • 結果の出力先はホストPCのDocker-composeで動かしているinfluxdb(結果はGrafanaから確認)

k6-operatorをk3d上で動かす

ツールのインストール

公式ドキュメントの記載に沿って行っていきますが、リクエスト先や結果の出力先は以下のように変更しています。(前回作成したものの流用)

リクエスト先はホストPCのdocker-composeで動かしているnginx
結果の出力先はホストPCのdocker-composeで動かしているinfluxdb(結果はgrafanaから確認)

brew install k3d
brew install make
brew install kubectl
brew install kustomize
brew install stern

k6-operatorをcloneする

k6-operatorはツールとして配布されているわけではないのでcloneして使用します。

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

docker-composeを起動

前回の記事で作成したdocker-compose.yamlと同様のものを作成

version: "3.6"
services:
  nginx:
    image: nginx:latest
    container_name: loadtest_nginx
    ports:
      - "80:80"
 
  grafana:
    image: grafana/grafana
    container_name: loadtest_grafana
    ports:
      - '3000:3000'
    user: 'root'
    depends_on:
      - influxdb
 
  influxdb:
    image: influxdb:1.8 # k6でがv2に対応していないため1.8を指定
    container_name: loadtest_influxdb
    ports:
      - '8086:8086'
    environment:
      - INFLUXDB_DB=loadtest

docker-composeを起動

docker-compose up -d

k3dのクラスター作成

k3d cluster create loadtest-cluster

k6-operatorをk3dにデプロイ

cd k6-operator
 
# contextが前の手順で作成したものになっていることを確認(違ったらset-contextsしてください)
kubectl config get-contexts
 
# k6-operatorのMakefileに定義されているdeploy
make deploy

テストスクリプトを作成

適当なテストスクリプトを用意!相変わらずリクエスト先はホストPCのdocker-composeで動かしているnginxです。

import http from 'k6/http';
import { check } from 'k6';
 
export const options = {
  stages: [
    { target: 100, duration: '10s' },
    { target: 200, duration: '10s' },
  ],
};
 
export default function () {
  # k3dではhost.k3d.internalでホストPCを指定できる
  const result = http.get('http://host.k3d.internal:80');
  check(result, {
    'http response status code is 200': result.status === 200,
  });
}

テストスクリプトのデプロイ

テストスクリプトをconfigmapとしてデプロイします。別のテストスクリプトをデプロイする場合はconfigmap名を変更する必要があります。

# コンフィグマップを作成
kubectl create configmap k6-operator-sample --from-file ./k6-operator-sample.js
 
# コンフィグマップの確認
kubectl describe configmap k6-operator-sample

カスタムリソースを作成

カスタムリソースを作成します!

apiVersion: k6.io/v1alpha1
kind: K6
metadata:
  name: k6-load-test
spec:
  parallelism: 4
  arguments: --out influxdb=http://host.k3d.internal:8086/loadtest # ホスト側で動いているinfluxdbへ結果を送信する
  script:
    configMap:
      name: k6-operator-sample
      file: k6-operator-sample.js

テスト実行(カスタムリソースのapply)

applyするとテスト実行されるのでその前にsternを起動しログを見れるようにしています。

# sternを起動(フォアグラウンドで動くので別ターミナルを起動すること)
stern k6-load-test
 
# テスト実行する
kubectl apply -f ./custom-resource.yml

sternで以下のように結果(4つ分でているはず)とpodが削除されるログが表示されるはずです。

k6-load-test-1-hrqnv k6
k6-load-test-1-hrqnv k6      ✓ http response status code is 200
k6-load-test-1-hrqnv k6
k6-load-test-1-hrqnv k6      checks.........................: 100.00% ✓ 10296      ✗ 0
k6-load-test-1-hrqnv k6      data_received..................: 8.8 MB  437 kB/s
k6-load-test-1-hrqnv k6      data_sent......................: 886 kB  44 kB/s
k6-load-test-1-hrqnv k6      http_req_blocked...............: avg=256.93µs min=691ns    med=1.78µs  max=131.69ms p(90)=2.52µs  p(95)=3.09µs
k6-load-test-1-hrqnv k6      http_req_connecting............: avg=254.33µs min=0s       med=0s      max=131.61ms p(90)=0s      p(95)=0s
k6-load-test-1-hrqnv k6      http_req_duration..............: avg=49.03ms  min=851.62µs med=45.82ms max=248.95ms p(90)=93.29ms p(95)=107.29ms
k6-load-test-1-hrqnv k6        { expected_response:true }...: avg=49.03ms  min=851.62µs med=45.82ms max=248.95ms p(90)=93.29ms p(95)=107.29ms
k6-load-test-1-hrqnv k6      http_req_failed................: 0.00%   ✓ 0          ✗ 10296
k6-load-test-1-hrqnv k6      http_req_receiving.............: avg=1.84ms   min=15.6µs   med=54.48µs max=141.67ms p(90)=90.3µs  p(95)=192.29µs
k6-load-test-1-hrqnv k6      http_req_sending...............: avg=9.85µs   min=3.66µs   med=8.01µs  max=913.01µs p(90)=11.32µs p(95)=22.31µs
k6-load-test-1-hrqnv k6      http_req_tls_handshaking.......: avg=0s       min=0s       med=0s      max=0s       p(90)=0s      p(95)=0s
k6-load-test-1-hrqnv k6      http_req_waiting...............: avg=47.18ms  min=810.77µs med=44.73ms max=164.92ms p(90)=90.75ms p(95)=101.98ms
k6-load-test-1-hrqnv k6      http_reqs......................: 10296   512.702559/s
k6-load-test-1-hrqnv k6      iteration_duration.............: avg=49.36ms  min=892.73µs med=46.05ms max=249.03ms p(90)=93.78ms p(95)=108.07ms
k6-load-test-1-hrqnv k6      iterations.....................: 10296   512.702559/s
k6-load-test-1-hrqnv k6      vus............................: 48      min=0        max=48
k6-load-test-1-hrqnv k6      vus_max........................: 50      min=50       max=50
- k6-load-test-2-94klf › k6
- k6-load-test-4-8qrww › k6
- k6-load-test-3-4jbfr › k6
- k6-load-test-1-hrqnv › k6

grafanaで確認したらこのように表示されます。いい感じ!!

grafanaへのアクセス方法等は以下を参考にしてください。

後片付け

# カスタムリソースの削除
kubectl delete -f ../custom-resource.yml
 
# クラスター削除
k3d cluster delete loadtest-cluster

最後に

今回はk3d上で試しましたが、EKSとかGKEで今後試してみようと思います。

今回の使用したコードは以下に配置しています。(k6-operatorディレクトリはgithub管理対象外にしているのとファイル配置箇所が少し違います)

https://github.com/i-shinya/k6-github-actions-sample/pull/5

参考

Discussion