4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

K6 Operatorを試す

Last updated at Posted at 2023-10-16

k6とはOSSの負荷テストツールで、2016年頃から開発されている、そこそこ歴史のある負荷ツールである。
現在はGrafana Labsの下で継続して開発が行われている。GitHubはこちら
これにはOperator版も用意されているので、これを使ってPodに負荷をかけた時のメモ。
Running distributed k6 tests on Kubernetesを参考にしている。

デプロイ

Operatorのデプロイはコードをcloneしてmakeする形で行う。コンテキストを切り替えた状態で以下を実行する。

git clone https://github.com/grafana/k6-operator && cd k6-operator
make deploy

デプロイに成功すると、k6-operator-systemというNamespaceにPodが作成される。

$ kubectl get pod -n k6-operator-system
NAME                                              READY   STATUS    RESTARTS   AGE
k6-operator-controller-manager-54488d95cd-gxd7b   2/2     Running   0          27s

なおMac環境でkustomizeコマンドが入っていないと以下のようなエラーになる。

cd config/manager && /Users/hogehoge/go/bin/kustomize edit set image controller=ghcr.io/grafana/k6-operator:latest
/bin/sh: line 1: 10199 Killed: 9               /Users/hogehoge/go/bin/kustomize edit set image controller=ghcr.io/grafana/k6-operator:latest
make: *** [deploy] Error 137

この場合はbrew install kustomizeを実行してkustomizeを入れればOKなはず。

検証

動作確認をする。
テストコードを作成する。

cat << EOF > test.js
import http from 'k6/http';
import { check } from 'k6';

export const options = {
  stages: [
    { target: 200, duration: '30s' },
    { target: 0, duration: '30s' },
  ],
};

export default function () {
  const result = http.get('https://test-api.k6.io/public/crocodiles/');
  check(result, {
    'http response status code is 200': result.status === 200,
  });
}
EOF

ConfigMapとして作成する。

kubectl create ns k6-test
kubectl create configmap crocodile-stress-test --from-file ./test.js -n k6-test

k6のカスタムリソースを作成する。
※古いドキュメントだとkind: K6となっているが、kind: TestRunに変更された。

cat << EOF > ./k6-test.yaml
apiVersion: k6.io/v1alpha1
kind: TestRun
metadata:
  name: k6-sample
spec:
  parallelism: 4
  script:
    configMap:
      name: crocodile-stress-test
      file: test.js
EOF

applyするとテストが実行される。

kubectl apply -f ./k6-test.yaml -n k6-test

testrunリソースを見ると、STAGEstartedになっている。

$ kubectl get testrun -n k6-test
NAME        STAGE     AGE   TESTRUNID
k6-sample   started   28s

Podは以下のようになっていて、parallelismで4並列で動かすよう指定していたため、テスト本体は4つ同時に動いている。

$ kubectl get pod -n k6-test
NAME                          READY   STATUS      RESTARTS   AGE
k6-sample-1-gf698             1/1     Running     0          41s
k6-sample-2-n2rbl             1/1     Running     0          41s
k6-sample-3-tbk6f             1/1     Running     0          41s
k6-sample-4-v657j             1/1     Running     0          41s
k6-sample-initializer-7cxff   0/1     Completed   0          50s
k6-sample-starter-ftdzh       0/1     Completed   0          34s

ちなみに各Podのcommandは以下のような感じ。

initializer
    - mkdir -p $(dirname /tmp/test.js.archived.tar) && k6 archive /test/test.js -O
      /tmp/test.js.archived.tar  2> /tmp/k6logs && k6 inspect --execution-requirements
      /tmp/test.js.archived.tar 2> /tmp/k6logs ; ! cat /tmp/k6logs | grep 'level=error'
starter
    - 'curl --retry 3 -X PATCH -H ''Content-Type: application/json'' http://10.98.39.51:6565/v1/status
      -d ''{"data":{"attributes":{"paused":false,"stopped":false},"id":"default","type":"status"}}'''
本体
    - k6
    - run
    - --quiet
    - /test/test.js
    - --address=0.0.0.0:6565
    - --paused
    - --tag
    - instance_id=1
    - --tag
    - job_name=k6-sample-1

initializerでテストコードのアーカイブ化などを行い、starterで起動したテスト用Podがpausedなのを解除して一斉にテストを実行している感じだと思われる。

テスト終了後はSTAGEfinishedになる。

$ kubectl get testrun -n k6-test
NAME        STAGE      AGE   TESTRUNID
k6-sample   finished   89s

ログを見るとテストの結果を確認することが出来る。

$ kubectl logs -n k6-test k6-sample-1-gf698

     ✓ http response status code is 200

     checks.........................: 100.00% ✓ 3557      ✗ 0
     data_received..................: 3.3 MB  56 kB/s
     data_sent......................: 450 kB  7.5 kB/s
     http_req_blocked...............: avg=4.01ms   min=1.8µs    med=5.56µs   max=270.01ms p(90)=6.9µs    p(95)=8.8µs
     http_req_connecting............: avg=1.92ms   min=0s       med=0s       max=120.45ms p(90)=0s       p(95)=0s
     http_req_duration..............: avg=432.43ms min=103.84ms med=124.67ms max=2.93s    p(90)=1.59s    p(95)=2.09s
       { expected_response:true }...: avg=432.43ms min=103.84ms med=124.67ms max=2.93s    p(90)=1.59s    p(95)=2.09s
     http_req_failed................: 0.00%   ✓ 0         ✗ 3557
     http_req_receiving.............: avg=125.08µs min=23.3µs   med=120.21µs max=3.12ms   p(90)=157.28µs p(95)=182.03µs
     http_req_sending...............: avg=35.59µs  min=7.79µs   med=28.69µs  max=735.26µs p(90)=51.94µs  p(95)=58.07µs
     http_req_tls_handshaking.......: avg=2.05ms   min=0s       med=0s       max=126.54ms p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=432.27ms min=103.71ms med=124.54ms max=2.93s    p(90)=1.59s    p(95)=2.08s
     http_reqs......................: 3557    59.281034/s
     iteration_duration.............: avg=436.66ms min=104.08ms med=125.48ms max=2.93s    p(90)=1.59s    p(95)=2.09s
     iterations.....................: 3557    59.281034/s
     vus............................: 2       min=0       max=50
     vus_max........................: 50      min=50      max=50

非常に簡単にテストを動かすことが出来た。

注意点

Istioを使って自動的にサイドカーを挿入している場合、以下のような感じで初期化用Podが終わらない。

$ kubectl get pod -n k6-test
NAME                          READY   STATUS     RESTARTS   AGE
k6-sample-initializer-9q5qd   1/2     NotReady   0          5m56s

これはk9sなんかで中を見ると理由が分かる。

┌─────────────────────────────────────────────────────────────────── Containers(k6-test/k6-sample-initializer-9q5qd)[3] ────────────────────────────────────────────────────────────────────┐
│ NAME↑             PF IMAGE                                                                        READY  STATE      INIT   RESTARTS PROBES(L:R) CPU MEM  CPU/R:L  MEM/R:L %CPU/R %CPU/L R │
│ istio-proxy       ●  public.ecr.aws/v6x6b8s5/vmwareallspark/proxyv2:1.17.3-release-v1-distroless  true   Running    false         0 off:on       7↑  68 100:2000 128:1024     7↑      0 3 │
│ istio-validation  ●  public.ecr.aws/v6x6b8s5/vmwareallspark/proxyv2:1.17.3-release-v1-distroless  true   Completed  true          0 off:off       0   0 100:2000 128:1024      0      0 0 │
│ k6                ●  ghcr.io/grafana/k6-operator:latest-runner                                    false  Completed  false         0 off:off       0   0      0:0      0:0    n/a    n/a a

Jobが終わっているにも関わらず、istio-proxyが動き続けるため、Jobが完了出来ずにいる状態となっている。
これはKubernetes v1.28以降のSidecarContainersを使えば対応できると思われる。(参考記事:Kubernetes v1.28: Introducing native sidecar containers
ただ、とりあえず手っ取り早く動かしたい人は、Istio環境ではOperatorの利用を諦めて、以下のようなPodを作成するのが早いと思う。

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: k6
  name: k6-sample
spec:
  containers:
  - command:
    - k6
    - run
    - /test/test.js
    image: ghcr.io/grafana/k6
    name: k6
    ports:
    volumeMounts:
    - mountPath: /test
      name: k6-test-volume
  volumes:
  - configMap:
      name: k6-test
    name: k6-test-volume
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?