Open5

k6+grafana+prometheusで作るパフォーマンス計測環境

tomonatomona

タイトルの通りアプリケーションのperformance計測環境を作成する。
計測するアプリケーションは今回

  • Nestjs

で作成する。
計測に使用するのは以下のツール

  • k6: 負荷テストツール
  • Grafana: モニタリング用のダッシュボード
  • Prometheus: メトリクス収集して時系列データベースに保存
tomonatomona

Nestjsアプリケーションの作成と起動確認

まずはNestjsアプリケーションを立ち上げる部分まで行う。
前提条件として

  • nodeがinstallされている
  • @nest/cliがinstallされている

とする。
今回のパフォーマンス測定をするfolderを作成する。
適当なfolderでterminalを起動して、以下を実行する。
mkdir performance-insights
cd performance-insights
nest new sample-project --strict
Nestコマンドを実行するとterminal上にpackage-managerの選択画面が出るのでnpmを選択してプロジェクトの作成は完了。

Docker上で動作させたいので
cd sample-project
touch Dockerfile
としてDockerfileに以下の内容を記述する

# ベースイメージ
FROM node:latest

# 作業ディレクトリ設定
WORKDIR /usr/src/app

# 依存関係のインストール
COPY package*.json ./
RUN npm install

# アプリケーションのソースをコピー
COPY . .

# アプリケーションのビルド
RUN npm run build

# ポートのエクスポート
EXPOSE 8080

# アプリケーションの起動
CMD ["npm", "run", "start:prod"]

Nestjsが起動して叩けることを確認したいので、
docker build -t nestjs-app .
docker run -d --cpus="1" --memory="1g" --name nestjs-app -p 8080:8080 nestjs-app
で起動させて、別のterminalを開いて以下を実行する。
curl localhost:8080
これで'Hello World!'とterminalに表示されていればNestjsのproject作成と起動テストは完了。

tomonatomona

k6コンテナの作成

k6を実行できるコンテナをDockerで作成する。

# ベースイメージとして Ubuntu を指定
FROM ubuntu:20.04

# k6 のインストールに必要なパッケージを更新・インストール
RUN apt-get update && apt-get install -y \
    ca-certificates \
    curl \
    gnupg \
    && rm -rf /var/lib/apt/lists/*

# Grafana の公式リポジトリを追加して k6 をインストール
RUN curl -fsSL https://dl.k6.io/key.gpg | apt-key add - \
    && echo "deb https://dl.k6.io/deb stable main" | tee /etc/apt/sources.list.d/k6.list \
    && apt-get update \
    && apt-get install -y k6 \
    && rm -rf /var/lib/apt/lists/*

# ENTRYPOINT に bash を設定
ENTRYPOINT ["/bin/bash"]

ファイルを作成したら以下のコマンドでk6コンテナを起動する。
docker build -t k6-image .
docker run -it --name k6-container k6-image

コンテナが起動できたらコンテナのterminalで以下を実行してscriptを作成する
k6 new
defaultでscript.jsのファイルが作成されるので、これを実行して動作テストを行う。
k6 run script.js
terminal上にk6の実行結果が表示されていればOK。

tomonatomona

k6 + Grafana + Prometheusのコンテナ郡の作成

k6コンテナでの実行結果を保存して可視化するためにGrafanaとPrometheusとのコンテナ群を作成する。
以下のようにdocker-compose.yamlを作成する

docker-compose.yaml
networks:
  k6-prometheus:
  prometheus-grafana:

services:
  k6:
    build:
      context: ./k6
    tty: true
    stdin_open: true 
    volumes:
      - type: bind
        source: "./scripts"
        target: "/scripts"
    environment:
      - K6_PROMETHEUS_RW_SERVER_URL=http://prometheus:9090/api/v1/write
    networks:
      - k6-prometheus

  prometheus:
    image: prom/prometheus:v2.49.1
    ports:
      - "9090:9090"
    volumes:
      - type: bind
        source: "./prometheus.yml"
        target: "/etc/prometheus/prometheus.yml"
      - type: bind
        source: "./prometheus-data"
        target: "/prometheus"
    command:
      - "--web.enable-remote-write-receiver"
      - "--config.file=/etc/prometheus/prometheus.yml"
    networks:
      - k6-prometheus
      - prometheus-grafana

  grafana:
    image: grafana/grafana:10.3.1
    ports:
      - "3000:3000"
    volumes:
      - type: bind
        source: "./grafana"
        target: "/etc/grafana/provisioning"
    networks:
      - prometheus-grafana

yamlを作成したらコンテナ群をbuildして立ち上げるために以下のコマンドを実行する
docker compose up -d
コンテナが立ち上がったらlocalhost:3000をブラウザで叩いてgrafanaにアクセスする。
初期のユーザー名とパスワードは両方adminなので、アクセスしたらパスワードを任意のものに変更する。
ログインしたらgrafanaにprometheusのデータを読み込むように接続を行う。
手順としては

  1. Data sourceとしてPrometheusを設定する
  2. ダッシュボードを作成し、先ほど設定したPrometheusのデータを表示する
    ますは1としてHome画面の左のサイドバーからHome > Connections > Data sourcesへと進み、Add data sourceのボタンを押下する。
    Data Connection
    追加するData sourceを選択できるので検索欄にPrometheus入力して選択する。
    Chose Prometheus for data source
    Settingsの画面が出てくるのでNameとConnectionのServer Urlを入力する。
    Nameは任意のものでいいがServer Urlはhttp://prometheus:9090を入力する。これはdocker-compose内のネットワークの名前解決で接続するためこのurlになる。
    data source settings
    入力が完了したら一番下にあるsave & testのボタンを押下してSuccessfullyのメッセージが出れば1は完了。
    Data Connection Success

2としてHome画面の左のサイドバーからDashboardsを選択し、Create Dashboardボタンを押下する。
Dashboards
ダッシュボードをどの方法で作成するのかの画面が出てくるので、Import a dashboardを選択してそのボタンを押下する。
Select how to create dashboard
Import dashboard画面のFind and import dashboards for common applicationの部分で19665のidを入力する。
Loadボタンを押下してdashoboardの画面に移動したら2は完了。

tomonatomona

実際にパフォーマンスの測定

実際にアプリケーションの速度を測定する。
まずはNestjsを立ち上げておく。
次に作成したパフォーマンス測定用のコンテナ群を起動して、grafanaの作成したダッシュボード画面を開いておく。
次に実行するscriptファイルを作成する。
docker-composeでscriptsとい名前のフォルダーをbindするように設定しているので、
mkdir scripts
でフォルダーを作成してそこに以下のファイルを作成する。

sample.js
import http from "k6/http";
import { check, sleep } from "k6";

// Test configuration
export const options = {
  thresholds: {
    // Assert that 99% of requests finish within 500ms.
    http_req_duration: ["p(99) < 500"],
  },
  // Ramp the number of virtual users up and down
  stages: [
    { duration: "30s", target: 10 },
    { duration: "1m", target: 10 },
    { duration: "30s", target: 0 },
  ],
};

// Simulated user behavior
export default function () {
  let res = http.get("http://host.docker.internal:8080");
  // Validate response status
  check(res, { "status was 200": (r) => r.status == 200 });
  sleep(1);
}

次にk6コンテナに以下のコマンドかdocker-desktopのexeタブからterminalに接続する。

コンテナに接続するコマンド

docker exec -it ${container_id} /bin/bash

terminalに接続できたら以下のコマンドを実行してk6による負荷試験を行う。
k6 run -o experimental-prometheus-rw ./scripts/sample.js
ダッシュボードを新規にリロードすると結果が反映されるのを確認したら完了。
Prometheus-k6 dashboard