EC2 で実行した k6 負荷テスト結果を Grafana OSS でリアルタイム可視化してみた

EC2 で実行した k6 負荷テスト結果を Grafana OSS でリアルタイム可視化してみた

2026.01.30

製造ビジネステクノロジー部の小林です。

最近、EC2 上で k6 を使用して負荷テストを実施しています。実行中に「今の VU 数はどれくらい?」「レイテンシーは問題ない?」とリアルタイムで確認したくなることがありませんか?

Grafana OSS(無料) を使えばダッシュボードでリアルタイム可視化できます。ただし、今回の環境では EC2 への接続が EC2 Instance Connect のみで、SSH 用のポートは開放できないという制約がありました。

この記事では、そんな制約のある環境でも k6 の負荷テスト結果を Grafana OSS で可視化する方法を解説します。pem キーなしの EC2 Instance Connect 環境でも大丈夫です!

grafana-oss

前提条件

  • k6 実行環境: Graviton EC2
  • OS: Amazon Linux 2023(ARM)
  • テスト対象:REST API(API Gateway + Lambda + DynamoDB)
  • Lambda のタイムアウト:30 秒
  • AWS クレデンシャル情報: aws-vault

以前、下記の記事で作成した環境を利用します。
https://dev.classmethod.jp/articles/shoma-aws-cdk-graviton-ec2-k6-load-test-environment-setup/
https://dev.classmethod.jp/articles/shoma-k6-rest-api-load-testing-ramping-spike-soak-tests/

利用ツール

  • k6: 負荷テストツール
  • InfluxDB: テスト結果(時系列データ)を保存
  • Grafana OSS: データを可視化

Grafana OSS とは?

Grafana OSS(Open Source Software)は、オープンソースのデータ可視化・監視プラットフォームです。様々なデータソースからメトリクスを収集し、リアルタイムでダッシュボード表示できます。

特徴

  • 豊富なデータソース対応: InfluxDB、Prometheus、MySQL、PostgreSQL、CloudWatch など 150 以上
  • カスタマイズ可能なダッシュボード: ドラッグ&ドロップで直感的に作成
  • アラート機能: 閾値を超えた際に通知
  • 無料で利用可能: OSS 版は完全無料
  • 活発なコミュニティ: 公式・コミュニティ製のダッシュボードテンプレートが豊富

Grafana のエディション比較

エディション 特徴
Grafana OSS 無料、セルフホスト、基本機能
Grafana Enterprise 有料、追加機能・サポートあり
Grafana Cloud マネージドサービス、無料枠あり

https://grafana.com/oss/grafana/
https://github.com/grafana/grafana

InfluxDB とは?

InfluxDB は時系列データに特化したオープンソースのデータベースです。
https://www.influxdata.com/

特徴

  • 時系列データ(メトリクス、センサーデータ、ログなど)の保存
  • 高速な書き込み・読み取り性能
  • k6 が公式サポート(標準で連携可能)
  • 完全無料で利用可能

k6 での選択肢

k6 の負荷テスト結果を保存する方法はいくつかあります。

データストア 特徴
InfluxDB k6 公式サポート、設定簡単、公式ダッシュボードあり
Prometheus 汎用性高い、他の監視にも使える
JSON/CSV 最もシンプル

データフロー

k6(負荷テスト実行)
  ↓ --out influxdb=http://localhost:8086/k6
InfluxDB(データ保存)
  ↓ Data Source設定
Grafana(可視化)

InfluxDB 1.8 系を使う理由

1.8 系はセットアップが少なく、本記事のユースケースに適していました。2.x 系との詳細な比較は公式ドキュメントをご参照ください。
https://grafana.com/docs/k6/latest/results-output/real-time/influxdb/

Grafana OSS だけじゃダメ?

Grafana は可視化ツールであって、データを保存する機能はありません。つまり、

グラフを描く = Grafana
データを保存する = InfluxDB(または他の DB)

という役割になります。

やってみた

InfluxDB のインストール

EC2 に Instance Connect でログインし、下記のコマンドを実行します。

# ダウンロード&解凍
wget https://dl.influxdata.com/influxdb/releases/influxdb-1.8.10_linux_amd64.tar.gz
tar xvfz influxdb-1.8.10_linux_amd64.tar.gz

# バックグラウンドで起動
cd influxdb-1.8.10-1/usr/bin
./influxd &

実行すると、以下のように influxdb が起動します。

ec2-user@ip-10-0-2-7 ~]$ cd influxdb-1.8.10-1/usr/bin
[ec2-user@ip-10-0-2-7 bin]$ cd influxdb-1.8.10-1/usr/bin
-bash: cd: influxdb-1.8.10-1/usr/bin: No such file or directory
[ec2-user@ip-10-0-2-7 bin]$ ./influxd &
[1] 30415
[ec2-user@ip-10-0-2-7 bin]$
 8888888           .d888 888                   8888888b.  888888b.
   888            d88P"  888                   888  "Y88b 888  "88b
   888            888    888                   888    888 888  .88P
   888   88888b.  888888 888 888  888 888  888 888    888 8888888K.
   888   888 "88b 888    888 888  888  Y8bd8P' 888    888 888  "Y88b
   888   888  888 888    888 888  888   X88K   888    888 888    888
   888   888  888 888    888 Y88b 888 .d8""8b. 888  .d88P 888   d88P
 8888888 888  888 888    888  "Y88888 888  888 8888888P"  8888888P"

2026-01-29T15:22:01.751286Z     info    InfluxDB starting       {"log_id": "10jaP0al000", "version": "1.8.10", "branch": "1.8", "commit": "688e697c51fd"}
2026-01-29T15:22:01.751314Z     info    Go runtime      {"log_id": "10jaP0al000", "version": "go1.13.8", "maxprocs": 2}
2026-01-29T15:22:01.852530Z     info    Using data dir  {"log_id": "10jaP0al000", "service": "store", "path": "/home/ec2-user/.influxdb/data"}
2026-01-29T15:22:01.852575Z     info    Compaction settings     {"log_id": "10jaP0al000", "service": "store", "max_concurrent_compactions": 1, "throughput_bytes_per_second": 50331648, "throughput_bytes_per_second_burst": 50331648}
2026-01-29T15:22:01.852590Z     info    Open store (start)      {"log_id": "10jaP0al000", "service": "store", "trace_id": "10jaP0~0000", "op_name": "tsdb_open", "op_event": "start"}
2026-01-29T15:22:01.856060Z     info    Reading file    {"log_id": "10jaP0al000", "engine": "tsm1", "service": "cacheloader", "path": "/home/ec2-user/.influxdb/wal/_internal/monitor/1/_00001.wal", "size": 1088998}
2026-01-29T15:22:01.856153Z     info    Opened file     {"log_id": "10jaP0al000", "engine": "tsm1", "service": "filestore", "path": "/home/ec2-user/.influxdb/data/k6/autogen/2/000000003-000000001.tsm", "id": 2, "duration": "0.059ms"}
2026-01-29T15:22:01.856265Z     info    Opened file     {"log_id": "10jaP0al000", "engine": "tsm1", "service": "filestore", "path": "/home/ec2-user/.influxdb/data/k6/autogen/2/000000001-000000001.tsm", "id": 0, "duration": "0.041ms"}
2026-01-29T15:22:01.856337Z     info    Opened file     {"log_id": "10jaP0al000", "engine": "tsm1", "service": "filestore", "path": "/home/ec2-user/.influxdb/data/k6/autogen/2/000000002-000000001.tsm", "id": 1, "duration": "0.039ms"}
2026-01-29T15:22:01.863294Z     info    Opened shard    {"log_id": "10jaP0al000", "service": "store", "trace_id": "10jaP0~0000", "op_name": "tsdb_open", "index_version": "inmem", "path": "/home/ec2-user/.influxdb/data/k6/autogen/2", "duration": "7.752ms"}
2026-01-29T15:22:01.940814Z     info    Opened shard    {"log_id": "10jaP0al000", "service": "store", "trace_id": "10jaP0~0000", "op_name": "tsdb_open", "index_version": "inmem", "path": "/home/ec2-user/.influxdb/data/_internal/monitor/1", "duration": "85.396ms"}
2026-01-29T15:22:01.940916Z     info    Open store (end)        {"log_id": "10jaP0al000", "service": "store", "trace_id": "10jaP0~0000", "op_name": "tsdb_open", "op_event": "end", "op_elapsed": "88.326ms"}
2026-01-29T15:22:01.940944Z     info    Opened service  {"log_id": "10jaP0al000", "service": "subscriber"}
2026-01-29T15:22:01.940951Z     info    Starting monitor service        {"log_id": "10jaP0al000", "service": "monitor"}
2026-01-29T15:22:01.940957Z     info    Registered diagnostics client   {"log_id": "10jaP0al000", "service": "monitor", "name": "build"}
2026-01-29T15:22:01.940966Z     info    Registered diagnostics client   {"log_id": "10jaP0al000", "service": "monitor", "name": "runtime"}
2026-01-29T15:22:01.940973Z     info    Registered diagnostics client   {"log_id": "10jaP0al000", "service": "monitor", "name": "network"}
2026-01-29T15:22:01.940985Z     info    Registered diagnostics client   {"log_id": "10jaP0al000", "service": "monitor", "name": "system"}
2026-01-29T15:22:01.941008Z     info    Starting precreation service    {"log_id": "10jaP0al000", "service": "shard-precreation", "check_interval": "10m", "advance_period": "30m"}
2026-01-29T15:22:01.941023Z     info    Starting snapshot service       {"log_id": "10jaP0al000", "service": "snapshot"}
2026-01-29T15:22:01.941033Z     info    Starting continuous query service       {"log_id": "10jaP0al000", "service": "continuous_querier"}
2026-01-29T15:22:01.941046Z     info    Starting HTTP service   {"log_id": "10jaP0al000", "service": "httpd", "authentication": false}
2026-01-29T15:22:01.941055Z     info    opened HTTP access log  {"log_id": "10jaP0al000", "service": "httpd", "path": "stderr"}
2026-01-29T15:22:01.941169Z     info    Listening on HTTP       {"log_id": "10jaP0al000", "service": "httpd", "addr": "[::]:8086", "https": false}
2026-01-29T15:22:01.941192Z     info    Starting retention policy enforcement service   {"log_id": "10jaP0al000", "service": "retention", "check_interval": "30m"}
2026-01-29T15:22:01.941178Z     info    Storing statistics      {"log_id": "10jaP0al000", "service": "monitor", "db_instance": "_internal", "db_rp": "monitor", "interval": "10s"}
2026-01-29T15:22:01.941314Z     info    Listening for signals   {"log_id": "10jaP0al000"}
2026-01-29T15:22:01.941560Z     info    Sending usage statistics to usage.influxdata.com        {"log_id": "10jaP0al000"}

起動確認

[ec2-user@ip-10-0-2-7 bin]$ ps aux | grep influxd
ec2-user   30415  0.3  1.0 232528 41220 pts/0    Sl   15:22   0:00 ./influxd

Grafana OSS のインストール

Amazon Linux 2023 で Graviton(ARM)を使っている場合、以下の手順でインストールします。

# ARM版(aarch64)のGrafanaをダウンロード
wget https://dl.grafana.com/oss/release/grafana-11.4.0-1.aarch64.rpm

# インストール
sudo dnf install grafana-11.4.0-1.aarch64.rpm -y

# 起動&自動起動設定
sudo systemctl start grafana-server
sudo systemctl enable grafana-server

# 状態確認
sudo systemctl status grafana-server

systemctl enable について

C2 再起動時に Grafana を自動起動する設定です。これがないと再起動のたびに手動で sudo systemctl start grafana-server が必要になります。

EC2 の IAM ロールに必要なポリシーをアタッチ

EC2 インスタンスの IAM ロールに AmazonSSMManagedInstanceCore ポリシーが必要です。今回は AWS コンソールから設定しました。

IAM → ロール → EC2 インスタンスのロールを検索
スクリーンショット 2026-01-30 0.27.41

許可を追加 → ポリシーをアタッチで、AmazonSSMManagedInstanceCore を検索してチェック。ポリシーをアタッチします。
スクリーンショット 2026-01-30 0.29.01

SSM Agent を再起動(EC2 内で)

sudo systemctl restart amazon-ssm-agent
sudo systemctl status amazon-ssm-agent

SSM Agent を再起動できました。

[ec2-user@ip-10-0-2-7 ~]$ sudo systemctl status amazon-ssm-agent
● amazon-ssm-agent.service - amazon-ssm-agent
     Loaded: loaded (/usr/lib/systemd/system/amazon-ssm-agent.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-01-29 15:30:00 UTC; 1s ago
   Main PID: 30648 (amazon-ssm-agen)
      Tasks: 24 (limit: 4504)
     Memory: 74.7M
        CPU: 220ms
     CGroup: /system.slice/amazon-ssm-agent.service
             ├─28030 /usr/bin/ssm-session-worker cm-kobayashi.shoma-5oj4qgonalcid36yb7catfktky
             ├─30648 /usr/bin/amazon-ssm-agent
             └─30660 /usr/bin/ssm-agent-worker

ポートフォワーディングを開始(ローカルマシン)

# aws-vaultを使っている場合
aws-vault exec <プロファイル名> -- aws ssm start-session \
  --target <instance-id> \
  --document-name AWS-StartPortForwardingSession \
  --parameters "portNumber=3000,localPortNumber=3000"

# 通常のAWS CLIの場合
aws ssm start-session \
  --target <instance-id> \
  --document-name AWS-StartPortForwardingSession \
  --parameters "portNumber=3000,localPortNumber=3000"

実行すると下記のように表示されます。

serverless-backend %aws-vault exec my-profile -- aws ssm start-session --target i-00d734009aa8e8a25 --document-name AWS-StartPortForwardingSession --parameters "portNumber=3000,localPortNumber=3000"

Starting session with SessionId: cm-XXXXXXXX-XXXXXXXXX
Port 3000 opened for sessionId cm-XXXXXXXXX-XXXXXXXX
Waiting for connections...

この状態のまま、ブラウザで http://localhost:3000 にアクセスします。

トラブルシュート
ポートフォワーディング時に下記のようなエラーが発生することがあります。

An error occurred (TargetNotConnected) when calling the StartSession operation: i-00d734009aa8e8a25 is not connected.
serverless-backend %aws-vault exec my-profile -- aws ssm describe-instance-information --filters "Key=InstanceIds,Values=i-00d734009aa8e8a25"

これは、SSM Agent は登録されていますが、現在接続が切れている状態です。この場合下記のように再接続します。

# SSM Agentを再起動
sudo systemctl restart amazon-ssm-agent

# ステータス確認
sudo systemctl status amazon-ssm-agent

Grafana の画面が表示されました!
ログイン情報などを設定します。初回ログインではユーザー名、パスワード共にadminとなっています。
スクリーンショット 2026-01-29 23.15.16
スクリーンショット 2026-01-29 23.15.27

初回ログイン後、パスワード変更を求められます。
スクリーンショット 2026-01-29 23.15.40

ログインが完了するとダッシュボードが表示されます!
スクリーンショット 2026-01-29 23.15.51

データソース追加

左メニューから Connections → Data Sources を選択します。
スクリーンショット 2026-01-30 0.53.11

検索メニューでInfluxDBを検索して選択します。
スクリーンショット 2026-01-29 23.29.07

以下の情報を設定していきます。

その他はデフォルトのままです。
スクリーンショット 2026-01-29 23.15.51
スクリーンショット 2026-01-29 23.30.14

Save & Test をクリックします。
スクリーンショット 2026-01-29 23.30.50
"Data source is working" と表示されれば OK です!

k6 ダッシュボードをインポート

左メニュー + → Import
スクリーンショット 2026-01-29 23.31.26

Import via grafana.com に 2587 を入力します。2587 は k6 公式の Grafana ダッシュボードの ID です。
https://grafana.com/grafana/dashboards/2587-k6-load-testing-results/
スクリーンショット 2026-01-29 23.32.36

Load をクリックします。
スクリーンショット 2026-01-29 23.32.58

InfluxDB データソースで先ほど作成したものを選択して Import をクリックします。
スクリーンショット 2026-01-29 23.33.19

以上で設定完了です。ダッシュボードが表示されました!
スクリーンショット 2026-01-30 1.01.45

k6 実行

それでは k6 を実行して実際にダッシュボードに表示されるか確認してみます。今回は前回の記事で使用したスクリプトを使用します。

まずテスト対象の URL を環境変数に設定します。

# テスト対象の URL を設定(自分の API エンドポイントに置き換えてください)
export BASE_URL=https://your-api-endpoint.com

# InfluxDB へメトリクスを送信しながらテストを実行
k6 run --out influxdb=http://localhost:8086/k6 dist/ramping-test.js

--out influxdb=... で InfluxDB にリアルタイムでメトリクスが送信されます。

トラブルシュート
コマンド実行時に下記のようなエラーが発生することがあります。

ERRO[0002] Couldn't write stats                          error="Post \"http://localhost:8086/write?consistency=&db=k6&precision=ns&rp=\": dial tcp 127.0.0.1:8086: connect: connection refused" output=InfluxDBv1

これは、InfluxDB が起動していないか、ポート 8086 がリッスンしていない状態です。下記のコマンドで起動しましょう。

# InfluxDBのディレクトリに移動
cd ~/influxdb-1.8.10-1/usr/bin

# バックグラウンドで起動
./influxd &

# Enterキーを押してプロンプトに戻る

起動確認

# プロセス確認
ps aux | grep influxd | grep -v grep

# ポート確認
netstat -tuln | grep 8086

tcp6 0 0 :::8086 :::* LISTEN と表示されれば OK です。

再度 k6 run コマンドを実行してみましょう。成功すると下記のように k6 が実行されます。
スクリーンショット 2026-01-30 1.12.56

k6 実行後、先ほど作成した Grafana のダッシュボードを確認するとリアルタイムでメトリクスが確認できます。
スクリーンショット 2026-01-30 1.14.08
スクリーンショット 2026-01-30 1.16.04

ダッシュボードで見れるメトリクス

公式ダッシュボード(ID: 2587)では以下が可視化されます。

主要メトリクス

Virtual Users(仮想ユーザー数)

同時実行ユーザー数の推移をグラフで表示。段階的負荷テスト(Ramping Test)では、0 → 20 → 50 → 100 と段階的に増加する様子が確認できます。
スクリーンショット 2026-01-30 1.17.05

Requests per Second(秒間リクエスト数)

Mean(平均): 平均的なスループット
Max(最大): ピーク時の処理能力
システムがどれだけのリクエストを処理できるかの指標です。
スクリーンショット 2026-01-30 1.17.40

http_req_duration(レスポンスタイム)

mean(平均): 全リクエストの平均応答時間
med(中央値): 半数のリクエストがこの時間以内に完了
p90: 90%のリクエストがこの時間以内
p95: 95%のリクエストがこの時間以内
max(最大): 最も遅かったリクエスト

例: p95 が 500ms なら、95%のユーザーが 0.5 秒以内にレスポンスを得られる
スクリーンショット 2026-01-30 1.18.22

Errors Per Second(エラー率)
エラーが発生しているかをリアルタイムで確認できます。今回のリクエストではエラーが発生しなかったため No data と表示されています。
スクリーンショット 2026-01-30 1.19.19

Checks Per Second(テストチェックの成功率)
スクリプトで定義した check 関数の成功/失敗
例:「status is 200」のチェックが何回成功したかを確認できます。
スクリーンショット 2026-01-30 1.19.40

おわりに

今回は Grafana OSS を利用して k6 の実行結果をリアルタイムで確認できるように可視化してみました。

セキュリティ要件で EC2 のインバウンドルールに穴を開けられない環境でも、EC2 Instance Connect のポートフォワーディングを活用することで、ローカル PC から localhost 経由でダッシュボードにアクセスできました。pem キー不要で手軽に実現できるのも嬉しいポイントです。

この記事がどなたかの参考になれば幸いです。

この記事をシェアする

FacebookHatena blogX

関連記事