GEOM MIRROR (ミラーリング/RAID1) を使ってみる (1)

GEOM

今回は GEOM によるディスクのミラーリング (RAID1) について纏めてみたいと思います.
ミラーリングは複数のディスクに対して同じデータを格納し、ディスク障害が発生してもデータの損失を防ぐ技術です.コンカチやストライピングと違いディスク容量は増えません.

GEOM MIRROR のイメージ

ミラーリングのイメージはこのような形です.ディスクが2本の場合,3本の場合を表しています.

GEOM MIRROR の利用・管理

GEOM MIRROR は gmirror というコマンドを通じて利用・管理を行います.簡単に触れますが,詳細はコマンドのオプションの詳細は FreeBSD の マニュアル「gmirror」を見てください.

# gmirror
usage: gmirror activate [-v] name prov ...
       gmirror clear [-v] prov ...
       gmirror configure [-adfFhnv] [-b balance] [-s slice] name
       gmirror configure [-v] -p priority name prov
       gmirror create [-Fnv] [-b balance] [-s slice] name prov ...
       gmirror deactivate [-v] name prov ...
       gmirror destroy [-fv] name ...
       gmirror dump prov ...
       gmirror forget name ...
       gmirror label [-Fhnv] [-b balance] [-s slice] name prov ...
       gmirror insert [-hiv] [-p priority] name prov ...
       gmirror rebuild [-v] name prov ...
       gmirror remove [-v] name prov ...
       gmirror resize [-s size] [-v] name
       gmirror stop [-fv] name ...
       gmirror help
       gmirror list [-a] [name ...]
       gmirror status [-ags] [name ...]
       gmirror load [-v]
       gmirror unload [-v]

GEOM 関連のコマンドは gconcat の際にも触れましたが createlabel の両方があり分かりづらいのですが,create は一時的,label は恒久的と覚えるのがよいです.

create で作った場合はどうなるのか?

create で作成してマウント,再起動を行うとどのようになるのかを以下に一連の流れを記載します.

gmirror create コマンドで ディスク da1 と da2 をミラーリングして mirror0 を作成します.

# kldload geom_mirror
# gmirror create mirror0 da1 da2

gconcatgstripe の場合はコマンド実行時に自動でカーネルモジュールがロードされるのですが,gmirror「gmirror: Class not found: “MIRROR”」というエラーが出力されてしまいます.
ですのでコマンド実行前に明示的にモジュールをロードさせてから gmirror コマンドを実行しています.

# kldstat
Id Refs Address                Size Name
 1   10 0xffffffff80200000  1f3e2d0 kernel
 2    1 0xffffffff82319000     3218 intpm.ko
 3    1 0xffffffff8231d000     2180 smbus.ko
 4    1 0xffffffff82320000     7490 vmci.ko
 5    1 0xffffffff82328000     fef0 geom_mirror.ko

また,再起動時に必ず有効になるように明示的にロードさせる必要があります.

# cat /boot/loader.conf
geom_mirror_load="YES"

gmirror status コマンドでステータスを表示できます.
以下は mirror0 のステータスです.da1, da2 がコンポーネントとして含まれており,ステータスが COMPLETE の状態です.
COMPLETE の状態とは,このミラーリングで指定しているディスクの同期が取れている状態となります.

# gmirror status
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)

gmirror list コマンドで詳細を表示する事ができます.
da1, da2 が 100GB のディスクでこれを RAID1 でミラーリングしている為,mirror0 は 100G となっています.

# gmirror list
Geom name: mirror0
State: COMPLETE
Components: 2
Balance: load
Slice: 4096
Flags: NONE
GenID: 0
SyncID: 1
ID: 2029918663
Type: MANUAL
Providers:
1. Name: mirror/mirror0
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r0w0e0
Consumers:
1. Name: da1
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 0
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 3804043814
2. Name: da2
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 1
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 3614838224

newfs でファイルシステムを作成します.指定するデバイスは GEOM MIRROR の場合は /dev/mirror 以下に指定した名前のデバイスファイルが作成されますので,これを指定します.
今回は create の際に mirror0 を名前としたため,/dev/mirror/mirror0 がデバイスファイルとなります.

# newfs /dev/mirror/mirror0
/dev/mirror/mirror0: 102400.0MB (209715200 sectors) block size 32768, fragment size 4096
        using 164 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
super-block backups (for fsck_ffs -b #) at:
 192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776, 11524224, 12804672, 14085120, 15365568,
 16646016, 17926464, 19206912, 20487360, 21767808, 23048256, 24328704, 25609152, 26889600, 28170048, 29450496, 30730944,
 32011392, 33291840, 34572288, 35852736, 37133184, 38413632, 39694080, 40974528, 42254976, 43535424, 44815872, 46096320,
....

マウントおよびマウントの結果です./mnt にマウントをしています.
これを /etc/fstab に記載した状態で再起動を行ってみます.

# mount /dev/mirror/mirror0 /mnt

# df
Filesystem          1K-blocks    Used    Avail Capacity  Mounted on
/dev/da0p2           19279260 2590868 15146052    15%    /
devfs                       1       1        0   100%    /dev
/dev/mirror/mirror0 101561756       8 93436808     0%    /mnt

# cat /etc/fstab
# Device        Mountpoint      FStype  Options Dump    Pass#
/dev/da0p2      /               ufs     rw      1       1
/dev/da0p3      none            swap    sw      0       0
/dev/mirror/mirror0     /mnt    ufs     rw      1       1

残念な事に (想定どおりです),デバイスが無く起動途中に失敗してしまっています.
これは create で作成した為,ディスクに GEOM MIRROR の情報が記録されてい為作成したデバイスが存在しておらず,この状態となります.

恒久的に使う場合は label を利用しよう

先ほどと変わって create ではなく label で mirror0 を作成しました.

# gmirror label mirror0 da1 da2

同じディスクを同じように指定している為,status および list の結果は先ほどと変わりません.
また,create で作成した際に newfs していますが,再作成の際にディスク連結順番に変更を入れていませんのでファイルシステムとしては正しく生成された状態となっていますのでこのままマウントさせる事も可能です.

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)
root@bsd13:~ # gmirror list mirror0
Geom name: mirror0
State: COMPLETE
Components: 2
Balance: load
Slice: 4096
Flags: NONE
GenID: 0
SyncID: 1
ID: 4078222260
Type: AUTOMATIC
Providers:
1. Name: mirror/mirror0
   Mediasize: 107374181888 (100G)
   Sectorsize: 512
   Mode: r0w0e0
Consumers:
1. Name: da1
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 0
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 3192641748
2. Name: da2
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 1
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 159192916

ですので,createlabel を間違った… という場合でも正しくコマンドを発行してあげる事で今までの状態を復元できますので,データがなくなってしまった.という事は起きませんので安心してください.
いずれにせよ… label で作成しましょう.が教訓となりますが…

# mount /dev/mirror/mirror0 /mnt

# df
Filesystem          1K-blocks    Used    Avail Capacity  Mounted on
/dev/da0p2           19279260 2590884 15146036    15%    /
devfs                       1       1        0   100%    /dev
/dev/mirror/mirror0 101561756       8 93436808     0%    /mnt

IOについて確認してみる

ミラーリングですので,ミラーしているディスク全てに同じデータが書き込まれます.実際にどの様な IO が発生しているのかを確認してみます.

dd でランダムデータを生成,random.img としてファイル書き込みの IO を発生させました.
見て頂くと分かる通り da1 と da2 の両方に IO がかかっています.
このことから,分散してのディスクの読み書きが行われる事が分かります.

# dd if=/dev/random of=/mnt/random.img

# iostat 2
       tty             da0              da1              da2             cpu
 tin  tout KB/t  tps  MB/s  KB/t  tps  MB/s  KB/t  tps  MB/s  us ni sy in id
   0     4 17.7    0   0.0   223    0   0.0   230    0   0.0   0  0  0  0 100
   0   231 32.0    0   0.0   256   45  11.2   256   53  13.2   1  0  4  0 96
   0   159  0.0    0   0.0   256   34   8.6   256   39   9.8   0  0  4  0 96
   0    81  0.0    0   0.0   255  156  38.8   254  142  35.3   1  0 16  0 83
   0    79  0.0    0   0.0   256  116  29.1   256  114  28.6   1  0 11  0 88

# ls /mnt
.snap           random.img

イメージとしてはこのような形ですね.

GEOM RAID MIRROR デバイスを管理する

ミラーデバイスを追加する

ミラー先を追加,取り外しを行う事でのバックアップ運用が可能です.2つ以上のディスクをローテーションして管理する事で複数世代のバックアップも可能です.
もちろん,オペミスだったり,取り外したディスクの管理 (静電袋に入れてエアキャップ保存とか) は重要になります.

ミラーの追加は insert サブコマンドを使用して行う事が可能です.
追加後のステータスを確認すると DEGRADED 状態となり,追加したデバイスが SYNCHRONIZING として同期中である事を確認できます.

# gmirror insert mirror0 da3

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  DEGRADED  da1 (ACTIVE)
                          da2 (ACTIVE)
                          da3 (SYNCHRONIZING, 3%)

ミラーデバイスを取り外す

同期が完了したら取り外す事が可能です.
取り外しは remove サブコマンドを使用して行う事が可能です.

まずはステータスが COMPLETE である事を確認します.
その次に remove でディスクをミラーから切り離します.その後,切り離しが完了した事を確認します.
この場合は da3 を切り離しを行っており,status で表示されない状態になっていればディスク本体の取り外しが可能な状態となります.

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)
                          da3 (ACTIVE)

# gmirror remove mirror0 da3

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)

ディスクを拡張する

ディスク というか,ファイルシステムを拡張する事が可能です.
今回説明するシチュエーションとしては,da1, da2 を玉突きで大きいディスクに置き換えていく.というシチュエーションを想定して説明します.

このようなイメージで da1 を取り外し,大きなディスクに交換の上ミラーに組み込み.
da2 を取り外し,大きなディスクに交換の上ミラーに組み込み.という流れとなります.

まずは remove でディスクを取り外します.

# gmirror status
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)
# gmirror remove mirror0 da1
# gmirror status
          Name    Status  Components
mirror/mirror0  COMPLETE  da2 (ACTIVE)

次に容量の大きいディスクと交換し insert サブコマンドを実行して mirror0 に組み込みます.
status サブコマンドで確認するとリビルド処理が走っている事が確認できます.

また,list サブコマンドで確認すると da1 が 150GB である事が確認できます.

# gmirror insert mirror0 da1

# gmirror status
          Name    Status  Components
mirror/mirror0  DEGRADED  da2 (ACTIVE)
                          da1 (SYNCHRONIZING, 0%)

# gmirror list
Geom name: mirror0
State: DEGRADED
Components: 2
Balance: load
Slice: 4096
Flags: NONE
GenID: 0
SyncID: 1
ID: 3318650467
Type: AUTOMATIC
Providers:
1. Name: mirror/mirror0
   Mediasize: 107374181888 (100G)
   Sectorsize: 512
   Mode: r2w1e1
Consumers:
1. Name: da2
   Mediasize: 107374182400 (100G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 1
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 3061855275
2. Name: da1
   Mediasize: 161061273600 (150G)
   Sectorsize: 512
   Mode: r1w1e1
   State: SYNCHRONIZING
   Priority: 0
   Flags: DIRTY, SYNCHRONIZING
   GenID: 0
   SyncID: 1
   BytesSynced: 1282408448
   Synchronized: 1%
   ID: 1348065949

status サブコマンドで COMPLETE である事を確認し,remove サブコマンドで da2 の切り離しを行います.
その後容量の大きいディスクに入れ替えて insert サブコマンドで mirror0 に組み込みます.
status サブコマンドでリビルド処理が行われている事を確認します.

# gmirror status
          Name    Status  Components
mirror/mirror0  COMPLETE  da2 (ACTIVE)
                          da1 (ACTIVE)

# gmirror remove mirror0 da2

# gmirror status
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)

# gmirror insert mirror0 da2

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  DEGRADED  da1 (ACTIVE)
                          da2 (SYNCHRONIZING, 0%)

この際,list サブコマンドで確認すると,da1,da2 の両方が 150GB ですが,mirror0 は 100GB のままとなっています.
この点についてはリビルドが完了したら拡張を行う流れになります.

# gmirror list mirror0
Geom name: mirror0
State: DEGRADED
Components: 2
Balance: load
Slice: 4096
Flags: NONE
GenID: 0
SyncID: 1
ID: 3318650467
Type: AUTOMATIC
Providers:
1. Name: mirror/mirror0
   Mediasize: 107374181888 (100G)
   Sectorsize: 512
   Mode: r2w1e1
Consumers:
1. Name: da1
   Mediasize: 161061273600 (150G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 0
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 1348065949
2. Name: da2
   Mediasize: 161061273600 (150G)
   Sectorsize: 512
   Mode: r1w1e1
   State: SYNCHRONIZING
   Priority: 0
   Flags: DIRTY, SYNCHRONIZING
   GenID: 0
   SyncID: 1
   BytesSynced: 9633267712
   Synchronized: 8%
   ID: 2184573350

リビルドが完了したら,resize サブコマンドを実行して mirror0 の拡張を行います.
その後 list サブコマンドで mirror0 の容量が増えている事を確認します.

# gmirror status mirror0
          Name    Status  Components
mirror/mirror0  COMPLETE  da1 (ACTIVE)
                          da2 (ACTIVE)

# gmirror resize mirror0

# gmirror list
Geom name: mirror0
State: COMPLETE
Components: 2
Balance: load
Slice: 4096
Flags: NONE
GenID: 0
SyncID: 1
ID: 3318650467
Type: AUTOMATIC
Providers:
1. Name: mirror/mirror0
   Mediasize: 161061273088 (150G)
   Sectorsize: 512
   Mode: r1w1e1
Consumers:
1. Name: da1
   Mediasize: 161061273600 (150G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 0
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 1348065949
2. Name: da2
   Mediasize: 161061273600 (150G)
   Sectorsize: 512
   Mode: r1w1e1
   State: ACTIVE
   Priority: 0
   Flags: NONE
   GenID: 0
   SyncID: 1
   ID: 2184573350

ただし,まだこの時点ではファイルシステムは現状のままですので growfs でファイルシステムを拡張する必要があります.
growfsオンライン (マウントした状態) で実施可能です.growfs 実施前後の df の結果を見ると正しく拡張されている事が確認できます.

# df
Filesystem          1K-blocks    Used    Avail Capacity  Mounted on
/dev/da0p2           19279260 2590916 15146004    15%    /
devfs                       1       1        0   100%    /dev
/dev/mirror/mirror0 101561752   89608 93347204     0%    /mnt

# growfs /dev/mirror/mirror0
Device is mounted read-write; resizing will result in temporary write suspension for /mnt.
It's strongly recommended to make a backup before growing the file system.
OK to grow filesystem on /dev/mirror/mirror0, mounted on /mnt, from 100GB to 150GB? [yes/no] yes
super-block backups (for fsck_ffs -b #) at:
 209993664, 211274112, 212554560, 213835008, 215115456, 216395904, 217676352, 218956800, 220237248, 221517696, 222798144,
 224078592, 225359040, 226639488, 227919936, 229200384, 230480832, 231761280, 233041728, 234322176, 235602624, 236883072,
 238163520, 239443968, 240724416, 242004864, 243285312, 244565760, 245846208, 247126656, 248407104, 249687552, 250968000,
 252248448, 253528896, 254809344, 256089792, 257370240, 258650688, 259931136, 261211584, 262492032, 263772480, 265052928,
...

# df
Filesystem          1K-blocks    Used     Avail Capacity  Mounted on
/dev/da0p2           19279260 2590916  15146004    15%    /
devfs                       1       1         0   100%    /dev
/dev/mirror/mirror0 152342680   89608 140065660     0%    /mnt

GEOM MIRROR デバイスを終了 (破壊) する

ファイルシステムとして用済みになった.であったり,別用途に転用する為に初期化したい場合を説明します.

当然ながら,ファイルシステムはアンマウントする必要があります.
また,完全に終了 (停止・破壊) する場合は stop ではなく destroy を利用します.

# umount /mnt
# gmirror destroy mirror0
# gmirror list

もし間違って destory を実行してしまった場合ですが,これだけのオペレーションの場合だと label 情報がなくなっただけなので,再度 label を同じ引数で渡すことで復活させる事が可能です.
やらかしてしまった… という事案の場合は慌てずにそっと元に戻しましょう.

# gmirror label mirror0 da1 da2
# mount /dev/mirror/mirror0 /mnt
# df
Filesystem          1K-blocks    Used     Avail Capacity  Mounted on
/dev/da0p2           19279260 2590920  15146000    15%    /
devfs                       1       1         0   100%    /dev
/dev/mirror/mirror0 152342680   89608 140065660     0%    /mnt

# ls /mnt
.snap           random.img

以上で~ と終わりたい所ではあるのですが,拡張については他の手法もありますので次回はそれについて触れていきたいと思います.

コメント

タイトルとURLをコピーしました