GlusterFSを検証してみる。 (2)
今回はAuto Self-Healingを検証してみる。
全バージョンまでは手動でファイルの整合性を取っていたがこのバージョンからは pro-active selfhealing daemonが起動しており、10分間隔で修復が必要なファイルを自動的に診断、初期化するらしい。
まず、以下のシナリオを作ってみた。
シナリオ1
巨大なファイルを作成中、三台のうち1台を強制PowerOffして、1台のみデータ矛盾が生じるようにする。
データ矛盾の生じたサーバを起動、10分後に修復が必要なデータが自動的に修復されるかどうか。
シナリオ2
巨大なファイルを作成中、三台のうち1台を強制PowerOffして、1台のみデータ矛盾が生じるようにする。
ここで10分待たずにクライアントがデータ破損しているファイルにアクセスした場合、全バージョン同様データ修復を行った後にクライアントにデータを渡すかどうかを確認する。
シナリオ3
手動で修復するコマンドを実行し、即座に修復が開始されるかどうかを確認する。
シナリオ1について
データ書き込み中に1台のサーバを強制シャットダウン、その後、2台によってデータ書き込み、レプリケーションが完了した後、シャットダウンしたサーバを起動した時のGlusterFS poolデバイスのls -alの結果は以下の通り。
drw-------. 10 root root 4096 Jul 30 11:40 .glusterfs
drwx------. 2 root root 16384 Jul 30 11:33 lost+found
-rw-r--r--. 2 root root 0 Jul 30 11:51 usr.tar.gz
書き込みしたデータはusr.tar.gz。
データ矛盾を起こしていると判定されたファイルはデータサイズ0にさせるようだ。
しばらく放置していると確かに正しいファイルサイズに自動的に修正された。
-rw-r--r--. 2 root root 119814066 Jul 30 11:56 usr.tar.gz
シナリオ2について
前半までシナリオ位置と同様の手順だが、Auto Self-Healing機能が働く前に矛盾しているファイルにアクセスするとどうなるかをチェックしてみた。
矛盾したファイルアクセスするには今回、サーバとクライアントを兼務しているのでファイルの壊れたサーバにてクライアント機能(FUSE)を経由してアクセスすることでテストしてみる。
(クライアントがファイルにアクセスする際、どういうロジックでどのサーバへアクセスしに行くのかは別途検証するものとする。)
シナリオ1、データ書き込み中に1台のサーバを強制シャットダウン、その後、2台によってデータ書き込み、レプリケーションが完了した後、シャットダウンしたサーバを起動した時のGlusterFS poolデバイスのls -alの結果は以下の通り。
確かにデータは矛盾している。
gluster-sv1 (データ矛盾なし)
-rw-r--r--. 1 root root 120205989 Jul 30 12:01 usr.tar.gz
gluster-sv2(データ矛盾あり、データサイズが0になっている。)
-rw-r--r--. 2 root root 0 Jul 30 12:00 usr.tar.gz
さてこの状態でgluster-sv2のクライアント機能経由でusr.tar.gzをlocal /tmpへコピーしてみる。
従来のhealing機能が働くのであれば、データ復旧がなされ、正しいファイルサイズのデータがコピーされるはずである。
cp usr.tar.gz /tmp
ls -al /tmp/usr.tar.gz
-rw-r--r--. 1 root root 119814066 Jul 30 12:11 usr.tar.gz
正しくコピーできたようだ。
ただ、このテストを実施して分かったのだが、10分間隔でSelf-Healingが実行される、とあるが、再起動後は速やかにSelf-Healingが実行されるようだ。
(起動した直後なので、各種daemonも速やかに初期動作に移ってしまうからだろう)
という事でなかなかシナリオ1, 2のテストは困難であった。
ということで、シナリオ3は少々方法を変更して、Sealf-Healing機能をまず無効にして、データ矛盾を発生、手動復旧コマンドを実行してデータ矛盾がなくなるか?
というテストにしてみる。
まず、Self-Healingをストップする。
マニュアルにあるOptionにて制御できそうだ。
Option cluster.self-heal-daemon
Description Allows you to turn-off proactive self-heal on replicated volumes.
Default value on
上記Optionをoffにしてみる。
[root@gluster-sv1 gluster-test]# gluster volume set test-volume cluster.self-heal-daemon off
Set volume successful
確認
[root@gluster-sv3 ~]# gluster volume info all
Volume Name: test-volume
Type: Replicate
Volume ID: 76d2f5aa-b713-4d55-880e-2965d6b24398
Status: Started
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: gluster-sv1:/exp1
Brick2: gluster-sv2:/exp2
Brick3: gluster-sv3:/exp3
Options Reconfigured:
cluster.self-heal-daemon: off
network.ping-timeout: 10
それではgluster-sv1にてデータ矛盾を発生させる状況を作り出してみる。
確認事項としては、Self-Healingが無効になっているか?もあるので、障害をシミュレーションしたサーバを起動した後、15分間程度放置してデータが自動的に復旧しないことも確認する。
と思ったが、サーバ再起動後にglusterFSをmountしている領域でls -alしたところ、
-rw-r--r--. 1 root root 119814066 Jul 30 12:31 usr.tar.gz
と自動的に復旧している事が2度のテストで確認できた。
これは正直想定外。
データサイズは障害時のままになるはずなのだが。
データサイズを計る対象はGlusterFS Storage poolデバイスである/exp1~3を直接調べる方法とFUSEでマウントしているクライアントからファイルを見る2つの方法がある。
今まではFUSE経由でデータを確認していた。
そこで方法を変えて障害を起こして再起動させたgluster-sv1の/exp1をまず確認することにした。
[root@gluster-sv1 exp1]# ls -al
total 40
drwxr-xr-x. 4 root root 4096 Jul 30 12:36 .
dr-xr-xr-x. 24 root root 4096 Jul 30 12:37 ..
drw-------. 13 root root 4096 Jul 30 12:38 .glusterfs
drwx------. 2 root root 16384 Jul 30 11:33 lost+found
-rw-r--r--. 2 root root 0 Jul 30 12:34 usr.tar.gz
とすると確かにhealはされていないことが分かった。
なお、cluster.self-heal-daemon: offのままである。
次にFUSE経由でデータを確認してみる。
[root@gluster-sv1 /]# ls -al /mnt/gluster-test/
total 234056
drwxr-xr-x. 4 root root 4096 Jul 30 12:36 .
drwxr-xr-x. 3 root root 4096 Jul 27 15:58 ..
drwx------. 2 root root 16384 Jul 30 11:33 lost+found
-rw-r--r--. 1 root root 119814066 Jul 30 12:35 usr.tar.gz
とするとデータは復旧している(復旧した)ことが分かる。
cluster.self-heal-daemonパラメータに関係なくFUSE経由で対象ディレクトリにアクセスすると復旧機能が働くようだ。それも障害復旧しているファイルを直接タッチする必要もなさそうだ。
では、このパラメータを再度有効にしてFUSEでもアクセスせず、proactiveに復旧するのかどうかを試してみよう。
確認方法は ls -al /exp1 で行い、10分間待ってみたところ、数分で復旧されることが確認できた。
結局のところ、以下の2パターンでデータは復旧されるようだ。
1 FUSE経由でデータにアクセスするとデータは復旧される。
2 self-heal-daemon経由で10分間隔おきに修復機能が働き、修復される。
仮にデータ矛盾した状態で再起動したとしても1の機能も引き続き有効なので特にデータ矛盾対策をすることなく利用する事は可能だろう。
シナリオ3について
コマンドで復旧させてみよう、という試み。
コマンドは
# gluster volume heal VOLNAME all
となる。
これを実行してどうなるか、を見てみよう。
ただし、このコマンドを実行するにはcluster.self-heal-daemonが有効ではなければならない、という警告が表示されるので、改めて有効後、実行してみた。
[root@gluster-sv1 ~]# ls /exp1/ -al
total 40
drwxr-xr-x. 4 root root 4096 Jul 30 12:43 .
dr-xr-xr-x. 24 root root 4096 Jul 30 14:12 ..
drw-------. 14 root root 4096 Jul 30 12:43 .glusterfs
drwx------. 2 root root 16384 Jul 30 11:33 lost+found
-rw-r--r--. 2 root root 0 Jul 30 14:09 usr.tar.gz
(usr.tar.gz のサイズが0である事を確認。)
[root@gluster-sv1 ~]# gluster volume heal test-volume full
Heal operation on volume test-volume has been successful
[root@gluster-sv1 ~]# ls /exp1/ -al
total 117048
drwxr-xr-x. 4 root root 4096 Jul 30 12:43 .
dr-xr-xr-x. 24 root root 4096 Jul 30 14:12 ..
drw-------. 14 root root 4096 Jul 30 12:43 .glusterfs
drwx------. 2 root root 16384 Jul 30 11:33 lost+found
-rw-r--r--. 2 root root 119814066 Jul 30 14:14 usr.tar.gz
このコマンドを使えば強制的に同期できるようであった。
補足
cluster.self-heal-daemonパラメータを無効にしても障害サーバのデータはしばらくするとFUSE経由でアクセスしなくても修復されていた。
正しくは自動で修復されず、FUSE経由でアクセスした時だけデータは修復される、のはず。
という事はこのパラメータ、実装が間違えているのかそもそもの使用方法を間違えているかのどちらかになりそうだ。
補足
シナリオ2について
どうもself-healingが動作しないことがあるようだ。
あるサーバ(gluster-sv2)でFUSE経由で書き込みをしている最中に別のクライアントサーバ(gluster-sv1)を強制ダウン、アップ、10分間以上待ってもBRICKディレクトリ(この場合、/exp1)ディレクトリ内のデータ(FUSE mount内のデータではない)が修復されないようだ。
しかし、gluster-sv1のFUSE mountしている/mnt/gluster-testディレクトリのデータが修復されて見えている。
つまり、いつまでたってもgluster-sv1のlocal BRICKデータは修復されていない、という事になる。
これはよろしくない。
一応、テスト的に強制的に同期するコマンドを流してみる。
# gluster volume heal test-volume
結果、変わらず。
# gluster volume heal test-volume full
結果、変わらず。
さて、どうしたものか。(汗)
以前テストで成功した/exp2内のディレクトリデータ(.gluster lost+foundを除き)手動で削除、gluster volume heal test-volume fullも実行したが結果変わらず。
そこでheal状況を確認するコマンドがあるので実行してみた。
# gluster volume heal test-volume info healed
Heal operation on volume test-volume has been successful
Brick gluster-sv1:/exp1
Number of entries: 0
Brick gluster-sv2:/exp2
Number of entries: 2
at path on brick
-----------------------------------
571273681-12-09 11:15:29 /usr.tar.gz
Segmentation fault (core dumped)
なぜか、Segmentation faultを吐いて強制終了してしまった。
この事からも何か内部で矛盾した状態を抱えているのだろう。
まあ、検証中だしちょうど良いので修復させてみよう。
といってもあと考えられる対応方法は一度gluster-sv1をstorage poolから削除して、再度追加するという方法か。
# gluster peer detach gluster-sv1
Brick(s) with the peer gluster-sv1 exist in cluster
cluster内にgluster-sv1のbrickが残っているのでダメ
というエラーが。確かに。
それでは次にgluster-sv1のbrickを除去してみよう。
[root@gluster-sv1 exp1]# gluster volume remove-brick test-volume gluster-sv1:/exp1
Removing brick(s) can result in data loss. Do you want to Continue? (y/n) y
Removing bricks from replicate configuration is not allowed without reducing replica count explicitly.
現在のreplica数は3に設定しているからだろう。
replica数以下になるbricksに合わせてreplica数も減少させないとダメ、というエラーが表示された。
それではreplica数も2へ減らしてみよう。
# gluster volume remove-brick test-volume replica 2 gluster-sv1:/exp1
Removing brick(s) can result in data loss. Do you want to Continue? (y/n) y
Remove Brick commit force successful
確かに成功したように見える。
確認してみよう。
# gluster volume info
Volume Name: test-volume
Type: Replicate
Volume ID: 76d2f5aa-b713-4d55-880e-2965d6b24398
Status: Started
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: gluster-sv2:/exp2
Brick2: gluster-sv3:/exp3
Options Reconfigured:
network.ping-timeout: 10
確かに成功したようだ。
それでは次にgluster1 /exp1をstorage poolに復帰させてみる。
# gluster volume add-brick test-volume replica 3 gluster-sv1:/exp1
/exp1 or a prefix of it is already part of a volume
さて、面白い冗談に遭遇してしまった。
/exp1は既にvolumeの一部というエラー。
storage poolを管理するメタデータに矛盾が発生しているのだろうか。
そもそもglusterdの管理情報とvolume brick情報はどこにあるんだろうかと探してみた。
/var/lib/glusterd/vols/test-volume
にあるようだ。
その中にあるbricksをみてみると。
[root@gluster-sv1 bricks]# cd bricks
[root@gluster-sv1 bricks]# ls
gluster-sv2:-exp2 gluster-sv3:-exp3
うーむ。
ここだけを見るとtest-volumeのbrickにgluster-sv1の/exp1は存在していないように見える。
なお、test-volume内にあるinfoファイルを覗くと。
[root@gluster-sv1 test-volume]# cat info
type=2
count=2
status=1
sub_count=3
stripe_count=1
replica_count=2
version=12
transport-type=0
volume-id=76d2f5aa-b713-4d55-880e-2965d6b24398
username=a1909f25-b2f3-40c3-a9c5-89533005a291
password=b91557a1-ffbc-4fa9-918a-9a87c4f38876
network.ping-timeout=10
brick-0=gluster-sv2:-exp2
brick-1=gluster-sv3:-exp3
ちょっと探していたvolumeのreplica数も見れることが分かった。
(きっとglusterコマンドでも見れるのだろうけど。)
ここでもgluster-sv1は見当たらない。
そこでもう少し調べたところ、すでにbrickへ組み込まれたディレクトリは拡張属性を設定されており、それが邪魔をしているようだ。
[root@gluster-sv1 exp1]# attr -l /exp1/
Attribute "glusterfs.volume-id" has a 16 byte value for /exp1/
Attribute "gfid" has a 16 byte value for /exp1/
Attribute "afr.test-volume-client-0" has a 12 byte value for /exp1/
Attribute "afr.test-volume-client-1" has a 12 byte value for /exp1/
Attribute "afr.test-volume-client-2" has a 12 byte value for /exp1/
[root@gluster-sv1 exp1]# getfattr -m glusterfs.volume-id /exp1
getfattr: Removing leading '/' from absolute path names
# file: exp1
trusted.glusterfs.volume-id
[root@gluster-sv1 exp1]# getfattr -m gfid /exp1
getfattr: Removing leading '/' from absolute path names
# file: exp1
trusted.gfid
そこで以下の設定を行った。
[root@gluster-sv1 exp1]# setfattr -x trusted.glusterfs.volume-id /exp1/
[root@gluster-sv1 exp1]# setfattr -x trusted.gfid /exp1/
念のために/exp1内にあるglusterdのメタ情報が格納されていると思われるディレクトリ.glusterfsも削除。
[root@gluster-sv1 exp1]# rm -rf /exp1/.glusterfs
その後、
[root@gluster-sv1 exp1]# gluster volume add-brick test-volume replica 3 gluster-sv1:/exp1
Add Brick successful
データが復旧されているかどうかも確認。
[root@gluster-sv1 exp1]# ls -al /exp1/
total 117376
drwxr-xr-x. 5 root root 4096 Jul 31 15:03 .
dr-xr-xr-x. 24 root root 4096 Jul 31 12:21 ..
drw-------. 18 root root 4096 Jul 31 14:53 .glusterfs
drwx------. 2 root root 16384 Jul 30 11:33 lost+found
drwxr-xr-x. 13 root root 4096 Jul 27 11:46 usr
-rw-r--r--. 2 root root 120141688 Jul 31 12:29 usr.tar.gz
ということで見事にstorage poolに/exp1 brickを再追加することが出来た。
どうやらこの問題はGlusterFS3.3ではFAQのようだ。
これはstorage poolからbrickを削除する時に/exp1の拡張属性もクリーニングすべきであるので明らかな仕様ミスだと思う。
とここまで書いたが。
もう一度改めて再起動テストを実施したところ、問題なくreplicationできていた。
ま、切り離し、切り戻し手順が確立出来たのでよしとしよう。
ということで、きょうはここまで。