第2回:Eucalyptusのストレージ機能


エフェメラル領域とEBSボリュームの違い

 今回はストレージ関連の技術を紹介します。EucalyputsのVMインスタンスには、ユーザが自由に利用できるディスク領域として、エフェメラル(ephemeral)領域とEBS(Elastic Block Storage)ボリュームがあります。

 エフェメラル領域については、「ユーカリプタス入門」第6回に簡単な説明があります。基本的には、第1回の【図1-3】で説明した「ファイルシステム・イメージ」内の1つのパーティションになります。まずは、EucalyptusがVMインスタンス用のファイルシステム・イメージを用意する方法を簡単に説明しておきましょう【図2-1】。この部分は、使用する仮想化ハイパーバイザーによって処理の詳細が異なります。ここでは、KVMの場合で説明します。

【図2-1】VMインスタンス起動時に作成するファイルシステム・イメージ

 VMインスタンス起動の指示を受けたノードコントローラは、指定されたディスクサイズを持った空のファイルシステム・イメージをローカルディスク上に作成します。

 次に、このファイルシステム・イメージ内部に3つのディスクパーティションを作成して、その内の1つに、Walrusからダウンロードしたマシン・イメージの内容をコピーします。これがVMインスタンスのOS領域になります。もう1つのディスクパーティションは、Swap領域としてフォーマットします。

 最後に残ったディスクパーティションがエフェメラル領域です。新規にファイルシステムを作成して、VMインスタンスから自由に使用することができます。

 このように、VMインスタンスを起動するごとに個別のファイルシステム・イメージを作成することで、同一のOS領域を持ったVMインスタンスを複数起動することができます。VMインスタンス起動時に作成するファイルシステム・イメージのサイズを大きくすれば、それだけ、エフェメラル領域のサイズも大きくなります。

 OS領域のサイズはマシン・イメージのサイズであらかじめ決まっています。VMインスタンスを停止すると、対応するファイルシステム・イメージは破棄されますので、エフェメラル領域に保存したファイルは失われることになります。

 一方、EBSボリュームに保存したファイルは、VMインスタンスを停止しても内容が失われることはありません。新しく起動したVMインスタンスに同じEBSボリュームを再接続して、使用を継続することができます。EBSボリュームを作成して、VMインスタンスから利用する手順については、「ユーカリプタス入門」第3回に記載があります。

このようにして作成されたEBSボリュームの実体は、どこにあるのでしょうか? 答えは、ストレージコントローラのローカルディスク上のディスクイメージ・ファイルです。Linuxが持つiSCSIの機能を利用して、これをノードコントローラのローカルディスクであるかのように認識させます【図2-2】(注1)。さらにこれをノードコントローラ上で稼働するVMインスタンスの仮想ディスクとして利用するのです。


(注1)正確には、ストレージコントローラ上でディスクイメージ・ファイルからLVMで構成した論理ボリュームを使用します。これについては後ほど詳しく説明します。

 VMインスタンスを停止してもストレージコントローラ上のディスクイメージ・ファイルはそのまま残ります。iSCSIを利用してネットワーク経由でストレージコントローラに接続することで、任意のノードコントローラ上のVMインスタンスから再利用することができます。

【図2-2】iSCSIによるボリュームの認識

 

LinuxでつくるiSCSIストレージ装置

 【図2-2】にある「ターゲット」と「イニシエータ」は、SCSIの用語です。少し荒っぽく言うと「ターゲット」は、ストレージ装置のことで、「イニシエータ」はストレージを利用するサーバーのことです。

 つまり、本来はサーバーであるストレージコントローラをiSCSIストレージ装置として利用していることになります。Linuxのネットワーク機能を利用して、Linuxサーバーを自宅ルータに仕立て上げた経験のある方は多いと思いますが、実は、LinuxサーバーをiSCSIストレージ装置に仕立て上げることもできるのです。

 これは、Eucalyptus以外でもさまざまな利用方法が考えられます。いわゆるHAクラスタを構成する際は、比較的高価な共有ストレージ装置が必要ですが、性能や信頼性がそれほど要求されない環境では、Linuxサーバーで作ったiSCSIストレージ装置を共有ストレージとして利用することも可能です。ここでは、Red Hat Enterprise Linux 5、および6の環境で、iSCSIのターゲットとイニシエータを構成する手順を紹介しておきます。SELinuxは使用しない前提とします。

 はじめにターゲットとして構成するサーバーの設定です。scsi-target-utilsパッケージを導入した後に、空のディスクイメージ・ファイルを作成します。ここでは、/opt/volume01.imgというファイルを512MBの容量で作成しています。

# yum install scsi-target-utils
# dd if=/dev/zero of=/opt/volume01.img bs=1M count=512

 次に、iSCSIターゲットの設定ファイル/etc/tgt/targets.confに次の内容を追加します。

<target iqn.2011-06.com.example.server01:tgt01>
    backing-store /opt/volume01.img
</target>

 1行目の「iqn.2011・・・」は、「iqn.< YYYY-MM>.<サーバーのFQDNを逆順にしたもの>:< 任意の識別子>」という形式で指定するユニークなターゲット名です。backing-storeは、先程作成したディスクイメージ・ファイルです。複数のディスクイメージ・ファイルを用意した場合は、backing-storeの行を複数並べて、それらを指定することもできます。最後に、tgtdサービスを開始して、tgt-adminコマンドで設定状況を確認します。「LUN: 0」(iSCSIコントローラ)と「LUN: 1」(論理ボリューム)の2個のLUNが作成されていれば成功です。

# chkconfig tgtd on
# service tgtd start
# tgt-admin -s

 続いて、イニシエータとして構成するサーバーの設定です。まず、iscsi-initiator-utilsパッケージを導入した後に、iscsiサービスを開始します。

# yum install iscsi-initiator-utils
# chkconfig iscsi on
# service iscsi start

 この時、「No records found!」と表示されることがありますがこれは問題ありません。次のコマンドで、先に準備したターゲットを登録してiscsiサービスを再起動すると、新しいローカルディスク/dev/sdXが認識されます。

# iscsiadm -m discovery --type sendtargets --portal <ターゲットのIPアドレス>
# service iscsi restart

 この後は、通常の手順で、ext3などのファイルシステムとしてフォーマットして使用することができます。もちろん、このローカルディスクの実体は、ターゲットとして構成したサーバー上のディスクイメージ・ファイルです。

 その他には、ターゲット側のLVMで構成した論理ボリューム(/dev/<VG名>/<LV名>)をbacking-storeに指定して利用することも可能です。この点については後でもう一度触れることにします。手順の確認が終わったら、イニシエータ側で(必要に応じて)ファイルシステムをアンマウントしてiscsiサービスを停止した後に、ターゲット側でtgtdサービスを停止しておいてください。

 

ループバック・デバイスの活用

 ここで、【図2-1】のファイルシステム・イメージに話を戻します。「ユーカリプタス入門」第2回では、VMインスタンスを起動して、SSHで接続する手順が紹介されています。この時、SSHのログイン認証に使用する鍵ペアを事前に作成しておき、VMインスタンスの起動時に、使用する鍵ペアを指定します。すると、Eucalyptusは、起動するVMインスタンスのOS領域に対して、認証用の公開鍵の設定を自動的に行います。これにより、対応する秘密鍵を持つユーザだけがこのVMインスタンスにログインできるようになります。

 この公開鍵の設定は、どのようにして行われるのでしょうか。

 先に、ノードコントローラがファイルシステム・イメージを用意する方法を説明しました。この中で、ファイルシステム・イメージ内のパーティションにマシン・イメージの内容をコピーして、OS領域を作成する部分がありました。ノードコントローラは、この後、該当パーティションの内容を自身のディレクトリ上にマウントします。これにより、OS領域のディレクトリの内容がノードコントローラから見えるようになるので、rootユーザのホームディレクトリ(/home/root/.ssh/authorized_keys)にある認証設定ファイルを直接に編集します。

 この手法は、一般のサーバー仮想化環境でも活用することができます。たとえば、KVMの環境では、virt-cloneコマンドで既存の仮想ディスクイメージを複製して、新しい仮想マシンを定義することができますが、ネットワークの設定などは新しい仮想マシンを起動した後に手で修正する必要があります。この時、複製した仮想ディスクイメージをホストLinux上でマウントすれば、新しい仮想マシンを起動する前に必要な修正をおこなうことができます。スクリプトで修正作業を自動化することも可能です。

 仮想ディスクイメージをホストLinux上でマウントするには、Linuxのループバック・デバイス(/dev/loopX)を利用します。これは、仮想ディスクイメージをあたかも普通のブロックデバイスであるかのように扱う機能です【図2-3】。

 仮想ディスクイメージの内部がパーティションに分かれておらず、全体として1つのファイルシステムになっている場合は、mountコマンドにloopオプションを指定するだけです。isoファイルをマウントする際にもよく使うテクニックです。

# mkdir /mnt/image
# mount -o loop volume01.img /mnt/image
【2-3】ループバック・デバイスの仕組み

 見かけ上はループバック・デバイスが利用されていることは分かりませんが、内部的には仮想的なブロックデバイス/dev/loopXを通して、仮想ディスクイメージvolume01.imgへのアクセスが行われます。

 一方、仮想ディスクイメージの内部がパーティションに分かれている場合は、次の手順になります。

# losetup -fv volume01.img
Loopデバイス は /dev/loop0 です

# kpartx -av /dev/loop0
add map loop0p1 (253:0): 0 208782 linear /dev/loop0 63
add map loop0p2 (253:1): 0 8193150 linear /dev/loop0 208845
add map loop0p3 (253:2): 0 1044225 linear /dev/loop0 8401995

# mount /dev/mapper/loop0p2 /mnt/image

 losetupコマンドで、仮想ディスクイメージをループバック・デバイスに接続します。コマンドの出力から実際に接続されたデバイス名(この例では/dev/loop0)を確認して、kpartxコマンドの引数に指定します。

 その結果、仮想ディスクイメージ内部のパーティション(この例では3つのパーティション)がブロックデバイス/dev/mapper/loop0p1~/dev/mapper/loop0p3にマッピングされています。ここでは、ルートファイルシステムを含む2つめのパーティションを/mnt/imageにマウントしています。次のように、仮想ディスクイメージ内のディレクトリがそのまま見えていることがわかります。

# ls -l /mnt/image/
合計 184
drwxr-xr-x. 2 root root 4096 2月 14 11:56 2011 bin
drwxr-xr-x. 2 root root 4096 2月 14 09:57 2011 boot
drwxr-xr-x. 2 root root 4096 2月 14 09:57 2011 dev
drwxr-xr-x. 74 root root 4096 3月 4 08:56 2011 etc
(省略)

 この後、仮想ディスクイメージ内の必要なファイルを修正したら、次のコマンドでループバック・デバイスとの接続を解除します。

# umount /mnt/image
# kpartx -d /dev/loop0
# losetup -d /dev/loop0

 Eucalyptusを含めて、サーバー仮想化環境では、仮想ディスクイメージを扱うために多数のループバック・デバイスが同時に使用されることがあります。使用可能なループバック・デバイスが不足すると問題が発生しますので、ループバック・デバイスの数を事前に増やしておくことが推奨されます。

 「ユーカリプタス入門」第1回で紹介されている手順でもループバック・デバイスを増やす設定が行われています。Red Hat Enterprise Linux 5でも同じ手順が使えます。Red Hat Enterprise Linux 6では、次のコマンドになります。

# for i in $(seq 8 255); do echo "loop$i" >> /etc/udev/makedev.d/50-udev.nodes; done

ここでは、loop0~loop255を作成しています。loop256以上を作成する場合は、設定ファイル/etc/makedev.d/01linux-2.6.xの下記の256の部分を作成する個数以上に指定します。

b $STORAGE               7   0  1 256 loop%d

 

ディスクイメージ・ファイルとLVMの組み合わせ

 最後に、少し複雑な応用例として、ディスクイメージ・ファイルをLVMとして構成した後にiSCSIのターゲットにする手法を紹介します。まずは次の手順を見てください。

# dd if=/dev/zero of=/opt/volume02.img bs=1M count=576
# losetup -fv volume02.img
Loopデバイス は /dev/loop0 です
# pvcreate /dev/loop0
  Physical volume "/dev/loop0" successfully created
# vgcreate vg01 /dev/loop0
  Volume group "vg01" successfully created
# lvcreate -L 512M -n lv01 vg01
  Logical volume "lv01" created

 この後、/etc/tgt/targets.confのbacking-storeに/dev/vg01/lv01を指定して、tgtdサービスを開始します。

 この手順は何を行っているかわかるでしょうか? これは、ディスクイメージ・ファイルvolume02.imgを接続したループバック・デバイス/dev/loop0を物理ボリュームとみなして、LVMを構成しています。(仮想的な)物理ボリュームから作成したボリュームグループvg01内の論理ボリュームlv01をiSCSIのターゲット・ボリュームとして構成しています。イニシエータからこのボリュームに接続して書き込みを行うと、その内容は、最終的にはディスクイメージ・ファイルvolume02.imgに書き込まれることになります。

 わざわざLVMを構成するには理由があります。こうすることで、LVMのスナップショット機能を利用して、ボリュームの内容を一時保存することができるようになるのです。

 EucalyptusのEBSボリュームでもこれと同じことが行われています。Eucalyptusの機能で、EBSボリュームのスナップショットを作成すると、その裏側では、ストレージコントローラ上で対応する論理ボリュームのLVMスナップショットが作成されます。LVMスナップショットの作成は瞬時に終わりますので、オリジナルのEBSボリュームはすぐに利用を再開できます。ストレージコントローラは、この後でゆっくりとLVMスナップショットからEBSボリュームの複製を作成します。複製が完了するとLVMスナップショットは破棄されます。

 手順の確認が終わったら、tgtdサービスを停止して、次のコマンドでループバック・デバイスを解放します。

# vgchange -an vg01
  0 logical volume(s) in volume group "vg01" now active
# losetup -d /dev/loop0

 

さいごに

 クラウドのストレージというと、いわゆる分散ストレージを想像する方が多いかもしれません。しかしながら、分散ストレージも魔法の技術ではありません。分散ストレージを構成する個々のストレージ・ノードの上では、さまざまなLinuxの基礎技術が活用されているはずです。

 前回のさいごにも触れたように、単純なものを組み合わせて複雑なものを創り上げていく、この発想を忘れずにIaaSクラウドの完全理解を目指していきましょう。また、今回紹介した内容は、一般的なサーバー仮想化環境を管理する上でも有用です。サーバーインフラを扱う上で、サーバー仮想化は必須の技術になりつつありますので、ぜひ有効活用してください。


中井 悦司
素粒子論の研究、予備校講師、外資系ベンダーのインフラSE、Linux/OSSエバンジェリストと堅実なのか奔放なのかよくわからない経歴を重ねた後、Linux/OSSを愛するあまりレッドハットに転職。オープンソースの「エンジニアを幸せにする力」を信じながら、企業システムにおけるLinux/OSSの活用促進に情熱を注いでいます。
関連情報