lsyncd

(作成:2012/11)

冗長化の一環として。用途としてはMySQLレプリケーションに通じるものがあるね。
ストレージサーバなどでリアルタイムにファイルを同期できるサービス。 cronrsync ぶん回すってのも乱暴ながらお手軽でアリかもだけど、こちらはファイル更新を監視して同期するので、もうちょい良心的かな?

ここでは以下のような要望に応える感じで設計してみる。

コピー元 コピー先
サーバ名 master slave1, slave2
ディレクトリ /home/riyo/public_html/ /var/www/html/

Install on CentOS

まずはコピー元(マスタ)からコピー先(スレイヴ)へ、SSHでパスワード無しログインが出来るようにしておく。ここでは rootroot で設定しているが、同期データのアクセス権限上問題なければ、一般アカウントのみに限定した方がセキュリティ上は安全。
やり方はこんな感じ。

(master)# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX root@master
The key's randomart image is:
+--[ RSA 2048]----+
|        .=+o+=   |
|        ++..+..  |
|        +.o  .   |
|       = + .     |
|      o S . .    |
|       . o +     |
|        o E      |
|         .       |
|                 |
+-----------------+
# cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApgeqDMMkrC3LmiWk7VeKoS3gadXKZYqGOIriVDKHa+DzR1zQwfqUYFOR7joXpCOBcXjPF8M/vBQS0gJYLmfDu89KR3McPdaQ4UZIbW5/3P1M+znvP8xkleahd0piNFwzaiYKZO8+DU+aT3qtS1I3QUjuieABXfIhh5pD9RMGr4iguTDb9hLoAIjYAn00bNjvBktbg+R5B3hrSaMgLVke+2hQ0XnYynFfvc2JvAzircYbv+tJYHjnPI70esr4kcr8eUvyHTEnJ5Pb/A2Kl5GIJJ7JNqe1rUApaIExoV4zuZpvoBH9j62aUaoL2j5X6RSYllpbPQ7mlTjhrgcGAKmueQ== root@master

この情報をコピーしておく。

(slave)# mkdir .ssh
#### .ssh/authorized_keys

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApgeqDMMkrC3LmiWk7VeKoS3gadXKZYqGOIriVDKHa+DzR1zQwfqUYFOR7joXpCOBcXjPF8M/vBQS0gJYLmfDu89KR3McPdaQ4UZIbW5/3P1M+znvP8xkleahd0piNFwzaiYKZO8+DU+aT3qtS1I3QUjuieABXfIhh5pD9RMGr4iguTDb9hLoAIjYAn00bNjvBktbg+R5B3hrSaMgLVke+2hQ0XnYynFfvc2JvAzircYbv+tJYHjnPI70esr4kcr8eUvyHTEnJ5Pb/A2Kl5GIJJ7JNqe1rUApaIExoV4zuZpvoBH9j62aUaoL2j5X6RSYllpbPQ7mlTjhrgcGAKmueQ== root@master
# chmod -R go-rwx .ssh

基本的にはこれでOK。ログイン確認して、出来ないようならコピー先(スレイヴ)サーバのSSHサービス設定を見直す。以下の設定がされている事が大事。

#### /etc/ssh/sshd_config

PermitRootLogin yes
...
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys
# service sshd restart

続いてコピー元(マスタ)サーバの設定。
lsyncd はEPELリポジトリにアーカイブがあるので使えるようにしておく。

# yum install --enablerepo=epel lsyncd

アーカイブ内に設定サンプルがあるけれど、正直情報不足感が否めない……ググった方が良いかも知れない。GitHubのドキュメントはちょろっと目を通しておくと良いかも。
ここではv2.1.xでの設定方法を紹介しておく。

#### /etc/lsyncd/lsyncd.conf

settings{
        statusFile = "/tmp/lsyncd.stat",
        logfile = "/var/log/lsyncd/lsyncd.log",
        delay = "3",
}

-- to slave1
sync{
        default.rsyncssh,
        source="/home/riyo/public_html/",
        host="root@slave1",
        targetdir="/var/www/html",
        exclude={".svn"},
        rsync={compress = true,}
}

-- to slave2
sync{
        default.rsyncssh,
        source="/home/riyo/public_html/",
        host="root@slave2",
        targetdir="/var/www/html",
        exclude={".svn"},
        rsync={compress = true,}
}

-- で始まる行はコメント。同期先の追加は sync{} のブロックをどんどん追加していくだけでOK。 exclude の項目は同期対象から除外する設定。 rsync の項目は rsync オプションらしいけれど、v2.0.x系とかなり違っているのでドキュメント必読。
settingslogfile に、同期したファイルのコピー結果が記載される。動作確認はこのファイルを参照すれば良い。

起動スクリプトも作る。

/etc/init.d/lsyncd(長いので折り畳み)
#!/bin/bash
#
# chkconfig: - 85 15
# description: Lightweight inotify based sync daemon
#
# processname:  lsyncd
# config:       /etc/lsyncd/lsyncd.conf
# config:       /etc/sysconfig/lsyncd
# pidfile:      /var/run/lsyncd.pid

#### /etc/init.d/lsyncd

# Source function library
. /etc/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

OPTIONS="-pidfile /var/run/lsyncd.pid /etc/lsyncd/lsyncd.conf"

if [ -e /etc/sysconfig/lsyncd.options ]; then
  . /etc/sysconfig/lsyncd.options
fi

RETVAL=0

prog="lsyncd"
thelock=/var/lock/subsys/lsyncd

start() {
        echo -n $"Starting $prog: "
        if [ $UID -ne 0 ]; then
                RETVAL=1
                failure
        else
                daemon /usr/bin/lsyncd $OPTIONS
                RETVAL=$?
                [ $RETVAL -eq 0 ] && touch $thelock
        fi;
        echo
        return $RETVAL
}

stop() {
        echo -n $"Stopping $prog: "
        if [ $UID -ne 0 ]; then
                RETVAL=1
                failure
        else
                killproc /usr/bin/lsyncd
                RETVAL=$?
                [ $RETVAL -eq 0 ] && rm -f $thelock
        fi;
        echo
        return $RETVAL
}

reload(){
        echo -n $"Reloading $prog: "
        killproc /usr/bin/lsyncd -HUP
        RETVAL=$?
        echo
        return $RETVAL
}

restart(){
        stop
        start
}

condrestart(){
    [ -e $thelock ] && restart
    return 0
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  reload)
        reload
        ;;
  condrestart)
        condrestart
        ;;
  status)
        status lsyncd
        RETVAL=$?
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
        RETVAL=1
esac

exit $RETVAL

起動。

# service lsyncd start

ログ肥大化を抑えるために。

#### /etc/logrotate.d/lsyncd

/var/log/lsyncd/*log {
    daily
    rotate 7
    missingok
    notifempty
    sharedscripts
    postrotate
        service lsyncd restart 2&>1 >null || true
    endscript
}

v2.1.xの場合、コピー先(スレイヴ)サーバの設定は不要。便利になったなぁ。

動作確認

マスタサーバでファイルを追加してみる。

# touch ~/public_html/hoge
# cat /var/log/lsyncd/lsyncd.log
Tue Jul 16 13:29:50 2013 Normal: Rsyncing list
/hoge
Tue Jul 16 13:29:52 2013 Normal: Finished (list): 0

スレイヴで確認すると、確かにある。

# ssh slave ls /var/www/html
hoge

次、マスタサーバから消してみる。

# rm -f ~/public_html/hoge
# cat /var/log/lsyncd/lsyncd.log
Tue Jul 16 13:30:04 2013 Normal: Deleting list
/home/riyo/public_html//hoge
Tue Jul 16 13:30:04 2013 Normal: Finished (list): 0

確認すると成程消えてる。

# ssh slave ls /var/www/html