KubernetesにHelmでLocustによる分散負荷試験環境を立てる

gcpkubernetespython

OSSの負荷試験ツールLocustをK8sクラスタに立てる。 K8sならworkerの増減も簡単だし、HelmのChartもあるので立てるのも楽。

CDKでEKSクラスタの作成からHelm ChartでのLocustのインストールまでを一気に行う - sambaiz-net

LocustはPython製で、以下のようなコードで処理を書くことができる。

@task(10)のように括弧の中に数字を書いて実行される割合を偏らせることもできる。 異なるTaskSetに対応するユーザーを複数作ることもできて、こちらもweightで重みを付けられる。 ユーザー数はあとでWeb上から入力する。

$ mkdir tasks
$ cat tasks/tasks.py
from locust import HttpLocust, TaskSet, task

class ElbTasks(TaskSet):
  @task
  def task1(self):
    with self.client.get("/", catch_response=True) as response:
      if response.content != "Success":
        response.failure("Got wrong response")

class ElbWarmer(HttpLocust):
  task_set = ElbTasks
  min_wait = 1000
  max_wait = 3000

stableにChartはあるが、今のところtasksの中を書き換えなくてはいけないようなので、forkしてきてtasksの中を書き換え、package して、helm repo index でこれを参照するindex.yamlを生成した。

追記(2020-03-11): 今はConfigmapを自分で作成し –set worker.config.configmapName=*** することでforkしなくてもよくなった kubectl create configmap locust-worker-configs –from-file tasks/tasks.py

$ helm package .
$ helm repo index .
$ ls
index.yaml		locust-0.1.2.tgz		...
$ cat index.yaml
apiVersion: v1
entries:
  locust:
    ...
    urls:
    - locust-0.1.2.tgz
    version: 0.1.2
$ helm repo add my-locust 'https://raw.githubusercontent.com/sambaiz/charts/my-locust/stable/locust'
$ helm repo list
NAME     	URL                                                                     
stable   	https://kubernetes-charts.storage.googleapis.com
local    	http://127.0.0.1:8879/charts    
my-locust	https://raw.githubusercontent.com/sambaiz/charts/my-locust/stable/locust

GKEのようなRBACが有効な環境でHelmを使う場合、TillerにServiceAccountを設定しておく。

RBACが有効なGKEでHelmを使う - sambaiz-net

addしたrepoからinstallする。

$ helm install -n my-locust --set master.config.target-host=**** my-locust/locust 

masterとworker(デフォルトで2つ)が立った。

$ kubectl get pods
NAME                                READY     STATUS    RESTARTS   AGE
my-locust-master-7f7d57f5dc-k966s   1/1       Running   0          1m
my-locust-worker-66cc964748-7ff5w   1/1       Running   0          1m
my-locust-worker-66cc964748-wx5hf   1/1       Running   0          1m
...

port-forwardしてweb-uiにアクセスしてみる。

$ kubectl port-forward $POD_NAME 8089
$ open localhost:8089

User数と生成速度の設定

実行開始するとRPSなどがリアルタイムで表示される。 1000Users、50spawned/sで始めてみたところ、200Userにも到達せずにリクエスト自体が止まってしまった。

実行結果

少なく再設定してもUsersはそのままでよく分からない。 一旦立ち上げ直して100,10で実行してみたら100Userまで行くことは確認できた。

再び止まるまで上げてみたところ、途中でOOMになっていることが分かった。

$ kubectl describe pod my-locust-worker-****
Containers:
  locust:
    ...
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
...

メモリ(割り当て128mi)だけではなく、CPU(割り当て100millicores)もそれなりに使われていて、単純にreplica数を増やせばよさそう。

$ watch kubectl top node
NAME                                CPU(cores)   MEMORY(bytes)
my-locust-master-7f7d57f5dc-h9mvt   1m           19Mi
my-locust-worker-66cc964748-9dp8n   72m          112Mi
my-locust-worker-66cc964748-h94v9   61m          114Mi

ということでworkerを2から5に増やしてみたところUser数を増やしても止まらなくなった。

$ kubectl scale deployment my-locust-worker --replicas=5

EKS上のLocustから負荷をかける際のリソースの割り当てやインスタンスタイプの調整 - sambaiz-net