GFS2 + GNBD + DRBD + HEARTBEAT 설치

GFS2 + GNBD + DRBD + HEARTBEAT 설치

아침에 일찍 출근하여 두시간씩 남는 시간을 이용하여 구성을 해보고 싶었던 것이 있었다.
클러스터링 파일 시스템을 사용해 보고 싶어서 일단 검색을 해보니 역시나 국내에는 자료가 맘에 드는게 없었다
.
결국 구글의 힘을 빌려 검색을 하였으나 대부분의 자료가 redhat 에서 그냥 rpm으로 설치를 하라는 몇줄 안되는 간단한 설명만 있었다. debian 을 사용하고 있는 상황에서 redhat 으로 다시 설치하기도 귀찮고 남들이 쉽게 하는 방법으로 만들기 싫었다. 남들이 잘 하지 않는 방법으로 해보자고 결심을 하고 수 많은 try and error 를 경험하고 결국 만들어졌다
.
생각보다 많은 시간을 쏟았다
.
다른 사람들은 그 시간을 줄여서 다른 더 좋은 곳에 사용하길 바라면서 이 문서를 포스팅 한다.

GFS2 필요성


GFS2를 필요로 하는 곳은 대부분 클러스터링을 구성하였을 때 뒷 단에서 스토리지에 어떤 파일 시스템을 사용 할 찌의 선택에서 좋은 결과물을 가져다 준다. 물론 NFS 를 사용하면 되지 않겠느냐는 이야기를 할 수 있다. 하지만 GFS는 퍼포먼스에서 NFS 보다 좋은 결과를 얻을 수 있다. 보통 SAN 이나 NAS 등을 이용하여 파일시스템이 클러스터링 지원되는지 여부를 체크하지 않고 사용하는 경우를 가끔 볼 수 있는데 매우 위험하다. 클러스터링 환경에서 공유로 파일을 사용을 한다면 반드시 클러스터링이 지원되는 파일 시스템을 사용해야 한다.

클러스터링이 지원되는 파일 시스템의 예로는  GFS2, OCFS2, PVFS 등 이외에도 여러 가지가 있으나 최근 주목을 받고 있는 것은 위 파일 시스템들이다.

 

준비


구성하기 위해서는 기본적으로 서버가 3대가 필요하다.
이중 두대는 DRBD를 이용하여 데이터를 저장하고 있는 스토리지의 역활로 사용을 하게 되고 나머지 한 대는 여기에 access 하여 사용하는 client 로 사용을 할 계획이다. 서버 하드웨어 스펙은 용도에 맞게 적당히 마련하면 된다
.
여기서는 테스트 장비이므로 Cel 급으로 준비를 하였다
.

 dongho7, dongho8
 CPU : Celeron(R) 2.66GHz 256K Cache
 RAM : 512M
 HDD : SATA 80G
 ETHERNET : RTL8139, RTL8169


 dongho9
 CPU : Pentium(R) III CPU family 1133MHz
 RAM : 1G
 
OS
debian etch  버전으로 기본 설치를 한 다음에 진행을 하면 된다.
아래는 간략히 설치한 구성도 이다
.
서버 두대는 랜 카드를 두장을 이용하여 하나는 DRBD 용도의 SYNC 를 위해서 사용을 한다
.
다른 랜 카드는 외부와 통신을 하면서 Heartbeat 를 통해 VIP 가 관리가 된다
.
마지막으로 Client 는 이 VIP 랑 통신을 하면서 Server 단이 하나 죽더라도 서비스를 지속적으로 할 수 있게 된다.



설치 파일 준비


설치는 debian etch에서 기본적으로 제공 되는 패키지는 apt-get 을 이용하여 설치를 하고 없거나 호환이 되지 않는 경우 Source 로 받아서 설치를 진행을 하도록 한다.

우선 패키지를 최신 버전으로 업데이트를 한다.

dongho9:~# apt-get update
dongho9:~#
apt-get dist-upgrade
Reading
package lists… Done
Building dependency tree… Done
Calculating upgrade… Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.


그리고 설치를 진행 하면서 필요한 의존성 파일들이 있다.
미리 설치를 한다.

dongho9:~# apt-get install binutils bzip2 cpp cpp-4.1 flex gcc gcc-4.1 libc6-dev libncurses5-dev libslang2-dev libssp0 libvolume-id-dev linux-kernel-headers make libxml2 libxml2-dev libreadline5-dev


다음은 현재 설치되어 있는 패키지 리스트 이다.
debian
설치를 하다 보면 아무래도 현재 설치 되어 있는 패키지의 리스트가 이 테스트 환경과 다른 상황일 수 있다.

dongho9:~# dpkg -l |grep ^ii|awk ‘{print $2}’|xargs
acpid adduser apt apt-utils aptitude at base-files base-passwd bash bc bind9-host binutils bsdmainutils bsdutils busybox bzip2 ca-certificates console-common console-data console-tools coreutils cpio cpp cpp-4.1 cron dc debconf debconf-i18n debian-archive-keyring debianutils dhcp3-client dhcp3-common dictionaries-common diff dmidecode dnsutils doc-debian doc-linux-text dpkg dselect e2fslibs e2fsprogs ed eject exim4 exim4-base exim4-config exim4-daemon-light file findutils finger flex ftp gcc gcc-4.1 gcc-4.1-base gettext-base gnupg gpgv grep groff-base grub gzip heartbeat-2 hostname iamerican ibritish ifupdown info initramfs-tools initscripts installation-report iproute iptables iputils-ping ispell jfbterm klibc-utils klogd language-env laptop-detect less libacl1 libapr1 libaprutil1 libatm1 libattr1 libbind9-0 libblkid1 libbz2-1.0 libc6 libc6-dev libc6-i686 libcap1 libcomerr2 libconsole libcurl3 libdb4.2 libdb4.3 libdb4.4 libdbd-mysql-perl libdbi-perl libdevmapper1.02 libdns22 libedit2 libevent1 libexpat1 libgc1c2 libgcc1 libgcrypt11 libgdbm3 libglib1.2 libglib2.0-0 libgnutls13 libgpg-error0 libgpmg1 libgssapi2 libidn11 libisc11 libisccc0 libisccfg1 libklibc libkrb53 libldap2 liblocale-gettext-perl liblockfile1 libltdl3 liblwres9 liblzo1 libmagic1 libmysqlclient15off libncurses5 libncurses5-dev libncursesw5 libneon26 libnet-daemon-perl libnet1 libnewt0.52 libnfsidmap2 libopencdk8 libopenipmi0 libpam-modules libpam-runtime libpam0g libpci2 libpcre3 libplrpc-perl libpopt0 libpq4 libreadline5 libreadline5-dev librpcsecgss3 libsasl2 libsasl2-2 libselinux1 libsemanage1 libsensors3 libsepol1 libsigc++-2.0-0c2a libslang2 libslang2-dev libsnmp-base libsnmp9 libsqlite3-0 libss2 libssl-dev libssl0.9.8 libssp0 libstdc++6 libsvn1 libsysfs2 libtasn1-3 libtasn1-3-bin libtext-charwidth-perl libtext-iconv-perl libtext-wrapi18n-perl libusb-0.1-4 libuuid1 libvolume-id-dev libvolume-id0 libwrap0 libxml2 libxml2-dev lilo linux-image-2.6-686 linux-image-2.6.18-4-686 linux-image-2.6.18-6-686 linux-kernel-headers locales login logrotate lsb-base lsof m4 mailx make makedev man-db manpages manpages-ko mawk mbr mime-support mktemp module-init-tools mount mpack mtools mtr-tiny mutt mysql-client-5.0 mysql-common mysql-server mysql-server-5.0 nano ncurses-base ncurses-bin ncurses-term net-tools netbase netcat nfs-common nfs-kernel-server openbsd-inetd openssh-blacklist openssh-client openssh-server openssl passwd patch pciutils perl perl-base perl-modules pidentd policycoreutils portmap procmail procps psmisc python python-central python-minimal python-newt python-selinux python-semanage python-support python2.4 python2.4-minimal rcconf readline-common reportbug sed selinux-policy-refpolicy-targeted sharutils ssh strace subversion sudo sysklogd sysv-rc sysvinit sysvinit-utils tar tasksel tasksel-data tcpd tcsh telnet texinfo time traceroute tzdata ucf udev unifont update-inetd usbutils util-linux vim-common vim-tiny w3m wamerican wget whiptail whois zlib1g zlib1g-dev


이제 본격적으로 필요한 Source 파일들을 받는다.
먼저 커널이다.

dongho9:~# cd /usr/src
dongho9:/usr/src#
wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.3.tar.bz2
10:56:01—  http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.3.tar.bz2
           => `linux-2.6.26.3.tar.bz2′
Resolving kernel.org… 204.152.191.37, 204.152.191.5
Connecting to kernel.org|204.152.191.37|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 49,452,289 (47M) [application/x-bzip2]

100%[========================================>] 49,452,289     2.76M/s    ETA 00:00

10:56:21 (2.40 MB/s) – `linux-2.6.26.3.tar.bz2′ saved [49452289/49452289]

 


그리고 openais 를 다운로드 받는다.
http://www.openais.org
에서 받을 수 있다.

dongho9:/usr/src# wget ftp://ftp%40openais.org:downloads@openais.org/downloads/openais–    0.80.3/openais-0.80.3.tar.gz
10:50:27—  ftp://ftp%40openais.org:*password*@openais.org/downloads/openais-0    .80.3/openais-0.80.3.tar.gz
           => `openais-0.80.3.tar.gz’
Resolving openais.org… 67.15.211.9
Connecting to openais.org|67.15.211.9|:21… connected.
Logging in as
ftp@openais.org
… Logged in!
==> SYST … done.    ==> PWD … done.
==> TYPE I … done.  ==> CWD /downloads/openais-0.80.3 … done.
==> PASV … done.    ==> RETR openais-0.80.3.tar.gz … done.

    [       <=>                           ] 478,936      249.55K/s

10:50:37 (249.01 KB/s) – `openais-0.80.3.tar.gz’ saved [478936]


cluster
프로그램은 redhat 사이트에서 받는다.

dongho9:/usr/src# wget ftp://sources.redhat.com/pub/cluster/releases/cluster-2.03.07.tar.gz
10:52:26—  ftp://sources.redhat.com/pub/cluster/releases/cluster-2.03.07.tar.gz
           => `cluster-2.03.07.tar.gz’
Resolving sources.redhat.com… 209.132.176.174
Connecting to sources.redhat.com|209.132.176.174|:21… connected.
Logging in as anonymous … Logged in!
==> SYST … done.    ==> PWD … done.
==> TYPE I … done.  ==> CWD /pub/cluster/releases … done.
==> PASV … done.    ==> RETR cluster-2.03.07.tar.gz … done.
Length: 1,751,728 (1.7M) (unauthoritative)

100%[========================================>] 1,751,728    420.93K/s    ETA 00:00

10:52:40 (368.73 KB/s) – `cluster-2.03.07.tar.gz’ saved [1751728]

 

 

설치


커널 부터 설치 한다.
커널 컴파일시에 모듈 지원이 가능 하도록 컴파일을 하고 어차피 아래 gfs2 등의 관련 모듈은 Source 컴파일 하여 후에 다시 새로운 버전으로 모듈로 설치를 하게 될 것이다. 설치가 완료 되면 부트 로드에 적용을 하고

dongho9:/usr/src# tar jxvf linux-2.6.26.3.tar.bz2
dongho9:/usr/src#
cd linux-2.6.26.3
dongho9:/usr/src/linux-2.6.26.3#
make menuconfig
dongho9:/usr/src/linux-2.6.26.3#
make
dongho9:/usr/src/linux-2.6.26.3#
make install
dongho9:/usr/src/linux-2.6.26.3#
make modules_install
INSTALL drivers/scsi/scsi_wait_scan.ko
  INSTALL fs/configfs/configfs.ko
  INSTALL fs/dlm/dlm.ko
  INSTALL fs/gfs2/gfs2.ko
  INSTALL fs/gfs2/locking/dlm/lock_dlm.ko
  INSTALL fs/gfs2/locking/nolock/lock_nolock.ko
  INSTALL net/sctp/sctp.ko
  INSTALL net/tipc/tipc.ko
  DEPMOD  2.6.26.3
dongho9:/usr/src/linux-2.6.26.3#
vi /etc/lilo.conf
dongho9:~#
lilo
Added linux *
Added linux-old

dongho9:/usr/src/linux-2.6.26.3# reboot

Broadcast message from root@dongho9 (pts/0) (Sat Sep 20 11:04:12 2008):

The system is going down for reboot NOW!


openais
를 설치한다.
설치시에 QUICKSTART 파일을 한번쯤 읽어 보면 도움이 된다
.
Makefile
에서 DESTDIR=/usr/local 로 되어 있는 부분을 DESTDIR=/ 로 변경을 하고 진행을 하자
.
그래야 후에 /usr/local/usr/sbin 이렇게 설치가 되는 것을 방지 할 수 있다
.
그냥 두고 설치를 하면 후에 path 를 추가로 등록을 해야 하는 번거로움이 발생한다
.
설치가 끝나고 인증키를 만들면 /etc/ais 디렉토리에 생성이 된다.

dongho9:/usr/src# tar zxvf openais-0.80.3.tar.gz
dongho9:/usr/src#
cd openais-0.80.3
dongho9:/usr/src/openais-0.80.3#
less QUICKSTART
dongho9:/usr/src/openais-0.80.3#
useradd ais
dongho9:/usr/src/openais-0.80.3#
passwd ais
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

dongho9:/usr/src/openais-0.80.3# vi Makefile
dongho9:/usr/src/openais-0.80.3#
make
dongho9:/usr/src/openais-0.80.3#
make install
dongho9:/usr/src/openais-0.80.3# ais-keygen

OpenAIS Authentication key generator.
Gathering 1024 bits for key from /dev/random.
Writing openais key to /etc/ais/authkey.
dongho9:/usr/src/openais-0.80.3#
ls -l /etc/ais
total 16
-rw-r–r– 1 root root 5001 Sep 20 11:15 amf.conf
-r——– 1 root root  128 Sep 20 11:16 authkey
-rw-r–r– 1 root root  309 Sep 20 11:15 openais.conf


마지막으로 cluster 를 설치를 진행 한다.

dongho9:/usr/src# tar zxvf cluster-2.03.07.tar.gz
dongho9:/usr/src#
cd cluster-2.03.07
dongho9:/usr/src/cluster-2.03.07#
./configure –kernel_src=/usr/src/linux-2.6.26.3
Configuring Makefiles for your system…

Checking tree: nothing to do

Checking kernel:
 Current kernel version appears to be OK

Building against OpenAIS Whitetank

The following fence agents will be build on this system:
 bladecenter rsb ilo rackswitch xcat ibmblade apc_snmp mcdata scsi lpar ipmilan cpint bullpap rsa vixel zvm drac sanbox2 baytech manual vmware apc brocade gnbd wti rps10 egenera xvm ifmib

NOTE: xvm will build only if –enable_xen has been specified

Completed Makefile configuration
dongho9:/usr/src/cluster-2.03.07# make
dongho9:/usr/src/cluster-2.03.07#
make install


설치를 마치면 다음과 같은 파일들이 설치 된 것을 확인 할 수 있다.

dongho9:~# ls -lt /usr/sbin |more
total 35032
-rwxr-xr-x 1 root root   20341 Sep 20 11:53 clubufflush
-rwxr-xr-x 1 root root   11643 Sep 20 11:53 clufindhostname
-rwxr-xr-x 1 root root   41277 Sep 20 11:53 clulog
-rwxr-xr-x 1 root root    1285 Sep 20 11:53 clunfslock
-rwxr-xr-x 1 root root  590742 Sep 20 11:53 clurgmgrd
-rwxr-xr-x 1 root root   48754 Sep 20 11:53 clurmtabd
-rwxr-xr-x 1 root root  163652 Sep 20 11:53 clustat
-rwxr-xr-x 1 root root  125773 Sep 20 11:53 clusvcadm
-rwxr-xr-x 1 root root  279771 Sep 20 11:53 rg_test
-rwxr-xr-x 1 root root   39692 Sep 20 11:53 gnbd_clusterd
-rwxr-xr-x 1 root root   72737 Sep 20 11:53 gnbd_export
-rwxr-xr-x 1 root root     415 Sep 20 11:53 gnbd_get_uid
-rwxr-xr-x 1 root root   95119 Sep 20 11:53 gnbd_import
-rwxr-xr-x 1 root root   83750 Sep 20 11:53 gnbd_monitor
-rwxr-xr-x 1 root root   64996 Sep 20 11:53 gnbd_recvd
-rwxr-xr-x 1 root root  120769 Sep 20 11:53 gnbd_serv
-rwxr-xr-x 1 root root  507401 Sep 20 11:53 fsck.gfs2
lrwxrwxrwx 1 root root       9 Sep 20 11:53 gfs2_fsck -> fsck.gfs2
lrwxrwxrwx 1 root root       9 Sep 20 11:53 gfs2_grow -> mkfs.gfs2
lrwxrwxrwx 1 root root       9 Sep 20 11:53 gfs2_jadd -> mkfs.gfs2
lrwxrwxrwx 1 root root       9 Sep 20 11:53 gfs2_mkfs -> mkfs.gfs2
-rwxr-xr-x 1 root root  136416 Sep 20 11:53 gfs2_quota
-rwxr-xr-x 1 root root  320434 Sep 20 11:53 gfs2_tool
-rwxr-xr-x 1 root root  295614 Sep 20 11:53 mkfs.gfs2
-rwxr-xr-x 1 root root  248933 Sep 20 11:53 gfs2_convert
-rwxr-xr-x 1 root root  364025 Sep 20 11:53 gfs2_edit
–More–


여기 까지 설치를 세군데 서버 모두에서 동일하게 진행을 한다.

이제 DRBD 를 설치 한다.
DRBD
dongho7,dongho8 두 서버간에 연동을 할 것이므로 dongho7,8 두 서버에서만 설치를 진행 한다
.
소스 파일을 다운로드 받아서 압축을 풀고 설치를 진행 하다 보면 에러를 만나게 된다.

dongho7:/usr/src# wget http://oss.linbit.com/drbd/8.2/drbd-8.2.6.tar.gz
18:32:07—  http://oss.linbit.com/drbd/8.2/drbd-8.2.6.tar.gz
           => `drbd-8.2.6.tar.gz’
Resolving oss.linbit.com… 212.69.162.23
Connecting to oss.linbit.com|212.69.162.23|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 335,382 (328K) [application/x-tar]

100%[====================================>] 335,382      127.79K/s

18:32:12 (127.62 KB/s) – `drbd-8.2.6.tar.gz’ saved [335382/335382]

dongho7:/usr/src# tar zxvf drbd-8.2.6.tar.gz
dongho7:/usr/src# cd drbd-8.2.6

dongho7:/usr/src/drbd-8.2.6#
make clean all

make -C /lib/modules/2.6.26.3/build SUBDIRS=/usr/src/drbd-8.2.6/drbd  modules
make[2]: Entering directory `/usr/src/linux-2.6.26.3′
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_buildtag.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_bitmap.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_proc.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_worker.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_receiver.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_req.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_actlog.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/lru_cache.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_main.o
/usr/src/drbd-8.2.6/drbd/drbd_main.c: In function ‘drbd_cleanup’:
/usr/src/drbd-8.2.6/drbd/drbd_main.c:2567: error: ‘proc_root’ undeclared (first use in this function)
/usr/src/drbd-8.2.6/drbd/drbd_main.c:2567: error: (Each undeclared identifier is reported only once
/usr/src/drbd-8.2.6/drbd/drbd_main.c:2567: error: for each function it appears in.)
/usr/src/drbd-8.2.6/drbd/drbd_main.c: In function ‘drbd_init’:
/usr/src/drbd-8.2.6/drbd/drbd_main.c:2789: error: ‘proc_root’ undeclared (first use in this function)
make[3]: *** [/usr/src/drbd-8.2.6/drbd/drbd_main.o] Error 1
make[2]: *** [_module_/usr/src/drbd-8.2.6/drbd] Error 2
make[2]: Leaving directory `/usr/src/linux-2.6.26.3′
make[1]: *** [kbuild] Error 2
make[1]: Leaving directory `/usr/src/drbd-8.2.6/drbd’
make: *** [module] Error 2

 


패치가 필요하다.
아래와 같이 patch 파일을 만들어 패치를 하고 진행을 하면 된다.

dongho7:/usr/src# cat patch-drbd_main
— drbd/drbd_main.c    2008-09-01 12:01:56.000000000 +0900
+++ drbd/drbd_main.c    2008-09-01 12:02:14.000000000 +0900
@@ -2564,7 +2564,7 @@

        if (minor_table) {
                if (drbd_proc)
–                       remove_proc_entry(“drbd”, &proc_root);
+                       remove_proc_entry(“drbd”, NULL);
                i = minor_count;
                while (i–) {
                      struct drbd_conf        *mdev  = minor_to_mdev(i);
@@ -2786,7 +2786,7 @@
        /*
         * register with procfs
         */
–       drbd_proc = create_proc_entry(“drbd”,  S_IFREG | S_IRUGO , &proc_root);
+       drbd_proc = create_proc_entry(“drbd”,  S_IFREG | S_IRUGO , NULL);

        if (!drbd_proc) {
                printk(KERN_ERR “drbd: unable to register proc file\n”);


패치를 적용 시키고 다시 컴파일을 한다.

dongho7:/usr/src# cd drbd-8.2.6
dongho7:/usr/src/drbd-8.2.6# patch -p0 -l < ../patch-drbd_main

patching file drbd/drbd_main.c

dongho7:/usr/src/drbd-8.2.6# make clean all

make -C /lib/modules/2.6.26.3/build SUBDIRS=/usr/src/drbd-8.2.6/drbd  modules
make[2]: Entering directory `/usr/src/linux-2.6.26.3′
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_buildtag.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_bitmap.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_proc.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_worker.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_receiver.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_req.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_actlog.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/lru_cache.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_main.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_strings.o
  CC [M]  /usr/src/drbd-8.2.6/drbd/drbd_nl.o
  LD [M]  /usr/src/drbd-8.2.6/drbd/drbd.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /usr/src/drbd-8.2.6/drbd/drbd.mod.o
  LD [M]  /usr/src/drbd-8.2.6/drbd/drbd.ko
make[2]: Leaving directory `/usr/src/linux-2.6.26.3′
mv .drbd_kernelrelease.new .drbd_kernelrelease
Memorizing module configuration … done.
make[1]: Leaving directory `/usr/src/drbd-8.2.6/drbd’

        Module build was successful.

dongho7:/usr/src/drbd-8.2.6# make install

 


HeartBeat
를 설치한다.
HeartBeat
도 마찬가지로 dongho7,8 두 서버에서만 설치를 한다
.
편하게 apt-get 을 이용하여 설치를 한다.

dongho7:~# apt-get install heartbeat-2

 

 

설정


우선 /etc/init.d/cman 스크립트가 redhat 용으로 만들어져 있어 이를 수정이 좀 필요하다. 그리고 데몬 시작시에 start-stop-daemon 를 사용하도록 되어 있지 않고 기존 redhat /etc/init.d/functions 의 정의된 함수를 이용해서 사용을 하도록 되어 있어 redhat /etc/init.d/functions 를 복사해서 사용하는게 편리하다. functions 에서는  한가지 initlog 프로그램은 logger 라는 프로그램으로 대체해서 사용하도록 수정을 해서 사용을 했다.
아래는 수정한 functions 파일이다.

dongho9:/etc/init.d# vi functions
dongho9:/etc/init.d#
chmod 755 functions
dongho9:~#
cat /etc/init.d/functions
#!/bin/bash
#
# functions     This file contains functions to be used by most or all
#               shell scripts in the /etc/init.d directory.
#
# Version:      @(#) /etc/init.d/functions 1.01 26-Oct-1993
#
# Author:       Miquel van Smoorenburg, <
miquels@drinkel.nl.mugnet.org>
# Hacked by:    Greg Galloway and Marc Ewing
#
#
# i18n originally by:   Arnaldo Carvalho de Melo <
acme@conectiva.com.br>,
#                       Wanderlei Antonio Cavassin
TEXTDOMAIN=initscripts
TEXTDOMAINDIR=/etc/locale

# Make sure umask is sane
umask 022

# First set up a default search path.
export PATH=”/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin”

# Get a sane screen width
[ -z “${COLUMNS:-}” ] && COLUMNS=80

if [ -f /etc/sysconfig/i18n -a -z “${NOLOCALE:-}” ] ; then
  . /etc/sysconfig/i18n
  if [ “${LANG:-}” = “ja_JP.eucJP” -a “`/sbin/consoletype`” != “pty” ]; then
    unset LANG
  elif [ “${LANG:-}” = “ko_KR.eucKR” -a “`/sbin/consoletype`” != “pty” ]; then
    unset LANG
elif [ “${LANG:-}” = “zh_CN.GB2312” -a “`/sbin/consoletype`” != “pty” ]; then
    unset LANG
  elif [ “${LANG:-}” = “zh_TW.Big5” -a “`/sbin/consoletype`” != “pty” ]; then
    unset LANG
  else
    export LANG
  fi
fi

# Read in our configuration
if [ -z “${BOOTUP:-}” ]; then
  if [ -f /etc/sysconfig/init ]; then
      . /etc/sysconfig/init
  else
    # This all seem confusing? Look in /etc/sysconfig/init,
    # or in /usr/doc/initscripts-*/sysconfig.txt
    BOOTUP=color
    RES_COL=60
    MOVE_TO_COL=”echo -en
\\033[${RES_COL}G
    SETCOLOR_SUCCESS=”echo -en
\\033[1;32m
    SETCOLOR_FAILURE=”echo -en
\\033[1;31m
    SETCOLOR_WARNING=”echo -en
\\033[1;33m
    SETCOLOR_NORMAL=”echo -en
\\033[0;39m
    LOGLEVEL=1
  fi
  if [ -x /sbin/consoletype ]; then
    if [ “`consoletype`” = “serial” ]; then
      BOOTUP=serial
      MOVE_TO_COL=
      SETCOLOR_SUCCESS=
      SETCOLOR_FAILURE=
      SETCOLOR_WARNING=
      SETCOLOR_NORMAL=
    fi
fi
fi

if [ “${BOOTUP:-}” != “verbose” ]; then
   INITLOG_ARGS=”-q”
else
   INITLOG_ARGS=
fi

# Check if $pid (could be plural) are running
checkpid() {
        while [ “$1” ]; do
           [ -d /proc/$1 ] && return 0
           shift
        done
        return 1
}

 


# A function to start a program.
daemon() {
        # Test syntax.
        local gotbase= force=
        local base= user= nice= bg= pid
        nicelevel=0
        while [ “$1” != “${1##[-+]}” ]; do
          case $1 in
            ”)    echo $”$0: Usage: daemon [+/-nicelevel] {program}”
                   return 1;;
            –check)
                   base=$2
                   gotbase=”yes”
                   shift 2
                   ;;
          –check=?*)
                   base=${1#–check=}
                   gotbase=”yes”
                   shift
                   ;;
            –user)
                   user=$2
                   shift 2
                   ;;
            –user=?*)
                   user=${1#–user=}
                   shift
                   ;;
            –force)
                   force=”force”
                   shift
                   ;;
            [-+][0-9]*)
                   nice=”nice -n $1″
                   shift
                   ;;
            *)     echo $”$0: Usage: daemon [+/-nicelevel] {program}”
                   return 1;;
          esac
        done

        # Save basename.
        [ -z “$gotbase” ] && base=${1##*/}

        # See if it’s already running. Look *only* at the pid file.
        pid=`pidfileofproc $base`

        [ -n “${pid:-}” -a -z “${force:-}” ] && return

        # make sure it doesn’t core dump anywhere; while this could mask
        # problems with the daemon, it also closes some security problems
        ulimit -S -c 0 >/dev/null 2>&1

        # Echo daemon
        [ “${BOOTUP:-}” = “verbose” -a -z “$LSB” ] && echo -n ” $base”

        # And start it up.
        if [ -z “$user” ]; then
           #$nice initlog $INITLOG_ARGS -c “$*”
           /usr/bin/logger -p local0.info “$*”
        else
           #$nice initlog $INITLOG_ARGS -c “su -s /bin/bash – $user -c \”$*\””
           /usr/bin/logger -p local0.info “su -s /bin/bash – $user -c \”$*\””
        fi
        [ “$?” -eq 0 ] && success $”$base startup” || failure $”$base startup”
}

# A function to stop a program.
killproc() {
        RC=0
        # Test syntax.
        if [ “$#” -eq 0 ]; then
                echo $”Usage: killproc {program} [signal]”
                return 1
        fi

        notset=0
        # check for second arg to be kill level
        if [ “$2” != “” ] ; then
                killlevel=$2
        else
                notset=1
                killlevel=”-9″
        fi

        # Save basename.
        base=${1##*/}

        # Find pid.
        pid=`pidofproc $1`
        if [ -z “${pid:-}” ] ; then
                pid=`pidofproc $base`
        fi

        # Kill it.
        if [ -n “${pid:-}” ] ; then
                [ “$BOOTUP” = “verbose” -a -z “$LSB” ] && echo -n “$base “
                if [ “$notset” -eq “1” ] ; then
                       if checkpid $pid 2>&1; then
                           # TERM first, then KILL if not dead
                           kill -TERM $pid
                           usleep 100000
                           if checkpid $pid && sleep 1 &&
                              checkpid $pid && sleep 3 &&
                              checkpid $pid ; then
                                kill -KILL $pid
                                usleep 100000
                           fi
                        fi
                        checkpid $pid
                        RC=$?
                        [ “$RC” -eq 0 ] && failure $”$base shutdown” || success $”$base shutdown”
                        RC=$((! $RC))
                # use specified level only
                else
                        if checkpid $pid >/dev/null 2>&1; then
                                kill $killlevel $pid
                                RC=$?
                                [ “$RC” -eq 0 ] && success $”$base $killlevel” || failure $”$base $killlevel”
                        fi
                fi
        else
            failure $”$base shutdown”
            RC=1
        fi

        # Remove pid file if any.
        if [ “$notset” = “1” ]; then
            rm -f /var/run/$base.pid
        fi
        return $RC
}

# A function to find the pid of a program. Looks *only* at the pidfile
pidfileofproc() {
        local base=${1##*/}
        local pid

        # Test syntax.
        if [ “$#” = 0 ] ; then
                echo $”Usage: pidfileofproc {program}”
                return 1
        fi

        # First try “/var/run/*.pid” files
        if [ -f /var/run/${base}.pid ] ; then
                local line p pid=
                read line < /var/run/${base}.pid
                for p in $line ; do
                       [ -z “${p//[0-9]/}” -a -d /proc/$p ] && pid=”$pid $p”
                done
                if [ -n “${pid:-}” ] ; then
                        echo $pid
                        return 0
                fi
        fi
}

# A function to find the pid of a program.
pidofproc() {
        base=${1##*/}

        # Test syntax.
        if [ “$#” = 0 ] ; then
                echo $”Usage: pidofproc {program}”
                return 1
        fi

        # First try “/var/run/*.pid” files
        if [ -f /var/run/${base}.pid ] ; then
                local line p pid=
                read line < /var/run/${base}.pid
                for p in $line ; do
                       [ -z “${p//[0-9]/}” -a -d /proc/$p ] && pid=”$pid $p”
                done
                if [ -n “${pid:-}” ] ; then
                        echo $pid
                        return 0
                fi
        fi

        # Next try “pidof”
        pidof -o $$ -o $PPID -o %PPID -x $1 || \
        pidof -o $$ -o $PPID -o %PPID -x ${base}
}

status() {
        local base=${1##*/}
        local pid

        # Test syntax.
        if [ “$#” = 0 ] ; then
                echo $”Usage: status {program}”
                return 1
        fi

        # First try “pidof”
        pid=`pidof -o $$ -o $PPID -o %PPID -x $1 || \
             pidof -o $$ -o $PPID -o %PPID -x ${base}`
        if [ “$pid” != “” ] ; then
                echo $”${base} (pid $pid) is running…”
                return 0
        fi

        # Next try “/var/run/*.pid” files
        if [ -f /var/run/${base}.pid ] ; then
                read pid < /var/run/${base}.pid
                if [ “$pid” != “” ] ; then
                        echo $”${base} dead but pid file exists”
                        return 1
                fi
        fi
        # See if /var/lock/${base} exists
        if [ -f /var/lock/${base} ]; then
                echo $”${base} dead but subsys locked”
                return 2
        fi
        echo $”${base} is stopped”
        return 3
}

echo_success() {
  [ “$BOOTUP” = “color” ] && $MOVE_TO_COL
  echo -n “[  “
  [ “$BOOTUP” = “color” ] && $SETCOLOR_SUCCESS
  echo -n $”OK”
  [ “$BOOTUP” = “color” ] && $SETCOLOR_NORMAL
  echo -n ”  ]”
  echo -ne “\r”
  return 0
}

echo_failure() {
  [ “$BOOTUP” = “color” ] && $MOVE_TO_COL
  echo -n “[“
  [ “$BOOTUP” = “color” ] && $SETCOLOR_FAILURE
  echo -n $”FAILED”
  [ “$BOOTUP” = “color” ] && $SETCOLOR_NORMAL
  echo -n “]”
  echo -ne “\r”
  return 1
}

echo_passed() {
  [ “$BOOTUP” = “color” ] && $MOVE_TO_COL
  echo -n “[“
  [ “$BOOTUP” = “color” ] && $SETCOLOR_WARNING
  echo -n $”PASSED”
  [ “$BOOTUP” = “color” ] && $SETCOLOR_NORMAL
  echo -n “]”
  echo -ne “\r”
  return 1
}

echo_warning() {
  [ “$BOOTUP” = “color” ] && $MOVE_TO_COL
  echo -n “[“
  [ “$BOOTUP” = “color” ] && $SETCOLOR_WARNING
  echo -n $”WARNING”
  [ “$BOOTUP” = “color” ] && $SETCOLOR_NORMAL
  echo -n “]”
  echo -ne “\r”
  return 1
}

# Log that something succeeded
success() {
  if [ -z “${IN_INITLOG:-}” ]; then
     #initlog $INITLOG_ARGS -n $0 -s “$1” -e 1
     /usr/bin/logger -p daemon.info -t $0 “succeeded $1”
  else
     # silly hack to avoid EPIPE killing rc.sysinit
     trap “” SIGPIPE
     echo “$INITLOG_ARGS -n $0 -s \”$1\” -e 1″ >&21
     trap – SIGPIPE
  fi
  [ “$BOOTUP” != “verbose” -a -z “$LSB” ] && echo_success
  return 0
}

# Log that something failed
failure() {
  rc=$?
  if [ -z “${IN_INITLOG:-}” ]; then
     #initlog $INITLOG_ARGS -n $0 -s “$1” -e 2
     /usr/bin/logger -p daemon.info -t $0 “failed $1”
  else
     trap “” SIGPIPE
     echo “$INITLOG_ARGS -n $0 -s \”$1\” -e 2″ >&21
     trap – SIGPIPE
  fi
  [ “$BOOTUP” != “verbose” -a -z “$LSB” ] && echo_failure
  return $rc
}

# Log that something passed, but may have had errors. Useful for fsck
passed() {
  rc=$?
  if [ -z “${IN_INITLOG:-}” ]; then
     #initlog $INITLOG_ARGS -n $0 -s “$1” -e 1
     /usr/bin/logger -p daemon.info -t $0 “succeeded $1”
  else
     trap “” SIGPIPE
     echo “$INITLOG_ARGS -n $0 -s \”$1\” -e 1″ >&21
     trap – SIGPIPE
  fi
  [ “$BOOTUP” != “verbose” -a -z “$LSB” ] && echo_passed
  return $rc
}

# Log a warning
warning() {
  rc=$?
  if [ -z “${IN_INITLOG:-}” ]; then
     #initlog $INITLOG_ARGS -n $0 -s “$1” -e 1
     /usr/bin/logger -p daemon.info -t $0 “succeeded $1”
  else
     trap “” SIGPIPE
     echo “$INITLOG_ARGS -n $0 -s \”$1\” -e 1″ >&21
     trap – SIGPIPE
  fi
  [ “$BOOTUP” != “verbose” -a -z “$LSB” ] && echo_warning
  return $rc
}

# Run some action. Log its output.
action() {
  STRING=$1
  echo -n “$STRING “
  shift
  #initlog $INITLOG_ARGS -c “$*” && success $”$STRING” || failure $”$STRING”
  /usr/bin/logger -p local0.info “$*” && success $”$STRING” || failure $”$STRING”
  rc=$?
  echo
  return $rc
}

# returns OK if $1 contains $2
strstr() {
  [ “$1” = “$2” ] && return 0
  slice=${1#*$2*}
  [ “$slice” = “$1” ] && return 1
  return 0
}

# Confirm whether we really want to run this service
confirm() {
  local YES=$”yY”
  local NO=$”nN”
  local CONT=$”cC”

  while : ; do
      echo -n $”Start service $1 (Y)es/(N)o/(C)ontinue? [Y] “
      read answer
      if strstr “$YES” “$answer” || [ “$answer” = “” ] ; then
         return 0
      elif strstr “$CONT” “$answer” ; then
         return 2
      elif strstr “$NO” “$answer” ; then
         return 1
      fi
  done
}


그리고 /etc/init.d/cman 스크립트의 경우 경로가 debian 의 패키지 설치된 것과 다른게 있으며 cluster 소스 컴파일 하여 설치된 것은 /usr/sbin/ 아래에 명령이 설치가 되어 있어 이 부분을 수정이 필요하다. 아래 수정된 버전이다.

dongho9:/etc/init.d# cat cman
#!/bin/bash
#
# cman – Cluster Manager init script
#
# chkconfig: – 21 79
# description: Starts and stops cman
#
#
### BEGIN INIT INFO
# Provides:             cman
# Required-Start:       $network
# Required-Stop:        $network
# Default-Start:
# Default-Stop:
# Short-Description:    Starts and stops cman
# Description:          Starts and stops the Cluster Manager set of daemons
### END INIT INFO

. /etc/init.d/functions

[ -f /etc/sysconfig/cman ] && . /etc/sysconfig/cman
[ -z “$CCSD_OPTS” ] && CCSD_OPTS=

# CMAN_CLUSTER_TIMEOUT — amount of time to wait for joinging a cluster
#     before giving up.  If CMAN_CLUSTER_TIMEOUT is positive, then we will
#     wait CMAN_CLUSTER_TIMEOUT seconds before giving up and failing when
#     a cluster is not joined.  If CMAN_CLUSTER_TIMEOUT is zero, then
#     wait indefinately for a cluster join.  If CMAN_CLUSTER_TIMEOUT is
#     negative, do not check to see that the cluster has been joined
[ -z “$CMAN_CLUSTER_TIMEOUT” ] && CMAN_CLUSTER_TIMEOUT=120

# CMAN_QUORUM_TIMEOUT — amount of time to wait for a quorate cluster on
#     startup quorum is needed by many other applications, so we may as
#     well wait here.  If CMAN_QUORUM_TIMEOUT is less than 1, quorum will
#     be ignored.
[ -z “$CMAN_QUORUM_TIMEOUT” ] && CMAN_QUORUM_TIMEOUT=0

# CMAN_SHUTDOWN_TIMEOUT — amount of time to wait for cman to become a
#     cluster member before calling cman_tool leave during shutdown.
#     The default is 60 seconds
[ -z “$CMAN_SHUTDOWN_TIMEOUT” ] && CMAN_SHUTDOWN_TIMEOUT=60

# FENCED_START_TIMEOUT — amount of time to wait for starting fenced
#     before giving up.  If FENCED_START_TIMEOUT is positive, then we will
#     wait FENCED_START_TIMEOUT seconds before giving up and failing when
#     fenced does not start.  If FENCED_START_TIMEOUT is zero, then
#     wait indefinately for fenced to start.
[ -z “$FENCED_START_TIMEOUT” ] && FENCED_START_TIMEOUT=300

# NET_RMEM_DEFAULT — minimum value for rmem_default. If this is set
# higher elsewhere it will not be reduced here.
# These two values are only really needed for the DLM when using sctp
# but do no harm.
[ -z “$NET_RMEM_DEFAULT” ] && NET_RMEM_DEFAULT=4194304

# NET_RMEM_MAX — minimum value for rmem_max. If this is set
# higher elsewhere it will not be reduced here.
[ -z “$NET_RMEM_MAX” ] && NET_RMEM_MAX=4194304

# FENCE_JOIN — boolean value used to control whether or not this node
#     should join the fence domain. If FENCE_JOIN is set to “no”, then
#     the script will not attempt to the fence domain. If FENCE_JOIN is
#     set to “yes”, then the script will attempt to join the fence domain.
#     If FENCE_JOIN is set to any other value, the default behavior is
#     to join the fence domain (equivalent to “yes”).
[ -z “$FENCE_JOIN” ] && FENCE_JOIN=”yes”

[ -z “$LOCK_FILE” ] && LOCK_FILE=”/var/lock/cman”

[ -n “$CLUSTERNAME” ] && cman_join_opts=”-c $CLUSTERNAME”

[ -n “$NODENAME” ] && cman_join_opts+=” -n $NODENAME”

load_modules()
{
    errmsg=$( /sbin/modprobe configfs 2>&1 ) || return 1
    errmsg=$( /sbin/modprobe dlm 2>&1 ) || return 1
    errmsg=$( /sbin/modprobe lock_dlm 2>&1 ) || return 1
    return 0
}

start_configfs()
{
    # configfs
    awk ‘{ print $2 }’ /etc/mtab | grep “/sys/kernel/config” &> /dev/null \
    && awk ‘{ print $3 }’ /etc/mtab | grep “configfs” &> /dev/null
    if [ $? -ne 0 ]
    then
        errmsg=$( /bin/mount -t configfs none /sys/kernel/config 2>&1 )
        return $?
    fi
    return 0
}

start_ccsd()
{
    # ccsd
    status ccsd &> /dev/null
    if [ $? -ne 0 ]
    then
        errmsg=$(/usr/sbin/ccsd $CCSD_OPTS 2>&1)
        rtrn=$?
        return $rtrn
    fi
    return 0
}

start_cman()
{
    # cman
    /usr/sbin/cman_tool status &> /dev/null
    if [ $? -ne 0 ]
    then
        errmsg=$( /usr/sbin/cman_tool -t $CMAN_CLUSTER_TIMEOUT -w join \
            $cman_join_opts 2>&1 ) || return 1

        if [ $CMAN_QUORUM_TIMEOUT -gt 0 ]
        then
            errmsg=$( /usr/sbin/cman_tool -t $CMAN_QUORUM_TIMEOUT \
                  -q wait 2>&1 ) || return 1
        fi
    fi
    return 0
}

 


start_qdiskd()
{
    declare current_runlevel

    current_runlevel=$(/sbin/runlevel 2>/dev/null | awk ‘{ print $2 }’ 2>/dev/null)
    #
    # Start qdiskd before fenced to resolve bug #436381.  This only
    # happens if qdiskd is configured to run in the runlevel we are in
    #
    /sbin/chkconfig –levels “$current_runlevel” qdiskd 2>/dev/null
    if [ $? -ne 0 ]; then
        # qdiskd doesn’t start at this runlevel.
        return 0
    fi

    echo -n ”   Starting qdiskd… “
    /sbin/service qdiskd start &> /dev/null
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi
    return 0
}


start_daemons()
{
    status groupd &> /dev/null
    if [ $? -ne 0 ]; then
        errmsg=$( /usr/sbin/groupd 2>&1 ) || return 1
    fi
    status fenced &> /dev/null
    if [ $? -ne 0 ]; then
        errmsg=$( /usr/sbin/fenced 2>&1 ) || return 1
    fi
    status dlm_controld &> /dev/null
    if [ $? -ne 0 ]; then
        errmsg=$( /usr/sbin/dlm_controld 2>&1 ) || return 1
    fi
    status gfs_controld &> /dev/null
    if [ $? -ne 0 ]; then
        errmsg=$( /usr/sbin/gfs_controld 2>&1 ) || return 1
    fi
    return 0
}

start_fence()
{
    errmsg=$( /usr/sbin/fence_tool -w -t $FENCED_START_TIMEOUT join \
             > /dev/null 2>&1 ) || return 1
    return 0
}

start_fence_xvmd()
{
    status fence_xvmd &> /dev/null
    if [ $? -ne 0 ]; then
        errmsg=$( /usr/sbin/fence_xvmd $FENCE_XVMD_OPTS 2>&1 ) || return 1
    fi
    return 0
}

xend_bridged_net_enabled() {
      # Not a xen kernel
        test -d /proc/xen || return 1

    current_runlevel=$(/sbin/runlevel 2>/dev/null | awk ‘{ print $2 }’ 2>/dev/null)
    if [ -z “$current_runlevel” ]; then
        errmsg=’Unable to determine the current runlevel’
        return 1
    fi

    /sbin/chkconfig –levels “$current_runlevel” xend 2>/dev/null
    if [ $? -ne 0 ]; then
        # xend doesn’t start at this runlevel.
        return 1
    fi

    if [ ! -f /etc/xen/xend-config.sxp ]; then
        # xend isn’t configured to use bridged networking.
        return 1
    fi

    egrep “^[[:blank:]]*\([[:blank:]]*network-script[[:blank:]]+(‘)?[[:blank:]]*network-bridge([[:blank:]]*\)|[[:blank:]]+)” /etc/xen/xend-config.sxp >&/dev/null
    if [ $? -ne 0 ]; then
        # xend isn’t configured to use bridged networking.
        return 1
    fi
    return 0
}

xend_bridged_net_start() {
    if [ ! -x /etc/xen/scripts/network-bridge ]; then
        if [ -f /etc/xen/scripts/network-bridge ]; then
            errmsg=’The xend bridged network script cannot be run’
        else
            errmsg=’The xend bridged network script is missing’
        fi
        return 1
    fi

    /sbin/modprobe netbk >& /dev/null
    /sbin/modprobe netloop >& /dev/null
    bridge_parms=`egrep -m 1 “^[[:blank:]]*\([[:blank:]]*network-script[[:blank:]]+(‘)?[[:blank:]]*network-bridge([[:blank:]]*\)|[[:blank:]]+)” /etc/xen/xend-config.sxp| sed -r “s/^[[:blank:]]*\([[:blank:]]*network-script[[:blank:]]+’?[[:blank:]]*network-bridge[[:blank:]]*//; s/’?[[:blank:]]*\).*//”`
    errmsg=$(/etc/xen/scripts/network-bridge start $bridge_parms 2>&1) || return 1
    return 0
}

fence_xvmd_enabled()
{
    #
    # Check the value of FENCE_JOIN.
    # If FENCE_JOIN is set to “no”, then we should disable fence_xvm.
    #
    if [ “$FENCE_JOIN” == “no” ]; then
        return 1
    fi

    #
    # Check for the ‘xm’ binary.  If it’s not here, we are not
    # running on a machine capable of running xvmd.
    #
    which xm &> /dev/null || return 1

    #
    # Check for presence of /cluster/fence_xvmd in cluster.conf
    # (If -X is specified, it doesn’t matter if it’s in cluster.conf;
    #  we’ll start it anyway since ccsd is not required)
    #
    if [ “$FENCE_XVMD_OPTS” = “${FENCE_XVMD_OPTS/-X/}” ]; then
        xmllint –shell /etc/cluster/cluster.conf 2> /dev/null \
            < <(echo ls cluster) | grep -q fence_xvmd || return 1
    fi

    return 0
}

#<<<<<<< HEAD:cman/init.d/cman.in
set_networking_params()
{
    if [ ! -f  /proc/sys/net/core/rmem_default ]
    then
        return 0;
    fi

    value=”$(cat /proc/sys/net/core/rmem_default)”
    if [ $value -le $NET_RMEM_DEFAULT ]
    then
        echo $NET_RMEM_DEFAULT > /proc/sys/net/core/rmem_default
    fi

    value=”$(cat /proc/sys/net/core/rmem_max)”
    if [ $value -le $NET_RMEM_MAX ]
        then
        echo $NET_RMEM_MAX > /proc/sys/net/core/rmem_max
    fi
}

fence_join_enabled()
{
    #
    # Check the value of FENCE_JOIN.
    # If FENCE_JOIN is set to “no”, we will not attempt to join
    # the fence domain. If FENCE_JOIN is set to any other value,
    # we will attempt to join the fence domain (default).
    #
    if [ “$FENCE_JOIN” == “no” ]; then
        return 1
    else
        return 0
    fi
}

start()
{
    echo “Starting cluster: “

    xend_bridged_net_enabled
    if [ $? -eq 0 ]
    then
        echo -n ”   Enabling workaround for Xend bridged networking… “
        xend_bridged_net_start
        if [ $? -eq 0 ]
        then
            echo “done”
        else
            echo “failed: $errmsg”
                        return 1
        fi
    fi

    echo -n ”   Loading modules… “
    ulimit -c unlimited
    load_modules
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    echo -n ”   Mounting configfs… “
    start_configfs
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    echo -n ”   Setting network parameters… “
    set_networking_params
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    echo -n ”   Starting ccsd… “
    start_ccsd
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    echo -n ”   Starting cman… “
    start_cman
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    start_qdiskd

    echo -n ”   Starting daemons… “
    start_daemons
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    if fence_join_enabled; then
        echo -n ”   Starting fencing… “
        start_fence
        if [ $? -eq 0 ]
            then
            echo “done”
        else
            echo “failed”
            return 1
        fi
    fi

    if fence_xvmd_enabled; then
        echo -n ”   Starting virtual machine fencing host… “
        start_fence_xvmd
        if [ $? -eq 0 ]
        then
            echo “done”
        else
            echo “failed”
        return 1
        fi
    fi

    return 0
}

stop_configfs()
{
    awk ‘{ print $2 }’ /etc/mtab | grep “/sys/kernel/config” &> /dev/null\
    && awk ‘{ print $3 }’ /etc/mtab | grep “configfs” &> /dev/null
    if [ $? -eq 0 ] && [ -z “$(ls -1 /sys/kernel/config)” ]
    then
        errmsg=$( /bin/umount /sys/kernel/config 2>&1 )
        if [ $? -ne 0 ]
        then
            echo -n $errmsg ” “
        fi
    fi
    return 0
}

stop_ccsd()
{
    for sec in $(seq 1 10)
    do
        if /bin/pidof ccsd &> /dev/null
        then
            # get the pid of ccsd from /var/run/cluster/ccsd.pid
            # and break if the file is not there
            [ -r /var/run/cluster/ccsd.pid ] || break

            pid=$(cat /var/run/cluster/ccsd.pid)
            /bin/kill $pid &> /dev/null || break

            sleep 1
        else
            return 0
        fi
    done
    return 1
}

stop_cman()
{
    /usr/sbin/cman_tool status &> /dev/null
    if [ $? -eq 0 ]
    then
    errmsg=$( /usr/sbin/cman_tool -t $CMAN_SHUTDOWN_TIMEOUT \
            -w leave $1 2>&1 ) || return 1
    fi
    return 0 # all ok
}

stop_daemons()
{
    if pid=$(/bin/pidof gfs_controld 2>&1); then
        errmsg=$(/bin/kill $pid 2>&1) || return 1
    fi
    if pid=$(/bin/pidof dlm_controld 2>&1); then
        errmsg=$(/bin/kill $pid 2>&1) || return 1
    fi
    if pid=$(/bin/pidof fenced 2>&1); then
        errmsg=$(/bin/kill $pid 2>&1) || return 1
    fi
    if pid=$(/bin/pidof groupd 2>&1); then
        errmsg=$(/bin/kill $pid 2>&1) || return 1
    fi
    return 0 # all ok
}

stop_fence()
{
    if /bin/pidof fenced &> /dev/null
    then
        /usr/sbin/fence_tool -w leave > /dev/null 2>&1
        rtrn=$?
        sleep 1 # A bit of time for fenced to exit
        return $rtrn
    fi
    return 0 # all ok
}

stop_fence_xvmd()
{
    if /bin/pidof fence_xvmd &> /dev/null
    then
        pkill -TERM fence_xvmd
        sleep 1 # A bit of time for fenced to exit
    fi

    [ -z “`pidof fence_xvmd`” ]
    return $?
}

stop()
{
    echo “Stopping cluster: “

    if fence_xvmd_enabled; then
        echo -n ”   Stopping virtual machine fencing host… “
        stop_fence_xvmd
        if [ $? -eq 0 ]
        then
            echo “done”
        else
            echo “failed”
            return 1
        fi
    fi

    if fence_join_enabled; then
        echo -n ”   Stopping fencing… “
        stop_fence
        if [ $? -eq 0 ]
            then
            echo “done”
        else
            echo “failed”
            return 1
        fi
    fi

    echo -n ”   Stopping cman… “
    if [ $1 ]; then
        stop_cman $1
    else
        stop_cman
    fi
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

#   stop_daemons
#   [ $? -ne 0 ] && return 1

    echo -n ”   Stopping ccsd… “
    stop_ccsd
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    echo -n ”   Unmounting configfs… “
    stop_configfs
    if [ $? -eq 0 ]
    then
        echo “done”
    else
        echo “failed”
        return 1
    fi

    return 0
}

cmanstatus()
{
        errmsg=$( status ccsd 2>&1) || return 1
        errmsg=$( status groupd 2>&1) || return 1
        errmsg=$( status fenced 2>&1) || return 1
        errmsg=$( status dlm_controld 2>&1) || return 1
        errmsg=$( status gfs_controld 2>&1) || return 1

        fence_xvmd_enabled || return 0
        errmsg=$( status fence_xvmd 2>&1) || return 1

        return 0
}

rtrn=1

# See how we were called.
case “$1” in
    start)
        start
        rtrn=$?
        [ $rtrn = 0 ] && touch $LOCK_FILE
        if [ $rtrn -ne 0 ]
        then
            echo $errmsg
            failure “failed to start cman”
            echo
        else
            success “start”
            echo
        fi
        ;;
    stop)
        if [ $2 ]; then
            stop
        else
            stop remove
        fi
        rtrn=$?
        [ $rtrn = 0 ] && rm -f $LOCK_FILE
        if [ $rtrn -ne 0 ]
        then
            echo $errmsg
            failure “failed to stop cman”
            echo
        else
            success “shutdown”
            echo
        fi
        ;;

    restart|reload)
        $0 stop restart
        $0 start
        rtrn=$?
        ;;

    status)
        cmanstatus
        rtrn=$?
        if [ $rtrn -ne 0 ] ; then
            echo $errmsg
        else
            echo “cman is running.”
        fi
        ;;

    *)
            echo $”Usage: $0 {start|stop|reload|restart|status}”
            ;;
esac

exit $rtrn


openais
의 설정 파일도 수정을 한다.
bindnetaddr: 192.168.2.0
를 자신의 아이피 대역 network address로 적는다.

dongho9:/etc/ais# vi openais.conf
dongho9:/etc/ais# cat openais.conf

# Please read the openais.conf.5 manual page

totem {
        version: 2
        secauth: off
      threads: 0
        interface {
                ringnumber: 0
                bindnetaddr: 10.30.6.0
                mcastaddr: 226.94.1.1
                mcastport: 5405
        }
}

logging {
        to_stderr: yes
        to_file: yes
        logfile: /tmp/ais
        debug: off
        timestamp: on
}

amf {
        mode: disabled
}


/etc/hosts
에 서버들을 등록을 한다.

dongho9:/etc# vi /etc/hosts
dongho9:/etc#
cat /etc/hosts
10.30.6.13            dongho7.freeb.net dongho7
10.30.6.14            dongho8.freeb.net dongho8
10.30.6.15            dongho9.freeb.net dongho9
127.0.0.1               localhost.localdomain localhost


여기까지는 세군데 서버에서 동일하게 모두 설정을 한다.
그리고 아래 cluster.conf 는 한 서버에서만 설정을 하고 나머지 서버들은 빈 디렉토리만 만들어 놓으면 된다.

dongho9:~# mkdir /etc/cluster
dongho9:~# vi /etc/cluster/cluster.conf

dongho9:~#
cat /etc/cluster/cluster.conf
<?xml version=”1.0″?>
<cluster name=”donghocluster” config_version=”1″>
<cman expected_votes=”1″ >
</cman>

<fence_daemon post_join_delay=”60″>
</fence_daemon>

<clusternodes>
<clusternode name=”dongho7″ nodeid=”1″ votes=”1″>
        <fence>
                <method name=”single”>
                  <device name=”gnbd” nodename=”dongho7″/>
                </method>
        </fence>
</clusternode>
<clusternode name=”dongho8″ nodeid=”2″ votes=”1″>
        <fence>
                <method name=”single”>
                  <device name=”gnbd” nodename=”dongho8″/>
                </method>
        </fence>
</clusternode>
<clusternode name=”dongho9″ nodeid=”3″ votes=”1″>
        <fence>
                <method name=”single”>
                  <device name=”gnbd” nodename=”dongho9″/>
                </method>
        </fence>
</clusternode>

</clusternodes>
<fencedevices>
        <fencedevice name=”gnbd” agent=”fence_gnbd”/>
</fencedevices>
<rm/>
</cluster>


우선 여까지 잘 돌아 가는지 체크를 하고 DRBD Heartbeat 를 연동해 본다.
먼저 cman 스크립트를 이용하여 데몬이 잘 뜨는지 모든 노드에서 데몬을 시작해 본다
.
그리고 정상적으로 잘 join 되어서 도는지 등을 체크해 본다.

dongho9:~# /etc/init.d/cman start
Starting cluster:
   Loading modules… done
   Mounting configfs… done
   Setting network parameters… done
   Starting ccsd… done
   Starting cman… done
   Starting daemons… done
   Starting fencing… done
                                                           [  OK  ]

dongho9:~# cman_tool nodes
Node  Sts   Inc   Joined               Name
   1   M    180   2008-09-30 07:49:15  dongho7
   2   M    180   2008-09-30 07:49:15  dongho8
   3   M    176   2008-09-30 07:49:15  dongho9

dongho9:~# cman_tool services
type             level name     id       state
fence            0     default  00010003 none
[1 2 3]

dongho9:~# cman_tool status
Version: 6.1.0
Config Version: 1
Cluster Name: donghocluster
Cluster Id: 4532
Cluster Member: Yes
Cluster Generation: 180
Membership state: Cluster-Member
Nodes: 3
Expected votes: 2
Total votes: 3
Node votes: 1
Quorum: 2
Active subsystems: 7
Flags: Dirty
Ports Bound: 0
Node name: dongho9
Node ID: 3
Multicast addresses: 239.192.17.197
Node addresses: 10.30.6.15

dongho9:~# clustat
Cluster Status for donghocluster @ Tue Sep 30 07:50:32 2008
Member Status: Quorate

 Member Name                             ID   Status
 —— —-                             —- ——
 dongho7                                     1 Online
 dongho8                                     2 Online
 dongho9                                     3 Online, Local


기본적으로 잘 돌아가는 것을 확인하였으니 일단 데몬을 내리고 후속 작업에 들어 간다.

dongho9:~# /etc/init.d/cman stop
Stopping cluster:
   Stopping fencing… done
   Stopping cman… done
   Stopping ccsd… done
   Unmounting configfs… done
                                                           [  OK  ]


DRBD
설정을 한다.
먼저 비어 있는 파티션 혹은 깨도 되는 파티션을 정해서 다음의 conf 파일을 만든다.

dongho7:~# cat /etc/drbd.conf
resource “cluster2” {
        protocol C;
        handlers {
                pri-on-incon-degr “echo ‘pri-on-incon-degr'”;
              pri-lost-after-sb “echo ‘pri-lost-after-sb'”;
                local-io-error “echo ‘local-io-error'”;
        }
        startup {
                wfc-timeout 300;
                degr-wfc-timeout 120;
                #become-primary-on both;
        }
        disk {
                on-io-error detach;
        }
        net {
                timeout 60;
                connect-int 10;
                ping-int 10;
                max-buffers 20000;
                max-epoch-size 20000;
                unplug-watermark 20000;
                allow-two-primaries;

        }
        syncer {
                rate    512M;
                verify-alg md5;
        }

        on dongho7 {
                device  /dev/drbd1;
                disk    /dev/sda7;
                address 192.168.0.13:7790;
                meta-disk internal;
        }
        on dongho8 {
                device  /dev/drbd1;
                disk    /dev/sda7;
                address 192.168.0.14:7790;
                meta-disk internal;
        }
}


이제 meta data 를 만든다.

dongho7:~# drbdadm create-md cluster2
v08 Magic number not found
md_offset 41299091456
al_offset 41299058688
bm_offset 41297797120

Found some data
 ==> This might destroy existing data! <==

Do you want to proceed?
[need to type ‘yes’ to confirm]
yes

v07 Magic number not found
v07 Magic number not found
v08 Magic number not found
Writing meta data…
initialising activity log
NOT initialized bitmap
New drbd meta data block sucessfully created.

                –== Creating metadata ==–
As with nodes, we count the total number of devices mirrored by DRBD at
at
http://usage.drbd.org.

The counter works anonymously. It creates a random number to identify
the device and sends that random number, along with
DRBD’s version number, to usage.drbd.org.

http://usage.drbd.org/cgi-bin/insert_usage.pl?nu=6080684011646847229&ru=336614907672590042&rs=41299098624

* If you wish to opt out entirely, simply enter ‘no’.
* To continue, just press [RETURN]

Success


DRBD
데몬을 두 서버 모두 start 시킨다.

dongho7:~# /etc/init.d/drbd start
Starting DRBD resources:    [ d(cluster2) s(cluster2) n(cluster2) ].
…….dongho7:~#

dongho7:~# cat /proc/drbd
version: 8.2.6 (api:88/proto:86-88)
GIT-hash: 3e69822d3bb4920a8c1bfdf7d647169eba7d2eb4 build by
root@dongho7, 2008-09-01 19:20:28
 0: cs:Connected st:Secondary/Secondary ds:Inconsistent/Inconsistent C r—
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 oos:29301596


이제 초기 원본 서버를 정해서 데이터를 동기화를 해야 한다.
이때 만약 데이터가 들어 있는 상태라면 동기화 방향에 주의해야 한다
.
가급적 백업을 받아 놓고 진행을 하도록 한다
.
아래 명령은 원본 서버에서만 한번 실행을 하면 된다.

dongho7:~# drbdadm — –overwrite-data-of-peer primary cluster2
dongho7:~#
cat /proc/drbd
version: 8.2.6 (api:88/proto:86-88)
GIT-hash: 3e69822d3bb4920a8c1bfdf7d647169eba7d2eb4 build by
root@dongho7, 2008-09-01 19:20:28
 0: cs:SyncSource st:Primary/Secondary ds:UpToDate/Inconsistent C r—
    ns:1719812 nr:0 dw:0 dr:1798880 al:0 bm:104 lo:25 pe:294 ua:2496 ap:0 oos:27591164
        [>……………….] sync’ed:  5.9% (26944/28614)M
        finish: 0:07:29 speed: 61,328 (50,304) K/sec


동기화가 완료 되면 상태가 UpToDate 상태로 양쪽 서버 모두 표시가 된다.

dongho7:~# cat /proc/drbd
version: 8.2.6 (api:88/proto:86-88)
GIT-hash: 3e69822d3bb4920a8c1bfdf7d647169eba7d2eb4 build by root@dongho7, 2008-09-01 19:20:28
 0: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r—
    ns:29301596 nr:0 dw:0 dr:29301596 al:0 bm:1789 lo:0 pe:0 ua:0 ap:0 oos:0


drbd.conf
에서 옵션을 allow-two-primaries; 주었었다.
GFS2
로 사용시에는 allow-two-primaries; 옵션이 있을 때 primary/primary 로 사용이 가능 하다
.
두 노드를 모두 primary 로 만들어 보자
.
dongho8
서버에서 primary 로 추가 선언을 하면 된다
.
하지만 Heartbeat 와 연동하여 primary/secondary 형태로 사용을 할 계획 이므로 꼭 primary/primary 로 사용할 필요는 없다
.
단지 GFS2 에서 지원이 가능 하다는 것을 보여준 것이다.

dongho8:~# drbdadm primary cluster2
dongho8:~# cat /proc/drbd
version: 8.2.6 (api:88/proto:86-88)
GIT-hash: 3e69822d3bb4920a8c1bfdf7d647169eba7d2eb4 build by root@dongho8, 2008-09-01 13:01:24
 0: cs:Connected st:Primary/Primary ds:UpToDate/UpToDate C r—
    ns:0 nr:40329880 dw:40329880 dr:0 al:0 bm:2462 lo:0 pe:0 ua:0 ap:0 oos:0


파일 시스템을 만들어 보자.
만들때 사용하는 옵션은 다음과 같다
.
mkfs -t gfs2 -p lock_dlm -t <clustername>:<fsname> -j <#journals> <blockdev>
clustername
cluster.conf 에서 주었던 이름을 동일하게 사용을 하면 된다
.
fsname
은 중복 되지 않게 마음데로 만들면 된다
.
journals
는 노드수 혹은 그 이상으로 만들면 된다
.
아래 작업은 primary 서버에서만 한번 작업을 하면 된다.

dongho7:~# gfs2_mkfs -p lock_dlm -t donghocluster:donghodrbd -j 3 /dev/drbd1
This will destroy any data on /dev/drbd1.
  It appears to contain a gfs2 filesystem.

Are you sure you want to proceed? [y/n] y

Device:                    /dev/drbd1
Blocksize:                 4096
Device Size                38.46 GB (10082470 blocks)
Filesystem Size:           38.46 GB (10082469 blocks)
Journals:                  3
Resource Groups:           154
Locking Protocol:          “lock_dlm”
Lock Table:                “donghocluster:donghodrbd”


이제 HeartBeat를 통해서 resource 를 제어하도록 설정을 해보자.
HeartBeat
를 통해 기본적으로 DRBD를 제어 하면서 gnbdserv 를 띄워서 gnbd_export 를 할 예정이다
.
양쪽 서버에서 authkeys, ha.cf, resources 파일을 만든다
.
주의 할점은 node 이름에는 uname -n 값의 이름을 적는다. 그리고 node 순서는 자신의 서버 부터 적는다.

dongho7:/etc/ha.d# cat authkeys
auth 2
2 sha1 difficultp@ssw0rd

dongho7:/etc/ha.d# cat ha.cf
debugfile       /var/log/ha-debug
logfile         /var/log/ha-log
logfacility     local0

keepalive       1
deadtime        10
warntime        4
initdead        60
udpport         694
udp             eth0
respawn         hacluster       /usr/lib/heartbeat/ipfail
auto_failback   off

node    dongho7
node    dongho8

dongho7:/etc/ha.d# cat haresources
dongho7 drbddisk::cluster2 \
        gnbdserv \
        Delay::2::0 \
        IPaddr::10.30.6.10/24/eth0

 


그리고 다음과 같이 gnbdserv 스크립트를 양족 서버에서 모두 만든다.
gnbdserv
heartbeat 에서 제어를 해서 사용을 할 수 있도록 /etc/ha.d/resource.d/gnbdserv 파일을 만든다.

dongho7:/etc/ha.d/resource.d# cat gnbdserv
#!/bin/bash

#
# This script is inteded to be used as resource script by heartbeat
#

CMD=$1

case “$CMD” in
    start)
        /sbin/modprobe gnbd
        /usr/sbin/gnbd_serv
        /usr/sbin/gnbd_export -e cluster2 -d /dev/drbd1
        ;;
    stop)
        /usr/bin/killall gnbd_serv
        /usr/bin/killall gnbd_clusterd
        /sbin/rmmod gnbd
        ;;
    *)
        echo “Usage: gnbdserv {start|stop}”
        exit 1
        ;;
esac

exit 0


dongho7:/etc/ha.d/resource.d# chmod 755 gnbdserv


이제 양쪽 서버에서 heartbeat 데몬을 시작해 보자.
그리고 gnbd_export 가 정상적으로 잘 되었는지 살펴 보자.

dongho7:~# /etc/init.d/heartbeat start
Starting High-Availability services:
Done.

dongho7:~# gnbd_export -v -l
Server[1] : cluster2
————————–
      file : /dev/drbd1
   sectors : 80659760
  readonly : no
    cached : no
   timeout : 60


이제는 정상적으로 failover 가 되어서 넘어가는지 살펴 보자.
dongho7
번 에서 heartbeat 데몬을 restart 를 했을때 vip resource 가 넘어가는지 살펴 보자
.
아래처럼 아이피 및 gnbd_export dongho8번으로 넘어가서 잘 작동 되는 것을 확인 할 수 있다.

dongho7:~# /etc/init.d/heartbeat restart
Stopping High-Availability services:
Done.

Waiting to allow resource takeover to complete:
Done.

Starting High-Availability services:
Done.

dongho8:~# ip addr show
1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop
    link/ether 2a:5b:90:46:66:2e brd ff:ff:ff:ff:ff:ff
4: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:19:66:16:58:11 brd ff:ff:ff:ff:ff:ff
    inet 10.30.6.14/24 brd 10.30.6.255 scope global eth0
    inet 10.30.6.10/24 brd 10.30.6.255 scope global secondary eth0:0
5: eth1: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0e:2e:f7:03:d5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.14/24 brd 192.168.0.255 scope global eth1

dongho8:~# gnbd_export -v -l
Server[1] : cluster2
————————–
      file : /dev/drbd1
   sectors : 80659760
  readonly : no
    cached : no
   timeout : 60


마지막으로 dongho9 번 에서 gnbd_import 를 해서 사용을 해보자.

dongho9:~# modprobe gnbd
dongho9:~#
mount -t gfs2 /dev/gnbd/cluster2 /mnt/gfs -onoatime
dongho9:~#
df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda1               972404    195304    727704  22% /
tmpfs                   516340         0    516340   0% /lib/init/rw
udev                     10240        44     10196   1% /dev
tmpfs                   516340         0    516340   0% /dev/shm
/dev/hda2              4814968   1115440   3454940  25% /usr
/dev/hda5              2893628    550260   2196376  21% /var
/dev/hda6            282212396 191900668  90311728  68% /home
none                    516340         0    516340   0% /dev/shm
/dev/gnbd/cluster2    40326112    420328  39905784   2% /mnt/gfs

dongho9:~# mount
/dev/hda1 on / type ext3 (rw)
tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
procbususb on /proc/bus/usb type usbfs (rw)
udev on /dev type tmpfs (rw,mode=0755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)
/dev/hda2 on /usr type ext3 (rw)
/dev/hda5 on /var type ext3 (rw)
/dev/hda6 on /home type jfs (rw)
none on /dev/shm type tmpfs (rw)
nfsd on /proc/fs/nfsd type nfsd (rw)
none on /sys/kernel/config type configfs (rw)
/dev/gnbd/cluster2 on /mnt/gfs type gfs2 (rw,noatime,hostdata=jid=0:id=262147:first=1)

dongho9:~# gfs2_tool journals /mnt/gfs
journal2 – 128MB
journal1 – 128MB
journal0 – 128MB
3 journal(s) found.

dongho9:~# gfs2_tool df /mnt/gfs
/mnt/gfs:
  SB lock proto = “lock_dlm”
  SB lock table = “donghocluster:donghodrbd”
  SB ondisk format = 1801
  SB multihost format = 1900
  Block size = 4096
  Journals = 3
  Resource Groups = 154
  Mounted lock proto = “lock_dlm”
  Mounted lock table = “donghocluster:donghodrbd”
  Mounted host data = “jid=0:id=262147:first=1”
  Journal number = 0
  Lock module flags = 0
  Local flocks = FALSE
  Local caching = FALSE

  Type           Total          Used           Free           use%
————————————————————————
  data           10081528       105082         9976446        1%
  inodes         9979473        3027           9976446        0%


gnbd_import
gfs2 파일시스템을 마운트 한 곳에서 아래 처럼 파일을 1000개 정도 만드는 동안 failover 를 시켜보도록 한다.
정상적으로 문제 없이 파일이 만들어 지는지 살펴 본다
.
정상적으로 1000개 모두 파일이 만들어 진 것을 테스트 해 보았다.

dongho9:/mnt/gfs/test# ls
dongho9:/mnt/gfs/test#
for a in `seq 1 1000`
>
do
>
printf “$a “
>
touch $a
>
done
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 dongho9:/mnt/gfs/test#

dongho9:/mnt/gfs/test# ls -1 |wc -l
1000


하지만 실질적으로는 세션은 끊어졌다가 붙게 된다.
다음의 커널 로그를 살펴 볼 수 있다.

dongho9:/mnt/gfs/test# dmesg |tail -5
gnbd0: Receive control failed (result -32)
gnbd0: shutting down socket
exiting GNBD_DO_IT ioctl
gnbd0: Attempted send on closed socket
resending requests

 


이로서 이중화된 GFS2 gnbd server 를 기반으로 gnbd client  에서 동일한 내용이 담긴 파일 시스템을 동시에 여러 노드에서 마운트하여 서비스가 가능한 구조가 된다. 보통은 heartbeat 에서 haresources 를 설정을 할때 관련된 서비스를 전체적으로 heartbeat 에서 관리를 하도록 만들지만 failover 시에 빠르게 넘기기 위해서 gnbd_export 하는 부분만 사용을 하였다바람직한 방법은 아니나 테스트 목적에서는 빨리 결과를 볼 수 있어서 그렇게 만들었다.

 

5923545228.doc

서진우

슈퍼컴퓨팅 전문 기업 클루닉스/ 상무(기술이사)/ 정보시스템감리사/ 시스존 블로그 운영자

You may also like...

페이스북/트위트/구글 계정으로 댓글 가능합니다.