LocustはPythonベースの負荷試験ツールで、JMeterやTsungの不満を解消するために作られており、有名どころのサービスの負荷試験にも使われているらしい。
これ、使ってみると非常に便利だが、Kubernetes向けの導入方法が'23/8時点では見当たらなかった。
負荷対象がkind: Ingress
等で外部にサービスを公開していればいいが、公開されておらずkind: Service
+type: ClusterIP
経由でアクセスしたい場合とかはクラスタ内部から負荷を掛ける必要がある。
今回はそのための確認を行った時のメモ。
Locustを使うシーンとしては、UIから手動で実行するケースと、UIなし(Headless)で自動で実行するケースが考えられるため、それぞれKubernetesで動かしてみる。
なお、ここでの確認手順はk8sのディストリビューションに依存しないため、どのk8s環境でも利用できる。はず。
WebUIのLocustコンテナを動かす
元々Locustのイメージが提供されているので、それを使う。
最初に、locustfile.py
をConfigMapで定義する。
テストケースに応じて差し替えるとよい、
cat << EOF > ./locustfile.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: locustfile
data:
locustfile.py: |
from locust import HttpUser, task
class LocustTest(HttpUser):
@task
def test_case1(self):
self.client.get("/")
EOF
Locust本体をDeployment
とService
で定義する。locustfile.py
はConfigMap
をmountして-fで渡す。
cat << EOF > ./locust.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: locust
spec:
replicas: 1
selector:
matchLabels:
app: locust
template:
metadata:
labels:
app: locust
spec:
containers:
- name: locust
image: locustio/locust
args:
- -f
- /mnt/locust/locustfile.py
ports:
- containerPort: 8089
volumeMounts:
- name: locustfile-volume
mountPath: /mnt/locust
volumes:
- name: locustfile-volume
configMap:
name: locustfile
---
apiVersion: v1
kind: Service
metadata:
name: locust
spec:
selector:
app: locust
ports:
- protocol: TCP
port: 80
targetPort: 8089
type: LoadBalancer
EOF
それぞれデプロイし、LocustのExternalIPを確認する。
kubectl apply -f ./locust.yaml -f ./locustfile.yaml
kubectl get svc locust -o jsonpath={.status.loadBalancer.ingress[0].ip}
ExternalIPにアクセスすると、無事にUIが表示される。ここでは試しにdefaultのNamespaceに立てたnginxに対して負荷を掛けてみる。
実行すると、Failsにカウントが増えることなくリクエストが処理されており、問題ないことが確認できた。
Headlessモードで動かす
Locustは--headless
を付けて実行すると、Headlessモードとして動作し、指定の負荷を実行した後に終了する。
コマンドとしては以下のような感じになる。
locust --headless -H $TARGET_URL -u $NUM_USERS -r $SPAWN_RATE -t $RUN_TIME
オプションはそれぞれ以下の意味となる。
-
-H
: Host -
-u
: 最大ユーザ数 -
-r
: 1秒あたりの増加数 -
-t
: 実行時間。これを過ぎるとコマンドは終了する。指定しないと無制限。
このオプションや環境変数を最初コマンドに渡そうと思ったが、この手の設定を設定ファイルとして用意して渡すことも出来る。
locust --config=master.conf
master.conf
には公式の記述によると、以下のような内容を記述でき、環境変数で設定したものがまとめて設定できるようになっている。。
locustfile = locust_files/my_locust_file.py
headless = true
master = true
expect-workers = 5
host = http://target-system
users = 100
spawn-rate = 10
run-time = 10m
ということで、上記のmaster.confをConfigMap
で作成し、実行側はJob
で作成してmountして利用する。
locustfile.py
とは別に以下のConfigMap
を作成する。
cat << EOF > ./locust-master-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: locust-master-config
data:
master.conf: |
locustfile = /mnt/locust/locustfile.py
headless = true
host = http://nginx.default.svc
users = 100
spawn-rate = 10
run-time = 10m
EOF
Job
は以下のようになる。
cat << 'EOF' > ./locust-headless.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: locust-headless
labels:
app: locust-headless
spec:
backoffLimit: 1
template:
metadata:
labels:
app: locust-headless
spec:
restartPolicy: Never
containers:
- name: locust-headless
image: locustio/locust
args:
- --config
- /mnt/locust-master-config/master.conf
volumeMounts:
- name: locustfile-volume
mountPath: /mnt/locust
- name: locust-master-config
mountPath: /mnt/locust-master-config
volumes:
- name: locustfile-volume
configMap:
name: locustfile
- name: locust-master-config
configMap:
name: locust-master-config
EOF
起動する。ConfigMap
のlocustfile
はUI確認時にデプロイ済みなのでここでは割愛しているが、必要なのでHeadless版から試している人はUI版で実施している内容を実施しておくこと。
kubectl apply -f ./locust-master-config.yaml -f ./locust-headless.yaml
ログを見ると、しっかり負荷が掛かっているようだ。
kubectl logs locust-headless-4sx25
[2023-08-12 23:51:26,093] locust-headless-4sx25/INFO/locust.main: Run time limit set to 600 seconds
[2023-08-12 23:51:26,094] locust-headless-4sx25/INFO/locust.main: Starting Locust 2.16.1
Type Name # reqs # fails | Avg Min Max Med | req/s failures/s
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
Aggregated 0 0(0.00%) | 0 0 0 0 | 0.00 0.00
[2023-08-12 23:51:26,128] locust-headless-4sx25/INFO/locust.runners: Ramping to 100 users at a rate of 10.00 per second
Type Name # reqs # fails | Avg Min Max Med | req/s failures/s
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
GET / 1057 0(0.00%) | 13 5 71 10 | 0.00 0.00
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
Aggregated 1057 0(0.00%) | 13 5 71 10 | 0.00 0.00