EC2でGlusterFSを使ってみた

2013.11.05

GlusterFSとは

GlusterFSとはオープンソースの分散ファイルシステムです。

複数のサーバ上の記憶領域を集約して、1つのファイルシステムとして扱うことができます。

例えば、10台のLinuxサーバから、それぞれ100GBのディスク領域をGlusterFS用に提供し、1つの1TBのストレージとして使用することができます。

今回は、GlusterFSクラスタ(GlusterFS3.3.2)をEC2上に構築し、簡単な動作確認をしてみました。

用語説明

実際の構築に入る前に、GlusterFSで使われる用語について簡単に説明しておきます。

Storage Pool

ストレージクラスタに参加するサーバ(ノード)の集まりです。GlusterFSにストレージを提供するサーバは、あらかじめStorage Poolに参加させておく必要があります。

Brick

個々のサーバ上のディレクトリで、GlusterFSにストレージとして提供されるものです。

GlusterFSの分散ファイルシステム(Volume)に保存されたファイルは、物理的にはBrick上に保存されます。

Volume

Brickを論理的に集約したもので、1つのストレージとして扱うことができます。ストレージを使う側は、このVolumeをマウントして利用することになります。GlusterFSの運用はVolumeの操作に関するものがほとんどです。

Glusterfs

 

Volumeタイプ

Volumeには3つのタイプ(Distributed Volume、Replicated Volume、Striped Volume)があり、Volumeを作成するとき選択できます。タイプごとにファイルの保存のされ方が異なります。

Distributed Volume(分散ボリューム)

Distributed Volumeの場合、ファイルはVolumeを構成するBrickのいずれか一つに保存されます。Volumeの容量はBrickの容量の合計になるため、大容量のストレージを利用したい場合に向いています。ただし、Brickに障害が発生した場合、そのBrickに保存されていたファイルにはアクセスできなくなります。下の図の場合、ノード3が障害で停止した場合、ファイル3の情報は失われてしまいます。

DistributedVolumeGlusterFS

Replicated Volume(複製ボリューム)

Replicated Volumeの場合、ファイルは指定したレプリカ数分のBrickに重複して保存されます。Volumeの容量はBrick容量の合計をレプリカ数で割ったものになります。Brickに障害が発生しても他のBrickにある複製されたファイルを利用できるため、可用性や耐久性が重要な場合に適しています。

下図はレプリカ数3のReplicated Volumeです。2つのBrickに障害が発生してもファイルは失われません。

ReplicatedVolumeGlusterFS

Striped Volume

Striped Volumeの場合、ファイルは分割され(デフォルトだと128KB)、指定したストライプ数分のBrickに分散して保存されます。Volumeの容量はBrickの容量の合計になります。複数のBrickを並行して利用できるため、巨大なファイルに頻繁にアクセスする場合に向いていますが、一つでもBrickに障害が発生すると、ファイルにアクセスできなくなります。

下図はストライプ数3のStriped Volumeです。一つでもノードが失われるとファイル1、ファイル2いずれもアクセスできなくなります。

StripedVolume

今回の検証内容

2台のEC2インスタンスからなるGlusterFSクラスタ上にDistributed Volumeを一つ作成し、別のEC2インスタンスからマウントします。

マウント後、ファイルがどのように保存されるか確認し、最後にノードに障害が発生した場合の挙動について見ていきます。

構築手順

構成

まず、GlusterFS用のEC2インスタンス2台とクライアント用EC2インスタンス1台を用意しましょう。

  • クライアント用インスタンス(1台)
    • AMI: Amazon Linux AMI 2013.09
    • セキュリティグループ
      • base(0.0.0.0/0からの22/TCPを許可)
      • glusterfs-clients(空)
  • GlusterFS用インスタンス(2台)
    • AMI: Amazon Linux AMI 2013.09
    • セキュリティグループ
      • base(22/TCPを許可)
      • glusterfs-nodes(glusterfs-clientsからの111/TCP, 24007-24010/TCP, 38465-38468/TCPを許可。glusterfs-nodesからの24007-24010/TCPを許可※)
    • 追加EBS: 5GB(Brick用)

 ※24007以降のポートはGlusterFSのVolume管理とクライアント-Brick間の通信に利用します。Brick1つにつき1つのポートを利用するので、24007〜(24008 + 使用する最大ブリック数)のポートが必要です。今回は2Brick使うので24010までオープンしています。実際に利用するときには多め(100ポートとか)にオープンしておくことをお勧めします。111/TCPと38465〜38468/TCPはGlusterFSのVolumeにNFS接続するときに利用します。今回はNFSでは接続しないので必要ないのですが、一応オープンしています。

パッケージのインストール

EC2インスタンスが立ち上がったら、SSHでログインし、クラスタを作っていきます。

以下の作業はGlusterFS用インスタンス全て(今回は2台)で行ってください。

rootユーザで作業します。

[ec2-user@node01 ~]$ sudo su -
[root@node01 ~]# 

GlusterFS用yumレポジトリを登録し、レポジトリ情報を一部修正します。

Amazon Linuxでは$releaseverの値が「latest」なのですが、

[ec2-user@node01 ~]$ grep releasever /etc/yum.conf 
cachedir=/var/cache/yum/$basearch/$releasever
releasever=latest

GlusterFSのサイトには該当するレポジトリがないため、$releaseverの部分を「6」に変更します。(最初から設置してある/etc/yum.repos.d/epel.repoで「6」を指定しているのでそれに合わせています。)

[root@node01 ~]# curl -o /etc/yum.repos.d/glusterfs-epel.repo http://download.gluster.org/pub/gluster/glusterfs/3.3/LATEST/EPEL.repo/glusterfs-epel.repo

[root@node01 ~]# vim /etc/yum.repos.d/glusterfs-epel.repo
# Place this file in your /etc/yum.repos.d/ directory

[glusterfs-epel]
name=GlusterFS is a clustered file-system capable of scaling to several petabytes.
#baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.2/EPEL.repo/epel-$releasever/$basearch/
baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.2/EPEL.repo/epel-6/$basearch/
enabled=1
skip_if_unavailable=1
gpgcheck=0

[glusterfs-swift-epel]
name=GlusterFS is a clustered file-system capable of scaling to several petabytes.
#baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.2/EPEL.repo/epel-$releasever/noarch
baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.2/EPEL.repo/epel-6/noarch
enabled=1
skip_if_unavailable=1
gpgcheck=0

[glusterfs-source-epel]
name=GlusterFS is a clustered file-system capable of scaling to several petabytes. - Source
#baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.2/EPEL.repo/epel-$releasever/SRPMS
baseurl=http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.2/EPEL.repo/epel-6/SRPMS
enabled=0
skip_if_unavailable=1
gpgcheck=0

変更したらglusterfs-serverパッケージをインストールしてください。

[root@node01 ~]# yum install -y glusterfs-server
(出力略)

ちょっと脇道にそれますが、/var/lib/glusterd/glusterd.infoというファイルの中身を見てみてください。

[root@node01 ~]# cat /var/lib/glusterd/glusterd.info 
UUID=161832ab-17e3-4f60-8594-209c561cbab2

これはノードのユニークなIDを表しており、パッケージインストール時に付与されます。ですので、パッケージインストール後にAMIを作成し、それをもとにノード群(Storage Pool)を作ろうとすると、IDが重複してしまい、正常に動作しないので、注意してください。

クラスタを管理するglusterdプロセスを立ち上げましょう。

[root@node01 ~]# chkconfig glusterd on
[root@node01 ~]# service glusterd start
Starting glusterd:                                         [  OK  ]

Brickの作成

次に、Brick用のディレクトリを作成します。

今回、追加のEBSは/dev/xvdbにアタッチされているので、ext4でフォーマットします。inodeサイズは512バイトにする必要があります。

[root@node01 ~]# mkfs.ext4 -I 512 /dev/xvdb
(出力略)

フォーマットが終わったら、適当なディレクトリを作成し、マウントしましょう。インスタンス起動時に自動でマウントされるようにfstabにも追記しておきます。

[root@node01 ~]# mkdir -p /bricks/vol01/
[root@node01 ~]# mount /dev/xvdb /bricks/vol01/
[root@node01 ~]# echo '/dev/xvdb /bricks/vol01 ext4 defaults,noatime 1 1' >> /etc/fstab
[root@node01 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/xvda1            7.9G  977M  6.9G  13% /
tmpfs                 298M     0  298M   0% /dev/shm
/dev/xvdb             4.9G  138M  4.5G   3% /bricks/vol01

これで、Brickの準備まで終わりました。

クラスタを作るため、もう一台のインスタンスnode02も同じ状態にします。

[root@node02 ~]# service glusterd status
glusterd (pid  1440) is running...
[root@node02 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/xvda1            7.9G  977M  6.9G  13% /
tmpfs                 298M     0  298M   0% /dev/shm
/dev/xvdb             4.9G  138M  4.5G   3% /bricks/vol01

GlusterFSクラスタの構築

もう一台の準備が終わったら、クラスタを構成していきましょう。

今回のGlusterFS用インスタンスのホスト名のプライベートIPアドレスは以下の通りです。
node01: 172.16.101.11
node02: 172.16.102.11

GlusterFSのノードにはマスタやスレイブといった役割の違いはないので、以下の作業はいずれか1つのインスタンスで行えばOKです。今回はnode01で行います。

まず、glusterコマンドで対話モードに入ります。

[root@node01 ~]# gluster
gluster>

最初に、Storage Poolにノードを登録します。自分自身(node01)は最初から登録されているので、自分以外のノード、node02登録します。

peer probe <<追加したいノードのホスト名またはIPアドレス>>
で登録できます。

gluster> peer status                                                                                                                           
No peers present                                                                                                                               
gluster> peer probe 172.16.102.11
Probe successful
gluster> peer status
Number of Peers: 1

Hostname: 172.16.102.11
Uuid: d11e714d-f8bd-43f9-89d0-3f42df82cd9d
State: Peer in Cluster (Connected)

ノード数2のStorage Poolができていることが確認できました。

次に、Volumeを作成します。

Distributed Volumeの場合
volume create <<Volume名>> <<ノードのホスト名またはIPアドレス>>:<<Brickのパス>> <<ノードのホスト名またはIPアドレス>>:<<Brickのパス>> ....
で作成できます。Brickは必要な数だけ指定してください。今回は2つです。Volume名はvol01にします。

gluster> volume info
No volumes present
gluster> volume create vol01 172.16.101.11:/bricks/vol01 172.16.102.11:/bricks/vol01
Creation of volume vol01 has been successful. Please start the volume to access data.
gluster> volume info
 
Volume Name: vol01
Type: Distribute
Volume ID: 58378596-bbfa-475f-b37d-dda4c63edc3c
Status: Created
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: 172.16.101.11:/bricks/vol01
Brick2: 172.16.102.11:/bricks/vol01

node01とnode02の/bricks/vol01でVolumeが作られているのが確認できました。

Volumeを利用するには起動させる必要があります。

起動方法は
volume start <<Volume名>>
です。

gluster> volume status vol01
Volume vol01 is not started
gluster> volume start vol01
Starting volume vol01 has been successful
gluster> volume status
Status of volume: vol01
Gluster process                                         Port    Online  Pid
------------------------------------------------------------------------------
Brick 172.16.101.11:/bricks/vol01                       24009   Y       17716
Brick 172.16.102.11:/bricks/vol01                       24009   Y       1500
NFS Server on localhost                                 38467   Y       17722
NFS Server on 172.16.102.11                             38467   Y       1506

これで、Volumeが利用できるようになったので、クライアントインスタンスから接続してみましょう。

Volumeへの接続

接続方法はNFS、CIFS、GlusterFSのNativeクライアントから選べます。今回はNativeクライアントで接続してみましょう。

クライアントパッケージglusterfs, glusterfs-fuseを導入してください。

[ec2-user@client01 ~]$ sudo su -
[root@node01 ~]# 

[root@client01 ~]# curl -o /etc/yum.repos.d/glusterfs-epel.repo http://download.gluster.org/pub/gluster/glusterfs/3.3/LATEST/EPEL.repo/glusterfs-epel.repo

[root@client01 ~]# vim /etc/yum.repos.d/glusterfs-epel.repo
(略)
[root@client01 ~]# yum install -y glusterfs glusterfs-fuse
(出力略)

適当なディレクトリを作成し、マウントしてみましょう。

マウントタイプはglusterfs、マウント先は「ホスト名(またはIPアドレス):/(Volume名)」です。BrickのパスではなくVolume名を指定する点に注意してください。

[root@client01 ~]# mkdir -p /glusterfs/vol01
[root@client01 ~]# mount -t glusterfs 172.16.101.11:/vol01 /glusterfs/vol01/
[root@client01 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/xvda1            7.9G  975M  6.9G  13% /
tmpfs                 298M     0  298M   0% /dev/shm
172.16.101.11:/vol01  9.7G  277M  9.0G   3% /glusterfs/vol01

Volumeサイズは5GB + 5GBで約10GBになっています。

動作確認

実際にファイルをいくつか作成してみましょう。

[root@client01 ~]# touch /glusterfs/vol01/{01..10}
[root@client01 ~]# ls /glusterfs/vol01/
01  02  03  04  05  06  07  08  09  10  lost+found

無事作成できました。

各Brickの中身を見てみると、ファイル03, 04, 05がnode01に、それ以外がnode02分散して保存されていることがわかります。

node01

[root@node01 ~]# ls /bricks/vol01/
03  04  05  lost+found

node02

[root@node02 ~]# ls /bricks/vol01/                                                                                                             
01  02  06  07  08  09  10  lost+found

node01に障害が起きたと仮定して、停止させてみましょう。

[root@node01 ~]# shutdown -h now

node02からクラスタ情報をみると、

[root@node02 ~]# gluster
gluster> peer status
Number of Peers: 1

Hostname: 172.16.101.11
Uuid: 161832ab-17e3-4f60-8594-209c561cbab2
State: Peer in Cluster (Disconnected)
gluster> volume info vol01

Volume Name: vol01
Type: Distribute
Volume ID: 58378596-bbfa-475f-b37d-dda4c63edc3c
Status: Started
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: 172.16.101.11:/bricks/vol01
Brick2: 172.16.102.11:/bricks/vol01
gluster> volume status vol01
Status of volume: vol01  
Gluster process                                         Port    Online  Pid
------------------------------------------------------------------------------
Brick 172.16.102.11:/bricks/vol01                       24009   Y       1500
NFS Server on localhost                                 38467   Y       1506

node01(172.16.101.11)はStorage Poolに所属しているがDisconnectedであること、VolumeにBrickを提供しているが、Onlineでないことが確認できます。

クライアント側からみると

[root@client01 ~]# ls /glusterfs/vol01/                                                                                                        
01  02  06  07  08  09  10  lost+found

node01側に保存されていたファイルだけ消えました。 ここで注意していただきたいのは、先ほどVolumeをマウントするとき、node01を指定してマウントしたにもかかわらず、node01停止後もVolumeが利用できる点です。node02に保存されているファイルには正常にアクセスできます。Nativeクライアントは各ノード上のBrickと直接通信しているので、マウント先が停止しても正常にVolumeへのアクセスを続けることができます。

試しに、クライアントで接続情報をみてみると

[root@client01 ~]# netstat -anp|grep gluster
tcp        0      1 172.16.1.11:1022            172.16.101.11:24009         SYN_SENT    1442/glusterfs      
tcp        0      1 172.16.1.11:1023            172.16.101.11:24007         SYN_SENT    1442/glusterfs      
tcp        0      0 172.16.1.11:1019            172.16.102.11:24009         ESTABLISHED 1442/glusterfs      
unix  2      [ ]         DGRAM                    8045   1442/glusterfs

Nativeクライアントと各Brickが直接通信していることがわかります。

ただし、これはNativeクライアントで接続した場合のみであり、NFSやCIFSで接続した場合はマウント先のノードが停止するとVolumeにアクセスできなくなります。

では、node01を再び起動し、glusterdプロセスを起動させましょう。

[root@client01 ~]# ls /glusterfs/vol01/
01  02  03  04  05  06  07  08  09  10  lost+found

元に戻りました。

以上、GlusterFSクラスタを構築し、簡単な動作確認をして見ましたが、分散システムにしてはかなり取っ付きやすかったです。また、メタ情報を管理するサーバが必要ないため、運用もしやすいと思います。

今回はVolumeの作成まででしたが、次回以降、Volumeの構成変更や他のタイプのVolumeについて書いてみたいと思います。