2010년 4월 7일 수요일

lsyncd 동기화 (inotify + rsyncd)

참고 :
http://coffeenix.net/board_view.php?bd_code=1696
http://code.google.com/p/lsyncd/

동기화에 또다른 방법이 있어서 알려드립니다.
좋은진호님에 글에 개인적으로 테스트하면서 해당내역을 추가해서 적습니다.



Lsyncd vs. DRBD
DRBD 블록 장치 수준에서 동작하며 스토리지형태의 큰파일 시스템을 동기화할경우에는 유용합니다.  하지만 백업되는 상황만 볼수 있으며 실제 백업 데이타를 확인하지는 못한다는것... 속도성면에서 빠르나 블록단위 백업이라 쓸모없는것까지 모조리 백업되기도 하는점이 있습니다.

하지만 Lsyncd 는 장치 변경 및 지점을 필요로하지 않습니다.
더군다나 rsync의 단점인 특정스케줄에 의해서 동기화 되기때문에 완전한 미러링 시스템으로는 부족한점이 있다.

이부분에 대해서 rsync 기능에 추가해서 실시간 미러링 시스템으로 구축할수 있는 방법이 있어서 소개드립니다.



1. lsyncd 동기화 툴

1) lsyncd의 원리는 간단하다.

- 리눅스 커널의 inotify로 파일시스템의 변경사항을 체크한다.          (판단은 inotify로)
- 변경사항이 생기자마자, rsync를 호출하여 상대 서버로 싱크를 해준다. (동기화는 rsync로)

inotify는 리눅스 커널에 포함된 기능으로, 파일시스템에 변경사항이 발생할 때 이벤트를 통보해준다. 이 inotify를 이용하게 되면, 파일 변경사항을 수시로 파악할 필요없이 가만히 앉아있으면 된다. 파일이 바뀔 때 커널에서 통보해주는 신호를 덥석 받아먹으면 되기 때문이다.

0.5초(0.5초는 그만큼 짧다는 것을 표현하기 위해서 사용했음)도 안되는 아주 짧은 시간 동안의 차이는 생길 수 있지만, 소규모 서버를 운영할 경우에는 무리가 없을 것으로 보인다.

- 원본 데이터가 있는 서버(1대의 서버)에는 lsyncd 데몬(lsyncd 데몬 + rsync 클라이언트)이 동작하게 되고,
- 동기화 대상 서버(다수의 서버)에는 rsync 데몬(rsync 서버)이 띄워져 있어야 한다.


3) lsyncd master서버에서 필요 환경은 다음과 같다. 대상 서버는 rsync만 동작하면 OS종류, 버전에 상관없다.

- Linux Kernel 2.6.13 이상 (inotify를 위해)
- rsync 프로그램
- lsyncd 컴파일을 위해서 libxml2가 필요하다.
  CentOS : libxml2-devel 패키지
  Ubuntu : libxml2-dev   패키지


4) 어떤 경우 유용할까?
  • 소규모 사이트에서 NFS대신하여 동기화를 고민할 때. (단, 파일이 너무 많으면 동기화가 늦어질 수 있음)
  • 실시간 백업이 필요할 때.
  • 대규모 웹사이트에서 메인페이지나 대메뉴의 첫페이지 등 유저 접속이 많다.
    이 페이지에서 실시간으로 변경되는 데이터를 매번 DB접속하여 처리하는 것은 좋지 않다.
    실시간 데이터를 1분 또는 더 짧은 간격으로 텍스트로 저장하고, 변경이 되자마자 자동 동기화 되도록 처리할 때.
    규모가 크면 1차 master -> 2차 여러대의 master -> 상당수의 서비스 서버의 구조가 될 수도 있다.

설치
 -
http://code.google.com/p/lsyncd/downloads/list

[root@node1 src]# wget http://lsyncd.googlecode.com/files/lsyncd-1.26.tar.gz

[root@node1 src]# tar zxf lsyncd-1.26.tar.gz

[root@node1 src]# cd lsyncd-1.26

[root@node1 lsyncd-1.26]# ./configure
[root@node1 lsyncd-1.26]# make
[root@node1 lsyncd-1.26]# make install



 2. lsyncd를 이용한 실시간 동기화

기본 형식은 다음과 같다.

USAGE: lsyncd [OPTION]... [SOURCE] [TARGET 1] [TARGET 2] ...
SOURCE: a directory to watch and rsync.
TARGET: can be any name accepted by rsync. e.g. "foohost::barmodule/"

다음은 간단한 사용 예이다. lsyncd은 rsync를 사용하여 동기화하므로, TARGET은 rsync처럼 로컬 디렉토리를 지정할 수도 있으며, 원격지의 rsync 경로도 가능하다. TARGET을 다수 지정하게 되면 여러 서버로 실시간 동기화가 이뤄진다.

[root@node1 lsyncd-1.26]# ./lsyncd /home/aaa/ /data/backup/
[root@node1 lsyncd-1.26]# ./lsyncd /home/aaa/ 192.168.123.3::test1/
[root@node1 lsyncd-1.26]# ./lsyncd /home/aaa/ 192.168.123.3::test1/ 192.168.123.4::test1/


테스트)
동기화할 서버에는 rsync 설정과 동일하게 /etc/rsyncd.conf 설정을...

[test1]
path =/home/aaa
comment =
uid = root
gid = root
use chroot = yes
read only = no
hosts allow = 218.236.115.225
max connections = 5
timeout = 600


Master 서버에서 lsyncd 데몬을....올리고

[root@node1 lsyncd-1.26]# /usr/local/src/lsyncd-1.26/lsyncd /home/aaa 218.236.115.226::test1

[root@node1 lsyncd-1.26]# ps -aux
root     15226  0.0  0.0  13884   488 ?        Ss   12:31   0:00 /usr/local/src/lsyncd-1.26/lsyncd /home/aaa 218.236.115.226::test1

 

두개의 서버에서 동기화되는 과정을 FTP 를 통해 파일을 계속해서 올리면서 확인해보면...실시간으로 바로 동기화가 되고있음이 확인된다.




lsyncd는 기본적으로 daemon형태로 실행되며, /var/log/lsyncd 파일에 로그가 저장된다. 다음은 테스트를 위해서 --no-daemon옵션을 넣고 실행했다. 로그를 살펴보면 다음과 같은 사항을 파악할 수 있다.


  • 어디에서 어디로 동기화가 되는지 확인할 수 있다. ( syncing /home/aaa/ -> 192.168.123.3::test1/ )
  • 16개 디렉토리( /home/aaa/ + 15개의 서브디렉토리 )를 모니터링한다. ( [16] monitored directories )
  • truefeel.txt 파일이 생성되자마자 rsync를 호출하여 동기화된다.
  • 서브 디렉토리( /home/aaa/docs/ ) 내의 파일이 변경된 경우 그 디렉토리만 동기화한다. ( rsyncing /home/aaa/docs/ --> 192.168.123.3::test1/docs/ ) 전체 디렉토리를 동기화하지 않기 때문에 그 만큼 동기화 시간이 빨라진다.
 
# ./lsyncd --no-daemon /home/cnx/ 192.168.123.3::backup/
Fri Dec  4 18:13:13 2009: command line options: syncing /home/cnx/ -> 192.168.123.3::backup/

Fri Dec  4 18:13:13 2009: Starting up
Fri Dec  4 18:13:13 2009: watching /home/cnx/
Fri Dec  4 18:13:13 2009: found new directory: ?????? in /home/cnx/ -- added on tosync stack.
Fri Dec  4 18:13:13 2009: found new directory: ?????? in /home/cnx/ -- added on tosync stack.
... 생략 ...
Fri Dec  4 18:13:13 2009: --- Entering normal operation with [16] monitored directories ---
Fri Dec  4 18:14:40 2009: event CREATE:truefeel.txt triggered.
Fri Dec  4 18:14:40 2009: rsyncing /home/cnx/ --> 192.168.123.3::backup/
Fri Dec  4 18:14:40 2009: event CLOSE_WRITE:truefeel.txt triggered.
Fri Dec  4 18:14:40 2009: rsyncing /home/cnx/ --> 192.168.123.3::backup/
Fri Dec  4 18:16:22 2009: event CREATE:vimcheatsheet.pdf triggered.
Fri Dec  4 18:16:22 2009: rsyncing /home/cnx/docs/ --> 192.168.123.3::backup/docs/
Fri Dec  4 18:16:22 2009: event CLOSE_WRITE:vimcheatsheet.pdf triggered.
Fri Dec  4 18:16:22 2009: rsyncing /home/cnx/docs/ --> 192.168.123.3::backup/docs/
 



다음은 TARGET을 2곳으로 지정했을 때 동기화 결과이다.

 
Fri Dec  4 19:04:37 2009: event CREATE:cnx.txt triggered.
Fri Dec  4 19:04:37 2009: rsyncing /home/cnx/ --> 192.168.123.3::backup/
Fri Dec  4 19:04:37 2009: rsyncing /home/cnx/ --> 192.168.123.4::backup/
Fri Dec  4 19:04:37 2009: event CLOSE_WRITE:cnx.txt triggered.
Fri Dec  4 19:04:37 2009: rsyncing /home/cnx/ --> 192.168.123.3::backup/
Fri Dec  4 19:04:37 2009: rsyncing /home/cnx/ --> 192.168.123.4::backup/
 
3. lsyncd config 파일

lsyncd.conf 샘플 설정 파일이다.

 
<lsyncd version="1">

<settings>
   <!--uncomment to log all debug messages.-->
   <!--debug/-->
   
   <!--uncomment to log only errors.-->
   <!--scarce/-->
   
   <!--uncomment to not detach, log to stdout/stderr.-->
   <!--no-daemon/-->

   <!--uncomment to not call any actions, run dry only.-->
   <!--dryrun/-->

   <!--uncomment to exclude file handled to rsync.-->
   <!--exclude-from filename="/tmp/exclude"/-->

   <logfile      filename="/var/log/lsyncd"/>
   <binary       filename="/usr/bin/rsync"/>
   <!--pidfile      filename="/var/run/lsyncd.pid"/-->

   <callopts>
      <option text="-ltogp%r"/>
      <option text="--delete"/>
      <exclude-file/>
      <source/>
      <destination/>
   </callopts>
</settings>

<directory>
        <source path="/home/aaa/"/>
        <target path="218.236.115.226::test1/"/>
</directory>

</lsyncd>
 


<settings> 의 설정에는 다음 항목들이 있다.


  • debug     : debug mode로 실행한다. 상세한 로그가 남는다. 적용하려면 <debug/> 처럼 설정한다.
  • scarce    : debug와는 반대되는 개념. 에러만 로그에 남긴다.
  • no-daemon : 데몬형태로 실행하지 않으며, 로그는 화면에 바로 출력된다.
  • dryrun    : 실제 적용하지는 않는다 어떻게 동작하는지 로그에만 남기고, 동기화(rsync)는 실행하지 않는다.
  • exclude-from : 제외할 목록이 들어있는 파일명을 지정한다.
  • logfile   : 로그 파일명
  • binary    : rsync의 경로
  • pidfile   : PID 파일명
  • callopts  : rsync 호출할 때 사용할 옵션을 지정한다.


<directory> 은 따로 설명하지 않아도 바로 이해가 될 것이다. 대상 서버가 많으면 쭈욱 나열해주면 된다.

 
# ./lsyncd --conf lsyncd.conf
 


따로 시작/중지 스크립트를 만들어서 사용...

#!/bin/bash
# description: lsyncd auto start script

start() {
    pid=`pidof lsyncd`
    if [ $? -eq 0 ]; then
        echo "lsyncd (pid $pid) is running..."
        echo " "
    else
        echo "Starting lsyncd..."
        echo " "
        /usr/local/bin/lsyncd
    fi
}

stop() {
    echo "Stopping lsyncd..."
    echo " "
    /bin/kill -9 `/sbin/pidof rsync`
    until [ -z $(/sbin/pidof lsyncd) ]; do :; done
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        pid=`pidof lsyncd`
        if [ $? -eq 0 ]; then
            echo "lsyncd (pid $pid) is running..."
            echo " "
        else
            echo "lsyncd is not running"
            echo " "
        fi
        ;;
    *)

    echo "Usage: lsyncd {start|stop|restart|status}"
    exit 1
esac

exit $?



4. lsyncd 깊이 알기

1) 특정 서브 디렉토리나 파일을 제외(exclude)하려면?

lsyncd는 동기화에서 제외할 디렉토리 목록을 '--exclude-from FILE' 옵션으로 지정할 수 있다. lsyncd_exclude.lst 파일에 아래 내용을 넣으면 2개 디렉토리를 제외하게 된다. 특정 파일만 제외할 수는 없다. 디렉토리만 지정이 가능하다. 제외한 디렉토리는 rsync할 때 제외되는 것이 아니라, inotify의 모니터링 대상 자체에서 빠진다. 빠진 디렉토리수(서브디렉토리도 있다면 그 것도 포함)만큼 'Entering normal operation with [??] monitored directories' 로그에 남으니, 계산해보면 확인이 될 것이다.

 
doc/
photo/
 


config파일에서 설정하려면 다음과 같이 한다.

 
<exclude-from filename="/etc/lsyncd_exclude.lst"/>
 


디렉토리가 아닌 파일을 동기화 대상에서 제외하려면 어떻게 해야할까? rsync 옵션을 활용해야 한다. rsync의 --exclude-from=FILE 옵션이 있다. 파일(예. lsyncd_file_exclude.lst) 에 제외할 파일목록을 넣는다. 그리고, config 파일의  rsync옵션부분에 다음을 추가하면 된다.

 
<option text="--exclude-from=/etc/lsyncd_file_exclude.lst"/>
 


파일 제외할 때 주의할 것은 서브 디렉토리에 같은 파일명이 있을 때도 제외될 수 있다. 만약 lsyncd_file_exclude.lst에 cnx.doc 을 지정했다고 하자. 그러나 우연찮게 lib/cnx.doc 파일이 실제 존재할 때 lib/cnx.doc 파일이 변경되어도 동기화 안될 수 있다.

2) 퍼미션, 소유자까지 변경하려면?

lsyncd는 퍼미션과 소유자의 변경은 무시하도록 되어 있다. debug 모드로 살펴보면 로그에 다음과 같이 남는다.

 
Fri Dec  4 19:13:18 2009: inotfy event: ATTRIB:cnx.txt
Fri Dec  4 19:13:18 2009: ... ignored this event.
Fri Dec  4 19:13:18 2009: Processing through tosync stack.
Fri Dec  4 19:13:18 2009: being done with tosync stack
 


파일 속성 변경까지 동기화하기 위해서는 lsyncd.c 소스 수정이 필요하다. 1131번째줄에서 IN_ATTRIB를 추가해주면 파일속성 변경시 동기화된다.

 
        if ((IN_CREATE | IN_CLOSE_WRITE | IN_DELETE |
             IN_MOVED_TO | IN_MOVED_FROM | IN_ATTRIB ) & event->mask
 


그리고, config파일에서 rsync 옵션 변경이 필요하다. <callopts> 에서 <option text="-lt%r"/> 대신 <option text="-ltogp%r"/>로 변경한다. o는 소유자 유지, g는 소유그룹 유지, p는 퍼미션 유지.

3) lsyncd가 rsync를 어떻게 호출하는지 궁금하다?

lsyncd가 실행되는 서버에서 다음 스크립트를 실행한다. 파일변경시 즉시 실행되는 rsync 명령을 확인할 수 있다.

 
#!/bin/bash

while [ 1 ]
do
   date +'%H:%M:%S'
   ps auxww|grep [r]sync
   sleep 0.05
done
 


rsync가 호출되는 순간에 다음과 같이 화면에 출력될 것이다.

 
19:19:46
19:19:46
root      4076  0.0  0.0   5812  1036 ?        S    19:19   0:00 /usr/bin/rsync -ltogpd --delete /home/cnx/docs/ 192.168.123.3::backup/docs/
 


4) rsync 대신 다른 동기화 프로그램 호출

lsyncd는 rsync의 경로를 --binary 옵션이나 config에서 설정할 수 있다. 따라서 이 경로를 수정하게 되면 rsync를 직접 호출하지 않고, 스크립트를 통해 호출할 수가 있다. 그래서 동기화할 때 ① 원하는 명령을 실행할 수도 있고, ③ rsync 대신 다른 동기화 프로그램도 사용할 수가 있게 된다.

일본 KLAB에서 만든 동기화 툴인 Makuosan( http://lab.klab.org/wiki/Makuosan )이 있다. 이 툴은 동기화 서버가 1대이든 몇십대이든 속도 저하없이 거의 동시에 동기화된다. 이 툴을 이용하여 스크립트를 만든다면 재밌는 조합( lsyncd + Makuosan )이 될 것이다. 실시간 파일 변경 판단은 lsyncd로 하고, 동기화는 빠른 Makuosan로 이뤄지는 것이다.

참고로 rsync를 스크립트로 만든 경우는 http://code.google.com/p/lsyncd/wiki/HowToExecAfter 를 읽어보기 바란다.


5. 주의할 점

  • DB 파일, log 파일처럼 파일이 계속 active된 상태로 변경되는 디렉토리에는 사용하지 않는다.
  • 파일 변화가 상당히 잦을 디렉토리에는 사용하지 않는다.
  • 한 개의 디렉토리 내에 파일이 너무 많으면 동기화가 느려질 수 있다.
  • 파일이 큰 파일(몇 백메가 또는 몇 기가)이 변경될 경우 동기화가 느려질 수 있다. 또한 이렇게 큰 파일의 변경이 잦으면 제외해주는 것이 좋다.
  • lsyncd가 파일 변화를 모니터링할 수 있는 디렉토리 갯수는 최대 8192개이다.
 커널변수를 이용해서 수정가능하다.  
 기본설정은 8192개 이나 수정하면 늘릴수 있습니다.
그리고 ext2. ext3 파일시스템에서는 기본적으로 디렉토리가 32000개 까지 만들어집니다.
 cat /proc/sys/fs/inotify/max_user_watches

댓글 없음:

댓글 쓰기