[アップデート] EBSボリュームで1分間の平均IOPSとスループットを表すCloudWatchメトリクスが追加されました

[アップデート] EBSボリュームで1分間の平均IOPSとスループットを表すCloudWatchメトリクスが追加されました

パッとEBSボリュームのIOPSとスループットを把握したいときに
2025.10.30

自分でEBSボリュームのIOPSやスループットを計算するの面倒だな

こんにちは、のんピ(@non____97)です。

皆さんは自分でEBSボリュームのIOPSやスループットを計算するの面倒だなと思ったことはありますか? 私はあります。

「EC2コンソールからIOPSはないものの、以下のように読み取りスループットや書き込みスループットは見れるじゃないの」と思われる方もいるかもしれません。

2.ボリュームのメトリクス.png

しかし、こちらの読み取りスループットのウィジェットをメトリクスで開くと、以下のように読み取りデータ量を統計期間で割っていることが分かります。(1,024は単位をKiBにするための調整)

3.ボリュームのメトリクス2.png

要するに直接的にスループットを表すメトリクスが存在している訳ではありませんでした。

CloudWatchのコンソールから手早くスループットやIOPSを把握したいときに、このように計算をするのは地味に面倒です。

そんな折、EBSボリュームで1分間の平均IOPSとスループットを表すCloudWatchメトリクスが追加されました。

https://aws.amazon.com/jp/about-aws/whats-new/2025/10/amazon-ebs-performance-monitoring-metrics-ebs-volumes/

具体的なメトリクスはAWS公式ドキュメントで紹介されている以下です。

  • VolumeAvgIOPS
  • VolumeAvgThroughput

これにより簡単にIOPSやスループットを確認できるようになりました。

実際に確認をしてみます。

やってみた

検証環境

検証は以下のEC2インスタンス、EBSボリュームを用いて行います。

  • AZ : us-east-1d (use1-az4)
  • AMI : al2023-ami-2023.9.20251020.0-kernel-6.1-x86_64 (ami-07860a2d7eb515d9a)
  • インスタンスタイプ : t3.micro
  • EBSボリュームタイプ : gp3
  • EBSボリュームスループット : 125 MBps
  • EBSボリュームIOPS : 3,000 IOPS

1.EBSボリューム.png

追加で用意したボリュームにfioで書き込みます。

追加したボリュームは以下のようにxfsでフォーマットしてマウントします。

$ sudo lsblk -f
NAME          FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
nvme0n1
├─nvme0n1p1   xfs          /     4a77b7a2-6d11-4714-ba76-e7dc21d23cc9    6.3G    21% /
├─nvme0n1p127
└─nvme0n1p128 vfat   FAT16       161A-5EA2                               8.7M    13% /boot/efi
nvme1n1

$ sudo mkfs -t xfs /dev/nvme1n1
meta-data=/dev/nvme1n1           isize=512    agcount=8, agsize=262144 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1 nrext64=0
         =                       exchange=0
data     =                       bsize=4096   blocks=2097152, imaxpct=25
         =                       sunit=1      swidth=1 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1, parent=0
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

$ sudo lsblk -f
NAME          FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
nvme0n1
├─nvme0n1p1   xfs          /     4a77b7a2-6d11-4714-ba76-e7dc21d23cc9    6.3G    21% /
├─nvme0n1p127
└─nvme0n1p128 vfat   FAT16       161A-5EA2                               8.7M    13% /boot/efi
nvme1n1       xfs                f01da118-d2cc-465c-8b49-13ed3c5fcf72

$ sudo mkdir -p /mnt/vol
$ sudo mount /dev/nvme1n1 /mnt/vol/

$ df -hT
Filesystem       Type      Size  Used Avail Use% Mounted on
devtmpfs         devtmpfs  4.0M     0  4.0M   0% /dev
tmpfs            tmpfs     453M     0  453M   0% /dev/shm
tmpfs            tmpfs     181M  432K  181M   1% /run
/dev/nvme0n1p1   xfs       8.0G  1.7G  6.3G  21% /
tmpfs            tmpfs     453M     0  453M   0% /tmp
/dev/nvme0n1p128 vfat       10M  1.3M  8.7M  13% /boot/efi
tmpfs            tmpfs      91M     0   91M   0% /run/user/0
/dev/nvme1n1     xfs       8.0G   90M  7.9G   2% /mnt/vol

5分間書き込みをしてみる

実際にfioで書き込みをします。5分間書き込みをします。

$ sudo fio \
  --directory=/mnt/vol/ \
  --name fio_rw_1MiB_block_1GiB_4jobs \
  --ioengine=psync \
  --direct=1 \
  --rw=randwrite \
  --bs=1M \
  --size=1G \
  --numjobs=4 \
  --runtime=300 \
  --eta-newline=10 \
  --time_based=1 \
  --group_reporting \
  --norandommap
fio_rw_1MiB_block_1GiB_4jobs: (g=0): rw=randwrite, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=psync, iodepth=1
...
fio-3.32
Starting 4 processes
fio_rw_1MiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
fio_rw_1MiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
fio_rw_1MiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
fio_rw_1MiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
Jobs: 4 (f=4): [w(4)][4.0%][w=125MiB/s][w=125 IOPS][eta 04m:48s]
Jobs: 4 (f=4): [w(4)][7.7%][w=125MiB/s][w=125 IOPS][eta 04m:37s]
Jobs: 4 (f=4): [w(4)][11.3%][w=125MiB/s][w=125 IOPS][eta 04m:26s]
Jobs: 4 (f=4): [w(4)][15.0%][w=125MiB/s][w=125 IOPS][eta 04m:15s]
Jobs: 4 (f=4): [w(4)][18.7%][w=126MiB/s][w=126 IOPS][eta 04m:04s]
Jobs: 4 (f=4): [w(4)][22.3%][w=125MiB/s][w=125 IOPS][eta 03m:53s]
Jobs: 4 (f=4): [w(4)][26.0%][w=125MiB/s][w=125 IOPS][eta 03m:42s]
Jobs: 4 (f=4): [w(4)][29.7%][w=125MiB/s][w=125 IOPS][eta 03m:31s]
Jobs: 4 (f=4): [w(4)][33.3%][w=92.1MiB/s][w=92 IOPS][eta 03m:20s]
Jobs: 4 (f=4): [w(4)][37.0%][w=126MiB/s][w=126 IOPS][eta 03m:09s]
Jobs: 4 (f=4): [w(4)][40.7%][w=122MiB/s][w=122 IOPS][eta 02m:58s]
Jobs: 4 (f=4): [w(4)][44.3%][w=125MiB/s][w=125 IOPS][eta 02m:47s]
Jobs: 4 (f=4): [w(4)][48.0%][w=125MiB/s][w=125 IOPS][eta 02m:36s]
Jobs: 4 (f=4): [w(4)][51.7%][w=117MiB/s][w=117 IOPS][eta 02m:25s]
Jobs: 4 (f=4): [w(4)][55.3%][w=126MiB/s][w=126 IOPS][eta 02m:14s]
Jobs: 4 (f=4): [w(4)][59.0%][w=126MiB/s][w=126 IOPS][eta 02m:03s]
Jobs: 4 (f=4): [w(4)][62.7%][w=125MiB/s][w=125 IOPS][eta 01m:52s]
Jobs: 4 (f=4): [w(4)][66.3%][w=125MiB/s][w=125 IOPS][eta 01m:41s]
Jobs: 4 (f=4): [w(4)][70.0%][w=125MiB/s][w=125 IOPS][eta 01m:30s]
Jobs: 4 (f=4): [w(4)][73.7%][w=125MiB/s][w=125 IOPS][eta 01m:19s]
Jobs: 4 (f=4): [w(4)][77.3%][w=125MiB/s][w=125 IOPS][eta 01m:08s]
Jobs: 4 (f=4): [w(4)][81.0%][w=134MiB/s][w=134 IOPS][eta 00m:57s]
Jobs: 4 (f=4): [w(4)][84.7%][w=126MiB/s][w=126 IOPS][eta 00m:46s]
Jobs: 4 (f=4): [w(4)][88.3%][w=125MiB/s][w=125 IOPS][eta 00m:35s]
Jobs: 4 (f=4): [w(4)][92.0%][w=145MiB/s][w=145 IOPS][eta 00m:24s]
Jobs: 4 (f=4): [w(4)][95.7%][w=131MiB/s][w=131 IOPS][eta 00m:13s]
Jobs: 4 (f=4): [w(4)][99.3%][w=125MiB/s][w=125 IOPS][eta 00m:02s]
Jobs: 4 (f=4): [w(4)][100.0%][w=125MiB/s][w=125 IOPS][eta 00m:00s]
fio_rw_1MiB_block_1GiB_4jobs: (groupid=0, jobs=4): err= 0: pid=17942: Thu Oct 30 11:54:53 2025
  write: IOPS=125, BW=125MiB/s (131MB/s)(36.7GiB/300031msec); 0 zone resets
    clat (usec): min=1892, max=102069, avg=31837.70, stdev=7527.12
     lat (usec): min=1951, max=102132, avg=31899.31, stdev=7527.06
    clat percentiles (msec):
     |  1.00th=[    4],  5.00th=[   22], 10.00th=[   26], 20.00th=[   31],
     | 30.00th=[   32], 40.00th=[   32], 50.00th=[   32], 60.00th=[   33],
     | 70.00th=[   33], 80.00th=[   34], 90.00th=[   36], 95.00th=[   41],
     | 99.00th=[   61], 99.50th=[   70], 99.90th=[   91], 99.95th=[   96],
     | 99.99th=[  101]
   bw (  KiB/s): min=49152, max=383356, per=100.00%, avg=128461.80, stdev=5700.00, samples=2396
   iops        : min=   48, max=  374, avg=125.39, stdev= 5.56, samples=2396
  lat (msec)   : 2=0.01%, 4=1.03%, 10=0.95%, 20=2.32%, 50=93.67%
  lat (msec)   : 100=2.02%, 250=0.01%
  cpu          : usr=0.28%, sys=0.20%, ctx=37694, majf=0, minf=40
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,37613,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
  WRITE: bw=125MiB/s (131MB/s), 125MiB/s-125MiB/s (131MB/s-131MB/s), io=36.7GiB (39.4GB), run=300031-300031msec

Disk stats (read/write):
  nvme1n1: ios=0/150458, merge=0/10, ticks=0/4308776, in_queue=4308776, util=100.00%

平均125MiBps、125IOPSであることが分かります。

CloudWatchからも確認します。

まずはVolumeAvgThroughputです。

4.VolumeAvgThroughput.png

確かにfioで書き込みをしている間、125MiBpsほどを示していますね。

続いて、VolumeAvgIOPSです。

5.VolumeAvgIOPS.png

fioの結果では125IOPSでしたが、こちらは500IOPSとなっています。

自分で計算する場合も500IOPSです。

7.自分で計算する場合.png

また、1分間のサンプル数は常に1であることも分かります。

6.サンプル数.png

これはSSDのEBSボリュームのIOサイズの上限が256KiBだからです。256KiBよりも大きいブロックは256KiB単位で分割をして処理をします。

IOPS とは、1 秒あたりの入出力操作数を表す測定単位です。操作は KiB 単位で計測され、基礎となるドライブテクノロジーが1 つの I/O としてカウントするデータの最大量を決定します。I/O サイズは、SSD ボリュームで 256 KiB、HDD ボリュームで 1,024 KiB に制限されます。これは、小さい I/O やランダム I/O の扱いにおいて、SSD ボリュームは HDD ボリュームに比べて はるかに効率的であるためです。

小さな I/O 操作が物理的に連続している場合、Amazon EBS ではできる限りこれらを最大の I/O サイズになるまで、単一の I/O 操作にマージして処理します。同様に、I/O 操作が最大 I/O サイズより大きい場合、Amazon EBS ではより小さな I/O 操作に分割して処理しようとします。例をいくつか、次の表に示します。

ボリュームタイプ 最大 I/O サイズ アプリケーションからの I/O 操作 IOPS 数 コメント
SSD 256 KiB 1 x 1024 KiB I/O 操作 4 (1,024 ÷ 256 = 4) Amazon EBS は、1,024 KiB の I/O オペレーションを 4 つの小さな 256 KiB オペレーションに分割します。
8 x シーケンシャル 32 KiB I/O 操作 1 (8 x 32 = 256) Amazon EBS は、8 つの連続した 32 KiB の I/O 操作を、1 つの 256 KiB の操作にマージします。
8 つのランダムな 32 KiB の I/O 操作 8 Amazon EBS は、ランダムな I/O 操作を個別にカウントします。

Amazon EBS I/O の特性およびモニタリング - Amazon EBS

そのため、先ほどfio上ではブロックサイズを1MiBとしていました。1MiB / 256KiB = 4であるため、125IOPS × 4 = 500IOPSとなります。

30秒書き込みをしてみる

続いて、30秒書き込みをします。

今度はブロックサイズを256KiBにします。

$ date
Thu Oct 30 12:15:03 UTC 2025

$ sudo fio \
  --directory=/mnt/vol/ \
  --name fio_rw_256KiB_block_1GiB_4jobs \
  --ioengine=psync \
  --direct=1 \
  --rw=randwrite \
  --bs=256K \
  --size=1G \
  --numjobs=4 \
  --runtime=30 \
  --eta-newline=5 \
  --time_based=1 \
  --group_reporting \
  --norandommap
fio_rw_256KiB_block_1GiB_4jobs: (g=0): rw=randwrite, bs=(R) 256KiB-256KiB, (W) 256KiB-256KiB, (T) 256KiB-256KiB, ioengine=psync, iodepth=1
...
fio-3.32
Starting 4 processes
fio_rw_256KiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
fio_rw_256KiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
fio_rw_256KiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
fio_rw_256KiB_block_1GiB_4jobs: Laying out IO file (1 file / 1024MiB)
Jobs: 4 (f=4): [w(4)][23.3%][w=125MiB/s][w=500 IOPS][eta 00m:23s]
Jobs: 4 (f=4): [w(4)][43.3%][w=125MiB/s][w=500 IOPS][eta 00m:17s]
Jobs: 4 (f=4): [w(4)][63.3%][w=125MiB/s][w=501 IOPS][eta 00m:11s]
Jobs: 4 (f=4): [w(4)][83.3%][w=125MiB/s][w=501 IOPS][eta 00m:05s]
Jobs: 4 (f=4): [w(4)][100.0%][w=125MiB/s][w=500 IOPS][eta 00m:00s]
fio_rw_256KiB_block_1GiB_4jobs: (groupid=0, jobs=4): err= 0: pid=26876: Thu Oct 30 12:15:35 2025
  write: IOPS=517, BW=129MiB/s (136MB/s)(3882MiB/30009msec); 0 zone resets
    clat (usec): min=963, max=10373, avg=7711.02, stdev=1834.40
     lat (usec): min=978, max=10388, avg=7726.69, stdev=1834.51
    clat percentiles (usec):
     |  1.00th=[ 1434],  5.00th=[ 5669], 10.00th=[ 5866], 20.00th=[ 5997],
     | 30.00th=[ 6128], 40.00th=[ 8029], 50.00th=[ 8848], 60.00th=[ 8979],
     | 70.00th=[ 8979], 80.00th=[ 9110], 90.00th=[ 9241], 95.00th=[ 9372],
     | 99.00th=[ 9896], 99.50th=[10028], 99.90th=[10159], 99.95th=[10159],
     | 99.99th=[10421]
   bw (  KiB/s): min=112640, max=383488, per=100.00%, avg=132608.00, stdev=8689.03, samples=236
   iops        : min=  440, max= 1498, avg=518.00, stdev=33.94, samples=236
  lat (usec)   : 1000=0.03%
  lat (msec)   : 2=1.49%, 4=3.25%, 10=94.76%, 20=0.46%
  cpu          : usr=0.42%, sys=0.44%, ctx=15544, majf=0, minf=45
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,15526,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
  WRITE: bw=129MiB/s (136MB/s), 129MiB/s-129MiB/s (136MB/s-136MB/s), io=3882MiB (4070MB), run=30009-30009msec

Disk stats (read/write):
  nvme1n1: ios=0/15477, merge=0/0, ticks=0/118598, in_queue=118598, util=99.75%

$ date
Thu Oct 30 12:15:36 UTC 2025

平均129MiBps、517IOPSです。

VolumeAvgThroughputとVolumeAvgIOPSのメトリクスを確認します。

9.30秒fioを実行した場合のVolumeAvgThroughput.png
8.30秒fioを実行した場合のVolumeAvgIOPS.png

はい、64MiBpsと259IOPSと半分になっています。

これがいずれのメトリクスも1分間の平均を記録するものだからです。今回は30秒書き込んだため、fioの結果の半分となっています。

つまりは、マイクロバーストのような60秒未満の瞬間的な挙動は気付きづらいです。これは従来のやり方でも同様ですがが気をつけましょう。

パッとEBSボリュームのIOPSとスループットを把握したいときに

EBSボリュームで1分間の平均IOPSとスループットを表すCloudWatchメトリクスが追加されたアップデートを紹介しました。

パッとEBSボリュームのIOPSとスループットを把握したいときに非常に便利です。

なお、今までのように書き込み/読み込みの量や操作数から把握する方法が全く無駄になったという訳ではありません。今回追加されたいずれのメトリクスも読み取りと書き込みの区別はされていません。そのため、読み取りと書き込みのどちらの処理が重く性能が出ていないのかを把握したい場合などには変わらず必要な指標となります。ケースバイケースで使い分けましょう。

この記事が誰かの助けになれば幸いです。

以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!

この記事をシェアする

FacebookHatena blogX

関連記事