猫の手なら貸せる

いろいろ共有できたらいいなとおもってます

ラズパイで分散ファイルシステム(GlusterFS)を試した

f:id:nkhnd:20210324011718p:plain

以前うちの環境の見直しを行った続きです。

nkhnd.hatenablog.jp

分散ファイルシステムを使おう、ということでその一つであるGlusterFSを導入しました。それはもう驚くほど簡単でした。

本当はCephを使うべきなんでしょうけど家庭内でファイルのバックアップを取ったりメディアの取り出し・保存をするくらいならこれくらいが十分なのかなと。

シナリオ

今回はrasp3に1TBのディスクが2枚、rasp2に2TBのディスクが一枚刺さっていて、rasp3で作成->rasp2を追加->rasp3を停止->rasp2のみ残る、という工程を実施しました。

rasp3を再構築する必要が生まれてしまったので...という話は置いておいて、そんな感じでやっていきます。

登場人物

  • RaspberryPi 4B x2(Ubuntu 20.04 LTS)
  • 3.5インチHDD x2(1TBと2TB)
  • 2.5インチHDD x1(2TB)

Raspbianではないのはなぜかと言いますとRaspbianである必要がないからです。

Ubuntuである必要はあります(microk8sがcannonical製なので情報が多い・cloudinitが利用できて楽など。)

セットアップ

SDカードへの書き込みやCloudinitについてはサーバ構築の際に説明するため、ここでは割愛します。

ディスクの初期化

ディスクをラズパイに接続し、lsblkコマンドで認識を確認します。

root@rasp3:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0         7:0    0  48.9M  1 loop /snap/core18/1949
loop1         7:1    0  61.6M  1 loop /snap/lxd/19040
loop2         7:2    0    27M  1 loop /snap/snapd/10709
sda           8:0    0 931.5G  0 disk 
sdb           8:16   0 931.5G  0 disk 
mmcblk0     179:0    0  29.7G  0 disk 
├─mmcblk0p1 179:1    0   256M  0 part /boot/firmware
└─mmcblk0p2 179:2    0  29.5G  0 part /

sdaとsdbに接続済みです。これらのディスクの初期化を行います。gdiskwipefsコマンドでディスクのパーティション情報を削除します。

root@rasp3:~# gdisk /dev/sda 
GPT fdisk (gdisk) version 1.0.5

Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries in memory.

Command (? for help): p
Disk /dev/sda: 1953525168 sectors, 931.5 GiB
Model: External HDD    
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 2EED82D4-8AD5-430D-A9D3-5D33BBB907A6
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 1953525134
Partitions will be aligned on 2048-sector boundaries
Total free space is 1953525101 sectors (931.5 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.
root@rasp3:~# wipefs /dev/sda
DEVICE OFFSET       TYPE UUID LABEL
sda    0x200        gpt       
sda    0xe8e0db5e00 gpt       
sda    0x1fe        PMBR
# パーティション情報を削除
root@rasp3:~# wipefs /dev/sda -a
/dev/sda: 8 bytes were erased at offset 0x00000200 (gpt): 45 46 49 20 50 41 52 54
/dev/sda: 8 bytes were erased at offset 0xe8e0db5e00 (gpt): 45 46 49 20 50 41 52 54
/dev/sda: 2 bytes were erased at offset 0x000001fe (PMBR): 55 aa
/dev/sda: calling ioctl to re-read partition table: Success

xfsフォーマットで初期化します。GlusterFSではxfs形式が推奨されているためです。

root@rasp3:~# mkfs -t xfs /dev/sda
meta-data=/dev/sda               isize=512    agcount=4, agsize=61047662 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=244190646, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=119233, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

以上で初期化完了です。/dev/sdbに対しても同様に実施します。

fstab・マウントを実施

/dev/sda/dev/sdbなどをfstabに書くとマウントに失敗することがあるので、blkidコマンドでUUID情報を確認します。

root@rasp3:# blkid
(省略)
/dev/sdb: UUID="AAAAAAAAAAAAAAAAAAAAAAAA" TYPE="xfs"
/dev/sda: UUID="BBBBBBBBBBBBBBBBBBBBBBBBB" TYPE="xfs"

# マウントポイントの作成
root@rasp3:/# mkdir -p gluster/25inch gluster/35inch

# UUIDを指定してfstabに記述
root@rasp3:/gluster# cat /etc/fstab 
LABEL=writable   /    ext4   defaults    0 0
LABEL=system-boot       /boot/firmware  vfat    defaults        0       1

UUID= AAAAAAAAAAAAAAAAAAAAAAAA   /gluster/25inch xfs defaults,nofail 1  2
UUID=BBBBBBBBBBBBBBBBBBBBBBBBB   /gluster/35inch xfs defaults,nofail 1  2

# エラーなくマウントが完了
root@rasp3:~# mount -a
root@rasp3:~# df
Filesystem     1K-blocks    Used Available Use% Mounted on
(略)
/dev/sda       976285652 6839812 969445840   1% /gluster/35inch
/dev/sdb       976285652 1005456 975280196   1% /gluster/25inch

GlusterFSの導入

前準備

名前解決できるようにあらかじめ/etc/hostsにホストを追加します。

root@rasp3:~# cat /etc/hosts
127.0.0.1 localhost
(省略)
192.168.3.11 rasp1
192.168.3.12 rasp2
192.168.3.13 rasp3

glusterdを実行します。

root@rasp3:~# systemctl start glusterd
root@rasp3:~# systemctl status glusterd
● glusterd.service - GlusterFS, a clustered file-system server
     Loaded: loaded (/lib/systemd/system/glusterd.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2021-03-21 22:52:27 JST; 1min 29s ago
(省略)
root@rasp3:~# systemctl enable glusterd

ボリュームの作成

brickするディレクトリを作成し、glusterコマンドでボリュームを作成します。

root@rasp3:/gluster# mkdir -p 25inch/brick 35inch/brick
root@rasp3:/gluster# gluster vol create gv1 rasp3:/gluster/25inch/brick/ rasp3:/gluster/35inch/brick/
volume create: gv1: success: please start the volume to access data

# 確認
root@rasp3:/gluster# gluster vol info
 
Volume Name: gv1
Type: Distribute
Volume ID: eccdfd18-3407-417b-8b2d-9231b80a4641
Status: Created
Snapshot Count: 0
Number of Bricks: 2
Transport-type: tcp
Bricks:
Brick1: rasp3:/gluster/25inch/brick
Brick2: rasp3:/gluster/35inch/brick
Options Reconfigured:
transport.address-family: inet
storage.fips-mode-rchecksum: on
nfs.disable: on

作成したボリュームを開始します。

root@rasp3:/# gluster vol start gv1
volume start: gv1: success

これでボリュームはできあがりです。

GlusterFSでマウントしてみる

glusterfs-clientをインストールしたクライアントでマウントを実施すると利用ができるようです。

root@rasp3:/# mount -t glusterfs rasp3:/gv1 /mnt
root@rasp3:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.9G     0  1.9G   0% /dev
tmpfs           380M  4.0M  376M   2% /run
/dev/mmcblk0p2   29G  2.6G   26G  10% /
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
tmpfs           380M     0  380M   0% /run/user/1000
/dev/mmcblk0p1  253M  120M  133M  48% /boot/firmware
/dev/sdb        932G  982M  931G   1% /gluster/25inch
/dev/sda        932G  6.6G  925G   1% /gluster/35inch
rasp3:/gv1      1.9T   27G  1.8T   2% /mnt

root@rasp3:/# cd /mnt/
root@rasp3:/mnt# touch test
root@rasp3:/mnt# ls -al
total 8
drwxr-xr-x  3 root root 4096  321 23:31 .
drwxr-xr-x 21 root root 4096  321 23:24 ..
-rw-r--r--  1 root root    0  321 23:31 test

Glusterクラスタの追加

Glusterクラスタを追加しストレージプールの拡張を行います。

ノード追加

glusterコマンドでノードを追加します。

# Peerは0
root@rasp3:/# gluster peer status
Number of Peers: 0

# 追加
root@rasp3:/# gluster peer probe rasp2
peer probe: success. 
root@rasp3:/# gluster peer status
Number of Peers: 1

Hostname: rasp2
Uuid: XXXXXXXXXXXXXXXXXXXXXXX
State: Peer in Cluster (Connected)

rasp2で確認してもrasp3が追加されていることが確認できます。

root@rasp2:~# gluster peer status
Number of Peers: 1

Hostname: 192.168.3.13
Uuid: 1d8c172b-5399-4e1f-9396-7de1f5094dbb
State: Peer in Cluster (Connected)

brickの追加

gluster vol add-brickで追加します。あらかじめ追加するbrickは作成しておきます。

root@rasp2:/gluster# gluster vol add-brick gv1 rasp2:/gluster/35inch/brick/
volume add-brick: success
root@rasp2:/gluster# gluster vol info
 
Volume Name: gv1
Type: Distribute
Volume ID: eccdfd18-3407-417b-8b2d-9231b80a4641
Status: Started
Snapshot Count: 0
Number of Bricks: 3
Transport-type: tcp
Bricks:
Brick1: rasp3:/gluster/25inch/brick
Brick2: rasp3:/gluster/35inch/brick
Brick3: rasp2:/gluster/35inch/brick
Options Reconfigured:
transport.address-family: inet
storage.fips-mode-rchecksum: on
nfs.disable: on

brickの再配置

追加が完了したらファイルの再配置を行います。

root@rasp2:/gluster# gluster vol rebalance gv1 start
volume rebalance: gv1: success: Rebalance on gv1 has been started successfully. Use rebalance status command to check status of the rebalance process.
ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

再配置はバックグラウンドで実施されgluster vol rebalance <volume-name> statusで進捗を確認することが可能です。

root@rasp2:/gluster# gluster vol rebalance gv1 status
                                    Node Rebalanced-files          size       scanned      failures       skipped               status  run time in h:m:s
                               ---------      -----------   -----------   -----------   -----------   -----------         ------------     --------------
                            192.168.3.13              284       741.3MB           876             0            65          in progress        0:00:46
                               localhost                0        0Bytes             0             0             0            completed        0:00:00
The estimated time for rebalance to complete will be unavailable for the first 10 minutes.
volume rebalance: gv1: success

Glusterクラスタの除外

追加したGlusterクラスタを除外します。

brickの再配置

先にcluster.force-migrationがoffであることを確認します。 これをoffにしておかないと、再配置中に変更されたファイルも無理やり再配置が行われてしまい、ファイルが破損する可能性があるためです。

root@rasp3:~# gluster volume get gv1 cluster.force-migration
Option                                  Value                                   
------                                  -----                                   
cluster.force-migration                 off  

確認後はgluster vol remove-brickでbrickを削除します。以下はrasp3にある2つのbrickを除去しています。

root@rasp3:~# gluster vol remove-brick gv1 rasp3:/gluster/35inch/brick/ rasp3:/gluster/25inch/brick/ start
It is recommended that remove-brick be run with cluster.force-migration option disabled to prevent possible data corruption. Doing so will ensure that files that receive writes during migration will not be migrated and will need to be manually copied after the remove-brick commit operation. Please check the value of the option and update accordingly. 
Do you want to continue with your current cluster.force-migration settings? (y/n) y
volume remove-brick start: success
ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

再配置はバックグラウンドで実施され、上記のコマンドをstatusに変更することで進捗を確認することが可能です。

root@rasp3:~# gluster vol remove-brick gv1 rasp3:/gluster/35inch/brick/ rasp3:/gluster/25inch/brick/ status
                                    Node Rebalanced-files          size       scanned      failures       skipped               status  run time in h:m:s
                               ---------      -----------   -----------   -----------   -----------   -----------         ------------     --------------
                               localhost              158       348.3MB           630             0             0          in progress        0:00:30
The estimated time for rebalance to complete will be unavailable for the first 10 minutes.
(時間経過)
root@rasp3:~# gluster vol remove-brick gv1 rasp3:/gluster/35inch/brick/ rasp3:/gluster/25inch/brick/ status
                                    Node Rebalanced-files          size       scanned      failures       skipped               status  run time in h:m:s
                               ---------      -----------   -----------   -----------   -----------   -----------         ------------     --------------
                               localhost            84223       585.1GB         92623             0             0            completed        5:07:54

再配置の確定

再配置が終わった時点で除外されたbrickにはデータは残っていないことが確認できます。

root@rasp3:~# du -sh /gluster/25inch/ /gluster/35inch/
2.4M   /gluster/25inch/
2.4M   /gluster/35inch/
root@rasp3:~# du -sh /gluster/25inch/ /gluster/35inch/
2.4M   /gluster/25inch/
2.4M   /gluster/35inch/
root@rasp3:~# find /gluster/25inch/ -type f -print 
/gluster/25inch/brick/.glusterfs/health_check
root@rasp3:~# find /gluster/35inch/ -type f -print 
/gluster/35inch/brick/.glusterfs/health_check

最後にcommitを行って再配置を確定します。

root@rasp3:~# gluster vol remove-brick gv1 rasp3:/gluster/35inch/brick/ rasp3:/gluster/25inch/brick/ commit
volume remove-brick commit: success
Check the removed bricks to ensure all files are migrated.
If files with data are found on the brick path, copy them via a gluster mount point before re-purposing the removed brick. 

ボリュームも確認します。Bricksからデータが除外されていれば完了です。

root@rasp3:~# gluster vol info
 
Volume Name: gv1
Type: Distribute
Volume ID: eccdfd18-3407-417b-8b2d-9231b80a4641
Status: Started
Snapshot Count: 0
Number of Bricks: 1
Transport-type: tcp
Bricks:
Brick1: rasp2:/gluster/35inch/brick
Options Reconfigured:
performance.client-io-threads: on
nfs.disable: on
storage.fips-mode-rchecksum: on
transport.address-family: inet

fstabを書き換え、マウントしていたディスクを外します。

root@rasp3:/# vi /etc/fstab 
root@rasp3:/# umount /gluster/
/gluster/25inch   /gluster/35inch   
root@rasp3:/# umount /gluster/25inch /gluster/35inch 

ノード削除

(追記のためホスト名が変わっていますが、方法に変わりはありません)

現在以下の状態です。rasp3=192.168.3.254のノードになります。

root@rasp1:~# gluster peer status
Number of Peers: 2

Hostname: rasp2.nyan.local
Uuid: f5ac7c62-5072-4d57-9e1b-1dd1814f0b50
State: Peer in Cluster (Connected)

Hostname: 192.168.3.254
Uuid: 14d5b858-0904-4f52-a46e-6db4a0ceb666
State: Peer in Cluster (Connected)

192.168.3.254はbrick撤去済みで、ノードから削除可能なため、これをクラスタから除外します。

root@rasp1:~# gluster peer detach 192.168.3.254
All clients mounted through the peer which is getting detached need to be remounted using one of the other active peers in the trusted storage pool to ensure client gets notification on any changes done on the gluster configuration and if the same has been done do you want to proceed? (y/n) y
peer detach: success

除外されると、statusの表示に表示されなくなります。

root@rasp1:~# gluster peer status
Number of Peers: 1

Hostname: rasp2.nyan.local
Uuid: f5ac7c62-5072-4d57-9e1b-1dd1814f0b50
State: Peer in Cluster (Connected)

以上で設定完了です。

/etc/fstabの設定

マウントの自動化をすることができます。backup-volfile-serversにサーバを追加してく感じです。

192.168.3.21:/gvol /gluster glusterfs defaults,_netdev,backup-volfile-servers=192.168.3.22:192.168.3.23 1 2

終わりに

驚くほど簡単でした。そもそも分散処理をファイル単位で実施しているので、mdadmのようなそこの見えなさもなければCephのような複雑さもありません。

性能はともかく、非常にコンパクトなシステムで小規模環境には十分かと思いました。

これから設計の見直しやreplicatedのディスクなどを設定し直します。その話はまた別の記事にしようと思います。

参考

とても参考になりました。感謝....

Ubuntu 20.04 LTS : GlusterFS : インストール : Server World

sites.google.com

dogmap.jp

sononi.com

serverfault.com