😎

k6-operatorを利用したk8s上での負荷テストの実行

2024/02/19に公開

はじめに

この記事は前回紹介したk6をKubernetes内で実行する記事の続きです。
https://zenn.dev/shorter/articles/8ba0bf62afa03a

上記の記事では、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のダッシュボードで確認することができます。
https://grafana.com/grafana/dashboards/18030-k6-prometheus-native-histograms/

おわりに

k6をローカルのPCで実行すると、PCの他のソフトウェアの影響や自宅オフィスなどの通信速度の影響を受け、クラスタ内のサービスの性能試験など正確にテストを実行できないケースもあるかと思います。
こうしてk6-operatorを利用すると、テストシナリオを記載しカスタムリソースを登録するだけでk6自体のイメージやテスト結果をPrometheusに送るなどを気にする必要がなくなります。そのため開発者がテストを書くことや実行することに対しての抵抗感がなくなるのではないかと思います。

GitHubで編集を提案

Discussion