GlusterFS vs. LizardFS ベンチマークテスト

## 1. 要約
このの記事では、GlusterFS と LizardFS のベンチマークテストを投稿します。
内容は、ミニマムなレプリケーション構成における、ファイル処理速度のベンチマークテストの一例とします。

## 2. はじめに
以前の記事で、[GlusterFS による分散ファイルシステムの構築例](https://qiita.com/KyojiOsada/items/aa38868c0bbc057ab4e4) や [LizardFS による分散ファイルシステムの構築例](https://qiita.com/KyojiOsada/items/d561cba228d93830e103) を投稿しました。
今回の記事では、GlusterFS と LizardFS のミニマムなレプリケーション構成における、ファイル処理速度のベンチマークテストの一例を投稿します。
この記事では、はじめにベンチマークテストスコアを明示し、透明性確保のためにその後で環境、設計、構築、設定、プログラム内容などを示します。
テストプログラムについては Go 言語で書きましたが、環境、設計、設定、条件、対象、状態などによって結果は変化しますので、あくまで参考値としてご覧ください。

## 3. ベンチマークテスト
### 3-1. テストフロー
```
1.  1 MB テキストコンテンツ生成
2.  GlusterFS 1,000 ファイル作成
3.  GlusterFS 1,000 ファイルに 1 MB テキストコンテンツ書込
4.  GlusterFS 1,000 ファイル読込
5.  GlusterFS 1,000 ファイル削除
6.  2 ~ 5 までの GlusterFS の処理速度を算出
7.  LizardFS 1,000 ファイル作成
8.  LizardFS 1,000 ファイルに 1 MB テキストコンテンツ書込
9.  LizardFS 1,000 ファイル読込
10. LizardFS 1,000 ファイル削除
11. 7 ~ 10 までの LizardFS の処理速度を算出  
12. 2 ~ 11 まで 10 回繰り返し
13. GlusterFS と LizardFS の各平均処理速度算出
```

### 3-2. テストスコア
このテストケースでは、LizardFS が GlusterFS より平均 14.5 秒速く処理を完了させています。

```
[0] GlusterFS: 35.833152222s
[0] LizardFS: 20.886616039s
[1] GlusterFS: 34.738371173s
[1] LizardFS: 20.062726523s
[2] GlusterFS: 34.375860453s
[2] LizardFS: 20.165206392s
[3] GlusterFS: 34.798906197s
[3] LizardFS: 20.077196137s
[4] GlusterFS: 34.988998509s
[4] LizardFS: 20.31467629s
[5] GlusterFS: 34.317651101s
[5] LizardFS: 20.670571343s
[6] GlusterFS: 34.674644516s
[6] LizardFS: 20.772529652s
[7] GlusterFS: 34.884337316s
[7] LizardFS: 20.684694363s
[8] GlusterFS: 34.709297641s
[8] LizardFS: 19.803402018s
[9] GlusterFS: 34.827282062s
[9] LizardFS: 19.854092583s
GlusterFS Average: 34.814850119s
LizardFS Average: 20.329171134s
```

## 4. 環境
* RHEL 7 系
 * 2 vCPU
 * 4GB RAM
 * xfs
* GlusterFS 4.1.5
* LizardFS 3.13.0-rc1
* Go 1.9

## 5. 設計
* GlusterFS サーバー x 2
  * gluster-server1
  * gluster-server2
* GlusterFS クライアント x 2
  * gluster-client1
  * gluster-client2
* LizardFS マスター x 3
  * mfs-master1
  * mfs-master2
  * mfs-master3
* LizardFS チャンクサーバー x 2
  * mfs-chunk1
  * mfs-chunk2
* LizardFS クライアント x 2
  * mfs-client1
  * mfs-client2

## 6. GlusterFS 構築
### 6-1. GlusterFS サーバーインストール
@ gluster-server1, 2
`$ sudo yum -y install centos-release-gluster`
`$ sudo yum -y install glusterfs-server`

### 6-2. GlusterFS サーバー起動
@ gluster-server1, 2
`$ sudo systemctl start glusterd`
`$ sudo systemctl status glusterd`

### 6-3. GlusterFS サーバー hosts 設定
@ gluster-server1, 2
`$ sudo vim /etc/hosts`

```conf:/etc/hosts
10.0.0.1    gluster-server1 mfs-chunk1
10.0.0.2    gluster-server2 mfs-chunk2
10.0.0.3    gluster-client1 mfs-client1
10.0.0.4    gluster-client2 mfs-client2
10.0.0.5    mfs-master1
10.0.0.6    mfs-master2
10.0.0.7    mfs-master3
10.0.0.8    mfs-cluster
```

### 6-4. GlusterFS サーバーストレージプール設定
@ gluster-server1
`$ sudo gluster peer probe gluster-server2`

### 6-5. GlusterFS サーバーストレージプール確認
@ gluster-server1, 2
`$ sudo gluster peer status`
`$ sudo mkdir /mnt/glusterfs`

### 6-6. GlusterFS サーバーボリューム作成
@ gluster-server1
`$ sudo gluster volume create gluster-server replica 2 gluster-server1:/mnt/glusterfs/ gluster-server2:/mnt/glusterfs/ force`

### 6-7. GlusterFS サーバーボリューム情報確認
@ gluster-server1, 2
`$ sudo gluster volume info`

### 6-8. GlusterFS サーバーボリューム起動
@ gluster-server1
`$ sudo gluster volume start gluster-server`

### 6-9. GlusterFS ボリューム状態確認
@ gluster-server1, 2
`$ sudo gluster volume status`

### 6-10. GlusterFS クライアントインストール
@ gluster-client1, 2
`$ sudo yum -y install glusterfs glusterfs-fuse glusterfs-rdma`

### 6-11. GlusterFS クライアント hosts 設定
@ gluster-client1, 2
`$ sudo vim /etc/hosts`

```conf:/etc/hosts
10.0.0.1    gluster-server1 mfs-chunk1
10.0.0.2    gluster-server2 mfs-chunk2
10.0.0.3    gluster-client1 mfs-client1
10.0.0.4    gluster-client2 mfs-client2
10.0.0.5    mfs-master1
10.0.0.6    mfs-master2
10.0.0.7    mfs-master3
10.0.0.8    mfs-cluster
```

### 6-12. GlusterFS クライアントマウント
@ gluster-client1
`$ sudo mkdir /mnt/gluster-client`
`$ sudo mount -t glusterfs gluster-server1:/gluster-server /mnt/gluster-client`
`$ sudo df -Th`

@ gluster-client2
`$ sudo mkdir /mnt/gluster-client`
`$ sudo mount -t glusterfs gluster-server2:/gluster-server /mnt/gluster-client`
`$ sudo df -Th`

## 7. LizardFS 構築
### 7-1. LizardFS サーバーダウンロード
[LizardFS ダウンロードページ](http://lizardfs.com/download/)
@ mfs-master1, 2, 3
`$ sudo mkdir /usr/local/src/lizardfs`
`$ sudo cd /usr/local/src/lizardfs`
`$ sudo wget https://lizardfs.com/wp-content/uploads/2018/07/lizardfs-bundle-CentOS-7.5.1804.tar `

### 7-2. LizardFS サーバーインストール
@ mfs-master1, 2, 3
`$ sudo tar -xvf lizardfs-bundle-CentOS-7.5.1804.tar`
`$ sudo cd lizardfs-bundle-CentOS-7.5.1804`
`$ sudo yum -y localinstall lizardfs-master-3.13.0-0el7.x86_64.rpm lizardfs-uraft-3.13.0-0el7.x86_64.rpm lizardfs-adm-3.13.0-0el7.x86_64.rpm`

### 7-3. LizardFS サーバー hosts 設定
@ mfs-master1, 2, 3
`$ sudo vim /etc/hosts`

```conf:/etc/hosts
10.0.0.1    gluster-server1 mfs-chunk1
10.0.0.2    gluster-server2 mfs-chunk2
10.0.0.3    gluster-client1 mfs-client1
10.0.0.4    gluster-client2 mfs-client2
10.0.0.5    mfs-master1
10.0.0.6    mfs-master2
10.0.0.7    mfs-master3
10.0.0.8    mfs-cluster
```

### 7-4. LizardFS サーバー metadata.mfs 設定
@ mfs-master1, 2, 3
`$ sudo cd /var/lib/mfs`
`$ sudo cp -a metadata.mfs.empty metadata.mfs`

### 7-5. LizardFS サーバー mfsmaster.cfg 設定
@ mfs-master1, 2, 3
`$ sudo cd /etc/mfs`
`$ sudo cp -a mfsmaster.cfg.dist mfsmaster.cfg`
`$ sudo vim /etc/mfs/mfsmaster.cfg`

```conf:/etc/mfs/mfsmaster.cfg
PERSONALITY = ha-cluster-managed
ADMIN_PASSWORD = パスワード
#  VIP アドレスまたは VIP ホスト名
MASTER_HOST = mfs-cluster
```

### 7-6. LizardFS サーバー lizardfs.cfg 設定
@ mfs-master1, 2, 3
`$ sudo cd /etc/mfs`
`$ sudo cp -a lizardfs-uraft.cfg.dist lizardfs-uraft.cfg`
`$ sudo vim /etc/mfs/lizardfs-uraft.cfg`

@ mfs-master1

```conf:/etc/mfs/lizardfs-uraft.cfg
URAFT_PORT = 9427
URAFT_STATUS_PORT = 9428
URAFT_NODE_ADDRESS = 10.0.0.5
URAFT_NODE_ADDRESS = 10.0.0.6
URAFT_NODE_ADDRESS = 10.0.0.7
URAFT_ID = 0
LOCAL_MASTER_ADDRESS = localhost
LOCAL_MASTER_MATOCL_PORT = 9421
ELECTION_TIMEOUT_MIN = 400
ELECTION_TIMEOUT_MAX = 600
HEARTBEAT_PERIOD = 20
LOCAL_MASTER_CHECK_PERIOD = 250
URAFT_FLOATING_IP = 10.0.0.8
URAFT_FLOATING_NETMASK = 255.255.255.0
URAFT_FLOATING_IFACE = eth0
```

@ mfs-master2

```conf:/etc/mfs/lizardfs-uraft.cfg
URAFT_PORT = 9427
URAFT_STATUS_PORT = 9428
URAFT_NODE_ADDRESS = 10.0.0.5
URAFT_NODE_ADDRESS = 10.0.0.6
URAFT_NODE_ADDRESS = 10.0.0.7
URAFT_ID = 1
LOCAL_MASTER_ADDRESS = localhost
LOCAL_MASTER_MATOCL_PORT = 9421
ELECTION_TIMEOUT_MIN = 400
ELECTION_TIMEOUT_MAX = 600
HEARTBEAT_PERIOD = 20
LOCAL_MASTER_CHECK_PERIOD = 250
URAFT_FLOATING_IP = 10.0.0.8
URAFT_FLOATING_NETMASK = 255.255.255.0
URAFT_FLOATING_IFACE = eth0
```

@ mfs-master3

```conf:/etc/mfs/lizardfs-uraft.cfg
URAFT_PORT = 9427
URAFT_STATUS_PORT = 9428
URAFT_NODE_ADDRESS = 10.0.0.5
URAFT_NODE_ADDRESS = 10.0.0.6
URAFT_NODE_ADDRESS = 10.0.0.7
URAFT_ID = 2
LOCAL_MASTER_ADDRESS = localhost
LOCAL_MASTER_MATOCL_PORT = 9421
ELECTION_TIMEOUT_MIN = 400
ELECTION_TIMEOUT_MAX = 600
HEARTBEAT_PERIOD = 20
LOCAL_MASTER_CHECK_PERIOD = 250
URAFT_FLOATING_IP = 10.0.0.8
URAFT_FLOATING_NETMASK = 255.255.255.0
URAFT_FLOATING_IFACE = eth0
```

### 7-7. LizardFS サーバー mfsgoals.cfg 設定
@ mfs-master1, 2, 3
`$ sudo cd /etc/mfs/`
`$ sudo cp -a mfsgoals.cfg.dist mfsgoals.cfg`
`$ sudo vim mfsgoals.cfg`

```conf:/etc/mfs/mfsgoals.cfg
2 2 : _ _
```

### 7-8. LizardFS サーバー cfg ファイル設定
@ mfs-master1, 2, 3
`$ sudo cd /etc/mfs`
`$ sudo cp -a globaliolimits.cfg.dist globaliolimits.cfg`
`$ sudo cp -a mfsexports.cfg.dist mfsexports.cfg`
`$ sudo cp -a mfstopology.cfg.dist mfstopology.cfg`

```
globaliolimits.cfg       lizardfs-uraft.cfg.dist  mfsgoals.cfg       mfsmaster.cfg.dist
globaliolimits.cfg.dist  mfsexports.cfg           mfsgoals.cfg.dist  mfstopology.cfg
lizardfs-uraft.cfg       mfsexports.cfg.dist      mfsmaster.cfg      mfstopology.cfg.dist
```

### 7-9. LizardFS サーバーカーネル設定
@ mfs-master1, 2, 3
`$ sudo echo 1 > /proc/sys/net/ipv4/conf/all/arp_accept`

### 7-10. Lizardfs チャンクサーバーダウンロード
[LizardFS ダウンロードページ](http://lizardfs.com/download/)
@ mfs-chunk1, 2
`$ sudo mkdir /usr/local/src/lizardfs`
`$ sudo cd /usr/local/src/lizardfs`
`$ sudo wget https://lizardfs.com/wp-content/uploads/2018/07/lizardfs-bundle-CentOS-7.5.1804.tar` 

### 7-11. Lizardfs チャンクサーバーインストール
@ mfs-chunk1, 2
`$ sudo tar -xvf lizardfs-bundle-CentOS-7.5.1804.tar`
`$ sudo cd lizardfs-bundle-CentOS-7.5.1804`
`$ sudo yum -y localinstall lizardfs-master-3.13.0-0el7.x86_64.rpm lizardfs-uraft-3.13.0-0el7.x86_64.rpm lizardfs-adm-3.13.0-0el7.x86_64.rpm`

### 7-12. Lizardfs チャンクサーバー hosts 設定
@ mfs-chunk1, 2
`$ sudo vim /etc/hosts`

```conf:/etc/hosts
10.0.0.1    gluster-server1 mfs-chunk1
10.0.0.2    gluster-server2 mfs-chunk2
10.0.0.3    gluster-client1 mfs-client1
10.0.0.4    gluster-client2 mfs-client2
10.0.0.5    mfs-master1
10.0.0.6    mfs-master2
10.0.0.7    mfs-master3
10.0.0.8    mfs-cluster
```

### 7-13.Lizardfs チャンクサーバー mfschunkserver.cfg 設定
@ mfs-chunk1, 2
`$ sudo cd /etc/mfs/`
`$ sudo cp -a mfschunkserver.cfg.dist mfschunkserver.cfg`
`$ sudo vim mfschunkserver.cfg`

```cfg:/etc/mfs/mfschunkserver.cfg
# ホスト名または IP アドレス
MASTER_HOST = mfs-cluster
```

### 7-14. Lizardfs チャンクサーバー mfshdd.cfg 設定
@ mfs-chunk1, 2
`$ sudo mkdir /mnt/lizardfs`
`$ sudo chown -R mfs:mfs /mnt/lizardfs`
`$ sudo cd /etc/mfs/`
`$ sudo cp -a mfshdd.cfg.dist mfshdd.cfg`
`$ sudo vim mfshdd.cfg`

```conf:/et/mfs/mfshdd.cfg
/mnt/lizardfs
```

### 7-15. LizardFS クライアントダウンロード
[LizardFS ダウンロードページ](http://lizardfs.com/download/)
@ mfs-client1, 2
`$ sudo mkdir /usr/local/src/lizardfs`
`$ sudo cd /usr/local/src/lizardfs`
`$ sudo wget https://lizardfs.com/wp-content/uploads/2018/07/lizardfs-bundle-CentOS-7.5.1804.tar`

### 7-16. LizardFS クライアントインストール
@ mfs-client1, 2
`$ sudo tar -xvf lizardfs-bundle-CentOS-7.5.1804.tar`
`$ sudo cd lizardfs-bundle-CentOS-7.5.1804`
`$ sudo yum -y localinstall lizardfs-master-3.13.0-0el7.x86_64.rpm lizardfs-uraft-3.13.0-0el7.x86_64.rpm lizardfs-adm-3.13.0-0el7.x86_64.rpm`

### 7-17. LizardFS クライアント hosts 設定
@ mfs-client1, 2
`$ sudo vim /etc/hosts`

```conf:/etc/hosts
10.0.0.1    gluster-server1 mfs-chunk1
10.0.0.2    gluster-server2 mfs-chunk2
10.0.0.3    gluster-client1 mfs-client1
10.0.0.4    gluster-client2 mfs-client2
10.0.0.5    mfs-master1
10.0.0.6    mfs-master2
10.0.0.7    mfs-master3
10.0.0.8    mfs-cluster
```

### 7-18. LizardFS クライアント mfsmount.cfg 設定
@ mfs-client1, 2
`$ sudo mkdir /mnt/lizardfs`
`$ sudo cd /etc/mfs/`
`$ sudo cp -a mfsmount.cfg.dist mfsmount.cfg`
`$ sudo vim mfsmount.cfg`

```conf:/etc/mfs/mfsmount.cfg
mfsmaster=mfs-cluster,mfsport=9421
/mnt/lizardfs
```

### 7-19. LizardFS クラスター起動
@ mfs-master1, 2, 3
`$ sudo systemctl start lizardfs-uraft`
`$ sudo systemctl status lizardfs-uraft`
`$ sudo lizardfs-admin list-metadataservers 10.0.0.8 9421`

```
Server 1:
	IP: 10.0.0.8
	Port: 9421
	Hostname: mfs-master1
	Personality: master
	Status: running
	Metadata version: 1
	Version: 3.13.0
Server 2:
	IP: 10.0.0.6
	Port: 9421
	Hostname: mfs-master2
	Personality: shadow
	Status: connected
	Metadata version: 1
	Version: 3.13.0
Server 3:
	IP: 10.0.0.7
	Port: 9421
	Hostname: mfs-master3
	Personality: shadow
	Status: connected
	Metadata version: 1
	Version: 3.13.0
```

### 7-20. LizardFS チャンクサーバー起動
@ mfs-chunk1, 2
`$ sudo systemctl start lizardfs-chunkserver`
`$ sudo systemctl status lizardfs-chunkserver`
`$ sudo lizardfs-admin list-chunkservers 10.0.0.8 9421`

```
Server 10.0.0.1:9422:
	version: 3.13.0
	label: _
	chunks: 0
	used space: 6.5GiB / 27GiB
	chunks marked for removal: 0
	used space marked for removal: 0B / 0B
	errors: 0
Server 10.0.0.2:9422:
	version: 3.13.0
	label: _
	chunks: 0
	used space: 6.5GiB / 27GiB
	chunks marked for removal: 0
	used space marked for removal: 0B / 0B
	errors: 0
```

### 7-21. Lizardfs クライアントマウント
@ mfs-client1, 2
`$ sudo mfsmount -o cacheexpirationtime=0 -o readaheadmaxwindowsize=4096 -o big_writes,nosuid,nodev,noatime /mnt/lizardfs`
`$ sudo lizardfs-admin list-mounts 10.0.0.8 9421`

```
session 1: 
	ip: 10.0.0.3
	mount point: /mnt/lizardfs
	version: 3.13.0
	root dir: /
	root uid: 0
	root gid: 0
	users uid: 999
	users gid: 999
	read only: no
	restricted ip: yes
	ignore gid: no
	all can change quota: no
	map all users: no
session 2: 
	ip: 10.0.0.4
	mount point: /mnt/lizardfs
	version: 3.13.0
	root dir: /
	root uid: 0
	root gid: 0
	users uid: 999
	users gid: 999
	read only: no
	restricted ip: yes
	ignore gid: no
	all can change quota: no
	map all users: no
```

## 8. ベンチマークテスト
### 8-1. Golang プログラム
`$ sudo nvim ~/go/main.go`

```go:~/go/main.go
package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "strconv"
    "time"
)

func main() {
    // Configure
    file_paths := []string{"/mnt/lizardfs/test", "/mnt/glusterfs/test"}
    systems := []string{"LizardFS", "GlusterFS"}
    results := []float64{0, 0}
    contents_size := 1000000
    benchmark_times := 10
    processing_times := 1000

    // Create contents
    var contents_string string
    for i := 0; i < contents_size; i++ {
        contents_string += "a"
    }
    contents_byte := []byte(contents_string)

    // Loop benchmark times
    for i := 0; i < benchmark_times; i++ {

        // Loop GlusterFS and LizardFS
        for j, _ := range file_paths {
            // Get processing start datetime
            start_datetime := time.Now()

            // Write files
            for k := 0; k < processing_times; k++ {
                err := ioutil.WriteFile(file_paths[j] + strconv.Itoa(k), contents_byte, 0644)
                if err != nil {
                    fmt.Println("File Writing Error: ", err)
                    os.Exit(1)
                }
			}

            // Read files
            for k := 0; k < processing_times; k++ {
                content_read, err := ioutil.ReadFile(file_paths[j] + strconv.Itoa(k))
                if err != nil {
                    fmt.Println("File Reading Error: ", err, content_read)
                    os.Exit(1)
                }
            }

            // Remove files
            for k := 0; k < processing_times; k++ {
                err := os.Remove(file_paths[j] + strconv.Itoa(k))
                if err != nil {
                    fmt.Println("File Removing Error: ", err)
                    os.Exit(1)
                }
            }

            // Get processing end datetime
            end_datetime := time.Now()

            // Get processing total time
            total_time := end_datetime.Sub(start_datetime)
            results[j] += total_time.Seconds()
            fmt.Printf("[%v] %v: %v\n", i, systems[j], total_time)
        }
    }

    // Get average processing time
    for i, v := range results {
        average := v / float64(benchmark_times)
        fmt.Printf("%v Average: %vs\n", systems[i], average)
    }

    os.Exit(0)
}
```

### 8-2. 実行
`$ sudo go build ~/go/main.go`
`$ sudo ~/go/main`

## 9. まとめ
この記事では、GlusterFS と LizardFS のミニマムなレプリケーション構成における、ファイル処理速度のベンチマークテストの一例を投稿しました。
ベンチマークテストスコアのように、このテストケースでは、LizardFS が GlusterFS より平均で約 14.5 秒速く処理を完了させています。
もちろん、環境、設計、設定、条件、対象、状態などによって結果は変化しますので、このスコアあくまで参考値としてです。