分散ファイルシステム glusterfs を試してみた

レッドハットに買収されたとかで、RHEVやovirtとも絡んできそうなので試してみた。実験用に仮想化環境で動かしたので真面目にパフォーマンスは調べてないけど、簡単に設定できる割にちゃんと動くので良い感じだと思いました。

drbdと適当に比較すると、drbdは2台のサーバでのnetwork raid1 で基本的にprimary側のサーバでしかmountできないのに対して、glusterfs は複数台のサーバでのnetwork raid(volume次第でraid0 , raid1, raid10, raid5 or 6 のような冗長性有り) で、複数のサーバからmount可能 (fuseを使ったglusterfs native client, nfs , cifs)。

defaultはtcpで、rdmaライブラリをインストールして、オプションを指定すればインフィニバンドも使用可能。

以下、用語は間違っている可能性あり。

install

サーバはCentOS6.3を使ったけど、RHEL系6.1以上だったらたぶん何でもいい。
公式からrpm取ってきてinstall。

# yum -y install fuse fuse-libs
# rpm -ivh ./glusterfs-3.3.0-1.el6.x86_64.rpm ./glusterfs-server-3.3.0-1.el6.x86_64.rpm \
    ./glusterfs-fuse-3.3.0-1.el6.x86_64.rpm \
    ./glusterfs-geo-replication-3.3.0-1.el6.x86_64.rpm

peer

  • 追加

host sv01 で実行するとする。

# gluster peer probe sv02
# gluster peer probe sv03

外すときはprobeの代わりにdetachで。

  • 確認
# gluster peer info

仮想化などでサーバをclone する際の注意

glusterd を起動すると/var/lib/glusterd にlocalhostやpeerのUUID等が保存されるので、glusterd install後にclone すると、UUIDが重複してpeer statusがおかしくなる。その場合は、一旦/var/lib/glusterd を削除した後、再度glusterd を起動すると良い。

volume

sv01 ~ sv03 の3台のbrickで3つのvolume 作ってみるテスト

vol1 destributed (default)
vol2 replicated
vol3 stripted
  • volume 作成
# gluster volume create vol1 sv01:/vol/vol1 sv02:/vol/vol1 sv03:/vol/vol1
# gluster volume info

  • volume 削除
# gluster volume delete vol1
  • volume 起動

作成しただけではmountできないのでstartする。

# gluster volume start vol1
distributed volume

raid0 like?(ちょっと違う) ファイルごとに複数のサーバに分けて分散する。とあるサーバが死ぬと、そのサーバに配置したファイルにはアクセスできなくなるが、他のサーバ上にあるファイルにはアクセス可能。

gluster voluem create でオプションを指定しない場合、distributed volumeになる。

# gluster volume create vol1 sv01:/vol/vol1 sv02:/vol/vol1 sv03:/vol/vol1
# gluster volume info vol1
	 
Volume Name: vol1
Type: Distribute
Volume ID: 47f9d050-fb59-44cf-8fd2-166593598cd7
Status: Started
Number of Bricks: 3
Transport-type: tcp
Bricks:
Brick1: sv01:/vol/vol1
Brick2: sv02:/vol/vol1
Brick3: sv03:/vol/vol1

replicated volume

raid1 like? ファイルを複数のサーバに複製する。create volume-name replica N のようにreplica keywordとレプリカの数を指定する。

# gluster volume create vol2 replica 3 sv01:/vol/vol2 sv02:/vol/vol2 sv03:/vol/vol2
# gluster volume info vol2
	 
Volume Name: vol2
Type: Replicate
Volume ID: ca0b4c10-c440-4413-8a39-dc89fc7ff5fa
Status: Started
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: sv01:/vol/vol2
Brick2: sv02:/vol/vol2
Brick3: sv03:/vol/vol2

striped

raid0 like ? ファイルを細切れに分割して複数のサーバに配置する。(扱うファイル次第では)他のモードと比較して最も高速になるけど、どれか1つのサーバが死ぬと全てのファイルにアクセスできなくなる。

# gluster volume create vol3 strip 3 sv01:/vol/vol3 sv02:/vol/vol3 sv03:/vol/vol3
# gluster volume info vol3
	 
Volume Name: vol3
Type: Stripe
Volume ID: ffd67330-270e-4529-8090-46e81e4f46f9
Status: Started
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: sv01:/vol/vol3
Brick2: sv02:/vol/vol3
Brick3: sv03:/vol/vol3

mount

mountする前にgluster volume start volume_name しておくのを忘れずに。

Glustefs Native Client

FUSEが必要なのでなければインストールして有効にしておく。

# yum -y install fuse fuse-libs
# modprobe fuse
# dmesg | grep -i fuse
# modinfo fuse

native clientからのアクセスの場合、見た目のmountは mount sv01:/vol1 のように1サーバしか指定しないが、どのファイルがどこにあるか(ファイル名のハッシュ値で計算)を知っているので、直接sv02, sv03などのサーバにもアクセスする。

  • mount

fstabに追記(or mountコマンドでもいいけど)。

mount pointのpathはvolumeへのfullpath ではなくて、volume名なことに注意。この例だとgluster volume create vol1 sv01:/vol/vol1 .... で作成したので、sv01:/vol/vol1 ではなく、sv01:/vol1 が正解。

document にはdefaults,_netdev と書いてあったけど、unknown option と言われて警告出たので_netdevは外した。

sv01:/vol1    /mnt/vol1    glusterfs    defaults    0 0
sv01:/vol2    /mnt/vol2    glusterfs    defaults    0 0
sv01:/vol3    /mnt/vol3    glusterfs    defaults    0 0
# mount -a 
# df -h -t fuse.glusterfs
Filesystem            Size  Used Avail Use% マウント位置
sv01:/vol1             80G  6.7G   69G   9% /mnt/vol1
sv01:/vol2             27G  2.3G   23G   9% /mnt/vol2
sv01:/vol3             80G  6.7G   69G   9% /mnt/vol3

vol2 はreplica 3 で作成したため、他のvolumeの1/3の容量になってるのもわかる。

  • mountコマンド
# gluster volume start vol1
# mount -t glusterfs sv01:/volume-name /mnt/vol1

NFS

なんと。defaultのままでNFSでもアクセスできるようだ。すごいね。fstabには普通にNFS利用するときの内容を記述する。
ただ、NFSの場合、clientはsv01にしかアクセスしないので、ファイルがその他のbrickにある場合、sv01がproxyのように動作する。(のでnative clientより遅いはず)

sv01:/vol1   /mnt/vol1     nfs     defaults,vers=3 0 0

CIFS

CIFSでもmountできるようだけど試してない。

volume typeの組み合わせ

ここからが本番。上で説明したように、

  • distributed の特定ノードで障害が発生した場合、clientからのマウント自体は正常に行えているまま、そのノード上に配置されているファイルが見えなくなる
  • striped のノードで障害が発生した場合、マウント自体にエラーが発生して全てのファイルへアクセス出来なくなる
  • distributed と striped はファイルを配置するサーバを分散させるため高速になるけど冗長性がなくなる
  • replicated は冗長性はあるけど全サーバへ複製をしているだけなので速くならない(read は速くなる?)

ということで実際に利用する場合、これらを組み合わせたvolumeを作成すると幸せになれる。
raid10 のようなことをするわけですね。


Distributed Replicated であれば、ファイルごとに複数のサーバに複製する。この場合、ノード(bricks)の数はreplicaの整数倍にする必要がある。

Striped Replicated Volumes であれば、ファイルをstriped して複数のサーバに分散して配置したものを複製する。

Distributed Replicated

# gluster volume create dist-replica-volume replica 2 sv01:/vol1 sv02:/vol1 sv03:/vol1 sv04:/vol1
Creation of volume dist-replica-volume has been successful. Please start the volume to access data.
# gluster volume start dist-replica-volume
Starting volume dist-replica-volume has been successful
# gluster volume info
	 
Volume Name: dist-replica-volume
Type: Distributed-Replicate
Volume ID: ca98e18a-4890-449d-98aa-038e1ed7ecff
Status: Started
Number of Bricks: 2 x 2 = 4
Transport-type: tcp
Bricks:
Brick1: sv01:/vol1
Brick2: sv02:/vol1
Brick3: sv03:/vol1
Brick4: sv04:/vol1
mount
# mount -t glusterfs server:/dist-replica-volume /mnt/vol1


試しに10Mのファイルを10個作ってみる。

# for i in {00..09}; do dd if=/dev/zero of=./$i.dat bs=1M count=10; done
# ls -lsh
合計 101M
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 00.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 01.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 02.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 03.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 04.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 05.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 06.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 07.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 08.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:28 2012 09.dat

各サーバのvolumeのディレクトリ見てみる。sv01 と sv02、sv03とsv04 でreplicatedされていて、 それぞれにファイルが分散しているのがわかる。また左端の実際のファイルサイズ(ls -s) も10Mになっているのがわかる。

$ for i in {01..04}; do ssh root@sv$i 'hostname && ls -lsh /vol1' ; done
sv01
合計 41M
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 00.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 05.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 08.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 09.dat
sv02
合計 41M
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 00.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 05.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 08.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 09.dat
sv03
合計 61M
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 01.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 02.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 03.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 04.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 06.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 07.dat
sv04
合計 61M
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 01.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 02.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 03.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 04.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 06.dat
11M -rw-r--r-- 2 root root 10M  9月  3 22:28 2012 07.dat

Striped Replicated

# gluster volume create striped-replica-volume \
       stripe 2 replica 2 sv01:/vol2 sv02:/vol2 sv03:/vol2 sv04:/vol2 
Creation of volume striped-replica-volume has been successful. Please start the volume to access data.
# gluster volume start striped-replica-volume 
Starting volume striped-replica-volume has been successful
# gluster volume info striped-replica-volume 
	 
Volume Name: striped-replica-volume
Type: Striped-Replicate
Volume ID: 76b46b15-d801-4e93-916a-b0df840af7bf
Status: Started
Number of Bricks: 1 x 2 x 2 = 4
Transport-type: tcp
Bricks:
Brick1: sv01:/vol2
Brick2: sv02:/vol2
Brick3: sv03:/vol2
Brick4: sv04:/vol2
mount

先ほどと同様に、mountして10個のファイル作ってみる。

# mount -t glusterfs server:/striped-replica-volume /mnt/vol2
# cd /mnt/vol2
# for i in {00..09}; do dd if=/dev/zero of=./$i.dat bs=1M count=10; done
# ls -lsh
合計 101M
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 00.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 01.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 02.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 03.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 04.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 05.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 06.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 07.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 08.dat
11M -rw-r--r-- 1 root root 10M  9月  3 22:38 2012 09.dat

各サーバのvolumeのディレクトリ見てみる。striped モードなので、全サーバにファイルが配置されていて、かつ実際に割り当てられている左端のサイズは半分の5Mになっているのもわかる。

$ for i in {01..04}; do ssh root@sv$i 'hostname && ls -lsh /vol2' ; done
sv01
合計 51M
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 00.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 01.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 02.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 03.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 04.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 05.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 06.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 07.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 08.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 09.dat
sv02
合計 51M
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 00.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 01.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 02.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 03.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 04.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 05.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 06.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 07.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 08.dat
5.1M -rw-r--r-- 2 root root 9.9M  9月  3 22:38 2012 09.dat
sv03
合計 51M
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 00.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 01.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 02.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 03.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 04.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 05.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 06.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 07.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 08.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 09.dat
sv04
合計 51M
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 00.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 01.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 02.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 03.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 04.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 05.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 06.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 07.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 08.dat
5.1M -rw-r--r-- 2 root root 10M  9月  3 22:38 2012 09.dat

Distributed Striped Replicated Volume

8台のサーバ(2 * 2 * 2 ) にするのでgluster peer probe でsv01 ~ sv08まで追加しておく。

# gluster volume create dist-striped-replica-volume stripe 2 replica 2 \
        sv01:/vol3 sv02:/vol3 sv03:/vol3 sv04:/vol3 \
        sv05:/vol3 sv06:/vol3 sv07:/vol3 sv08:/vol3
Creation of volume dist-striped-replica-volume has been successful. Please start the volume to access data.
# gluster volume start dist-striped-replica-volume 
Starting volume dist-striped-replica-volume has been successful
# gluster volume info dist-striped-replica-volume 
	 
Volume Name: dist-striped-replica-volume
Type: Distributed-Striped-Replicate
Volume ID: 8aa1c1da-3d5c-49d3-b045-ba15a7b2f01f
Status: Started
Number of Bricks: 2 x 2 x 2 = 8
Transport-type: tcp
Bricks:
Brick1: sv01:/vol3
Brick2: sv02:/vol3
Brick3: sv03:/vol3
Brick4: sv04:/vol3
Brick5: sv05:/vol3
Brick6: sv06:/vol3
Brick7: sv07:/vol3
Brick8: sv08:/vol3

コマンド出力結果は省略。

今までと同様に01~09の10個のファイルを作成して、各サーバの/vol3 の中を見ると、

  • まずファイルごとにグループがわかれていて(distributed)
  • かつ、ファイルサイズは半分になってて(striped)
  • 同じファイルが複製されている(replicated)
  • sv01 ~ sv04
    • 00.dat 05.dat 08.dat 09.dat
  • sv05 ~ sv08
    • 01.dat 02.dat 03.dat 04.dat 06.dat 07.dat

補足

ddで空のファイルを作ったから本当にstripedされているのかわからないけど、中身のあるデータを作ってみると、ファイルが細切れになって別々のサーバに分散されてるのがわかる。ファイルサイズ、md5sum値などを調べること。

brick (サーバ) の追加

# gluster volume add-brick volume_name new_brick
ファイルの再配置について (rebalance)

新規に追加されたサーバは既存のファイル情報を持っていないため、add-brick以前に作成されたファイルについては既存のサーバ群だけで処理することになる。(add-brick以後に作成されるファイルは、追加されたサーバを含めてハッシュで分散されて保存されるので何もしなくて良い)

手動で再配置を行う場合は、gluster volume rebalance volume_name start を実行する。

# gluster volume rebalance vol1 start
# gluster volume rebalance vol1 status
# gluster volume rebalance vol1 status
                                    Node Rebalanced-files          size       scanned      failures         status
                               ---------      -----------   -----------   -----------   -----------   ------------
                               localhost                8         1.4GB            25             0    in progress
                                    sv02                0        0Bytes            93             0      completed
# gluster volume rebalance vol1 status
                                    Node Rebalanced-files          size       scanned      failures         status
                               ---------      -----------   -----------   -----------   -----------   ------------
                               localhost               42         7.0GB           135             0      completed
                                    sv02                0        0Bytes            93             0      completed

その他

  • geo replication
  • quota
  • profile
# gluster volume profile vol1 start
# gluster volume profile vol1 info
  • status
# gluster volume status vol1
# gluster volume status vol1 detail

サーバ障害時のmount failover

データについてはreplicaを組み合わせればいいけど、特定のサーバが死んだ場合にそれをmountしているclientは接続が切れてしまう。どうしましょう。

対策

  • localhostをmountするのでサーバ障害は気にしない
  • keepalive, heartbeat などで仮想IPを設定して、そこをmountしておく
  • myDNS などを使って、名前でmountしておき、サーバが死んだらDNS Aレコードを変更する
localhostをmount

恐らくovirtがそのうちこういう構成になりそうだけど、特別なストレージを利用せず、仮想化ホストサーバ上でglusterfs を利用して仮想イメージ置き場を作る場合、gusterd == glusterfs client になる。この場合はlocalhostのglusterdをmountするようにすれば、そもそも障害を気にしなくていい。(glusterdが死ぬ==自分も死んでる)

補足: ここではglusterd プロセス障害は考えてない

keepalivedの実験

実際keepalived を使ってvipをmountするようにしてみた。まずサーバ障害時にvip はすぐ引き継がれる(keepalivedvrrpが早い)。icmp ロス1秒程度で。

その後、clientからmountしているデータにアクセスできるのには30秒程度の時間が必要だった。

おまけ : keepavlived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
     root@localhost
   }
   notification_email_from from@example.com
   smtp_server localhost
   smtp_connect_timeout 30
   router_id sv02
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 110
    priority 100
    advert_int 1
    nopreempt
    authentication {
        auth_type PASS
        auth_pass 1111
    }
   virtual_ipaddress {
        192.168.122.110/24 dev eth0
    }
}  

filesystemに関する追記

Red Hat Storageの場合、ストレージブリックのファイルシステムはLVM + XFSじゃないとサポートされないらしい。

failoverに関する追記

glusterfs native client

mount optionに"-o backupvolfile-server=server02" のような指定ができるらしい。GlusterFSだと出来なかった。Red Hat Storageのみ?

nfs, cifs

CTDBを利用すれば出来るらしい