Foreverly

メモ帳

EKS環境に対してlocust podをskaffoldでデプロイして負荷試験準備した

EKSは別に関係ないです。 負荷試験環境を用意した時、skaffoldでlocust環境を用意したので、そのメモ。

事前準備

  1. docker daemonの起動とskaffoldのインストール
  2. ecrにimageを置くためのリポジトリを用意

Description

Projectのlocustを動かすmanifestとシナリオ群を用意する。

パッケージ構成はこんな感じになった

├── Dockerfile                    //locustのimageの元
├── README.md                     //説明書
├── src                           //シナリオ置き場
│   └── {scenario_name}.py        // シナリオ
├── scripts                       //locust起動script置き場
│   └── docker-entrypoint.sh
└── deployment                    // シナリオmanifest置き場
     ├── helm                     // シナリオ毎にpathを切ります
     │  ├── Chart.yaml            // locustで実行するスクリプト
     │  ├── templates             // 
     │  │  ├─ _helpers.tpl        // helmのhelper
     │  │  ├─ master-deploy.yaml  // locustのmasterのmanifest
     │  │  ├─ master-svc.yaml     // locustのmasterのserviceのmanifest
     │  │  ├─ worker-deploy.yaml  // locustのworkerのmanifest
     │  │  └- worker-hpa.yaml    // hpaのmanifest
     │  └── values.yaml           // locustのチャートの値
     ├── helm_vars                // シナリオ毎にpathを切ります
     │  └─ values.yaml            // locustのチャートの値のoverride用
     └── skaffold.yaml            // skaffoldのmanifest

locust

locust自体はこの方がやっていることをそのまま参考にしています

docker-entrypoint.shはこんな感じにした。

#!/usr/bin/env sh

if [ -z "${TARGET_URL}" ]; then
    echo "ERROR: TARGET_URL not configured" >&2
    exit 1
fi

LOCUST_MODE="${LOCUST_MODE:=standalone}"
_LOCUST_OPTS="-f ${LOCUSTFILE_PATH:-/locustfile.py} -H ${TARGET_URL}"

if [ "${LOCUST_MODE}" = "master" ]; then
    _LOCUST_OPTS="${_LOCUST_OPTS} --master"
elif [ "${LOCUST_MODE}" = "slave" ]; then
    if [ -z "${LOCUST_MASTER_HOST}" ]; then
        echo "ERROR: MASTER_HOST is empty. Slave mode requires a master" >&2
        exit 1
    fi

    _LOCUST_OPTS="${_LOCUST_OPTS} --slave --master-host=${LOCUST_MASTER_HOST} --master-port=${LOCUST_MASTER_PORT:-5557}"
fi

echo "Starting Locust in ${LOCUST_MODE} mode..."
echo "$ locust ${LOCUST_OPTS} ${_LOCUST_OPTS}"

exec locust ${LOCUST_OPTS} ${_LOCUST_OPTS}

Dockerfile はこんな感じ

ENTRYPOINT ["./docker-entrypoint.sh"] にしたらpermission errorで実行できなかった。

FROM python:3.8-alpine
RUN apk add --no-cache -U zeromq-dev ca-certificates
COPY requirements.txt /tmp
RUN apk add --no-cache -U --virtual build-deps libffi-dev g++ gcc linux-headers &&\
    pip install --upgrade pip &&\
    pip install -r /tmp/requirements.txt && \
    apk del build-deps
EXPOSE 443 5557 5558
WORKDIR /locust
COPY ./src src
COPY ./scripts/docker-entrypoint.sh .
ENTRYPOINT ["sh", "./docker-entrypoint.sh"]

locustのmasterとworkerのマニフェストはhelmで書いて、 サービス毎にシナリオを追加できるようにしました。

master-deploy.yaml の中身

skaffold.yaml

こんな感じにマニフェスト作成 profilesを使って、対象を分けた。

apiVersion: skaffold/v1
kind: Config

build:
  local: {}
  artifacts:
    - image: {{AWSアカウントID}}.dkr.ecr.ap-northeast-1.amazonaws.com/project/locust
      context: .
  tagPolicy:
    sha256: {}
portForward:

profiles:
  - name: project-locust1
    deploy:
      kubeContext: arn:aws:eks:ap-northeast-1:{{AWSアカウントID}}:cluster/{{クラスタ名}}
      helm:
        releases:
          - name: project-locust1
            namespace: locust-test
            chartPath: ./deployment/helm
            valuesFiles:
              - ./deployment/helm_vars/locust1-values.yaml
            values:
              image: {{AWSアカウントID}}.dkr.ecr.ap-northeast-1.amazonaws.com/project/locust
            imageStrategy:
              helm: {}
  - name: project-locust2
    deploy:
      kubeContext: arn:aws:eks:ap-northeast-1:{{AWSアカウントID}}:cluster/{{クラスタ名}}
      helm:
        releases:
          - name: project-locust2
            namespace: locust-test
            chartPath: ./deployment/helm
            valuesFiles:
              - ./deployment/helm_vars/locust2-values.yaml
            values:
              image: {{AWSアカウントID}}.dkr.ecr.ap-northeast-1.amazonaws.com/project/locust
            imageStrategy:
              helm: {}
    portForward:
      - resourceType: service
        resourceName: locust2-master-svc
        namespace: locust-test
        port: 8089

Usage

deployとdeleteはこんな感じ。 -p でprofileを指定して、locustのターゲットを指定した。

## deploy
$ skaffold run -f deployment/skaffold.yaml -p project-locust1

## delete
$ skaffold delete -f deployment/skaffold.yaml -p project-locust1

新規にシナリオを追加したい時

以下の手順で増やしていけばいいだけ。

  1. src 配下にシナリオを追加
  2. helm_vars 配下にシナリオごとに変更したい値をoverrideさせるyamlを書く
  3. skaffold.yamlprofiles に追加したいシナリオの情報を追記する

番外編

aws2コマンドにしたらaws ecrへのloginコマンドが変わっていた。 以下でイケました。

 aws ecr get-login-password \
              --region {{リージョン名}} \
          | docker login \
              --username AWS \
              --password-stdin {{AWSアカウントID}}.dkr.ecr.ap-northeast-1.amazonaws.com

参考URL

【AWS】初めてのECR

今度はあんまりゴツくない!?「わりとゴツいKubernetesハンズオン」そのあとに

[アップデート]AWS CLI v2 で $ aws ecr get-login を使うときの注意点

Locustを触ってみた

Google発のコンテナアプリケーション開発支援ツール「Skaffold」や「Kaniko」を使ってみる

skaffold run

Kubernetesのアプリケーション開発で楽をしたい。そうだ、Skaffoldを使ってみよう!

/docker-entrypoint.sh": permission denied