1. 要約
この記事では、LizardFS による分散ファイルシステムの構築(GA 版 3.12 yum インストール編)の例と、keepalived や、スクラッチの Golang デーモンによる、自前のマスターフェイルオーバー機構の構築例について投稿します。
2. はじめに
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” では、lizardfs-uraft パッケージが入ったバージョンの構築例と、keepalived やスクラッチの Golang デーモンを使った、自前のマスターフェイルオーバー機構の構築例について投稿しました。
今回の記事では、lizardfs-uraft パッケージのない yum インストール編の構築例と、前回作った keepalived 構成やスクラッチの Golang デーモンを使った、自前の自動フェイルオーバー環境をカスタマイズした構築例を投稿します。
LizardFS の GA 版 3.12 yum インストール編と RC 版 3.13 RPM パッケージ編の違いは、“LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
3. LizardFS 環境
- RHEL 7 系
- LizardFS 3.12
- keepalived 1.3.5
- Go 1.9
4. LizardFS 設計
- LizardFS マスターサーバー x 2
- mfs-master1
- mfs-master2
- LizardFS チャンクサーバー x 2
- mfs-chunk1
- mfs-chunk2
- LizardFS クライアント x 2
- mfs-client1
- mfs-client2
LizardFS パッケージ一覧
lizardfs-master – LizardFS master server
lizardfs-chunkserver – LizardFS data server
lizardfs-client – LizardFS client
lizardfs-adm – LizardFS administration tools (e.g, lizardfs-probe)
lizardfs-cgi – LizardFS CGI Monitor
lizardfs-cgiserv – Simple CGI-capable HTTP server to run LizardFS CGI Monitor
lizardfs-metalogger – LizardFS metalogger server
lizardfs-debuginfo – (CentOS 7 / RHEL 7 only) Debugging symbols and sources for all the LizardFS binaries
5. LizardFS マスターサーバー
5-1. epel リポジトリインストール
@ mfs-master1, 2
$ sudo yum install -y epel-release
$ sudo vim /etc/yum.repos.d/epel.repo
- enabled=1
+ enabled=0
※ diff 表示
5-2. LizardFS リポジトリインストール
@ mfs-master1, 2
$ sudo curl http://packages.lizardfs.com/yum/el7/lizardfs.repo > /etc/yum.repos.d/lizardfs.repo
$ sudo vim /etc/yum.repos.d/lizardfs.repo
- enabled=1
+ enabled=0
※ diff 表示
5-6. LizardFS マスターインストール
@ mfs-master1, 2
$ sudo yum install -y --enablerepo=lizardfs,epel lizardfs-master lizardfs-adm
5-7. hosts ファイル設定
@ mfs-master1, 2
$ vim /etc/hosts
10.0.0.1 mfs-master1
10.0.0.2 mfs-master2
10.0.0.3 mfs-chunk1
10.0.0.4 mfs-chunk2
10.0.0.5 mfs-client1
10.0.0.6 mfs-client2
5-8. metadata.mfs 設定
@ mfs-master1, 2
$ sudo cd /var/lib/mfs/
$ sudo cp -a metadata.mfs.empty metadata.mfs
5-9. mfsmaster.cfg 設定
@ mfs-master1, 2
$ sudo cd /etc/mfs/
$ sudo cp -a mfsmaster.cfg.dist mfsmaster.cfg
$ sudo vim mfsmaster.cfg
@ mfs-master1
PERSONALITY = master
# ホスト名または IP アドレス
MASTER_HOST = mfs-cluster
@ mfs-master2
PERSONALITY = shadow
# ホスト名または IP アドレス
MASTER_HOST = mfs-cluster
5-10. mfsgloas.cfg 設定
@ mfs-master1, 2
$ sudo cd /etc/mfs/
$ sudo cp -a mfsgoals.cfg.dist mfsgoals.cfg
$ sudo vim mfsgoals.cfg
2 2 : _ _
5-11. その他設定ファイル
@ mfs-master1, 2
$ 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 mfsexports.cfg mfsgoals.cfg mfsmaster.cfg mfstopology.cfg
globaliolimits.cfg.dist mfsexports.cfg.dist mfsgoals.cfg.dist mfsmaster.cfg.dist mfstopology.cfg.dist
6 LizardFS チャンクサーバー
6-1. epel リポジトリインストール
@ mfs-chunk1, 2
$ yum install -y epel-release
- enabled=1
+ enabled=0
※ diff 表示
6-2. LizardFS リポジトリインストール
@ mfs-chunk1, 2
$ curl http://packages.lizardfs.com/yum/el7/lizardfs.repo > /etc/yum.repos.d/lizardfs.repo
$ vim /etc/yum.repos.d/lizardfs.repo
- enabled=1
+ enabled=0
※ diff 表示
6-3. LizardFS チャンクサーバーインストール
@ mfs-chunk1, 2
$ sudo yum install -y --enablerepo=lizardfs,epel lizardfs-chunkserver lizardfs-adm
6-4. hosts ファイル設定
@ mfs-chunk1, 2
$ vim /etc/hosts
10.0.0.1 mfs-master1
10.0.0.2 mfs-master2
10.0.0.3 mfs-chunk1
10.0.0.4 mfs-chunk2
10.0.0.5 mfs-client1
10.0.0.6 mfs-client2
6-5. mfschunkserver.cfg 設定
@ mfs-chunk1, 2
$ sudo cd /etc/mfs/
$ sudo cp -a mfschunkserver.cfg.dist mfschunkserver.cfg
$ sudo vim mfschunkserver.cfg
# ホスト名または IP アドレス
MASTER_HOST = mfs-cluster
6-6. mfshdd.cfg 設定
@ mfs-chunk1, 2
$ sudo cd /etc/mfs/
$ sudo cp -a mfshdd.cfg.dist mfshdd.cfg
$ sudo vim mfshdd.cfg
/mnt/mfs
7. LizardFS クライアント
7-1. epel リポジトリインストール
@ mfs-client1, 2
$ sudo yum install -y epel-release
- enabled=1
+ enabled=0
※ diff 表示
7-2. LizardFS リポジトリインストール
@ mfs-client1, 2
$ sudo curl http://packages.lizardfs.com/yum/el7/lizardfs.repo > /etc/yum.repos.d/lizardfs.repo
$ sudo vim /etc/yum.repos.d/lizardfs.repo
- enabled=1
+ enabled=0
※ diff 表示
7-3. LizardFS クライアントインストール
@ mfs-client1, 2
$ sudo yum install -y --enablerepo=lizardfs,epel lizardfs-client lizardfs-adm
7-4. hosts ファイル設定
@ mfs-client1, 2
$ sudo vim /etc/hosts
10.0.0.1 mfs-master1
10.0.0.2 mfs-master2
10.0.0.3 mfs-chunk1
10.0.0.4 mfs-chunk2
10.0.0.5 mfs-client1
10.0.0.6 mfs-client2
7-5. mfsmount.cfg 設定
@ mfs-client1, 2
$ sudo cd /etc/mfs/
$ sudo cp -a mfsmount.cfg.dist mfsmount.cfg
$ sudo vim mfsmount.cfg
mfsmaster=mfs-cluster,mfsport=9421
/mnt/mfs
8. マスターフェイルオーバー環境の準備
ここから、マスターフェイルオーバー機構を自前で用意します。
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” で、keepalived 構成と、Go 言語デーモンのスクラッチ開発の 2 通りで用意しましたので、それらを少しだけカスタマイズしていきます。
9. keepalived マスターフェイルオーバー機構
以降で、keepalived による、マスターフェイルオーバー機構を構築します。
9-1. keepalived インストール
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
9-3. keepalived 設定
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
9-4. notify Bash スクリプト作成
@ mfs-master1, 2
$ sudo cd /etc/keepalived
$ sudo touch notify.sh
$ sudo vim notify.sh
#!/bin/bash
# notify.sh
# Check argument counts
if [ $# -ne 3 ]; then
echo "Three arguments must be passed in $HOSTNAME." 1>&2
exit 1
fi
# Init variables
NOTIFY=$1
IPV4=$2
PORT=$3
# Validate 1st argument values
if [ $NOTIFY != "master" ] && [ $NOTIFY != "backup" ]; then
echo "The passed argument is invalid." 1>&2
exit 1
fi
# Validate 2nd argument values
#...
# Validate 3rd argument values
#...
# Take cluster personality
PERSONALITY=`lizardfs-admin metadataserver-status $IPV4 $PORT`
# Notify master
if [ $NOTIFY = "master" ]; then
## Promote master
if [[ $PERSONALITY =~ "personality: shadow" ]]; then
### Restart master
lizardfs-master -o initial-personality=master -o auto-recovery restart
fi
# Notify backup
elif [ $NOTIFY = "backup" ]; then
## Demote Master
if [[ $PERSONALITY =~ "personality: master" ]]; then
### Restart shadow
lizardfs-master -o initial-personality=shadow restart
fi
fi
# Check promotion or demotion of master
if [ $? != 0 ]; then
echo "Could not !$ in $HOSTNAME."
exit 1
fi
## Restart LizardFS
systemctl restart lizardfs-master 2>&1 >/dev/null
if [ $? != 0 ]; then
echo "Could not !$ in $HOSTNAME." 1>&2
exit 1
fi
exit 0
10. 起動
10-1. keepalived 起動
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
10-2. LizardFS マスターサーバー起動
@ mfs-master1, 2
$ sudo systemctl start lizardfs-master
$ sudo systemctl status lizardfs-master
10-3. LizardFS チャンクサーバー起動
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
10-4. クライアントマウント
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
10-5. 同期テスト
@ mfs-client1
$ sudo touch /mnt/mfs/test
@ mfs-client2
$ sudo ls /mnt/mfs
$ sudo rm -rf /mnt/mfs/test
@ mfs-client1
$ sudo ls /mnt/mfs
10-6. keepalived マスターフェイルオーバーテスト
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
10-7. keepalived マスターフェイルバックテスト
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
11. Golang マスターフェイルオーバーデーモン
以降で、スクラッチで Golang マスターフェイルオーバーデーモンを作成します。
11-1. VIP のアサイン
この構築例の VIP(フローティング IP)は、手動アサインします。
@ mfs-master1
$ sudo ip -f inet addr add 10.0.0.9/24 dev eth0
$ sudo arping -q -U -c5 -w1 10.0.0.9 -I eth0
11-2. Golang マスターフェイルオーバープログラム作成
@ mfs-master1, 2
$ sudo cd ~/go/
$ sudo nvim main.go
package main
import (
"fmt"
"net"
"os"
"os/exec"
"strings"
"time"
"unsafe"
)
func main() {
cluster_vip := os.Args[1]
cluster_port := os.Args[2]
cluster_address := cluster_vip + ":" + cluster_port
self_ip := os.Args[3]
self_port := os.Args[4]
greeting_interval := 1
greeting_timeout := 5
retry_interval := 3
retry_count := 3
retry_timeout := 5
for {
// Sleep healthcheck interval seconds
time.Sleep(time.Duration(greeting_interval) * time.Second)
// Greet to cluster
conn, err := net.DialTimeout("tcp", cluster_address, time.Duration(greeting_timeout)*time.Second)
// Succeeded greeting
if err == nil {
conn.Close()
fmt.Println("Could greet to cluster.")
continue
}
// Failed greeting
// Log
//...
fmt.Println("Could not greet to cluster.")
// Loop re-connection to cluster
health_flag := false
for j := 0; j < retry_count; j++ {
// Sleep re-connection interval seconds
time.Sleep(time.Duration(retry_interval) * time.Second)
// Re-connect
conn, err = net.DialTimeout("tcp", cluster_address, time.Duration(retry_timeout)*time.Second)
// Failed re-connection
if err != nil {
// Log
//...
fmt.Println("Could not re-connect to cluster.")
continue
}
// Succeeded re-connection
fmt.Println("Succeeded re-connection to cluster.")
health_flag = true
break
}
// Alive
if health_flag {
continue
}
// Dead
personality_byte, err := exec.Command("lizardfs-admin", "metadataserver-status", self_ip, self_port).Output()
personality := *(*string)(unsafe.Pointer(&personality_byte))
// Failed get personality
if err != nil {
// Log
//...
fmt.Println("Could not get personality.")
os.Exit(1)
}
// Demote from master
if -1 != strings.Index(personality, "personality: master") {
// Restart shadow
err = exec.Command("lizardfs-master", "-o initial-personality=shadow", "restart").Run()
// Failed master demotion
if err != nil {
// Log
//...
fmt.Println("Could not demote to master.")
os.Exit(1)
}
fmt.Println("Succeeded master demotion.")
// Unasign VIP
err = exec.Command("ip", "-f inet addr delete 10.0.0.9/24 dev eth0").Run()
// Failed VIP Unasigning
if err != nil {
// Log
//...
fmt.Println("Could not unasigning vip.")
os.Exit(1)
}
fmt.Println("Succeeded master demotion.")
// Promote to master
} else if -1 != strings.Index(personality, "personality: shadow") {
// Asign VIP
err = exec.Command("ip", "-f inet addr add 10.0.0.9/24 dev eth0").Run()
// Failed asigning VIP
if err != nil {
// Log
//...
fmt.Println("Could not asign VIP.")
os.Exit(1)
}
// Execute arping
err = exec.Command("arping", "-q -U -c5 -w1 10.0.0.9 -I eth0").Run()
// Failed arping
if err != nil {
// Log
//...
fmt.Println("Could not execute arping.")
os.Exit(1)
}
// Restart master
err = exec.Command("lizardfs-master", "-o initial-personality=master -o auto-recovery", "restart").Run()
// Failed master promotion
if err != nil {
// Log
//...
fmt.Println("Could not promote to master.")
os.Exit(1)
}
fmt.Println("Succeeded master promotion.")
}
// Restart LizardFS
err = exec.Command("systemctl", "restart", "lizardfs-master").Run()
// Failed restart
if err != nil {
// Log
//...
fmt.Println("Could not restart LizardFS.")
os.Exit(1)
}
fmt.Println("Succeeded restart LizardFs.")
} // End Loop
}
$ sudo go build main.go
11-3. Golang マスターフェイルオーバープログラムテスト
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
12. Golang マスターフェイルオーバーデーモン化
前回の記事 “LizardFS による分散ファイルシステムの構築(RC 版 3.13 RPM パッケージ編)” をご参照ください。
13. まとめ
この記事では、 LizardFS による分散ファイルシステムの構築(GA 版 3.12 yum インストール編)の例について投稿しました。
自前のマスターフェイルオーバー機構につきましては、keepalvied や、スクラッチの Golang デーモンにより実現しましたが、死活監視パターンにつきましては、実用にあわせて適宜実装してください。
他の分散ファイルシステムとのパフォーマンスのベンチマークテストにつきましては、別の機会に投稿しようと思います。