k6-operatorを利用したk8s上での負荷テストの実行
はじめに
この記事は前回紹介したk6をKubernetes内で実行する記事の続きです。
上記の記事では、k6を自前でビルドしてJobとしてデプロイしていました。
ただ、上記の場合だとスクリプトの変更でコンテナをビルドし、コンテナレポジトリにPushする必要がありました。
今回紹介するk6-operatorを利用すればベースとなるk6の実行環境とスクリプトをわけることができ、より使いやすくなります。
環境
- Docker Desktop for mac: v4.27.1
- Kubernetes: k3d
k6-operatorについて
k6-operatorはKubernetes Operatorの一つで、負荷テスト定義をCustom ResourceとしてApllyすると、このOperator Controllerが変更を検知し、クラスターの状態を更新します。必要があれば、k6テストのジョブを作成します。
引用元: https://grafana.com/blog/2022/06/23/running-distributed-load-tests-on-kubernetes/
k6-operatorのデプロイ
k6-operatorのデプロイにはhelm chartを利用します。
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm upgrade k6-operator grafana/k6-operator \
--install \
--namespace k6-operator \
--create-namespace
k6の実行
1回きりの実行
テスト定義をCustom Resourceとして作成します。
今回k6のスクリプトはArchiveコマンドを実行し、tarファイルとした上でConfigMapとして登録しています。
このk6スクリプトにCSVファイルを読み取って、利用するためです。
apiVersion: k6.io/v1alpha1
kind: TestRun
metadata:
name: k6-test
namespace: k6-operator-system
spec:
parallelism: 1
script:
configMap:
name: "k6-script-binary"
file: "k6-script.tar"
runner:
env:
- name: RAMP_UP_DURATION
value: '1m'
- name: RAMP_UP_TARGET
value: '3'
- name: STEADY_STATE_DURATION
value: '60m'
- name: STEADY_STATE_TARGET
value: '3'
- name: RAMP_DOWN_DURATION
value: '30s'
- name: RAMP_DOWN_TARGET
value: '0'
envFrom:
- configMapRef:
name: k6-operator-configmap
- secretRef:
name: k6-test-secrets
arguments:
# Write metrics to the prometheus
-o experimental-prometheus-rw
主な設定項目
-
spec.runner.env
: ジョブの実行時間などをここで定義し、k6の実行スクリプトは環境変数からこれらの値を読み込むことでテストの実行時間を変更することが容易になります。 -
spec.runner.envFrom
: Prometheusの接続先など固定した環境変数などあれば、ConfigMap, Secretとして登録し動的に設定することも可能です。 - arguments: k6を実行する上での引数です。ここの例ではPrometheusへ結果をメトリクスとして書き出すための設定を記載しています。
テストの実行はカスタムリソースをデプロイするだけです。
kubectl apply -f ./custom-resource.yaml
テスト終了後もカスタムリソースを削除しなければ、テスト実行用のコンテナは残ったままです。コンテナの中のログを確認することができます。
次回実行時にこのカスタムリソースが残っているとテスト実行がされないので、終了後はカスタムリソースを削除します。
kubectl delete -f ./custom-resource.yaml
定期的な実行
上記のカスタムリソース定義をConfigMapとして登録しておき、CronJobで作成と削除をすることで定期的な実行が可能です。
前提条件: 上記のカスタムリソースをk6-testというConfigMapにtest.yamlとして登録している。
apiVersion: batch/v1
kind: CronJob
metadata:
name: k6-load-testing-cron-job
spec:
schedule: "0 */3 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccount: k6
containers:
- name: kubectl
image: bitnami/kubectl
volumeMounts:
- name: k6-yaml
mountPath: /tmp/
command:
- /bin/bash
args:
- -c
- "kubectl delete -f /tmp/test.yaml; kubectl apply -f /tmp/test.yaml"
restartPolicy: OnFailure
volumes:
- name: k6-yaml
configMap:
name: k6-test
デフォルトのExtension以外を利用したい場合
前回の記事では、xk6-output-prometheus-remote
をビルドしてテスト結果をPrometheus
に送信していました。
k6 v0.42.0からこの拡張機能がExperimental moduleとして利用可能になりました。そのため、わざわざ自前のコンテナイメージをビルドする必要がなくなりました。
ただし、その他の拡張機能は引き続きビルドしレジストリにPushする必要があります。
# Build the k6 binary with the extension
FROM golang:1.20 as builder
RUN go install go.k6.io/xk6/cmd/xk6@latest
# For our example, we'll add support for output of test metrics to InfluxDB v2.
# Feel free to add other extensions using the '--with ...'.
RUN xk6 build \
--with github.com/grafana/xk6-output-influxdb@latest \
--output /k6
# Use the operator's base image and override the k6 binary
FROM grafana/k6:latest
COPY --from=builder /k6 /usr/bin/k6
カスタムリソースにて、こうしてビルドしたコンテナイメージを利用するように記載すれば、拡張機能をインストールしたテスト実行が可能になります。
apiVersion: k6.io/v1alpha1
kind: TestRun
metadata:
name: k6-sample-with-extensions
spec:
parallelism: 4
script:
configMap:
name: crocodile-stress-test
file: test.js
runner:
image: k6-extended:local
env:
- name: K6_OUT
value: xk6-influxdb=http://influxdb.somewhere:8086/demo
引用: https://github.com/grafana/k6-operator?tab=readme-ov-file#using-extensions
結果確認
もちろん、テスト結果をメトリクスとしてPrometheusに登録しているので、テスト結果はGrafanaのダッシュボードで確認することができます。
おわりに
k6をローカルのPCで実行すると、PCの他のソフトウェアの影響や自宅オフィスなどの通信速度の影響を受け、クラスタ内のサービスの性能試験など正確にテストを実行できないケースもあるかと思います。
こうしてk6-operatorを利用すると、テストシナリオを記載しカスタムリソースを登録するだけでk6自体のイメージやテスト結果をPrometheusに送るなどを気にする必要がなくなります。そのため開発者がテストを書くことや実行することに対しての抵抗感がなくなるのではないかと思います。
Discussion