Linux Software RAIDでRAID10を図解・構築する

概要

今回はRAID10を図解して構築してみます。具体的には、ソフトウェアRAIDで行い、四つのループバックデバイスを作成し、mdadmコマンドでRAID10を構築します。作業に入る前にRAIDの概念を押さえ、図解してイメージを把握します。それから実際に構築し、動作確認をして終了します。

RAIDとは?

RAID(Redundant Array of Independent Disks)とは、複数のHDDを一台の仮想的なHDDとして扱う技術です。通常PCに複数のHDDを接続した場合、それぞれ別々のものとして認識されますが、RAIDによって、複数のHDDをまとめて一台のHDDとして認識し、運用することができます。

このRAIDを使用することで、冗長性(予備装置を用意することによってもたらされる信頼性や安全性)による耐障害性の向上だったり、より高速なアクセスを実現したりします。

RAIDはハードウェアRAIDとソフトウェアRAIDに大別できます。名前の通りなのですが、ハードウェアRAIDはRAIDコントローラという専用ハードウェアによってRAIDを実現するのに対し、ソフトウェアRAIDはOSによってRAIDを実現させます。

ハードウェアRAIDの方がパフォーマンスも優れているため、一般的に使われるらしいのですが、検証のしやすさから、今回はソフトウェアRAIDを採用します。

また、RAIDは複数のレベルに分かれており、今回構築するRAIDレベルは10(イチゼロ)で、RAID1 + RAID0の構成をとります。以下、RAID0, 1, 10の仕組みを図解してから、作業に入っていきます。

RAID0

RAID0(ストライピング)は、複数のHDDに分散して読み書きを行います。これによって、複数のHDDに同時に読み書きを行えるので、高速なアクセスが実現します。

しかし、複数のHDDのどれか一つが故障してしまうと、全てのデータが失われてしまうので、冗長性がなく耐障害性がないということになります。上のイメージの例(二つのHDDの場合)だと、左のHDDが故障した場合、右のHDDは無事でも、”H”, “L”, “O”だけでは、HELLOというデータを再現することができなくなります。このRAID0はRAID10のように他のレベルと組み合わせると効果的です。

RAID1

RAID1(ミラーリング)は、複数のディスクに同じデータを同時に書き込みます。これによって、一台のHDDが故障しても、全く同じデータが入っている他のHDDで稼働することができます。つまり、冗長性が高く、耐障害性が高いということになります。

上のイメージの例だと、左のHDDが故障して、HELLOデータが消えてしまっても、右のHDDには同じデータが書き込まれているため、問題なく稼働することができます。

RAID10

以上RAID0とRAID1を組み合わせたのがRAID10です。これによって、ミラーリングによる冗長化と耐障害性の向上、ストライピングによるアクセス高速化のメリットを得ることができます。

上のイメージに沿って仕組みや構成を説明します。まずHELLOデータが書き込まれる際は、RAID0によるストライピングが行われます。”H”, “L”, “O”を左のRAID1に、”L”, “E”を右のRAID1に書き込もうとします。そして、それぞれのRAID1が、ストライピングによって振り分けられたデータをミラーリングします。左のRAID1だと”H”, “L”, “O”を、右のRAID1だと”L”, “E”をそれぞれミラーリングしています。

なので、RAID10は最低で四台のHDDが必要になるわけですが、実際に書き込める容量は、全てのHDDの容量の50%となります。

ではRAID10のイメージが掴めたと思うので、実際に構築していきます。

環境

  • vagrant 2.2.14
  • VirutalBox 6.1.16
  • 仮想マシン(CentOS8)

RAID10

RAID10を構築するにあたり、HDDが最低でも4台必要になります。今回は検証のしやすさから、実際にHDDを用意せず、四つのループバックデバイスを使用します。ループバックデバイスは普通のファイルをあたかもハードディスクのように扱うための機能です。なのでお手軽に検証環境を用意することができます。

ディスクイメージファイル作成

ループバックデバイスを作成するために、ddコマンドで512MBのディスクイメージファイルを四つ作ります。bs=1Mでcount=500で約500MBを作った方が断然処理が速かったです…。

# dd if=/dev/zero of=disk1.img count=1000000
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB, 488 MiB) copied, 1.70505 s, 300 MB/s

# dd if=/dev/zero of=disk2.img count=1000000
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB, 488 MiB) copied, 1.70555 s, 300 MB/s

# dd if=/dev/zero of=disk3.img count=1000000
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB, 488 MiB) copied, 1.7246 s, 297 MB/s

# dd if=/dev/zero of=disk4.img count=1000000
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB, 488 MiB) copied, 1.74102 s, 294 MB/s

ループバックデバイス作成

losetupコマンドはループバックデバイスの作成や削除等を行うコマンドです。-fでループバックデバイスと作成したディスクイメージが関連づけられ、使用することができるようになります。

# losetup -f disk1.img 
# losetup -f disk2.img 
# losetup -f disk3.img 
# losetup -f disk4.img 

-lオプションで作成した四つのループバックデバイスを確認します。

# losetup -l
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE       DIO LOG-SEC
/dev/loop3         0      0         0  0 /root/disk4.img   0     512
/dev/loop1         0      0         0  0 /root/disk2.img   0     512
/dev/loop2         0      0         0  0 /root/disk3.img   0     512
/dev/loop0         0      0         0  0 /root/disk1.img   0     512

パーティションタイプ設定

gdiskコマンドでGPTパーティションに設定します。

# gdisk /dev/loop0
GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries.

Command (? for help): n #パーティションを作成
Partition number (1-128, default 1): #デフォルトで良いので入力せずEnter
First sector (34-999966, default = 2048) or {+-}size{KMGTP}: #デフォルトで良いので入力せずEnter
Last sector (2048-999966, default = 999966) or {+-}size{KMGTP}: #デフォルトで良いので入力せずEnter
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): fd00  #fd00と入力し、Linux RAIDを使用することを伝える
Changed type of partition to 'Linux RAID'

Command (? for help): w #変更して保存

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y #確認
OK; writing new GUID partition table (GPT) to /dev/loop0.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.

このように同じ手順でloop1, loop2, loop3全て設定します。ここでは省略します。

RAID10構築

RAIDを構築するには、mdadmコマンドを使用します。書式は以下の通りです。

mdadm [モード] RAIDデバイス名 [オプション] デバイス名

# mdadm -C /dev/md0 -l10 -n4 /dev/loop0 /dev/loop1 /dev/loop2 /dev/loop3
mdadm: partition table exists on /dev/loop0
mdadm: partition table exists on /dev/loop0 but will be lost or
       meaningless after creating array
mdadm: partition table exists on /dev/loop1
mdadm: partition table exists on /dev/loop1 but will be lost or
       meaningless after creating array
mdadm: partition table exists on /dev/loop2
mdadm: partition table exists on /dev/loop2 but will be lost or
       meaningless after creating array
mdadm: partition table exists on /dev/loop3
mdadm: partition table exists on /dev/loop3 but will be lost or
       meaningless after creating array
Continue creating array? (y/n) y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

-CでRAIDを新規構築するモードを指定、-lは構築するRAIDレベルを指定、-nはRAIDに使用するHDDの数を指定、最後には使用するデバイス名を全て記載しています。

-Dオプションを使用することで、アクティブなRAIDの詳細情報を取得することができます。

# mdadm -D /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Tue Dec  1 11:39:12 2020
        Raid Level : raid10
        Array Size : 995328 (972.00 MiB 1019.22 MB)
     Used Dev Size : 497664 (486.00 MiB 509.61 MB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Tue Dec  1 11:39:17 2020
             State : clean 
    Active Devices : 4
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 0

            Layout : near=2
        Chunk Size : 512K

Consistency Policy : resync

              Name : centos8.localdomain:0  (local to host centos8.localdomain)
              UUID : 13410b87:a53c637d:48e5b85b:bf95fc36
            Events : 17

    Number   Major   Minor   RaidDevice State
       0       7        0        0      active sync set-A   /dev/loop0
       1       7        1        1      active sync set-B   /dev/loop1
       2       7        2        2      active sync set-A   /dev/loop2
       3       7        3        3      active sync set-B   /dev/loop3

Raid LevelにRAID10が指定され、下部のStateにはactiveが指定されているので、無事にRAID10が構築できていることがわかります。

-Dオプションでも状態は確認できますが、以下のコマンドでも簡潔な情報を取得することができます。

# cat /proc/mdstat
Personalities : [raid1] [raid10] 
md0 : active raid10 loop3[3] loop2[2] loop1[1] loop0[0]
      995328 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]

作成したmd0はactiveでraid10として稼働していることがわかります。

ファイルシステム作成

では/dev/md0をマウントしてファイルを扱えるようにするため、まずはファイルシステムを作成します。今回はXFSを採用しています。

# mkfs.xfs /dev/md0
log stripe unit (524288 bytes) is too large (maximum is 256KiB)
log stripe unit adjusted to 32KiB
meta-data=/dev/md0               isize=512    agcount=8, agsize=31104 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=248832, imaxpct=25
         =                       sunit=128    swidth=256 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=1416, version=2
         =                       sectsz=512   sunit=8 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

マウント

/dev/md0のマウント先ディレクトリを作成してマウントします。

# mkdir /raid10_test
# mount /dev/md0 /raid10_test

dfコマンドでディスクの状態を確認します。-Tはファイルシステムタイプを表示、-hで単位を含めてわかりやすく表示しています。

# df -Th /raid10_test/
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/md0       xfs   967M   40M  928M   5% /raid10_test

動作確認

では、RAID10がしっかりと動作しているかどうか確認していきます。

mdadm -Dで詳細をみれたと思うのですが、Stateの欄にset-A、もしくはset-Bが指定されていました。

# mdadm -D /dev/md0
----------(省略)-----------
Number   Major   Minor   RaidDevice State
       0       7        0        0      active sync set-A   /dev/loop0
       1       7        1        1      active sync set-B   /dev/loop1
       2       7        2        2      active sync set-A   /dev/loop2
       3       7        3        3      active sync set-B   /dev/loop3

これはどういう意味かというと、set-A同士、もしくはset-B同士なら一緒に故障してもOKということです。NGなのはset-Aで一つ故障、かつset-Bで一つ故障した時です。冒頭で図解したイメージで置き換えると以下のようになります。

この図で考えると、set-A同士、もしくはset-B同士の故障であるならば、HELLOというデータは問題なく取得することができます。

パターン1

まず一つ目の動作確認は、以下のようにset-A同士を取り除いてもRAID10が稼働しているかどうかです。結果は無事に稼働できるはずです。

ではset-Aであるloop0とloop1を取り除いていきます。取り除くにあたってまずは-fでfaultyフラグ(故障マーク)をつけます。これで擬似的に故障発生の状態を作り出しています。そして-rでRAID10からループバックデバイスを取り除きます。

# mdadm /dev/md0 -f /dev/loop0
mdadm: set /dev/loop0 faulty in /dev/md0
# mdadm /dev/md0 -r /dev/loop0
mdadm: hot removed /dev/loop0 from /dev/md0

# mdadm /dev/md0 -f /dev/loop2
mdadm: set /dev/loop2 faulty in /dev/md0
# mdadm /dev/md0 -r /dev/loop2
mdadm: hot removed /dev/loop2 from /dev/md0
# mdadm /dev/md0 -r /dev/loop0
mdadm: hot removed /dev/loop0 from /dev/md0

# mdadm /dev/md0 -r /dev/loop2
mdadm: hot removed /dev/loop2 from /dev/md0

この状態でもアクティブかどうか/proc/mdstatを確認してみます。

# cat /proc/mdstat 
Personalities : [raid1] [raid10] 
md0 : active raid10 loop3[3] loop1[1]
      1019904 blocks super 1.2 512K chunks 2 near-copies [4/2] [_U_U]

無事にアクティブのままでした。では、次の動作確認のために状態を戻します。先ほど使用していたloop0とloop1を戻す際は、まず–zero-superblockで既存のスーパーブロックの内容を初期化し、それから-aオプションで追加します。

# mdadm --zero-superblock /dev/loop0
# mdadm /dev/md0 -a /dev/loop0
mdadm: added /dev/loop0

# mdadm --zero-superblock /dev/loop2
# mdadm /dev/md0 -a /dev/loop2
mdadm: added /dev/loop2

mdadm -Dで元の状態に戻っていることを確認します。

# mdadm -D /dev/md0
Number   Major   Minor   RaidDevice State
       4       7        0        0      active sync set-A   /dev/loop0
       5       7        1        1      active sync set-B   /dev/loop1
       7       7        2        2      active sync set-A   /dev/loop2
       6       7        3        3      active sync set-B   /dev/loop3

パターン2

では最後にset-Aであるloop0とset-Bであるloop1を同時に取り除いてみます。結果としては、データが消滅することになるので、操作が拒否されるはずです。

ではまずはloop0にfaultyフラグを設定し、-rで取り除きます。

# mdadm /dev/md0 -f /dev/loop0
mdadm: set /dev/loop0 faulty in /dev/md0

# mdadm /dev/md0 -r /dev/loop0
mdadm: hot removed /dev/loop0 from /dev/md0

次にloop1に対して同じようにfaultyフラグを設定しようとしたところ、以下のように操作が拒否されました。

# mdadm /dev/md0 -f /dev/loop1
mdadm: set device faulty failed for /dev/loop1:  Device or resource busy

やはりここでloop1を使用不可にしてしまうと、データが消滅してしまうからです。

以上二つのパターンを通してRAID10がしっかりと稼働していることが確認できました。

RAID停止

では最後に後片付けしていきます。まずRAIDデバイスをアンマウントします。

# umount /raid10_test

それからmdadmコマンドで、-Sオプションを指定することでRAIDを停止することができます。

# mdadm -S /dev/md0

まとめ

以上、Linux Software RAIDでRAID10を図解し、構築してみました。やはり教材やサイトをみて仕組みを理解していたつもりでしたが、こうして自分なりに図解してみたり、構築してみたりしたことで、より理解が深まりました。

これからLPICの対策をされる方は特に手を動かしてやってみると、暗記だけで終わらない知識を定着させることができるのではないかと思います。

個人的にかなり図解の面白さにハマったので、これからもこのスタイルを続けていこうと思います。

参考文献

RAIDの環境構築手順 – Qiita

Linuxでループバック・デバイスを扱う – Qiita

標準テキスト CentOS7 構築・運用・管理パーフェクトガイド

Linux教科書 LPIC レベル2 Version4.5対応

Comments

Copied title and URL