Hyper-V のホストサーバ上に All Flash でインライン重複排除ができるストレージサーバを作る

過去の検証で、インライン重複排除ができるストレージの作成までは手段が確立している。
そして「おうち HCI」を目指すうえでどうしても必要となってくるのが、「All Flash でインライン重複排除ができるストレージサーバ」である。
普通に仮想イメージ上に作るだけなら楽だが、Hyper-V 上で Raw Device Mapping して作る場合、ちょっとだけ面倒だったので、本記事はそのメモとなる。
また、RAID Level の検証も合わせて実施したので、その備忘録である。

■まえがき
今まで書いてきた記事をもとに、仮想マシンのディスクイメージ置き場を作る手順である。
ただし、今までと違うのは、ストレージ用仮想マシンに SSD を Raw Device Mapping して RAID 設定を行うところである。
SSD で RAID を組む場合の要件などは理解しているつもりだが、パフォーマンス試験などを残していなかったため、それをメインに記録を残している。
また、実際の構築にあたっては、以下の記事の継ぎ接ぎとなっている。
【過去記事】Enterprise Linux で重複排除を使ってみる
【過去記事】おうち VMware ESXi 7.0 は HCI の夢を見るか
なお、エンタープライズ向けストレージほど素晴らしい物ではないのは当然である。

■本記事そのものの構成
・Hyper-V 上の設定
・SSD on mdraid の検証
・実際の構築

■構成
・Host Server
 - Windows Server 2019
 - Hyper-V 有効化済み
・Storage Server VM
 - CPU 8Cores
 - Memory 16GB
 - OS-Disk 20GB
 - Storage-SSD 480GB x4

■■■ Hyper-V 上の設定 ■■■
■ストレージサーバ用 VM へ物理ディスクの接続
仮想マシンに対して物理 SSD を接続する Raw Device Mapping を行う場合、ホスト OS から論理的に切り離す必要がある。
切り離しを実施することで、仮想マシンの設定からディスクを接続できるようになる。
・ホスト OS からの切り離し

・仮想マシン設定にて物理ディスクの接続

■■■ SSD on mdraid の検証■■■
■各 RAID レベルの比較
Linux Kernel の mdraid では、主に RAID0/1/4/5/6/10 がサポートされている。
今回は SSD が 4 本なので、利用可能な RAID レベルとしては RAID0/1/4/5/6/10 である。
また、オーバープロビジョニングを考慮し、480GB の SSD 1 つあたり 400GB の使用とする。

RAID Level Capacity Fault tolerance
RAID 4 1.2TB 1
RAID 5 1.2TB 1
RAID 6 800GB 2
RAID 10 800GB At least 1-drive failure

■Block Discard の重要度
SSD を使ったストレージの場合、Trim/UNMAP を行って Block Discard を実施しないとパフォーマンスが劣化していく。
パフォーマンスの劣化を防ぐためにも、Block Discard は重要である。
Windows や Intel Rapid Storage Technology 等による一般的な RAID 構築手法だと RAID0 でのみ Trim がサポートされている。
Linux の場合は、Kernel 3.6 にて RAID1 環境での Trim サポート、Kernel 3.7 にて RAID4/5/6 環境での Trim サポートが付いたらしい。
この辺の調査は、過去の記事参照。
Linux Server に SSD を Software RAID (mdraid) で入れるときの確認ポイント
そのため、RAID 構築した状態で本当に Block Discard がされているのかを確認しておく。

■Trim/UNMAP など Block Discard 処理の確認方法
Block Discard 処理を可視化する方法として、Linux では SystemTap を用いることで可視化することができる。
[SH2の日記] SSDに対するBlock Discard/TRIMをSystemTapで可視化する
Linux Kernel にて blkdev_issue_discard が呼び出されたとき、何がどのブロックに対して Discard したのかをモニタリングすることで、可視化できるようだ。
今回はこちらの方法を使って確認する。

■SystemTap による Block Discard 処理の可視化をする準備
SystemTap を利用するには、kernel-debuginfo と kernel-debuginfo-common が必要になる。
参考:[Red Hat] 第2章 SystemTap の使用
CentOS の場合、http://debuginfo.centos.org/ に存在するため、こちらから持ってくる。
なお、本来は yum/dnf コマンドにてインストール可能なのだが、最新 Kernel の repodata が作成されていないためエラーとなる。

# yum install --enablerepo=base-debuginfo kernel-debuginfo-`uname -r`
CentOS-8 - Debuginfo                                       13 MB/s |  17 MB     00:01
Last metadata expiration check: 0:00:04 ago on Sun 04 Oct 2020 06:57:03 PM JST.
No match for argument: kernel-debuginfo-4.18.0-193.19.1.el8_2.x86_64
Error: Unable to find a match: kernel-debuginfo-4.18.0-193.19.1.el8_2.x86_64

そのため、手動でファイルをダウンロードしてインストールを行う。

# cd
# mkdir ./systemtap
# cd ./systemtap
# wget -N http://debuginfo.centos.org/8/x86_64/Packages/kernel-debuginfo-`uname -r`.rpm http://debuginfo.centos.org/8/x86_64/Packages/kernel-debuginfo-common-x86_64-`uname -r`.rpm
# yum install ./kernel-debuginfo-`uname -r`.rpm ./kernel-debuginfo-common-x86_64-`uname -r`.rpm
Last metadata expiration check: 0:00:51 ago on Sun 04 Oct 2020 07:00:23 PM JST.
Dependencies resolved.
==========================================================================================
 Package                          Arch     Version                   Repository      Size
==========================================================================================
Installing:
 kernel-debuginfo                 x86_64   4.18.0-193.19.1.el8_2     @commandline   497 M
 kernel-debuginfo-common-x86_64   x86_64   4.18.0-193.19.1.el8_2     @commandline    57 M

Transaction Summary
==========================================================================================
Install  2 Packages

Total size: 554 M
Installed size: 2.9 G
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                  1/1
  Installing       : kernel-debuginfo-common-x86_64-4.18.0-193.19.1.el8_2.x86_64      1/2
  Installing       : kernel-debuginfo-4.18.0-193.19.1.el8_2.x86_64                    2/2
  Running scriptlet: kernel-debuginfo-4.18.0-193.19.1.el8_2.x86_64                    2/2
  Verifying        : kernel-debuginfo-4.18.0-193.19.1.el8_2.x86_64                    1/2
  Verifying        : kernel-debuginfo-common-x86_64-4.18.0-193.19.1.el8_2.x86_64      2/2
Installed products updated.

Installed:
  kernel-debuginfo-4.18.0-193.19.1.el8_2.x86_64
  kernel-debuginfo-common-x86_64-4.18.0-193.19.1.el8_2.x86_64

Complete!

インストールが完了した後 SystemTap スクリプトを作成し、動作確認を行う。

# vi discard.stp
probe kernel.function("blkdev_issue_discard").return {
  printf("%s, sector=%d, nr_sects=%d, return=%d (%d - %d KiB)\n",
    execname(), $sector, $nr_sects, $return,
    $sector / 2, ($sector + $nr_sects) / 2 - 1);
}
# stap discard.stp

SystemTap がエラーで終了しないことを確認した後に、別ターミナルにて「使っていないディスク」に向かって blkdiscard あたりしてみる。

# blkdiscard /dev/sdb

次のように出力されれば、問題なく Block Discard の可視化ができている。

blkdiscard, sector=0, nr_sects=937703088, return=0 (0 - 468851543 KiB)

■試験用 Software RAID の作成
試験として、RAID4/5/6/10 全ての種類を作成し、その後 Block Discard ができるか試す。
まずは、ディスク状況の確認から。

# fdisk -l
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5a0fe596

Device     Boot    Start      End  Sectors Size Id Type
/dev/sda1  *        2048  4196351  4194304   2G 83 Linux
/dev/sda2        4196352 12584959  8388608   4G 82 Linux swap / Solaris
/dev/sda3       12584960 41943039 29358080  14G 83 Linux


Disk /dev/sdb: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sdc: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sdd: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sde: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

sdb, sdc, sdd, sde が空ディスクのため、こちらを使って Software RAID の構築を行う。
Software RAID を作成する前に、Flash Translation Layer (FTL) が最適化されることを願ってディスクの全領域を Block Discard する。

# blkdiscard /dev/sdb
# blkdiscard /dev/sdc
# blkdiscard /dev/sdd
# blkdiscard /dev/sde

SystemTap にて以下の出力があったため、各 SSD に無事 Block Discard が発行された模様。

blkdiscard, sector=0, nr_sects=937703088, return=0 (0 - 468851543 KiB)
blkdiscard, sector=0, nr_sects=937703088, return=0 (0 - 468851543 KiB)
blkdiscard, sector=0, nr_sects=937703088, return=0 (0 - 468851543 KiB)
blkdiscard, sector=0, nr_sects=937703088, return=0 (0 - 468851543 KiB)

次に、Software RAID を作るためにパーティションの切り出しを行う。

# fdisk /dev/sdb

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x2caf8b68.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-937703087, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-937703087, default 937703087): +100G

Created a new partition 1 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (209717248-937703087, default 209717248):
Last sector, +sectors or +size{K,M,G,T,P} (209717248-937703087, default 937703087): +100G

Created a new partition 2 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (2 primary, 0 extended, 2 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (419432448-937703087, default 419432448):
Last sector, +sectors or +size{K,M,G,T,P} (419432448-937703087, default 937703087): +100G

Created a new partition 3 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (3 primary, 0 extended, 1 free)
   e   extended (container for logical partitions)
Select (default e): p

Selected partition 4
First sector (629147648-937703087, default 629147648):
Last sector, +sectors or +size{K,M,G,T,P} (629147648-937703087, default 937703087): +100G

Created a new partition 4 of type 'Linux' and of size 100 GiB.

Command (m for help): t
Partition number (1-4, default 4): 1
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 2
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 3
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 4
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): p
Disk /dev/sdb: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2caf8b68

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdb1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sdb2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sdb3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sdb4       629147648 838862847 209715200  100G fd Linux raid autodetect

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

# fdisk /dev/sdc

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x9007f5bc.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-937703087, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-937703087, default 937703087): +100G

Created a new partition 1 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (209717248-937703087, default 209717248):
Last sector, +sectors or +size{K,M,G,T,P} (209717248-937703087, default 937703087): +100G

Created a new partition 2 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (2 primary, 0 extended, 2 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (419432448-937703087, default 419432448):
Last sector, +sectors or +size{K,M,G,T,P} (419432448-937703087, default 937703087): +100G

Created a new partition 3 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (3 primary, 0 extended, 1 free)
   e   extended (container for logical partitions)
Select (default e): p

Selected partition 4
First sector (629147648-937703087, default 629147648):
Last sector, +sectors or +size{K,M,G,T,P} (629147648-937703087, default 937703087): +100G

Created a new partition 4 of type 'Linux' and of size 100 GiB.

Command (m for help): t
Partition number (1-4, default 4): 1
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 2
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 3
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 4
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): p
Disk /dev/sdc: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x9007f5bc

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdc1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sdc2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sdc3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sdc4       629147648 838862847 209715200  100G fd Linux raid autodetect

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

# fdisk /dev/sdd

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x23adeb66.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-937703087, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-937703087, default 937703087): +100G

Created a new partition 1 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (209717248-937703087, default 209717248):
Last sector, +sectors or +size{K,M,G,T,P} (209717248-937703087, default 937703087): +100G

Created a new partition 2 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (2 primary, 0 extended, 2 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (419432448-937703087, default 419432448):
Last sector, +sectors or +size{K,M,G,T,P} (419432448-937703087, default 937703087): +100G

Created a new partition 3 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (3 primary, 0 extended, 1 free)
   e   extended (container for logical partitions)
Select (default e): p

Selected partition 4
First sector (629147648-937703087, default 629147648):
Last sector, +sectors or +size{K,M,G,T,P} (629147648-937703087, default 937703087): +100G

Created a new partition 4 of type 'Linux' and of size 100 GiB.

Command (m for help): t
Partition number (1-4, default 4): 1
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 2
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 3
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 4
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): p
Disk /dev/sdd: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x23adeb66

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdd1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sdd2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sdd3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sdd4       629147648 838862847 209715200  100G fd Linux raid autodetect

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

# fdisk /dev/sde

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x2c205079.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-937703087, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-937703087, default 937703087): +100G

Created a new partition 1 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (209717248-937703087, default 209717248):
Last sector, +sectors or +size{K,M,G,T,P} (209717248-937703087, default 937703087): +100G

Created a new partition 2 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (2 primary, 0 extended, 2 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (419432448-937703087, default 419432448):
Last sector, +sectors or +size{K,M,G,T,P} (419432448-937703087, default 937703087): +100G

Created a new partition 3 of type 'Linux' and of size 100 GiB.

Command (m for help): n
Partition type
   p   primary (3 primary, 0 extended, 1 free)
   e   extended (container for logical partitions)
Select (default e): p

Selected partition 4
First sector (629147648-937703087, default 629147648):
Last sector, +sectors or +size{K,M,G,T,P} (629147648-937703087, default 937703087): +100G

Created a new partition 4 of type 'Linux' and of size 100 GiB.

Command (m for help): t
Partition number (1-4, default 4): 1
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 2
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 3
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): t
Partition number (1-4, default 4): 4
Hex code (type L to list all codes): fd

Changed type of partition 'Linux' to 'Linux raid autodetect'.

Command (m for help): p
Disk /dev/sde: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2c205079

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sde1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sde2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sde3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sde4       629147648 838862847 209715200  100G fd Linux raid autodetect

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

パーティションの状況を確認。

# fdisk -l
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5a0fe596

Device     Boot    Start      End  Sectors Size Id Type
/dev/sda1  *        2048  4196351  4194304   2G 83 Linux
/dev/sda2        4196352 12584959  8388608   4G 82 Linux swap / Solaris
/dev/sda3       12584960 41943039 29358080  14G 83 Linux


Disk /dev/sdd: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x23adeb66

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdd1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sdd2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sdd3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sdd4       629147648 838862847 209715200  100G fd Linux raid autodetect


Disk /dev/sdc: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x9007f5bc

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdc1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sdc2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sdc3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sdc4       629147648 838862847 209715200  100G fd Linux raid autodetect


Disk /dev/sdb: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2caf8b68

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sdb1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sdb2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sdb3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sdb4       629147648 838862847 209715200  100G fd Linux raid autodetect


Disk /dev/sde: 447.1 GiB, 480103981056 bytes, 937703088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2c205079

Device     Boot     Start       End   Sectors  Size Id Type
/dev/sde1            2048 209717247 209715200  100G fd Linux raid autodetect
/dev/sde2       209717248 419432447 209715200  100G fd Linux raid autodetect
/dev/sde3       419432448 629147647 209715200  100G fd Linux raid autodetect
/dev/sde4       629147648 838862847 209715200  100G fd Linux raid autodetect

sdb ~ sde に対して、パーティション 1 ~ 4 まで 100GB ずつ作成されたことを確認できたので、Software RAID を作成する。

# mdadm --create /dev/md0 --level=raid4 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
# mdadm --create /dev/md1 --level=raid5 --raid-devices=4 /dev/sdb2 /dev/sdc2 /dev/sdd2 /dev/sde2
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md1 started.
# mdadm --create /dev/md2 --level=raid6 --raid-devices=4 /dev/sdb3 /dev/sdc3 /dev/sdd3 /dev/sde3
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md2 started.
# mdadm --create /dev/md3 --level=raid10 --raid-devices=4 /dev/sdb4 /dev/sdc4 /dev/sdd4 /dev/sde4
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md3 started.

作成された Software RAID を確認する。

# cat /proc/mdstat
Personalities : [raid6] [raid5] [raid4] [raid10]
md3 : active raid10 sde4[3] sdd4[2] sdc4[1] sdb4[0]
      209582080 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]

md2 : active raid6 sde3[3] sdd3[2] sdc3[1] sdb3[0]
      209582080 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/4] [UUUU]

md1 : active raid5 sde2[4] sdd2[2] sdc2[1] sdb2[0]
      314373120 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]

md0 : active raid4 sde1[4] sdd1[2] sdc1[1] sdb1[0]
      314373120 blocks super 1.2 level 4, 512k chunk, algorithm 0 [4/4] [UUUU]

unused devices: 

問題なく作成されたようだ・w・

■Block Discard の有効化確認
作成された Software RAID の md Device に対して、Block Discard を発行してみる。

# blkdiscard /dev/md0
blkdiscard: /dev/md0: BLKDISCARD ioctl failed: Operation not supported
# blkdiscard /dev/md1
blkdiscard: /dev/md1: BLKDISCARD ioctl failed: Operation not supported
# blkdiscard /dev/md2
blkdiscard: /dev/md2: BLKDISCARD ioctl failed: Operation not supported
# blkdiscard /dev/md3

RAID 4/5/6 では、Block Discard が動かなかった。
なお、SystemTap の出力も、RAID10 でのみ以下の出力があった。

blkdiscard, sector=0, nr_sects=419164160, return=0 (0 - 209582079 KiB)

■RAID 4/5/6 における Block Discard の有効化
Linux Kernel のソースコードを確認してみた結果、RHEL に置いては追加の設定が必要ということが分かった。
まずは Linux Kernel 内にある mdraid RAID5 のコードにて「Discard」を検索すると、【 devices_handle_discard_safely 】というものが見つかる。
[Linux Kernel] raid5.c
devices_handle_discard_safely で検索していくと、Red Hat のドキュメントが見つかる
[Red Hat] 第21章 ソリッドステートディスクの導入ガイドライン
確認してみたところ、私が過去に書いた記事の通り Read Zero after TRIM の SSD を使わないと危険であるため、デフォルトでは RAID4/5/6 にて Block Discard ができないようになっているそうだ。
今回使ったディスクは Samsung PM863a MZ7LM480HMHQ であるため、RZAT に対応しているので、有効化処理を行う。

# vi /etc/modprobe.d/raid456.conf
options raid456 devices_handle_discard_safely=Y
# dracut -f
# reboot

リブート後、Block Discard を再び試してみると、今度はエラーが発生せずに無事 Block Discard が実行できた。

# blkdiscard /dev/md0
# blkdiscard /dev/md1
# blkdiscard /dev/md2
# blkdiscard /dev/md3

SystemTap 上でも、無事に Block Discard が発行されている様子が確認できた。

blkdiscard, sector=0, nr_sects=628746240, return=0 (0 - 314373119 KiB)
blkdiscard, sector=0, nr_sects=628746240, return=0 (0 - 314373119 KiB)
blkdiscard, sector=0, nr_sects=419164160, return=0 (0 - 209582079 KiB)
blkdiscard, sector=0, nr_sects=419164160, return=0 (0 - 209582079 KiB)

■md Device 上に作成した ext4 Filesystem 上で Block Discard が有効であることを確認
まずは各 md Device 上に ext4 Filesystem を作成する。

# mkfs -t ext4 /dev/md0
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 78593280 4k blocks and 19652608 inodes
Filesystem UUID: 23b6b4dc-7ab1-4dbf-ba6b-d592c6e5a9ee
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

# mkfs -t ext4 /dev/md1
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 78593280 4k blocks and 19652608 inodes
Filesystem UUID: bcdead1e-f403-4fda-b387-a6c28e50b988
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

# mkfs -t ext4 /dev/md2
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 52395520 4k blocks and 13099008 inodes
Filesystem UUID: 44551a84-1407-41e3-a76a-007b27c2bf87
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

# mkfs -t ext4 /dev/md3
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 52395520 4k blocks and 13099008 inodes
Filesystem UUID: 382c87f1-98c6-4726-a640-b51e12727757
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

ext4 Filesystem 作成中に Block Discard の結果が SystemTap により出力される。

mkfs.ext4, sector=0, nr_sects=32768, return=0 (0 - 16383 KiB)
mkfs.ext4, sector=32768, nr_sects=4194304, return=0 (16384 - 2113535 KiB)
mkfs.ext4, sector=4227072, nr_sects=4194304, return=0 (2113536 - 4210687 KiB)
    ... snip ...
mkfs.ext4, sector=616595456, nr_sects=4194304, return=0 (308297728 - 310394879 KiB)
mkfs.ext4, sector=620789760, nr_sects=4194304, return=0 (310394880 - 312492031 KiB)
mkfs.ext4, sector=624984064, nr_sects=3762176, return=0 (312492032 - 314373119 KiB)

mkfs.ext4, sector=0, nr_sects=32768, return=0 (0 - 16383 KiB)
mkfs.ext4, sector=32768, nr_sects=4194304, return=0 (16384 - 2113535 KiB)
mkfs.ext4, sector=4227072, nr_sects=4194304, return=0 (2113536 - 4210687 KiB)
    ... snip ...
mkfs.ext4, sector=616595456, nr_sects=4194304, return=0 (308297728 - 310394879 KiB)
mkfs.ext4, sector=620789760, nr_sects=4194304, return=0 (310394880 - 312492031 KiB)
mkfs.ext4, sector=624984064, nr_sects=3762176, return=0 (312492032 - 314373119 KiB)

mkfs.ext4, sector=0, nr_sects=32768, return=0 (0 - 16383 KiB)
mkfs.ext4, sector=32768, nr_sects=4194304, return=0 (16384 - 2113535 KiB)
mkfs.ext4, sector=4227072, nr_sects=4194304, return=0 (2113536 - 4210687 KiB)
    ... snip ...
mkfs.ext4, sector=406880256, nr_sects=4194304, return=0 (203440128 - 205537279 KiB)
mkfs.ext4, sector=411074560, nr_sects=4194304, return=0 (205537280 - 207634431 KiB)
mkfs.ext4, sector=415268864, nr_sects=3895296, return=0 (207634432 - 209582079 KiB)

mkfs.ext4, sector=0, nr_sects=32768, return=0 (0 - 16383 KiB)
mkfs.ext4, sector=32768, nr_sects=4194304, return=0 (16384 - 2113535 KiB)
mkfs.ext4, sector=4227072, nr_sects=4194304, return=0 (2113536 - 4210687 KiB)
    ... snip ...
mkfs.ext4, sector=406880256, nr_sects=4194304, return=0 (203440128 - 205537279 KiB)
mkfs.ext4, sector=411074560, nr_sects=4194304, return=0 (205537280 - 207634431 KiB)
mkfs.ext4, sector=415268864, nr_sects=3895296, return=0 (207634432 - 209582079 KiB)

マウントポイントを作成し、マウントの実行。

# mkdir /root/md0
# mkdir /root/md1
# mkdir /root/md2
# mkdir /root/md3
# mount /dev/md0 /root/md0
# mount /dev/md1 /root/md1
# mount /dev/md2 /root/md2
# mount /dev/md3 /root/md3

テストデータの書き込み。

# dd if=/dev/urandom of=/root/md0/random01.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md1/random01.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md2/random01.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md3/random01.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md0/random02.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md1/random02.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md2/random02.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md3/random02.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md0/random03.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md1/random03.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md2/random03.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md3/random03.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md0/random04.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md1/random04.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md2/random04.dat bs=1M status=progress &
# dd if=/dev/urandom of=/root/md3/random04.dat bs=1M status=progress &

テストデータの消去。

# ls -la /root/md*/random01.dat
-rw-r--r--. 1 root root 78964064256 Oct 04 17:31 /root/md0/random01.dat
-rw-r--r--. 1 root root 78896955392 Oct 04 17:31 /root/md1/random01.dat
-rw-r--r--. 1 root root 52465500160 Oct 04 16:56 /root/md2/random01.dat
-rw-r--r--. 1 root root 52464451584 Oct 04 16:56 /root/md3/random01.dat
# rm -f /root/md*/random01.dat
# sync
# fstrim -av
/root/md3: 48.9 GiB (52478418944 bytes) trimmed
/root/md2: 48.9 GiB (52454936576 bytes) trimmed
/root/md1: 73.5 GiB (78900338688 bytes) trimmed
/root/md0: 73.6 GiB (78972014592 bytes) trimmed
/boot: 0 B (0 bytes) trimmed
/: 0 B (0 bytes) trimmed

問題なく fstrim によって Block Discard が実行できた。
SystemTap からは 5000 行ほどの Block Discard の発行が検知されていたので、確実に実行された。

せっかくなので、ファイル消去と同時に Block Discard が実行されるモードも正常に動くことを確認したい。
まずは、アンマウント。

# umount /root/md0
# umount /root/md1
# umount /root/md2
# umount /root/md3

オプション discard を付与してマウントの実施。

# mount -o discard /dev/md0 /root/md0
# mount -o discard /dev/md1 /root/md1
# mount -o discard /dev/md2 /root/md2
# mount -o discard /dev/md3 /root/md3

マウント後に一度 fstrim を実行し、空き領域を Block Discard しておく。

# fstrim -av
/root/md3: 0 B (0 bytes) trimmed
/root/md2: 0 B (0 bytes) trimmed
/root/md1: 0 B (0 bytes) trimmed
/root/md0: 0 B (0 bytes) trimmed
/boot: 0 B (0 bytes) trimmed
/: 0 B (0 bytes) trimmed

テストデータの消去。

# ls -la /root/md*/random02.dat
-rw-r--r--. 1 root root 78897737728 Oct 04 17:31 /root/md0/random02.dat
-rw-r--r--. 1 root root 78950432768 Oct 04 17:31 /root/md1/random02.dat
-rw-r--r--. 1 root root 52583989248 Oct 04 16:56 /root/md2/random02.dat
-rw-r--r--. 1 root root 52529463296 Oct 04 16:56 /root/md3/random02.dat
# rm -f /root/md*/random02.dat

何かバックグラウンドで処理が動いているようだが、SystemTap では何も出力されない。
そのため、fstrim をしてみる。

# fstrim -av
/root/md3: 0 B (0 bytes) trimmed
/root/md2: 20.1 GiB (21560033280 bytes) trimmed
/root/md1: 41.7 GiB (44744699904 bytes) trimmed
/root/md0: 54.4 GiB (58382602240 bytes) trimmed
/boot: 0 B (0 bytes) trimmed
/: 108.1 MiB (113344512 bytes) trimmed

どうやらバックグラウンドで Block Discard が動いていた模様。
fstrim 等で一気に実施するとパフォーマンスに影響があるためか、徐々に実施するようだ。
また、RHEL7 のときは SystemTap で観測できていたので、何か仕様が変わったようだ。

■Block Discard の有効化後における、データの整合性確認
Block Discard を実施後、RAID が正常に稼働していることを確認する。
手順としては、ひとつ前に実施した”md Device 上に作成した ext4 Filesystem 上で Block Discard が有効であることを確認”テストをしたものをそのまま使う。
各 RAID テストパターンに作られたファイルシステム上からファイルを削除し、実際に Block Discard が実行された後であるため、RAID 整合性試験を行うのにちょうどよいからだ。

まずは、各 md Device に対して、整合性チェックの指示。

# echo check > /sys/block/md0/md/sync_action
# echo check > /sys/block/md1/md/sync_action
# echo check > /sys/block/md2/md/sync_action
# echo check > /sys/block/md3/md/sync_action

チェックが進行中であることを確認。

# cat /proc/mdstat
Personalities : [raid10] [raid6] [raid5] [raid4]
md2 : active raid6 sde3[3] sdd3[2] sdb3[0] sdc3[1]
      209582080 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/4] [UUUU]
        resync=DELAYED

md0 : active raid4 sde1[4] sdb1[0] sdd1[2] sdc1[1]
      314373120 blocks super 1.2 level 4, 512k chunk, algorithm 0 [4/4] [UUUU]
      [=>...................]  check =  6.1% (6489916/104791040) finish=4.2min speed=381759K/sec

md1 : active raid5 sde2[4] sdb2[0] sdd2[2] sdc2[1]
      314373120 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
        resync=DELAYED

md3 : active raid10 sde4[3] sdd4[2] sdc4[1] sdb4[0]
      209582080 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
        resync=DELAYED

unused devices: 

チェックの完了を Syslog にて確認。

Oct  4 21:32:18 sasya kernel: md: data-check of RAID array md0
Oct  4 21:32:20 sasya kernel: md: delaying data-check of md1 until md0 has finished (they share one or more physical units)
Oct  4 21:32:22 sasya kernel: md: delaying data-check of md2 until md0 has finished (they share one or more physical units)
Oct  4 21:32:22 sasya kernel: md: delaying data-check of md1 until md2 has finished (they share one or more physical units)
Oct  4 21:32:24 sasya kernel: md: delaying data-check of md3 until md0 has finished (they share one or more physical units)
Oct  4 21:37:19 sasya kernel: md: md0: data-check done.
Oct  4 21:37:19 sasya kernel: md: delaying data-check of md2 until md3 has finished (they share one or more physical units)
Oct  4 21:37:19 sasya kernel: md: data-check of RAID array md3
Oct  4 21:42:24 sasya kernel: md: md3: data-check done.
Oct  4 21:42:24 sasya kernel: md: data-check of RAID array md2
Oct  4 21:48:08 sasya kernel: md: md2: data-check done.
Oct  4 21:48:09 sasya kernel: md: data-check of RAID array md1
Oct  4 21:52:53 sasya kernel: md: md1: data-check done.

Software RAID ステータスを確認。

# cat /proc/mdstat
Personalities : [raid10] [raid6] [raid5] [raid4]
md2 : active raid6 sde3[3] sdd3[2] sdb3[0] sdc3[1]
      209582080 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/4] [UUUU]

md0 : active raid4 sde1[4] sdb1[0] sdd1[2] sdc1[1]
      314373120 blocks super 1.2 level 4, 512k chunk, algorithm 0 [4/4] [UUUU]

md1 : active raid5 sde2[4] sdb2[0] sdd2[2] sdc2[1]
      314373120 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]

md3 : active raid10 sde4[3] sdd4[2] sdc4[1] sdb4[0]
      209582080 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]

unused devices: 

md Device 的に問題がないため、アンマウントを実施した後に Filesystem の整合性チェックの実行。

# umount /root/md0
# umount /root/md1
# umount /root/md2
# umount /root/md3
# fsck /dev/md0
fsck from util-linux 2.32.1
e2fsck 1.45.4 (23-Sep-2019)
/dev/md0: clean, 12/19652608 files, 20785720/78593280 blocks
# fsck /dev/md1
fsck from util-linux 2.32.1
e2fsck 1.45.4 (23-Sep-2019)
/dev/md1: clean, 12/19652608 files, 20785464/78593280 blocks
# fsck /dev/md2
fsck from util-linux 2.32.1
e2fsck 1.45.4 (23-Sep-2019)
/dev/md2: clean, 12/13099008 files, 13928205/52395520 blocks
# fsck /dev/md3
fsck from util-linux 2.32.1
e2fsck 1.45.4 (23-Sep-2019)
/dev/md3: clean, 12/13099008 files, 13933583/52395520 blocks

最後に、Block Device としてエラーが無いかを badblocks の Read Only Test にて確認。

# badblocks -sv /dev/md0 -c 32768
Checking blocks 0 to 314373119
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)
# badblocks -sv /dev/md1 -c 32768
Checking blocks 0 to 314373119
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)
# badblocks -sv /dev/md2 -c 32768
Checking blocks 0 to 209582079
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)
# badblocks -sv /dev/md3 -c 32768
Checking blocks 0 to 209582079
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)

結果、問題がなかったと判断できた。

■速度確認
何も考えず、Disk Dump で Zero を書き込み、その後読み込む。
ベンチマークソフト使うべきなのはわかるけど、殆どの場合 Page Cache が効いてしまうので、Cache 無効にできる Disk Dump のほうが素直に感じたのでこの手法で試す。

# dd if=/dev/zero of=/dev/md0 bs=1G oflag=direct status=progress
321048805376 bytes (321 GB, 299 GiB) copied, 557 s, 577 MB/s
dd: error writing '/dev/md0': No space left on device
300+0 records in
299+0 records out
321918074880 bytes (322 GB, 300 GiB) copied, 558.491 s, 576 MB/s
# dd if=/dev/zero of=/dev/md1 bs=1G oflag=direct status=progress
321048805376 bytes (321 GB, 299 GiB) copied, 590 s, 544 MB/s
dd: error writing '/dev/md1': No space left on device
300+0 records in
299+0 records out
321918074880 bytes (322 GB, 300 GiB) copied, 591.578 s, 544 MB/s
# dd if=/dev/zero of=/dev/md2 bs=1G oflag=direct status=progress
213674622976 bytes (214 GB, 199 GiB) copied, 493 s, 433 MB/s
dd: error writing '/dev/md2': No space left on device
200+0 records in
199+0 records out
214612049920 bytes (215 GB, 200 GiB) copied, 495.475 s, 433 MB/s
# dd if=/dev/zero of=/dev/md3 bs=1G oflag=direct status=progress
213674622976 bytes (214 GB, 199 GiB) copied, 387 s, 552 MB/s
dd: error writing '/dev/md3': No space left on device
200+0 records in
199+0 records out
214612049920 bytes (215 GB, 200 GiB) copied, 389.045 s, 552 MB/s
# dd if=/dev/md0 of=/dev/null bs=1G status=progress
321048805376 bytes (321 GB, 299 GiB) copied, 207 s, 1.5 GB/s
299+1 records in
299+1 records out
321918074880 bytes (322 GB, 300 GiB) copied, 211.475 s, 1.5 GB/s
# dd if=/dev/md1 of=/dev/null bs=1G status=progress
321048805376 bytes (321 GB, 299 GiB) copied, 208 s, 1.5 GB/s
299+1 records in
299+1 records out
321918074880 bytes (322 GB, 300 GiB) copied, 212.563 s, 1.5 GB/s
# dd if=/dev/md2 of=/dev/null bs=1G status=progress
213674622976 bytes (214 GB, 199 GiB) copied, 140 s, 1.5 GB/s
199+1 records in
199+1 records out
214612049920 bytes (215 GB, 200 GiB) copied, 144.594 s, 1.5 GB/s
# dd if=/dev/md3 of=/dev/null bs=1G status=progress
214612049920 bytes (215 GB, 200 GiB) copied, 139 s, 1.5 GB/s
199+1 records in
199+1 records out
214612049920 bytes (215 GB, 200 GiB) copied, 142.974 s, 1.5 GB/s
RAID Level Read (MByte/Sec) Write (MByte/Sec)
RAID 4 1522 577
RAID 5 1514 544
RAID 6 1486 433
RAID 10 1503 552

読み書き速度を見る限り、書き込み速度はどうも SSD そのものの速度に足を引っ張られているように見える。
iostat 1 -m 等でモニタリングしていても、md Device I/O には余裕がみられるが、SSD そのものである sdX 側は張り付いたままの様子。
これでは比較にならないので、I/O は発生しないが RAID として処理が発生する Block Discard の速度も調査する。

md Device に対して Block Discard を実行。

# time blkdiscard /dev/md0

real    2m15.833s
user    0m0.001s
sys     0m53.701s
# time blkdiscard /dev/md1

real    2m17.624s
user    0m0.001s
sys     0m55.085s
# time blkdiscard /dev/md2

real    2m2.712s
user    0m0.000s
sys     0m47.870s
# time blkdiscard /dev/md3

real    2m52.710s
user    0m0.001s
sys     0m1.147s

どう判断すればいいんだこれ・x・?
Real はまあわかるが、 Sys が乖離しすぎている。

一応、SystemTap では、しっかり Block Discard が発行されているが・・・。

blkdiscard, sector=0, nr_sects=628746240, return=0 (0 - 314373119 KiB)
blkdiscard, sector=0, nr_sects=628746240, return=0 (0 - 314373119 KiB)
blkdiscard, sector=0, nr_sects=419164160, return=0 (0 - 209582079 KiB)
blkdiscard, sector=0, nr_sects=419164160, return=0 (0 - 209582079 KiB)

一回で Discard 投げる量が多すぎる気がするため、ext4 Filesystem を作成し、その上で fstrim -v を実行して測定することにする。

追試験をするために、以下のようにパーティションを作成する。

# fdisk -l | grep md
Disk /dev/md3: 199.9 GiB, 214612049920 bytes, 419164160 sectors
/dev/md3p1       2048 209717247 209715200  100G 83 Linux
Disk /dev/md1: 299.8 GiB, 321918074880 bytes, 628746240 sectors
/dev/md1p1       3072 209719295 209716224  100G 83 Linux
Disk /dev/md0: 299.8 GiB, 321918074880 bytes, 628746240 sectors
/dev/md0p1       3072 209719295 209716224  100G 83 Linux
Disk /dev/md2: 199.9 GiB, 214612049920 bytes, 419164160 sectors
/dev/md2p1       2048 209717247 209715200  100G 83 Linux

各パーティションに、ext4 Filesystem を作成する。

# time mkfs -t ext4 /dev/md0p1
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 26214400 4k blocks and 6566400 inodes
Filesystem UUID: bd2de3ca-093d-4818-80e5-ea67f396734a
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done


real    0m49.741s
user    0m0.010s
sys     0m19.423s
# time mkfs -t ext4 /dev/md1p1
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 26214400 4k blocks and 6566400 inodes
Filesystem UUID: 6bbc758e-f5d7-4790-918b-4827a848eb77
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done


real    0m50.821s
user    0m0.007s
sys     0m20.563s
# time mkfs -t ext4 /dev/md2p1
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 26214400 4k blocks and 6553600 inodes
Filesystem UUID: 08706b6c-9507-4879-a161-121ec9b1987f
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done


real    1m6.767s
user    0m0.006s
sys     0m24.637s
# time mkfs -t ext4 /dev/md3p1
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 26214400 4k blocks and 6553600 inodes
Filesystem UUID: 980407a5-dc3a-43af-ae94-bf896a1a5748
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done


real    0m1.561s
user    0m0.003s
sys     0m0.284s

もうこの時点で、答えは見えてしまっているが、一応試験継続する。

マウントの実施。

# mount /dev/md0p1 /root/md0
# mount /dev/md1p1 /root/md1
# mount /dev/md2p1 /root/md2
# mount /dev/md3p1 /root/md3

ext4 Filesystem に対して Block Discard の実施。

# time fstrim -v /root/md0
/root/md0: 97.9 GiB (105085960192 bytes) trimmed

real    0m47.667s
user    0m0.002s
sys     0m12.520s
# time fstrim -v /root/md1
/root/md1: 97.9 GiB (105085960192 bytes) trimmed

real    0m48.620s
user    0m0.001s
sys     0m13.596s
# time fstrim -v /root/md2
/root/md2: 97.9 GiB (105089236992 bytes) trimmed

real    1m7.436s
user    0m0.002s
sys     0m20.157s
# time fstrim -v /root/md3
/root/md3: 97.9 GiB (105089236992 bytes) trimmed

real    0m9.499s
user    0m0.004s
sys     0m0.313s

これらの結果を見るに、どうも blkdiscard で md Device を直接 Block Discard した場合、時間がかかるようだ。
fstrim にて Filesystem を Block Discard した場合は、それなりの速度で動く模様。
また、top で観測していると、md0_raid4, md1_raid5, md2_raid6, md3_raid10 というプロセスの負荷が sys に該当している様子。
そうなると、sys が一番少ない RAID10 が最も負荷が低いということになる。

違いを探してみたら、Kernel から認識されてる Block Discard に関する情報が問題に思えてきた。

# more /sys/block/sd[b,c,d,e]/queue/discard_*
::::::::::::::
/sys/block/sdb/queue/discard_granularity
::::::::::::::
512
::::::::::::::
/sys/block/sdb/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sdb/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sdb/queue/discard_zeroes_data
::::::::::::::
0
::::::::::::::
/sys/block/sdc/queue/discard_granularity
::::::::::::::
512
::::::::::::::
/sys/block/sdc/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sdc/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sdc/queue/discard_zeroes_data
::::::::::::::
0
::::::::::::::
/sys/block/sdd/queue/discard_granularity
::::::::::::::
512
::::::::::::::
/sys/block/sdd/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sdd/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sdd/queue/discard_zeroes_data
::::::::::::::
0
::::::::::::::
/sys/block/sde/queue/discard_granularity
::::::::::::::
512
::::::::::::::
/sys/block/sde/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sde/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/sde/queue/discard_zeroes_data
::::::::::::::
0
# more /sys/block/md[0,1,2,3]/queue/discard_*
::::::::::::::
/sys/block/md0/queue/discard_granularity
::::::::::::::
2097152
::::::::::::::
/sys/block/md0/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/md0/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/md0/queue/discard_zeroes_data
::::::::::::::
0
::::::::::::::
/sys/block/md1/queue/discard_granularity
::::::::::::::
2097152
::::::::::::::
/sys/block/md1/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/md1/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/md1/queue/discard_zeroes_data
::::::::::::::
0
::::::::::::::
/sys/block/md2/queue/discard_granularity
::::::::::::::
1048576
::::::::::::::
/sys/block/md2/queue/discard_max_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/md2/queue/discard_max_hw_bytes
::::::::::::::
4294966784
::::::::::::::
/sys/block/md2/queue/discard_zeroes_data
::::::::::::::
0
::::::::::::::
/sys/block/md3/queue/discard_granularity
::::::::::::::
512
::::::::::::::
/sys/block/md3/queue/discard_max_bytes
::::::::::::::
524288
::::::::::::::
/sys/block/md3/queue/discard_max_hw_bytes
::::::::::::::
524288
::::::::::::::
/sys/block/md3/queue/discard_zeroes_data
::::::::::::::
0

この辺のチューニングとかできないかといくつか試してみたものの、現時点では解決できなかった。
mdadm にて md Device を作成するときの chunk サイズをいろいろ試したものの、劇的に改善はしなかった。
なお RAID1 の場合は、Raw Device と同等の速度で Block Discard が実行できた。

■■■ 実際の構築 ■■■
■構成の確定
ディスク 2 本同時障害を考えると、RAID6 が一番良いと考える。
ただし、ファイルの削除が頻繁に行われる場合は、RAID10 のほうが良いように見えてくる。
容量を取るなら RAID5 がベストかもしれないが、一本壊れただけで後がなくなるのは怖い。
今回の用途は、仮想マシンのファイル置き場として VDO (Virtual Data Optimizer) も挟むため、負荷が少ない物を選びたい。
そのため今回は、RAID10 を採用することとした。

■テスト用 md Device の削除
まずは md Device の停止

# mdadm --misc --stop /dev/md3
mdadm: stopped /dev/md3
# mdadm --misc --stop /dev/md2
mdadm: stopped /dev/md2
# mdadm --misc --stop /dev/md1
mdadm: stopped /dev/md1
# mdadm --misc --stop /dev/md0
mdadm: stopped /dev/md0

次に、使っていたディスクの初期化。Block Discard を使って FTL の初期化を願う。

# blkdiscard /dev/sdb
# blkdiscard /dev/sdc
# blkdiscard /dev/sdd
# blkdiscard /dev/sde

■RAID10 md Device の作成
新しい RAID10 md Device 用パーティションの作成。
480GB の SSD なので、オーバープロビジョニングも考慮して、fdisk にて 400GB ずつパーティションを作成する。
作成した結果は以下の通り。

# fdisk -l | grep sd[b,c,d,e]
Disk /dev/sdb: 447.1 GiB, 480103981056 bytes, 937703088 sectors
/dev/sdb1        2048 838862847 838860800  400G fd Linux raid autodetect
Disk /dev/sdd: 447.1 GiB, 480103981056 bytes, 937703088 sectors
/dev/sdd1        2048 838862847 838860800  400G fd Linux raid autodetect
Disk /dev/sdc: 447.1 GiB, 480103981056 bytes, 937703088 sectors
/dev/sdc1        2048 838862847 838860800  400G fd Linux raid autodetect
Disk /dev/sde: 447.1 GiB, 480103981056 bytes, 937703088 sectors
/dev/sde1        2048 838862847 838860800  400G fd Linux raid autodetect

RAID10 md Device を作成する。

# mdadm --create /dev/md0 --level=raid10 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

■VDO Volume の作成
今回は、作成した一つの md Device を利用する。
そのため、永続的な命名属性として、直接 /dev/md0 を利用してしまう。
RAID10 によりおよそ 800GB の md Device が作成されているため、実効容量 5 倍と雑に考えて 4TB の VDO Volume を作成する。

# vdo create \
     --name=VDO-vol01 \
     --device=/dev/md0 \
     --sparseIndex=enabled --indexMem=0.25 \
     --vdoLogicalSize=4T
Creating VDO VDO-vol01
      The VDO volume can address 776 GB in 388 data slabs, each 2 GB.
      It can grow to address at most 16 TB of physical storage in 8192 slabs.
      If a larger maximum size might be needed, use bigger slabs.
Starting VDO VDO-vol01
Starting compression on VDO VDO-vol01
VDO instance 1 volume is ready at /dev/mapper/VDO-vol01

# fdisk -l /dev/mapper/VDO-vol01
Disk /dev/mapper/VDO-vol01: 4 TiB, 4398046511104 bytes, 1073741824 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

■マウントポイント
VMware vSphere HA 向けハートビート データストア領域向けマウントポイントも作る必要があるため、マウントポイントは 3 つ作るとする。

/export/heartbeat1  Heartbeat 用 1
/export/heartbeat2  Heartbeat 用 2
/export/VDO-vol01   VDO Volume

上記要件を満たすようにするため、マウントポイントの作成する。

# mkdir -p /export/heartbeat1
# mkdir -p /export/heartbeat2
# mkdir -p /export/VDO-vol01

■Filesystem の作成とマウント
・VDO Volume に、ext4 Filesystem を作成

# mkfs.ext4 -E nodiscard /dev/mapper/VDO-vol01
mke2fs 1.45.4 (23-Sep-2019)
Creating filesystem with 1073741824 4k blocks and 134217728 inodes
Filesystem UUID: c376314f-ccd9-4023-a9c8-659a73dfa6a4
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000, 214990848, 512000000, 550731776, 644972544

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

・マウント回数や最終 fsck から経過時間でのオート fsck を OFF にする

# tune2fs -c 0 -i 0 /dev/mapper/VDO-vol01
tune2fs 1.45.4 (23-Sep-2019)
Setting maximal mount count to -1
Setting interval between checks to 0 seconds

・VDO Volume をマウント

# mkdir -p /export/VDO-vol01
# cp -piav /etc/fstab /etc/fstab.org
# ls -la /etc/fstab*
# echo "/dev/mapper/VDO-vol01 /export/VDO-vol01 ext4 defaults,_netdev,x-systemd.device-timeout=0,x-systemd.requires=vdo.service 0 0" >> /etc/fstab
# diff /etc/fstab.org /etc/fstab
# mount -a
# mount
# mount | grep VDO-vol01
/dev/mapper/VDO-vol01 on /export/VDO-vol01 type ext4 (rw,relatime,seclabel,_netdev,x-systemd.device-timeout=0)
# df -h /export/VDO-vol01
Filesystem             Size  Used Avail Use% Mounted on
/dev/mapper/VDO-vol01  4.0T   89M  3.8T   1% /export/VDO-vol01

システム起動時に自動的にマウントさせるため、/etc/fstab に追記する。ただし、VDO ボリュームの場合、vdo.service が起動する前にはマウントすることができないため、上記のように requires=vdo を付与する必要がある。
参考:VDO ボリュームのマウント

・初回ブロック破棄(discard)の実施

# fstrim -av
/export/VDO-vol01: 4 TiB (4362206064640 bytes) trimmed

かかる時間は CPU の性能に左右されます。

・定期的なブロック破棄(discard)の有効化

# systemctl enable --now fstrim.timer

これを仕込むことで、/usr/sbin/fstrim -av が週に一度動くようになる。

・VMware vSphere HA 向けハートビート データストア領域の作成

# dd if=/dev/zero of=/export/heartbeat1.img bs=1G count=1
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.16528 s, 921 MB/s
# dd if=/dev/zero of=/export/heartbeat2.img bs=1G count=1
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.2624 s, 851 MB/s
# mkfs -t ext4 /export/heartbeat1.img
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: c50ccc72-21ed-4662-a859-fdb9d01f3989
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

# mkfs -t ext4 /export/heartbeat2.img
mke2fs 1.45.4 (23-Sep-2019)
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: 9f0a7644-fca4-4b89-bf01-519f970de954
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

# tune2fs -c 0 -i 0 /export/heartbeat1.img
tune2fs 1.45.4 (23-Sep-2019)
Setting maximal mount count to -1
Setting interval between checks to 0 seconds
# tune2fs -c 0 -i 0 /export/heartbeat2.img
tune2fs 1.45.4 (23-Sep-2019)
Setting maximal mount count to -1
Setting interval between checks to 0 seconds
# echo "/export/heartbeat1.img /export/heartbeat1 ext4 defaults 0 0" >> /etc/fstab
# echo "/export/heartbeat2.img /export/heartbeat2 ext4 defaults 0 0" >> /etc/fstab
# mount -a
# mount
# mount | grep heartbeat
/export/heartbeat1.img on /export/heartbeat1 type ext4 (rw,relatime,seclabel)
/export/heartbeat2.img on /export/heartbeat2 type ext4 (rw,relatime,seclabel)
# df -h /export/heartbeat[1,2]
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0      976M  2.6M  907M   1% /export/heartbeat1
/dev/loop1      976M  2.6M  907M   1% /export/heartbeat2

■NFS Server 設定
・NFS サーバ用パッケージのインストール

# yum install nfs-utils

・NFS v4 の Disable

# cp -piav /etc/nfs.conf /etc/nfs.conf.org
# sed -i -e 's/^# vers4=y/vers4=n/g' /etc/nfs.conf
# sed -i -e 's/^# vers4.0=y/vers4.0=n/g' /etc/nfs.conf
# sed -i -e 's/^# vers4.1=y/vers4.1=n/g' /etc/nfs.conf
# sed -i -e 's/^# vers4.2=y/vers4.2=n/g' /etc/nfs.conf
# diff /etc/nfs.conf.org /etc/nfs.conf
53,56c53,56
< # vers4=y
< # vers4.0=y
< # vers4.1=y
< # vers4.2=y
---
> vers4=n
> vers4.0=n
> vers4.1=n
> vers4.2=n

VMware ESXi は、NFS version 4 の対応が微妙である。
※参考:[VMware] NFS プロトコルと ESXi
また、一つの Datastore を複数バージョンの NFS でマウントすることは禁忌とされる。
そのため、NFS version 3 でしか動かないようにしてしまう。

・NFS サーバの起動

# systemctl enable rpcbind.service
# systemctl enable nfs-server.service
# systemctl start rpcbind.service
# systemctl start nfs-server.service

・マウントポイントの設定

# cp -piav /etc/exports /etc/exports.org
# echo -e "/export/heartbeat1\t192.168.24.0/24(rw,no_root_squash)" >> /etc/exports
# echo -e "/export/heartbeat2\t192.168.24.0/24(rw,no_root_squash)" >> /etc/exports
# echo -e "/export/VDO-vol01\t192.168.24.0/24(rw,no_root_squash)" >> /etc/exports
# diff /etc/exports.org /etc/exports
0a1,3
> /export/heartbeat1    192.168.24.0/24(rw,no_root_squash)
> /export/heartbeat2    192.168.24.0/24(rw,no_root_squash)
> /export/VDO-vol01     192.168.24.0/24(rw,no_root_squash)
# exportfs -v
# exportfs -ra
# exportfs -v
/export/heartbeat1
                192.168.24.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)
/export/heartbeat2
                192.168.24.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)
/export/VDO-vol01
                192.168.24.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)
カテゴリー: めも パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です