🔍

Grafana+Prometheus+k6で作るパフォーマンス測定基盤

2024/11/06に公開

概要

  • Grafana
  • Prometheud
  • kd
    を用いてバックエンドアプリケーションのAPIパフォーマンス測定基盤を作成します。
    localで動作するアプリケーションの簡便なパフォーマンス確認に使用できるようにdocker-composeを使用して立ち上げと破棄が楽な構成となっています。

背景

バックエンドアプリケーションを動作させる基盤においてパフォーマンス測定は確実に行われると思います。
そんな中で本番環境や開発環境でのチェックも簡単に行えるようになっているのですが、開発環境に上げるその前にlocal上で立ち上げたアプリケーションのパフォーマンスに問題がないか簡単にチェックしたいことがあります。
コンテナで構成することが多いバックエンドアプリケーションでは1コンテナあたりのパフォーマンスに問題がないことをチェックすることも大切なことだと思います。

目的

簡単に起動できて破棄できるパフォーマンス監視基盤を作成して、local上で動作するアプリケーションのパフォーマンスをチェックします。

実装内容

前提としてpreformance-insightという空のフォルダーを作成して、その階層でterminalは起動しているものとします。

k6コンテナの作成

k6を実行できるコンテナをDockerで作成します。
以下のDockerfileをk6というフォルダーを作成してその中に作成します。

# ベースイメージとして Ubuntu を指定
FROM ubuntu:22.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です。

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

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

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

ダッシュボードは公式が出してくれているもの[2]を使用します。
Import dashboard画面のFind and import dashboards for common applicationの部分で19665のidを入力します。
Loadボタンを押下してdashoboardの画面に移動したら2の手順は完了です。

実際にアプリケーションのパフォマンスを測定

それでは実際にアプリケーションのパフォーマンス測定を実施していきます。
この記事ではNestjsのアプリケーションをdcokerでlocal上にコンテナとして立ち上げてテストしていきます。
Nestjsアプリケーションの内容は余分ですが、次のアコーディオンの中に構築した内容を記載しておきます(内容は薄いです🙏)

Nestjsをコンテナで起動する

前提条件として以下が実施されているものとします。

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

適当な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作成と起動テストは完了。

まずは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
Grafanaのダッシュボードをリロードすると結果が反映されるのを確認したら完了です。(Auto-reloadの設定も右上にあるのですると便利です)
Prometheus-k6 dashboard

注意点

あくまでlocal上でのパフォーマンス測定は使用しているPCのスペックによりますので、本番環境に上げる前の問題確認程度にとどめておくのが良いでしょう。(コンテナ単位で動作するアプリケーションのレスポンスに問題がないことを確認することが目的です。)

参考文献

脚注
  1. docker-composeの参考にさせていただいた記事 ↩︎

  2. Grafanaの公式がk6用に出しているダッシュボード ↩︎

Discussion