めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

GlusterFSの気になるあれこれ

2011/10/23 執筆中。随時、追記していきます。

GlusterFSとは

GlusterFSって何?という方は、まずはこちらを参照ください。

これらを読めば分かるように、GlusterFSを使用すると、非常にシンプルに分散ファイルシステムをつくりあげることができます。一方、シンプルな仕組みだからこそ、「こんな時は、いったいどんな風になるの?」という素朴な疑問もわいてきます。

そんな素朴な疑問を実機確認しながら見ていきます。

(参考)RHELonEC2でGlusterFSを利用してみる

事前準備

RHEL6用のGlusterFSがEPELに含まれているので、これを利用して3ノードのGlusterFSをさくっと構築しておきます。

gluster01, gluster02, gluster03の3ノードで以下の準備をします。

EPELのリポジトリ準備

# yum -y localinstall http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm

GlusterFSのRPMを導入して、デーモンを起動

# yum install glusterfs-server glusterfs-fuse
# chkconfig glusterd on
# service glusterd start

これで導入完了。

gluster01を作業用ノードとします。ここから、他の2ノードをpeer登録してクラスタを構成します。

[root@gluster01 ~]# gluster peer probe gluster02
Probe successful
[root@gluster01 ~]# gluster peer probe gluster03
Probe successful
[root@gluster01 ~]# gluster peer status
Number of Peers: 2

Hostname: gluster02
Uuid: a4658b45-d431-4458-adce-1c7351054da0
State: Peer in Cluster (Connected)

Hostname: gluster03
Uuid: c1927294-86ae-4f0b-9eda-ff2f1bab6e77
State: Peer in Cluster (Connected)

ファイルのリネーム

GlusterFSでは、ファイル名のハッシュ値で、ファイルが保存されるノード(ブリック)が決まります。

じゃあ、ファイルをリネームして、保存ノードが変わったらどうなるの・・・???? ファイルをわざわざノード間で移動するの?

結論を先に言うと、わざわざノード間で移動しません。新しいノード上には、オリジナルのノードへのリンク情報を持ったダミーファイルが作成されます。クライアントがハッシュ計算で新しいノードを見に行くと、リンクがあるので、それを見てオリジナルのノードにアクセスします。

実際にやってみます。

まず、gluster01とgluster02の2ノードのブリックを使ったボリュームdata00を作成して、/mnt/data00にマウントします。

[root@gluster01 ~]# mkdir /disk01/brick01
[root@gluster01 ~]# ssh gluster02 mkdir /disk01/brick01
[root@gluster01 ~]# ssh gluster03 mkdir /disk01/brick01
[root@gluster01 ~]# gluster volume create data00 gluster01:/disk01/brick01 gluster02:/disk01/brick01
Creation of volume data00 has been successful. Please start the volume to access data.
[root@gluster01 ~]# gluster volume start data00
Starting volume data00 has been successful
[root@gluster01 ~]# gluster volume info data00

Volume Name: data00
Type: Distribute
Status: Started
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: gluster01:/disk01/brick01
Brick2: gluster02:/disk01/brick01
[root@gluster01 ~]# mkdir /mnt/data00
[root@gluster01 ~]# mount -t glusterfs localhost:/data00 /mnt/data00

file100.txt〜file199.txtを作成して、それぞれのノードに分散保存されることを確認します。

[root@gluster01 ~]# for a in $(seq 100 199);do date > /mnt/data00/file$a.txt;done
[root@gluster01 ~]# ls /disk01/brick01/
file106.txt  file116.txt  file126.txt  file145.txt  file160.txt  file176.txt  file195.txt
file107.txt  file118.txt  file127.txt  file146.txt  file161.txt  file180.txt  file197.txt
file108.txt  file119.txt  file130.txt  file150.txt  file167.txt  file183.txt  file198.txt
file109.txt  file121.txt  file134.txt  file153.txt  file170.txt  file185.txt  file199.txt
file112.txt  file122.txt  file138.txt  file155.txt  file171.txt  file187.txt
file113.txt  file123.txt  file139.txt  file156.txt  file172.txt  file188.txt
file114.txt  file124.txt  file142.txt  file157.txt  file174.txt  file190.txt
file115.txt  file125.txt  file144.txt  file158.txt  file175.txt  file193.txt

[root@gluster02 ~]# ls /disk01/brick01/
file100.txt  file117.txt  file136.txt  file151.txt  file166.txt  file182.txt
file101.txt  file120.txt  file137.txt  file152.txt  file168.txt  file184.txt
file102.txt  file128.txt  file140.txt  file154.txt  file169.txt  file186.txt
file103.txt  file129.txt  file141.txt  file159.txt  file173.txt  file189.txt
file104.txt  file131.txt  file143.txt  file162.txt  file177.txt  file191.txt
file105.txt  file132.txt  file147.txt  file163.txt  file178.txt  file192.txt
file110.txt  file133.txt  file148.txt  file164.txt  file179.txt  file194.txt
file111.txt  file135.txt  file149.txt  file165.txt  file181.txt  file196.txt

gluster01に作成されたファイル、gluster02に作成されたファイルをそれぞれ適当にリネームしてみます。

[root@gluster01 ~]# mv /mnt/data00/file106.txt /mnt/data00/file206.txt
[root@gluster01 ~]# mv /mnt/data00/file107.txt /mnt/data00/file207.txt

[root@gluster01 ~]# mv /mnt/data00/file100.txt /mnt/data00/file200.txt
[root@gluster01 ~]# mv /mnt/data00/file101.txt /mnt/data00/file201.txt

まちがって、ブリック上のファイルを直接リネームしないように。。。GlusterFSとしてマウントした方でリネームしてください。

結果を見ると、file207.txtがgluster02に移動して、file200.txtがgluster01に移動したようです。

次のように、元のノードのファイルがリネームされると同時に、相手ノードにファイルサイズ0の同名ファイルができています。

[root@gluster01 /]# ls -l /disk01/brick01/file207.txt
-rw-r--r--. 1 root root 43 10月 23 16:19 2011 /disk01/brick01/file207.txt
[root@gluster01 /]# ssh gluster02 ls -l /disk01/brick01/file207.txt
---------T. 1 root root 0 10月 23 16:20 2011 /disk01/brick01/file207.txt

[root@gluster01 /]# ls -l /disk01/brick01/file200.txt 
---------T. 1 root root 0 10月 23 16:45 2011 /disk01/brick01/file200.txt
[root@gluster01 /]# ssh gluster02 ls -l /disk01/brick01/file200.txt 
-rw-r--r--. 1 root root 43 10月 23 16:19 2011 /disk01/brick01/file200.txt

GlusterFSでは、ファイルの拡張属性にさまざまなメタ情報を記録しています。ファイルサイズ0のファイルの拡張属性を見ると、本体へのリンク情報が入っています。

[root@gluster01 /] # ssh gluster02 getfattr -d -m . /disk01/brick01/file207.txt 
getfattr: Removing leading '/' from absolute path names
# file: disk01/brick01/file207.txt
security.selinux="unconfined_u:object_r:default_t:s0
trusted.gfid=0sj3QA5n6STBSESrT6pJW5dw==
trusted.glusterfs.dht.linkto="data00-client-0

[root@gluster01 /]# getfattr -d -m . /disk01/brick01/file200.txt 
getfattr: Removing leading '/' from absolute path names
# file: disk01/brick01/file200.txt
security.selinux="unconfined_u:object_r:default_t:s0
trusted.gfid=0sJ06VrvJfRYyp2LSM+CImeg==
trusted.glusterfs.dht.linkto="data00-client-1

上記の"trusted.glusterfs.dht.linkto"がリンク情報で、"-client-<ノード番号>"が記録されています。

ボリュームの拡張

GlusterFSは、ボリュームを構成するブリックを追加して、動的にボリュームを拡張することができます。当然ながら、ブリックが増えるとハッシュ計算が変わって、ファイルの配置が変わります。ファイルの配置変更を動的にやることって可能なんでしょうか?

実際にやってみます。

先に作成したボリュームdata00に、gluster03のブリックを追加します。

[root@gluster01 /]# ssh gluster03 mkdir /disk01/brick01
[root@gluster01 /]# gluster volume add-brick data00 gluster03:/disk01/brick01

実は、追加しただけでは、ハッシュ計算の変更は行われません。いままで通りに、gluster01とgluster02のブリックのみが使用され続けます。


次のように新しいファイルを追加しても、gluster03のブリックには何も保存されません。

[root@gluster01 ~]# for a in $(seq 300 399);do date > /mnt/data00/file$a.txt;done

明示的にrebalance処理を実行することで、ファイルの配置変更とハッシュ計算の変更が行われます。

・・・って、rebalanceの実行中は、どうなるの? 動的なrebalanceって、難しくない?

という疑問に答えるために、rebalanceを開始して、即座に一時中止してみます。

[root@gluster01 ~]# gluster volume rebalance data00 start; gluster volume rebalance data00 stop
starting rebalance on volume data00 has been successful
stopped rebalance process of volume data00 
(after rebalancing 0 files totaling 0 bytes)

この時、gluster03のブリックの中を見ると、例のリンクファイルが作成されています。

[root@gluster03 ~]# ls -l /disk01/brick01/
合計 4
---------T. 1 root root 0 10月 23 17:35 2011 file175.txt

そうなんです、rebalanceを開始すると、まずは、新しいファイル配置にあわせて、例のリンクファイルを作りまくります。で、リンクファイルが全部できたところで、ハッシュ計算の変更をクライアントに通知します。

この後、ゆっくりと、実際にファイルを移動して、移動が終わったらリンクファイルを削除します。移動前のファイルは、リンクによって正しくアクセスできるので心配ありません。万一、移動中にオリジナルファイルに書き込みがはいった場合は、ファイルの移動をやめて、リンクファイルをそのまま残します。

実際に、さらに5秒ほどrebalance処理を進めて、また中断してみます。

[root@gluster01 ~]# gluster volume rebalance data00 start; sleep 5;gluster volume rebalance data00 stop
starting rebalance on volume data00 has been successful
stopped rebalance process of volume data00 
(after rebalancing 131 files totaling 5633 bytes)

この時、gluster03のブリックを見ると、移動前のリンクファイルと移動が終わったファイルが入り乱れています。

[root@gluster03 ~]# ls -l /disk01/brick01/
合計 432
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file102.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file103.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file113.txt
---------T. 1 root root  0 10月 23 17:37 2011 file120.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file122.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file124.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file127.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file129.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file134.txt
---------T. 1 root root  0 10月 23 17:37 2011 file136.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file137.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file140.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file142.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file144.txt
---------T. 1 root root  0 10月 23 17:37 2011 file154.txt
-rw-r--r--. 1 root root 43 10月 23 17:37 2011 file156.txt
---------T. 1 root root  0 10月 23 17:37 2011 file162.txt
---------T. 1 root root  0 10月 23 17:37 2011 file166.txt
(以下略)

この後、rebalance処理を最後まで実行すれば、きれいな状態になります。

[root@gluster01 ~]# gluster volume rebalance data00 start

※先のリネーム処理によって作成されたリンクは、rebalance処理では移動されないようです。

特定ブリックを使い切った場合

ストライピング構成にした場合は、すべてのブリックが均等に使用されます。したがって、最初にブリックの容量をそろえておけば、特定のブリックだけを先に使い切ることはありません。

一方、ストライピングしない、ファイル単位の分散の場合は大容量ファイルが保存されたブリックが先に使用量100%になることがあります。この場合は残念ながら、使用量100%のブリックのファイルに書きこみを行うと容量不足でエラーになります。

この例では、ボリューム全体(/mnt/data01)としては空き容量がありますが、gluster01のブリック(/disk01)は100%なので、そちらにあるファイルに書きこむとエラーになります。

[root@gluster01 ~]# ls -l /mnt/data01
合計 93901
-rw-r--r-- 1 root root 45694976 11月 19 14:23 2011 bigfile01
-rw-r--r-- 1 root root 50454560 11月 19 14:23 2011 bigfile02

[root@gluster01 ~]# cat /mnt/data01/bigfile01 >> /mnt/data01/bigfile02

cat: 書き込みエラー: デバイスに空き領域がありません
cat: 書き込みエラー: デバイスに空き領域がありません

[root@gluster01 ~]# df
Filesystem           1K-ブロック    使用   使用可 使用% マウント位置
/dev/vda2              4128448   1751404   2167332  45% /
tmpfs                   510788         0    510788   0% /dev/shm
/dev/vda1               198337     26718    161379  15% /boot
/dev/vda4                99553     99553         0 100% /disk01
localhost:/data01      1131520    133632    945408  13% /mnt/data01

一方、gluster02に保存されたファイルには、まだ書き込みができます。

[root@gluster01 ~]# cat /mnt/data01/bigfile01 >> /mnt/data01/bigfile03

[root@gluster01 ~]# ssh gluster02 ls -l /disk01/brick01/
合計 44628
-rw-r--r-- 1 root root 45695019 11月 19 14:26 2011 bigfile03

[root@gluster01 ~]# ssh gluster02 df
Filesystem           1K-ブロック    使用   使用可 使用% マウント位置
/dev/vda2              4128448   1748604   2170132  45% /
tmpfs                   510788         0    510788   0% /dev/shm
/dev/vda1               198337     26718    161379  15% /boot
/dev/vda4              1032056     78688    900904   9% /disk01