Ubuntu Weekly Recipe

第748回LXDとUbuntuサーバーでRAIDとmdadmのテスト環境を構築する

ストレージの信頼性・可用性を維持する措置として、サーバーではRAIDがよく使われています。もちろんUbuntuもRAID構成を組んだ構築が可能です。しかしながら実際にRAID環境を動作確認しようとすると、構成によってストレージの数がそれなりに必要になりますし、ハードウェアRAIDをやるなら専用のデバイスも必要です。

そこで今回はLXDを用いて、任意の数のストレージが繋がれたインスタンスを作成し、RAIDの構築方法や動作確認手順を気軽に試せるようにしてみましょう。

図1 RAIDを試すには複数のストレージが必要になる
図1

RAIDはバックアップではない

Ubuntuかどうかに関係なく、この世にあるものはだいたい壊れます。壊れてほしくないときに限って壊れます。それはストレージであっても例外ではありません。たとえ名前に金とか鉄とか星とかついていても、壊れる時は壊れます。だからこそバックアップが重要なわけですが、サービスそのものの信頼性や可用性を維持するためには、⁠壊れにくくする」⁠一部が壊れてもなんとかなる」という対応もほしいところです。

そこで出てくるのがRAID(Redundant Arrays of Inexpensive Disks⁠⁠」です。複数のストレージを組み合わせて、大容量で信頼性の高いストレージとして構築しようという仕組みとなります。RAIDを提唱したオリジナルの論文には「低価格なディスク(Inexpensive Disks⁠⁠」とあるように、もともとは低価格・低容量の安価なストレージを使う想定でしたが、今では信頼性を期待する環境においては、価格を問わず使われています。よって何らかのサーバーの構築を行う上で、RAIDを使用する選択肢が当然のことながら出てくるでしょう。

RAIDには専用のコントローラーを使うハードウェアRAIDと、OS内のプログラムなどでRAID機能を実現するソフトウェアRAID、さらにソフトウェアRAIDのうちBIOSなどがハードウェアRAIDっぽく振る舞うFakeRAID/HostRAIDなどが存在します。今回は特別はハードウェアが不要で、設定の自由度が高いソフトウェアRAIDを試してみましょう。

Ubuntuの場合はLinux MD/mdadmを利用したソフトウェアRAID環境の構築をサポートしていますし、サーバー版のインストーラーであればインストール時点でRAID環境を構築できます[1]。しかしながらRAID環境を構築するには、RAIDの種類に応じた数のストレージデバイスが必要です。ノートPCはもちろん、最近のデスクトップPCも小型が進んできて、接続できるストレージの台数は限られています[2]。よって、物理的に複数のストレージを複数台用意して試すのはなかなか大変です[3]

そこで登場するのがLXDを含む、仮想マシン環境です。LXDはもともとシステムコンテナの管理ツールでしたが、第609回LXDからコンテナではなく仮想マシンを起動するでも言及しているように、LXD 3.19から仮想マシンの管理ツールにもなりました。しかしながら、この仮想マシンインスタンスは、Ubuntuのcloud-imageをベースにした事前設定済みのイメージを使う仕組みになっており、システムにRAID環境を構築するには不向きです。それに対して、LXD 4.4からは仮想マシンの画面を気軽に取得できるようになりました。つまり任意のOSをISOイメージからインストールできるようになったのです。これはUbuntuのインストーラーを使えるということでもあります。

さらにLXDは、第571回のLXD 3.0のストレージ設定でも紹介したように、任意のストレージイメージをインスタンスに紐付けることが可能です。これにより「複数のストレージデバイスがつながったインスタンス」を仮想的に作れるわけです。

これにより任意のストレージ数で、UbuntuのソフトウェアRAIDの動作確認環境を構築できます。バックエンドが単なるイメージファイルになってしまうものの、mdadmやUbuntuインストーラーなどのRAID関連のフロントエンドの操作方法を習熟できますし、各種ソフトウェアの動作確認、障害時の予行演習、バックアップ・リストアのテストなどに活用できるわけです。

LXD環境の作り方については第521回の入門システムコンテナマネージャーLXD 3.0を参照してください。本記事ではlxcコマンドが使える前提で話を進めます。

ちなみにインターネットであれ書籍であれ、⁠RAID」に言及される記事は常に何か間違い・不正確さ・事実誤認・解釈違いなどが含まれていることが一般的です。もちろんこの記事にも何か間違いがありそうです。RAIDに言及する記事を読む場合は、内容を鵜呑みにせず、間違っているかもしれない点を念頭において読むようにしましょう。

LXDに専用のストレージプールを作成する

LXDはストレージプールという概念を持っていて、イメージやインスタンスなどのデータはこのストレージプールに保存されます。たとえばLXDの初期設定時には「defaultストレージプール」が作られ、インスタンス作成時などはこのdefaultストレージプールが使われます。

このストレージプールは、LXDがサポートしているファイルシステム・ブロックデバイスを用いて、複数の異なるプールを作成・管理可能です。今回の用途だと、defaultストレージプールをそのまま使っても問題はないのですが、せっかくなので新規にストレージプールを作ってRAID関連はそこにまとめてしまいましょう。

まずは次のように「raid」という名前でbtrfsベースのストレージプールを作成します。

$ lxc storage create raid btrfs size=400GB

$ lxc storage show raid
config:
  size: 400GB
  source: /var/snap/lxd/common/lxd/disks/raid.img
description: ""
name: raid
driver: btrfs
used_by: []
status: Created
locations:
- none

$ lxc storage info raid
info:
  description: ""
  driver: btrfs
  name: raid
  space used: 3.75MiB
  total space: 372.53GiB
used by: {}

btrfs等のファイルシステムを指定した場合は、sourceにあるようにイメージファイルが作られます。また、source=オプションを使うことで、指定したブロックデバイスをストレージプールとして専有することも可能です。詳しい設定はLXDのドキュメントにあるストレージプールを管理するにはを参照してください。

RAID 1:2台から始められるミラーリングシステム

RAIDはその構成によって「RAIDレベル」が指定されています。基本的にレベルが大きくなるほど構成が複雑になりますが、必ずしも耐障害性が高くなるわけではない点に注意が必要です[4]

さて、RAIDにおいてもっともシンプルな構成が「RAID 1」となります。最低2台のストレージから構成が可能です。RAID 1は要するに、同じデータを2台のストレージに同じように書き込んでおいておけば、1台壊れても大丈夫だよねという仕組みです。ただし利用できるサイズは1台分です。つまり8TBのHDDを2台用意してRAID 1を構築しても、データ保存先としての容量は8TBです。ちなみにmadadmのRAID 1は3台以上の構成も可能になっています。

同じ最小構成のRAIDとして「RAID 0(ストライピング⁠⁠」がありますが、これは単にあるデータを構成されたストレージに分割して書き込んで高速化する仕組みです。よって1台壊れただけでデータがロストしてしまい、耐障害性はありません。つまり「RAID」のRである冗長(Redundant)構成ではないのです。今回は言及しませんが、Ubuntuサーバーのインストーラーは、RAID 0の構成にも対応しています。

では、さっそくストレージ2台のインスタンスを作ってみましょう。まずは空のインスタンスを作ります。このときデフォルトプロファイルの設定によって1台のストレージが割り当てられます。

$ lxc init raid1 --empty --vm -c limits.cpu=2 -c limits.memory=8GiB --storage raid
$ lxc config device set raid1 root size=40GiB

--storage raidで先ほど作成したストレージプールを利用するようにしています。これがないとdefaultストレージプールが使われます。2行目ではストレージのサイズを40GiBに拡張しています。defaultストレージプールだとsetではなくoverrideを指定するのですが、今回はdefaultストレージプールではないのでsetを呼ぶ必要があるのがポイントです。overrideを使った場合はError: The profile device doesn't existと表示されます。

今回はUbuntuサーバーのインストーラーを使いたいので、Ubuntu 22.04 LTSのサーバー版のイメージをダウンロードしておきましょう。これを起動デバイスとして設定しておきます。

$ lxc config device add raid1 iso disk boot.priority=1 \
  source=$HOME/ダウンロード/ubuntu-22.04.1-live-server-amd64.iso

ここからが今回の重要な手順です。ここまではストレージが1台という構成でしたが、ストレージプールから新たにブロックデバイスを作成し、これを仮想マシンに割り当てます。まずはblockタイプのカスタムストレージボリュームを作成します。ストレージボリュームはストレージプールから、必要なサイズの領域を切り出したものです。ストレージボリュームにはインスタンスやそのベースイメージに使われるものなどがありますが、このうち「カスタムストレージボリューム」は任意のデータを保存できるボリュームです。

カスタムストレージボリューム自体は、複数のインスタンスに同時にアタッチし、データの共有などにも利用できます。さらに「コンテントタイプをblockタイプ」にすることで、仮想マシンからはブロックデバイスのように見えるようになります。ちなみにblockタイプのカスタムストレージボリュームは、仮想マシンにしかアタッチできません。

$ lxc storage volume create raid raid1b --type=block size=40GiB

raidが作成対象のストレージプール名、raid1bが今回作成するストレージボリュームの名前です。今回は「RAID 1用のsdb」ということでraid1bという名前にしてみました。また、--type=blockでコンテントタイプ指定、最後はストレージのサイズです。ストレージのサイズはインスタンス作成時に指定した値と合わせておくと良いでしょう。

さらに作成したカスタムストレージボリュームを、インスタンスにアタッチしておきます。

$ lxc storage volume attach raid raid1b raid1

attach以降の引数の順番はストレージプールの名前raid⁠、ストレージボリュームの名前raid1b⁠、アタッチ対象のインスタンス名raid1です。これでストレージの準備は完了しました。あとはインスタンスを起動して、インストールを開始しましょう。

$ lxc start raid1 --console=vga

Ubuntu 18.04 LTS以降のUbuntuサーバーのインストーラーは、インストーラーの中でインストーラーそのものを更新できるようになっています。通常は更新しなくても問題ありませんが、RAID系は機能が追加されたりUIが洗練されたりしていることもあるため、当面は更新してからインストールすることをすすめします。

図2 インストーラーの更新画面では「Update to the new installer」を選択しよう
図2

キーボードやネットワーク設定等が完了したら、ストレージの設定です。ここは「Custom storage layout」を選択しましょう。

図3 一番下の「Custom storage layout」を選択する
図3

UbuntuでRAIDの設定を行うには、いくつかわかりにくいポイントが存在します。まず、最初にESP(EFI System Partition)はRAIDにできませんので、独立して作成します。次にRAIDを構築する前に必要な台数のパーティションを作成します。

さて、正しくボリュームを追加できていたら、次の図の「AVAILABLE DEVICES」にある「DEVICE」のように2台のストレージが表示されているはずです。

図4 2台以上のストレージが表示されている
図4

どちらかの好きなほうのストレージにESPを作成します。⁠free space」上のデバイス名にカーソルを合わせ、Enterキーを押し、⁠Use as Boot Device」を選択するだけです。そうすると自動的に適切なパーティションが作成されます。

図5 「USED DEVICES」に1GiBのESPが表示されている。このパーティションは「Reset」を押さない限りは削除できない
図5

残りはRAID用に使ってしまいたいところですが、ESPを作らなかったほうもESP相当のパーティションを作っておくことをおすすめします。これは先ほどと同様にもうひとつのデバイス名にカーソルを合わせ、Enterキーを押し、今度は「Add As Another Boot Device」を選択するだけです。

図6 もうひとつESPが作られたが、こちらはマウントされない
図6

こちらのデバイスはUbuntuからは使われませんし、自動的にはマウントもしません。しかしながら「Add As Another Boot Device」として選択した場合は、Ubuntuインストール時に実際に使われるESP/boot/efiとしてマウントされるパーティション)と同じように、各種ファイルがインストールされます。さらにGRUB等のパッケージの更新時は、こちらのデバイスも自動的に中身が更新されるようになります。よって片方のストレージが故障してもUbuntuをもう片方から起動できるようになるので便利です。

さて、ようやくmdraidの設定に入ります。2台のストレージについて順番に「free space」を選択し、⁠Add GPT Partition」から「Size」が空、⁠Format」「Leave unformatted」なパーティションを作りましょう。空にしておくと残りすべてを使います。もちろん任意のサイズで分割してもかまいません。

図7 あとでRAID用のパーティションとして使うためには「Leave unformatted」を選択する必要がある
図7
図8 最低2台の「unused」なパーティションを作ると、「Create software RAID」を選択できるようになる
図8

次に「Create software RAID (md)」を選択します。ここでRAIDのレベルを選択可能です。Ubuntuの場合は、⁠0、1、5、6、10」から選べます。

図9 RAIDのレベルの選択メニュー
図9
図10 必要な台数に達していない場合は、このように赤字のメッセージが表示される
図10

名前は任意の値が設定可能です。ここは初期値の「md0」のままにしておきます。あとは必要なパーティションにチェックを入れ、⁠Create」を押せば完了です。

図11 RAID 1を選択し、2台のパーティションをチェックすると、下部の「Size」が正しい値になる
図11

「active」⁠spare」の選択項目が存在しますが、これは「ホットスペア」機能のための項目です。通常、必要な台数に対して1台以上の追加ストレージを用意し、それを「spare」にしておくことで、どれか1台が壊れたら「spare」のストレージが「active」になって、切り替わってくれるというシステム管理者に優しい便利機能となっています。今回はRAID 1で2台構成なので、両方とも「active」としておく必要があります。

図12 「AVAILABLE DECIES」が「md0」だけになった
図12

RAIDが設定できたので、ストレージがひとつの「md0」としてまとめて表示されるようになりました。そこでここの「free space」から「Add GPT Partition」を選択し、今度こそルートファイルシステムを作成します。

図13 今回はルートファイルシステム用のパーティションを1台だけの構成にしているが、もちろん分割しても構わないし、LVMを使うという手もある
図13

最近のGRUBはRAIDを認識できますので、/bootをRAIDの外に置く必要はありません。もちろん別にわけてもかまいません。あと、スワップパーティションをRAIDの外に作成しても良いでしょう。今回はRAIDの中の/swap.imgとして構築しているため、スワップファイルへの書き込みもミラーリングされてしまいます。

図14 RAID 1構成の準備が完了した。あとは普通にUbuntuをインストールするだけ
図14

あとは通常のUbuntuのインストール手順を実施しインストールが完了するまで待ちます。インストールが完了したら再起動しましょう。

図15 インストールの完了画面で「Reboot Now」を選択する
図15

そうすると、インストールイメージを削除するにはEnterキーを押すよう指示があるので、Enterを押します。LXDインスタンスが再起動しますので、今度は次のようなコマンドで接続します。

$ lxc console raid1 --type=vga

もちろんlxc list raid1でIPアドレスを確認して、SSHログインしてもいいでしょう。

RAID の動作確認

UbuntuにおけるRAID機能のフロントエンドはmdadmコマンドです。ただしその実態はLinuxカーネル側の各種実装が担っています[5]。よっていくつかの確認方法を紹介しましょう。

まず、RAIDの状態を確認する一番シンプルな方法は、/proc/mdstatを確認することです。

$ cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md0 : active raid1 sda2[1] sdb2[0]
      40806400 blocks super 1.2 [2/2] [UU]

unused devices: <none>

「Personalities」がサポートしている設定のリストで、その次の行からRAIDデバイスが一覧表示されます。上記の結果だとたとえば次のことがわかります。

  • RAIDデバイス(アレイ)としてmd0/dev/md0⁠」が存在する
  • md0はRAID 1であり、/dev/sda2/dev/sdb2から構成されている
  • 約40Mブロックであり、メタデータのバージョンは1.2
  • [UU]なのでどちらも「Used」状態

mdadmの設定は/etc/mdadm/mdadm.confに作成されています。これはインストール時に自動的に作られたものです。

$ cat /etc/mdadm/mdadm.conf
ARRAY /dev/md0 metadata=1.2 name=ubuntu-server:0 UUID=65e6f327:8b228a65:000de3d1:5ae1da1c
MAILADDR root

内容についてはman mdadm.confを参照してください。

より詳細な表示を行いたいなら、mdadmコマンドを利用します。

$ sudo mdadm --detail /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Sat Jan 28 16:17:05 2023
        Raid Level : raid1
        Array Size : 40806400 (38.92 GiB 41.79 GB)
     Used Dev Size : 40806400 (38.92 GiB 41.79 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

       Update Time : Sat Jan 28 17:09:22 2023
             State : clean
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 0

Consistency Policy : resync

              Name : ubuntu-server:0
              UUID : 65e6f327:8b228a65:000de3d1:5ae1da1c
            Events : 375

    Number   Major   Minor   RaidDevice State
       0       8       18        0      active sync   /dev/sdb2
       1       8        2        1      active sync   /dev/sda2

これでRAID 1の環境は準備ができました。しかしながら、これだけだと「RAID環境の構築」という点においては、まだ道半ばです。バックアップにおいてリストアのテストが必要なように、RAIDにおいても一度意図的に障害を起こして、その状態を回復させる手順を確認する必要があります。それに関してはまた次回以降に説明しましょう。

ボリュームの削除方法

最後にテスト用に作ったLXDのストレージボリュームのデタッチ方法やストレージプールの削除方法も紹介しておきましょう。まずLXDのインスタンスを終了しておきます。誰もボリュームないしプールを使わなくなったら、次のように削除可能です。

raid1インスタンスからraid1ストレージプールに所属する、カスタムストレージボリュームである「raid1b」をデタッチする
$ lxc storage volume detach raid raid1b raid1

raidストレージプールにあるカスタムストレージボリューム「raid1b」を削除する
$ lxc storage volume delete raid raid1b

raidストレージプールを削除する
$ lxc storage delete raid

デタッチは再アタッチすることで復活できます。しかしながら削除系のコマンドは、復旧方法が存在しないため注意してください。

今回はまず手始めとして、シンプルなRAID 1についてのみ説明しました。記事が長くなってきたましたので、もっと台数が必要なRAID環境の構築方法は次回に解説します。

おすすめ記事

記事・ニュース一覧