[클러스터][파일] GFS 로 구현하는 클러스터 파일 시스템 환경 구축 하기 – 아랑
#### GFS 로 구현하는 클러스터 파일 시스템 환경 구축 하기 ####
작성일 : 2005 년 11월 3일
작성자 : 서 진우/ 시스존 ( alang@syszone.co.kr )
1. GFS 란 ..
GFS 는 sistina 의 gfs project 에서 개발하여 진행하다 근래에 들어 Redhat 에 그 권한을
인수하여 진행되고 있는 클러스터 파일 시스템의 하나이다.
클러스터 파일 시스템은 분산된 클러스터 노드 환경에서 동일한 파일 시스템 이미지를 제공
하는 기능으로 구성과 동작 방식에 따라 GFS, DRBD, PVFS, Luster, InterMezzo, AFS 등
다양한 파일 시스템이 존재한다.
GFS 는 단일 불륨에 대한 접근을 분산 노드에서 Loacl Device 와 같은 block 방식으로 접근
이 가능하게 해 주는 파일 시스템 이다. 이는 Local 하드에 다중 프로세스가 동일 파일 시스템
을 동시에 접근하는 구조와 유사하게 작동된다. 일반적인 구성에서는 분산 시스템에 SAN 이나
SCSI 인터페이스를 통한 DAS 의 경우 하나의 호스트에서 볼륨을 잡고 있으면 다른 호스트에서
의 접근을 차단 혹은 read 권한으로만 접근이 가능하게 한다. 이는 파일에 대한 Locking 문제
를 고려하여 원천적으로 차단하지만 GFS 의 경우는 분산된 시스템에 GFS 의 dlm 혹은 gulm_lock
을 이용하여 별도의 lock manage system 기능을 보유하고 있기 때문에 분산환경에서도 단일
볼륨에 대한 다중 접근이 가능하게 되는 것이다.
GFS 프로젝트가 Redhat 에 종속 되면서 다소 Redhat 의 RHCS 구성에 의존하는 바가 크지만..
여전히 GNU 정책에 의해 Source 는 공개되어 지고 있기에 굳에 Redhat 의 방식으로 진행할
필요는 없다.
여기에서는 최대한 Redhat 의 Cluster Suite 의 의존성과는 별도로 구성하는 법에 대해
알아 보고 다양한 구성에 대한 접근을 해 보고자 한다.
GFS 의 자세한 기술적 사항은 아래 사이트에서 참조가 가능하다.
http://gfs.wikidev.net/Installation
http://gfs.wikidev.net/GNBD_installation#Starting_the_services_.28DLM.2C_CCSD.2C_FENCE.29
http://www.redhat.com/docs/manuals/csgfs/
http://code.ximeta.com/cgi-bin/trac.cgi/wiki/HowToGFS
https://open.datacore.ch/DCwiki.open/Wiki.jsp?page=GFS
http://sources.redhat.com/cluster
2. GFS 설치 환경 준비
GFS 관련 Package 는 http://sources.redhat.com/cluster 에서 다운 받을 수 있으며, Redhat 의
RHCS 에 의해 RPM 으로 패키징 된 binary 를 이용해도 된다.
기본적으로 Redhat RPM 으로 설치 하는 방법에 대해 알아보도록 하자.
설치에 필요한 패키지는 다음과 같다.
* 먼저 Redhat 에서 제공하는 kernel 과 kernel Source ( ES4 부터는 kernel-devel 에 포함 )
를 설치 한다. GFS 는 kernel 과의 의존성이 강하기 때문에 RPM 이나 SRPM 으로 설치 시 해당
패키지에 맞는 kernel 이 설치 되어져 있어야 한다. 아래 제시하는 버전의 패키지는 모두
2.6.9-11.ELsmp 버전에 맞게 build 되어 있다.
* GFS 관련 기본 환경 구성 패키지
# rpm -Uvh magma-1.0.0-0.i686.rpm
# rpm -Uvh magma-devel-1.0.0-0.i686.rpm
# rpm -Uvh ccs-1.0.0-0.i686.rpm
# rpm -Uvh ccs-devel-1.0.0-0.i686.rpm
# rpm -Uvh gulm-1.0.0-0.i686.rpm
# rpm -Uvh gulm-devel-1.0.0-0.i686.rpm
# rpm -Uvh magma-plugins-1.0.0-0.i386.rpm
# rpm -Uvh cman-kernel-2.6.9-36.0.i686.rpm
# rpm -Uvh cman-1.0.0-0.i686.rpm
# rpm -Uvh dlm-kernel-2.6.9-34.0.i686.rpm
# rpm -Uvh dlm-1.0.0-0.i686.rpm
# rpm -Uvh dlm-devel-1.0.0-0.i686.rpm
# rpm -Uvh perl-Net-Telnet-3.03-3.noarch.rpm
# rpm -Uvh fence-1.32.1-0.i686.rpm
# rpm -Uvh gnbd-kernel-2.6.9-8.27.i686.rpm
# rpm -Uvh gnbd-1.0.0-0.i686.rpm
* GFS 관련 패키지
# rpm -Uvh GFS-kernel-2.6.9-35.5.i686.rpm
# rpm -Uvh GFS-6.1.0-0.i386.rpm
# rpm -Uvh device-mapper-1.01.01-1.RHEL4.i386.rpm
# rpm -Uvh lvm2-2.01.08-1.0.RHEL4.i386.rpm
# rpm -Uvh lvm2-cluster-2.01.09-5.0.RHEL4.i386.rpm
# rpm -Uvh iddev-2.0.0-0.i686.rpm
# rpm -Uvh iddev-devel-2.0.0-0.i686.rpm
* RHCS 관련 패키지 ( Redhat 의 의존성을 피하고 싶을 경우는 굳이 설치 할 필요는 없음 )
rgmanager-1.9.34-1.i386.rpm ;; cluster resource 관련 프로그램
system-config-cluster-1.0.12-1.0.noarch.rpm ;; CCS 설정 프로그램
ipvsadm-1.24-6.i386.rpm ;; LVS admin tool ;; 부하분산 핵심 제어 명령 프로그램
3. GFS 환경 구축
여기서는 가징 기본저인 형태의 GFS 클러스터 환경을 구축해 보도록 하자.
먼저 SAN 혹은 SCSI 형태의 Interface를 제공하는 Storage 에 클러스터 노드를 2대를 준비
하여 구축 하도록 한다.
———– ————
| Node 1 | | Node 2 |
———– ————
| |
| SCSI/HBA | SCSI/HBA
| |
————————————
| |
——————
| |
| Storage |
| |
——————
Node1 ip address : 192.168.123.116
Node2 ip address : 192.168.123.117
위와 같이 node1 과 node2 에서 SCSI 나 HBA Card 를 이용하여 DAS 형태로 하나의 Storage
의 단일 볼륨에 mount 하여 read/write 가 모두 가능하게 클러스터 파일 시스템 환경을
구성하고자 한다.
먼저 node1, node2 에 /etc/hosts 파일을 설정하도록 한다.
[node1]# vi /etc/hosts
———————————————————————————-
192.168.123.116 node01
192.168.123.117 node02
———————————————————————————-
[node2]# vi /etc/hosts
———————————————————————————-
192.168.123.116 node01
192.168.123.117 node02
———————————————————————————
그런 후 GFS node 간의 시간을 동기화 한다. 시간 동기화는 NTP 혹은 /etc/xinet.d/time
등을 이용해서 동기화 할 수 있다. 또한 rdate를 cron에 걸어 놓고 원자 시계를 기준으로
동기화 해도 된다. 몇 분 정도의 오차는 시스템에 큰 영향을 주지 못하지만 몇 시간의
오차가 날 경우 시스템의 성능과 안정성에 큰 무리를 줄 수 있다.
이제 본격적으로 GFS 설정에 들어 간다. 제일 먼저 설정해야 할 것은 ccs 설정이다.
GFS 의 구성 요소를 정의하는 설정으로 ccsd 데몬에 의해 제어 되며, RHCS의 기본 클러스터
설정 관리 프로그램으로 사용되어진다. ccs 설정은 위에서 얘기한 system-config-cluster
란 패키지를 설치하면 X 상에서 User Interface 로 간단히 설정 할 수 있다. 하지만 이 설정
은 Redhat 에서 제공하는 RHCS 에서 제어하는 다양한 Resource 를 모두 다루는 tool 로
GFS 만을 이용할 경우에는 다소 복잡한 요소를 내재하고 있다. 여기서는 GFS 설정에 맞게
ccs 설정을 해보도록 한다.
먼저 node01, node02 에 /etc 밑에 cluster 란 폴더를 생성한다.
[node01]# mkdir /etc/cluster
[node02]# mkdir /etc/cluster
그런 후 node01, node02 동일한 내용의 cluster.conf 파일을 /etc/cluster 폴더 밑에 생성한다.
# vi /etc/cluster/cluster.conf
———————————————————————————–
<?xml version=”1.0″?>
<cluster name=”cluster” config_version=”1″>
<cman>
</cman>
<clusternodes>
<clusternode name=”node01″ votes=”1″>
<fence>
<method name=”single”>
<device name=”human” ipaddr=”node01″/>
</method>
</fence>
</clusternode>
<clusternode name=”node02″ votes=”1″>
<fence>
<method name=”single”>
<device name=”human” ipaddr=”node02″/>
</method>
</fence>
</clusternode>
</clusternodes>
<fence_devices>
<device name=”human” agent=”fence_manual”/>
</fence_devices>
</cluster>
———————————————————————————–
cluster.conf 는 xml 형식으로 제공 되며 ccsd 명령으로 반영 시킨다.
주요 설정으로 cluster name, clusternode name, device name, 등이 있고, 항목으로는
<cman>, <clusternodes>, <fence>, <fence_devices> 등이 있다.
cluster name 은 노드간의 클러스터 그룹을 정의하는 것으로 하나의 클러스터 그룹을 대표하는
name 이라 생각하면된다.
clusternode name 은 실제 cluster 를 구성하는 node 의 hostname 을 적어 주면 된다.
device name 은 해당 fence device 적어 주면 되는데 여기서는 별도의 fencing system 이
없기에human 이라 적어 주도록 한다.
fencing system 은 특정 노드에 대해 문제가 발생했을때 문제노드에 리소스 접근을 차단하여
정상적인 상황과 문제 상황에 대한 리소스 접근의 분리를 통해 리소스의 일관성을 유지해 주는
시스템이다. 흔히 SAN Switch 나 APIC 시스템의 경우 문제가 발생하면 SAN Switch 에서 문제
서버의 Port 를 차단하여 문제가 발생한 서버로는 데이터 접근을 원천적으로차단하거나 APIC
와 같이 시스템 파워를 차단해 버리는 시스템이다.
<cman> 은 cluster management 설정 항목으로 RHCS 에서 기본 제공하는 cluster 의 resource
를 management 할때 사용되는 통신 프로그램이다. GFS 만으로 이용할 경우는 별도의 설정이
필요하진 않는다.
이밖에 많은 설정이 있는데 이는 RHCS 의 문서를 살펴 보면 된다.
node01, node02 에 cluster.conf 파일을 모두 생성하면 일차적인 GFS 설정이 완료된다.
이제 수동으로 GFS 환경에 필요한 데몬과 GFS 파일 시스템을 생성해 보도록 하자.
아래 진행 사항은 node01, node02 모두 동일 하다.
우선 GFS 에 대한 modules 를 적재한다.
# depmod -a
# modprobe dm-mod
# modprobe gfs
# modprobe lock_dlm
GFS 관련 데몬을 실행한다.
# ccsd
# cman_tool join
# fence_tool join
별 다른 에러가 없으면 GFS 환경을 위한 모든 준비가 완료되었다.
간단한 테스트로 정상적인 작동 유무를 확인하자.
[node01]# ccs_test connect
Connect successful.
Connection descriptor = 1
[node01]# ccs_test get node ‘//cluster/@name’
Get successful.
Value = <cluster>
[node01]# cat /proc/cluster/nodes
Node Votes Exp Sts Name
1 1 2 M node01
2 1 2 M node02
[node01]# cat /proc/cluster/services
[node01]# cat /proc/cluster/dlm_stats
[node01]# cman_tool status
정상적으로 동작함을 확인 후 GFS 파일 시스템을 생성하도록 한다.
먼저 fdisk 로 node01 과 node02 에서 Storage의 디스크가 동일하게 인식이 되는지를 확인한다.
[node01]# fdisk -l
————————————————————————————-
Disk /dev/hda: 82.3 GB, 82348277760 bytes
255 heads, 63 sectors/track, 10011 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 13 104391 83 Linux
/dev/hda2 14 144 1052257+ 83 Linux
/dev/hda3 145 666 4192965 82 Linux swap
/dev/hda4 667 10011 75063712+ 5 Extended
/dev/hda5 1776 10011 66155638+ 83 Linux
-> Storage volume <-
Disk /dev/sda: 749.3 GB, 749356449792 bytes
255 heads, 63 sectors/track, 91104 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
————————————————————————————-
[node02]# fdisk -l
————————————————————————————-
Disk /dev/hda: 82.3 GB, 82348277760 bytes
255 heads, 63 sectors/track, 10011 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 13 104391 83 Linux
/dev/hda2 14 144 1052257+ 83 Linux
/dev/hda3 145 666 4192965 82 Linux swap
/dev/hda4 667 10011 75063712+ 5 Extended
/dev/hda5 1776 10011 66155638+ 83 Linux
-> Storage volume <-
Disk /dev/sda: 749.3 GB, 749356449792 bytes
255 heads, 63 sectors/track, 91104 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
————————————————————————————-
이제 node01 에서 fdisk 를 통해 Storage volume 에 partition 을 생성하도록 한다.
그런 후 fdisk -l 로 node01, node02 에서 변경된 volume 이 동일하게 적용 되었는지를 확인한다.
[node01]# fdisk -l
————————————————————————————-
Disk /dev/sda: 749.3 GB, 749356449792 bytes
255 heads, 63 sectors/track, 91104 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sda1 1 91104 731792848+ 83 Linux
————————————————————————————-
[node02]# fdisk -l
————————————————————————————-
Disk /dev/sda: 749.3 GB, 749356449792 bytes
255 heads, 63 sectors/track, 91104 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sda1 1 91104 731792848+ 83 Linux
————————————————————————————-
이제 node01, node02 에서 partprobe 명령어를 통해 갱신된 partition 구조를 시스템에서 인식
하도록 적용시킨다.
[node01]# partprobe
[node02]# partprobe
그런 후 GFS 파일 시스템을 생성하도록 한다.
생성 방식은 다음과 같다.
# gfs_mkfs -p lock_dlm -t <cluster name>:<File System Name> -j <journals number> <block device>
위 환경에서는 다음과 같이 생성한다.
[node01] gfs_mkfs -p lock_dlm -t cluster:enfs -j 2 /dev/sda1
<cluster name> 은 /etc/cluste/cluster.conf 에 정의된 cluster name 이다.
<File System Name> 은 해당 볼륨을 정의하는 의미를 가지면 된다.
<journals number> 는 실제 GFS로 구성되어지는 노드 수를 의미한다.
<block device> 는 각 partition 의 device name 으로 보면 된다.
파일 시스템 생성은 node01, node02 중 하나의 노드에서만 해주면 된다.
이제 GFS 파일 시스템에 mount 를 해보도록 하자.
[node01]# mkdir /gfs
[node02]# mkdir /gfs
[node01]# mount -t gfs /dev/sda1 /gfs
[node02]# mount -t gfs /dev/sda1 /gfs
이제 node01, node02 의 /gfs 디렉토리에 각각 파일을 생성,삭제 하면서 디스크의 일관성이 유지
되는지를 확인해 보도록 한다.
혹 NFS 와 무슨 차이가 있냐!! 라는 질의가 있는데 이는 성능이나 데이터 일관성 유지 측면에서
엄청난 차이가 있다. bonne++ 툴을 이용해서 디스크의 읽기/쓰기 성능을 확인해 보면 NFS 와는
엄청난 차이가 있을 것이다. 간단히 확인 하는 방법으로 hdparm 을 이용하여 read buffer 성능
을 측정해 보아도 된다.
NFS 의 경우가 보통 Gigabit 환경에서 17M/sec 정도로 나타난다.
GFS 의 경우는 SAN 의 경우 170M/sec, SCSI 의 경우 100M/sec 정도의 성능이 나온다.
또한 확장성에서 NFS 의 경우 실제 서비스 환경에서 10~15대의 서버가 접속하면, 성능, 안정성
에서 더 이상의 확장이 힘들게 되는데 GFS 의 경우는 300노드 이상의 확장이 가능하다.
지금까지 GFS 관련 프로그램을 설치 하고, GFS 파일 시스템 생성하여 시스템에 Mount 까지
시키는 방법에 대해 알아 보았다.
이제 GFS 의 Init 환경을 제어하는 방법에 대해 알아 보자.
실제 GFS 는 Locking 문제를 해결하기 위해 DLM 이란 Locking system을 사용하고, Fencing 까지
고려되어 있기에 정상적인 start step 과 stop step 을 파악하고 있어야 한다.
그렇지 못하면 시스템이 다운되거나 관리적 목적으로 reboot 할 경우 마다 복작한 파일 시스템
환경 구성에 대한 절차를 반복해야 할 것이다. 이것을 자동으로 제어 할 수 있는 initscripts
를 만들어 제어 해야 한다.
먼저 GFS 의 start/stop 절차에 대해 파악하도록 하자.
* GFS Starting 절차
# modprobe dm-mod
# modprobe gfs
# modprobe lock_dlm
# ccsd
# cman_tool join
# fence_tool join
# mount -t gfs /dev/sda1 /gfs
* GFS Stop 절차
# umount /gfs
# fence_tool leave
# cman_tool leave
# killall ccsd
# rmmod lock_dlm
# rmmod gfs
# rmmod dm-mod
혹 fence_tool, cman_tool 이 정상적으로 leave 되지 않을 경우 force 란 옵션으로 강제로
종료 할 수 있다.
위의 과정을 적절한 scripts 를 이용하여 통합적으로 제어할 수 있는 initscripts 를 만들도록
한다.
# vi /etc/rc.d/init.d/gfs
——————————————————————————————
#!/bin/bash
#
#
#
# description: mount/unmount gfs filesystems configured in /etc/fstab
#
#
### BEGIN INIT INFO
# Provides:
### END INIT INFO
. /etc/init.d/functions
[ -f /etc/sysconfig/cluster ] && . /etc/sysconfig/cluster
#
# This script’s behavior is modeled closely after the netfs script.
#
GFSFSTAB=`cat /etc/fstab | grep gfs | awk ‘{print $2}’`
GFSMTAB=$(LC_ALL=C awk ‘!/^#/ && $3 ~ /^gfs/ && $2 != “/” { print $2 }’ /proc/mounts)
# See how we were called.
case “$1” in
start)
if [ -n “$GFSFSTAB” ]
then
#load_module lock_harness MODULE_LOCK_HARNESS
#load_module crc32 MODULE_CRC32
modprobe lock_dlm
modprobe gfs
action $”Mounting GFS filesystems: ” mount -a -t gfs
fi
touch /var/lock/subsys/gfs
;;
stop)
if [ -n “$GFSMTAB” ]
then
sig=
retry=6
remaining=`LC_ALL=C awk ‘!/^#/ && $3 ~ /^gfs/ && $2 != “/” {print $2}’ /proc/mounts`
while [ -n “$remaining” -a “$retry” -gt 0 ]
do
action $”Unmounting GFS filesystems: ” umount -a -t gfs
if [ $retry -eq 0 ]
then
action $”Unmounting GFS filesystems (lazy): ” umount -l -a -t gfs
break
fi
sleep 2
remaining=`LC_ALL=C awk ‘!/^#/ && $3 ~ /^gfs/ && $2 != “/” {print $2}’ /proc/mounts`
[ -z “$remaining” ] && break
/sbin/fuser -k -m $sig $remaining >/dev/null
sleep 10
retry=$(($retry – 1))
sig=-9
done
fi
modprobe -r gfs
modprobe -r lock_dlm
rm -f /var/lock/subsys/gfs
;;
status)
if [ -f /proc/mounts ]
then
[ -n “$GFSFSTAB” ] && {
echo $”Configured GFS mountpoints: ”
for fs in $GFSFSTAB; do echo $fs ; done
}
[ -n “$GFSMTAB” ] && {
echo $”Active GFS mountpoints: ”
for fs in $GFSMTAB; do echo $fs ; done
}
else
echo “/proc filesystem unavailable”
fi
;;
restart)
$0 stop
$0 start
;;
reload)
$0 start
;;
*)
echo $”Usage: $0 {start|stop|restart|reload|status}”
exit 1
esac
exit 0
—————————————————————————————-
위 Scripts 를 사용하기 위해서는 gfs mount 정보를 /etc/fstab 에 적용을 해야 한다.
# vi /etc/fstab
—————————————————————————————-
/dev/sda1 /gfs gfs defaults 0 0
—————————————————————————————-
아래와 같은 방식으로 gfs file system 의 mount/umount 를 쉽게 관리 할 수 있을 것이다.
[node01]# /etc/rc.d/init.d/gfs start|stop|restart|status
[node02]# /etc/rc.d/init.d/gfs start|stop|restart|status
[node01]# df -Th
—————————————————————————————–
Filesystem Type Size Used Avail Use% Mounted on
/dev/hda2 ext3 1012M 135M 826M 15% /
/dev/hda1 ext3 99M 11M 83M 12% /boot
none tmpfs 1014M 0 1014M 0% /dev/shm
/dev/hda9 ext3 63G 85M 59G 1% /home
/dev/hda5 ext3 3.0G 1.4G 1.5G 48% /usr
/dev/hda7 ext3 2.0G 85M 1.8G 5% /usr/local
/dev/hda6 ext3 3.0G 65M 2.8G 3% /var
/dev/sda1 gfs 1012M 135M 826M 15% /gfs
——————————————————————————————
지금까지 SCSI/SAN 방식의 Share Storage 에 GFS를 이용하여 분산 시스템 환경에서 단일 파일
시스템 이미지 환경을 구성하는 방법에 대해 알아 보았다.
지금까지의설명은 가장 기본적인 구성으로 구현한 것이다.
다음 장에서는 GNBD 를 이용하여 SCSI/SAN Storage 가 아닌, 일반적인 네트워크 파일 서버를
이용하여 GFS 클러스터 파일 시스템 환경 구축에 대해 알아 보도록 하자.
4. GNBD 를 이용한 GFS 환경 구축
GNBD는 네트워크를 통해 떨어진 remote hosts 의 block device 를 network block device 를
통해 마치 local device 처럼 인식하여 데이터의 접근을 local disk 와 유사한 방식으로 접근
하게 된다.
네트워크 환경에서 remote sytem의 파일 시스템에 접근 하는 방식은 많이 있지만(FTP,WEB,NFS.)
local device 처럼 접근하는 방법과는 그 성능에서 차이가 많이 난다.
NBD 를 이용하는 대표적인파일 시스템으로 DRBD 가 있는데 이는 NBD 와 Soft Raid 를 혼합해서
만든 파일 시스템으로 주로 HA 시스템의 필요한 클러스터 파일 시스템으로 사용되어진다.
하지만 DRBD 로 제공되는 block device의 경우 하나의 호스트에서 mount 를 하고 있으면,
다른 나머지 호스트에서는 접근 하지 못하는단점이 있다.
이에 비해 GNBD 와 GFS 를 이용하면 GNBD 를 제공하는 시스템의 파일 시스템에 여러 호스트에서
접근이 가능하다. 즉 GNBD 를 이용하면 SAN Switch 환경의 SAN Storage 에 FC 를 통해 여러
노드에서 접근이 가능하게 하는 거와 같은 효과를 볼수 있다.
물런 하드웨어적으로 구성된 환경에 비해 성능은 떨어지나 NFS 와 같은 일반적인 네트워크
서비스 환경 보다 월등한 성능을 보장하며, 하드웨어 구성의 환경 보다 확장성을 가지고
고가의 장비가 필요하지 않는 점에서 매우 유용한 방식이라 할 수 있다.
또한 SAN/SCSI + RAID + GFS + GNBD 를 이용하면 성능, 확장성등을 모두 최적화 시키는 설계도
가능하다.
이장에서는 GNBD 를 이용한 기본적인 클러스터 파일 시스템 환경 구축에 대해 설명할 것이다.
아래는 가장 기본적인 GNBD 를 이용한 클러스터 파일 시스템 설계이다.
GNBD 로 구성된 환경이 제공하는 효과는 앞에서 다른 하드웨어 환경에서의 효과와 동일하다.
즉 Node03 의 하드 디스크를 Node01, Node02 에서 로컬에 붙어 있는 DAS 처럼 인식하게 된다.
하지만 SCSI/FC 같은 고가 장비를 이용하는게 아닌 일반적인 네트워크 환경에서 구현이 된다는
차이가 있다.
Mount Mount
————- ————-
| Node01 | GFS File System | Node02 | GFS File System
————- ————-
| GNBD Client | GNBD Client
| |
—————————————————————-
Gigabit Network Switch 환경
—————————————————————-
|
| GNBD Server
————
| Node03 | GFS File System
————
Disk Volume
이제 위 구성과 같이 GNBD 와 GFS 를 이용한 저가 비용으로 구축이 가능한 클러스터 파일
시스템 환경을 구현해 보자.
기본적인 설치 패키지는 GFS 와 동일하다.
앞서 다룬 GFS 에서 설치 한 모든 패키지를 설치 하도록한다.
GNBD 역시 GFS 를 통한 클러스터 파일 시스템 환경을 이루기 때문에 초기 준비 단계는 GFS의
모든 과정과 동일 하다.
GFS에서 거론한 모든 패키지를 설치 한 후 GNBD 관련 패키지를 설치 하도록 한다.
GNBD 패키지는 Node01, Node02, Node03 서버에 동일하게 설치 한다.
# rpm -Uvh gnbd-kernel-2.6.9-8.27.i686.rpm
# rpm -Uvh gnbd-1.0.0-0.i686.rpm
그런 후 /etc/cluster/cluster.conf 에 node03 에 대한 항목을 추가 한다.
설정의 방식은 GFS 와 동일하다.
# vi /etc/cluster/cluster.conf
——————————————————————————————-
<?xml version=”1.0″?>
<cluster name=”cluster” config_version=”1″>
<cman>
</cman>
<clusternodes>
<clusternode name=”node01″ votes=”1″>
<fence>
<method name=”single”>
<device name=”human” ipaddr=”node01″/>
</method>
</fence>
</clusternode>
<clusternode name=”node02″ votes=”1″>
<fence>
<method name=”single”>
<device name=”human” ipaddr=”node02″/>
</method>
</fence>
</clusternode>
<clusternode name=”node03″ votes=”1″>
<fence>
<method name=”single”>
<device name=”human” ipaddr=”node03″/>
</method>
</fence>
</clusternode>
</clusternodes>
<fence_devices>
<device name=”human” agent=”fence_manual”/>
</fence_devices>
</cluster>
——————————————————————————————–
모든 노드에 cluster.conf 파일을 동기화 한다.
그런 후 모든 노드에 먼저 GFS 관련 모듈과 데몬을 시작한다.
# depmod -a
# modprobe dm-mod
# modprobe gfs
# modprobe lock_dlm
# ccsd
# cman_tool join
# fence_tool join
그런 후 GNBD 모듈을 적재한다.
# modprobe gnbd
이제 GNBD Server ( node03 ) 에서 gnbd_serv 데몬을 실행한다.
[node03]# gnbd_serv -v
그런 후 GNBD 로 GNBD Client 에 제공한 Disk Block Device 를 export 시킨다.
[node03]# gnbd_export -v -e gnbd0 -d /dev/sda1
정상적으로 등록 되었는지 확인 한다.
[node03]# gnbd_export -v -l
Server[1] : gnbd0
——————————
file : /dev/sda1
sectors : 19551042
readonly : no
cached : no
timeout : 60
이제 GNBD Client ( node01, node02 ) 노드에서 서버의 export 된 정보를 import 시킨다.
[node01]# gnbd_import -v -i node03
[node02]# gnbd_import -v -i node03
정상적으로 import 된지 확인 한다.
[node01]# gnbd_import -v -l
Device name : gnbd0
———————-
Minor # : 0
Proc name : /dev/gnbd0
Server : n003
Port : 14567
State : Close Connected Clear
Readonly : No
Sectors : 19551042
[node02]# gnbd_import -v -l
Device name : gnbd0
———————-
Minor # : 0
Proc name : /dev/gnbd0
Server : n003
Port : 14567
State : Close Connected Clear
Readonly : No
Sectors : 19551042
정상적으로 import 된거을 확인하면 /dev/gnbd/gnbd0 이란 디바이스 파일이 생성되어 있을
것이다.
[node01]# ll /dev/gnbd/gnbd0
brw-r–r– 1 root root 251, 0 Oct 7 13:46 /dev/gnbd/gnbd0
이제 /dev/gnbd/gnbd0 device 를 local device 처럼 사용이 가능하다.
Gnbd 서버로 가서 gfs file system 을 생성한다.
[node03]# gfs_mkfs -p lock_dlm -t cluster:gnbdfs -j 3 /dev/sda1
This will destroy any data on /dev/hda6.
Are you sure you want to proceed? [y/n] y
GNBD Server 에서 GFS local block device 에 mount 한다.
[node03]# mount -t gfs /dev/sda1 /gfs
이제 GNBD Client 에서 Mount 를 시킨다.
[node01]# mount -t gfs /dev/gnbd/gnbd0 /gfs
[node02]# mount -t gfs /dev/gnbd/gnbd0 /gfs
[node01]# df -Th | grep /gfs
/dev/gnbd/gnbd0 gfs 9.0G 20K 9.0G 1% /gfs
[node02]# df -Th | grep /gfs
/dev/gnbd/gnbd0 gfs 9.0G 20K 9.0G 1% /gfs
[node03]# df -Th | grep /gfs
/dev/sda1 gfs 9.0G 20K 9.0G 1% /gfs
이것으로 node01, node02 시스템에서 node03 의 sda1 device 를 마치 DAS 방식의 Storage 처럼
사용하게 된다. 물런 node03 에서도 sda1 의 block 을 GFS 를 통해 사용이 가능하다.
실제 GNBD 의 경우 Gigabit 환경에서 40M/Sec 정도의 성능이 나온다. 이는 동일 환경에서의
NFS 에 비해 2배 이상의 성능이라 볼수 있다.
또한 확장성에서 역시 10배 이상의 효과가 있다고 한다.
마지막으로 GFS+GNBD 상의 시스템에서 안정하게 시스템을 종료하는 방법에 대해 알아보자.
GFS 의 경우에는 위에서 제시한 /etc/rc.d/init.d/gfs 스크립터를 이용하여 안전하게 종료할수
있지만 GNBD 의 경우는 다른다. 실제 GNBD 간의 통신이 이루어 지기 때문에 이 부분을 무시한채
시스템을 리부팅을 하게 되면 시스템 shutdown 과정에서 멈추게 된다.
아래 스크립터로 안전하게 시작과 종료를 제어 하도록 한다.
*** gnbd_start.sh
—————————————————————————————-
#!/bin/sh
GNBD_SERVER=”node03″
GNBD_NAME=”gnbd0″
GFS_MOUNT=”/gfs”
modprobe dm-mod
modprobe gfs
modprobe lock_dlm
modprobe gnbd
ccsd
cman_tool join
fence_tool join
sleep 2
gnbd_import -v -i $GNBD_SERVER
mount -t gfs /dev/gnbd/$GNBD_NAME $GFS_MOUNT
echo “GNBD Start complete …”
—————————————————————————————–
*** gnbd_stop.sh
—————————————————————————————–
#!/bin/sh
GNBD_NAME=”gnbd0″
GFS_MOUNT=”/gfs”
GFS_PID=`lsof /gfs | grep -v PID | awk ‘{print $2}’`
kill -9 `echo $GFS_PID` &> /dev/null
umount $GFS_MOUNT
# /etc/rc.d/init.d/clvmd stop
killall fenced
gnbd_import -r $GNBD_NAME
fence_tool leave
cman_tool leave force
killall ccsd
rmmod gnbd
rmmod lock_dlm
rmmod gfs
rmmod dm-mod
echo “GNBD Stop complete …”
—————————————————————————————–
*** gnbd_server_start.sh
—————————————————————————————–
#!/bin/sh
GNBD_SERVER=”node03″
GNBD_NAME=”gnbd0″
GFS_DEV=”/dev/sda1″
modprobe dm-mod
modprobe gfs
modprobe lock_dlm
modprobe gnbd
ccsd
cman_tool join
fence_tool join
sleep 2
gnbd_serv -v
gnbd_export -v -e $GNBD_NAME -d $GFS_DEV
echo “GNBD Server Start complete …”
—————————————————————————————–
*** gnbd_server_stop.sh
—————————————————————————————–
#!/bin/sh
GNBD_NAME=”gnbd0″
# /etc/rc.d/init.d/clvmd stop
killall fenced
gnbd_export -R
killall gnbd_serv
cman_tool leave force
killall ccsd
rmmod gnbd
rmmod lock_dlm
rmmod gfs
rmmod dm-mod
echo “GNBD Server Stop complete …”
—————————————————————————————–
5. GFS,GNBD 와 CLVM 를 이용한 클러스터 볼륨 관리하기
CLVM는 Cluster Logical Volume Manager 로 분산 된 시스템의 볼륨을 단일 하게 관리해 주는
볼륨메니저의 일종이다. 이는 리눅스의 lvm 기반위에서 동작하며, lvm2, device-mapper 프로그램
이 설치 되어 있어야 가능하다. Redhat RPM Package로는 lvm2-cluster 란 이름으로 배포되어진다.
아래의 구축 방안은 위에서 다룬 GFS 와 GNBD를 기반으로 GNBD 에서 제공하는 Network Block
Device기능을 이용하여 분산 노드의 디스크들을 LVM 으로 묶어 하나의 대형 볼륨으로 만들어
관리하는 방법에 대해 설명한다.
즉 네트워크 상에 분산된 시스템의 개별 디스크를 하나의 대형 볼륨으로 만들어 관리하는
설계 구조이다.
———– ———- ———
| node01 | | node02 | | node03 |
———– ———- ———
| GFS | GFS | GFS
| GNBD(client) | GNBD(client) | GNBD(client)
| CLVM | CLVM | CLVM
——————————————————————————–
Gigabit Network 환경
——————————————————————————–
| CLVM | CLVM
| GNBD(server) | GNBD(server)
————– ————–
| node04 | | node05 |
| 50G volume | | 50G volume |
————– ————–
위 구성에서 node04,node05에서 각각 50GByte 크기의 디스크를 gnbd를 이용하여 node01,02,03
에서 사용할 수 있도록 구성한 후, node01,02,03에서 LVM2 와 CLVM 을 이용하여 node04,05의
gnbd device를 하나로 취합함으로 node01,02,03에서는 node04,05에서 제공된 전체 디스크 용량
인 100GByte 를 하나의 볼륨으로 인식하여 마운트해서 사용이 가능하다.
이와 같은 방식으로 GNBD 서버 노드를 계속 확장 시켜 나간다면, 분산된 노드의 디스크를 이용
하여 거대한 클러스터 볼륨을 구성할 수 있게 된다.
또한 LVM 의 기능을 이용하면, 볼륨노드 추가 시 서비스를 정지하지 않고도 가능함으로 관리나
불륨 확장시 시스템의 안정성을 극대화 할수도 있을 것이다.
그럼 구체적인 설치 방법에 대해 알아보자.
먼저 앞에서 다룬 방식으로 GNBD 환경을 구성한다.
– GFS + GNBD 관련 패키지 설치
– cluster.conf 파일 설정 및 구성
# vi /etc/cluster/cluster.conf
——————————————————————————————
<?xml version=”1.0″?>
<cluster name=”cluster” config_version=”1″>
<cman>
</cman>
<clusternodes>
<clusternode name=”node01″ votes=”1″>
<fence>
<method name=”single”>
<device name=”gnbd” ipaddr=”node01″/>
</method>
</fence>
</clusternode>
<clusternode name=”node02″ votes=”1″>
<fence>
<method name=”single”>
<device name=”gnbd” ipaddr=”node02″/>
</method>
</fence>
</clusternode>
<clusternode name=”node03″ votes=”1″>
<fence>
<method name=”single”>
<device name=”gnbd” ipaddr=”node03″/>
</method>
</fence>
</clusternode>
<clusternode name=”node04″ votes=”1″>
<fence>
<method name=”single”>
<device name=”gnbd” ipaddr=”node04″/>
</method>
</fence>
</clusternode>
<clusternode name=”node05″ votes=”1″>
<fence>
<method name=”single”>
<device name=”gnbd” ipaddr=”node05″/>
</method>
</fence>
</clusternode>
</clusternodes>
<fence_devices>
<device name=”human” agent=”fence_manual”/>
<device name=”gnbd” agent=”fence_gnbd” option=”multipath” servers=”node04 node05″/>
</fence_devices>
</cluster>
—————————————————————————————–
# ensync /etc/cluster/cluster.conf
– GFS + GNBD 모듈 탑재 및 관련 데몬 구동
node01,02,03,04,05에서 동일하게 적용
# depmod -a
# modprobe dm-mod
# modprobe gfs
# modprobe lock_dlm
# ccsd
# cman_tool join
# fence_tool join
# modprobe gnbd
– GNBD Server 데몬 실행
node04 에 적용
# /sbin/gnbd_serv -v
# gnbd_export -v -e gnbd1 -d /dev/sda6
node05 에 적용
# /sbin/gnbd_serv -v
# gnbd_export -v -e gnbd2 -d /dev/sda6
– GNBD Client 데몬 설행
node01,02,03,04,05 에 적용
# gnbd_import -v -i node04
# gnbd_import -v -i node05
– CLVM 데몬 실행
node01,02,03,04,05 에 적용
# /etc/rc.d/init.d/clvmd start
– LVM2 구성
node01 에서 실행
# partprobe
# pvcreate /dev/gnbd/gnbd1 /dev/gnbd/gnbd2 -> physical volume 생성
# vgcreate vg0 /dev/gnbd/gnbd1 /dev/gnbd/gnbd2 -> volume group 생성
# lvcreate -L 100G -n lvm0 vg0 -> logical volume 생성
– LVM2 구성 확인
node01,02,03,04,05 에서 아래 방식으로 node01 에서 적용한 볼륨 구성이 동기화가 되었는지
확인한다.
# pvdisplay -> physical volume 구성 확인
# vgdisplay -> volume group 구성 확인
# lvdisplay -> logical volume 구성 확인
– GFS 파일 시스템 구성
node01 에서 GFS 로 파일 시스템을 포맷한다.
# gfs_mkfs -p lock_dlm -t cluster:enfs -j 5 /dev/vg0/lvm0
– GFS mount
모든 노드에서 아래와 같이 gfs 파일 시스템에 mount 를 한다.
# mount -t gfs /dev/vg0/lvm0 /gfs
# df
# df -h
————————————————————————————
Filesystem Size Used Avail Use% Mounted on
/dev/hda2 2.9G 289M 2.5G 11% /
/dev/hda1 99M 14M 81M 15% /boot
none 249M 0 249M 0% /dev/shm
/dev/hda3 9.7G 2.6G 6.7G 28% /usr
/dev/mapper/vg0-lvm0 99G 432M 98G 1% /gfs
————————————————————————————
참고 사항 :
* LVM2 의 사용방법은 기존의 LVM 과 동일하다.
* LVM 은 기본적으로 디스크를 하나로 묶을때 Span 방식으로 취합이 된다.
raid-0 의 striping 으로 취합될 경우 특정 디스크에 문제가 발생했을 경우 모든 볼륨이
깨어지게 되는데 span 방식의 경우 문제 발생 디스크 상의 저장된 정보만 상실하게 됨으로
나름대로의 안정성이 보장된다고 볼수 있다.
또한 현재는 개발 되지 않았지만, 향후 Raid-1 방식과 raid-5 방식의 array 구성을 lvm2에
포함시킬 계획을 가지고 있음으로 더욱 효율적인 볼륨을 구성할 수 있을 것이다.
6. Soft Raid 와 GNBD 를 이용한 고가용성 GFS 환경 구축하기
GNBD 구성 후 하나의 GNBD Client 에서 soft raid1 을 잡고..gfs 포맷을 한다.
그런 후 다른 GNBD Client 에 raid1 을 다시 묶는다..
***** GFS + GNBD + DRBD 를 이용한 2 node Active/Active HA
– node04,node05 에 GFS, GNBD 환경 구축
node04 : gnbd0 ( export name )
node05 : gnbd1 ( export name )
node04 -> import node04, node05
node05 -> import node04, node05
– node04, node05 DRBD 구성
node04, node05 : /etc/drbd.conf
———————————————————————————–
skip {
}
resource dr0 {
protocol C;
incon-degr-cmd “echo ‘!DRBD! pri on incon-degr’ | wall ; sleep 60 ; halt -f”;
startup {
degr-wfc-timeout 120; # 2 minutes.
}
disk {
on-io-error detach;
}
net {
}
syncer {
rate 10M;
group 1;
}
on node04 {
device /dev/drbd0;
disk /dev/gnbd/gnbd0;
address 192.168.123.114:7788;
meta-disk internal;
}
on node05 {
device /dev/drbd0;
disk /dev/gnbd/gnbd1;
address 192.168.123.115:7788;
meta-disk internal;
}
}
~
————————————————————————————–
node04 # drbdadm primary all
node04 # gfs format
node04 # mount -t gfs /dev/drbd0 /gfs
node05 # mount -t gfs /dev/gnbd/gnbd0 /gfs
실제 node05 에서는 gfs,gnbd 로 node04 의 resource 에 mount
node04 에 문제 발생 시 heartbeat 를 이용하여 gnbd1 에 drbd primary 권한을 넘기로
node05 에서는 자기 자신의 gnbd1 에 mount
gnbd0 -> gnbd1 로 network mirroring 이 되므로 디스크는 동일 환경 유지
7. GFS 관리 하기
Section 5.1 Making a File System
Section 5.2 Mounting a File System
Section 5.3 Unmounting a File System
Section 5.4 GFS Quota Management
Section 5.5 Growing a File System
Section 5.6 Adding Journals to a File System
Section 5.7 Direct I/O
Section 5.8 Data Journaling
Section 5.9 Configuring atime Updates
Section 5.10 Suspending Activity on a File System
Section 5.11 Displaying Extended GFS Information and Statistics
Section 5.12 Repairing a File System
Section 5.13 Context-Dependent Path Names
– GFS Kernel 과 SW 업그레이드 하기
GFS는 kernel에 의존되는 바가 크기 때문에 반드시 해당 커널에 맞는 패키지를 가지고
업그레이드를 해야 한다.
Redhat에서 배포하는 Src,rpm 으로 rebuild 를 하다보면 여러가지 의존성에 의해 문제가
발생하는데 이는 Redhat 에서 배포하는 패지지 개개별로 모두 다른 패키지들과의 의존성
을 가지고 있기 때문에다.
아래 순으로 build 를 하며, build 가 완료되면 다음것을 build 하기 전에 설치를 하고
난 후 build를 해야 정상적으로 rpm building 이 되어진다.
kernel-2.6.9-22.0.1.EL.i686.rpm
kernel-devel-2.6.9-22.0.1.EL.i686.rpm
kernel-utils-2.4-13.1.69.i386.rpm
mkinitrd-4.2.1.6-1.i386.rpm
magma-1.0.1-4.i686.rpm magma-devel-1.0.1-4.i686.rpm
ccs-1.0.2-0.i686.rpm ccs-devel-1.0.2-0.i686.rpm
gulm-1.0.4-0.i686.rpm gulm-devel-1.0.4-0.i686.rpm
magma-plugins-1.0.2-0.i386.rpm
cman-kernel-2.6.9-39.8.i686.rpm
cman-1.0.2-0.i686.rpm cman-devel-1.0.2-0.i686.rpm
dlm-kernel-2.6.9-37.9.i686.rpm
dlm-1.0.0-5.i686.rpm dlm-devel-1.0.0-5.i686.rpm
fence-1.32.6-0.i686.rpm
gnbd-kernel-2.6.9-9.14.i686.rpm
gnbd-1.0.1-1.i686.rpm
GFS-kernel-2.6.9-42.2.i686.rpm
GFS-6.1.2-0.i386.rpm
device-mapper-1.01.04-1.0.RHEL4.i386.rpm
lvm2-2.01.14-2.0.RHEL4.i386.rpm
lvm2-cluster-2.01.14-1.0.RHEL4.i386.rpm
iddev-2.0.0-3.i686.rpm iddev-devel-2.0.0-3.i686.rpm
이와 같이 src.rpm 의 building 과 설치가 완료되면, 현재 서비스 중인 gfs 관련 패키지를
모두 정지 한 후 리부팅 시 자동으로 gfs 가 구동되지 않도록 한다.
chkconfig –level 3 gfs off
chkconfig –level 3 cman off
chkconfig –level 3 lock_gulmd off
chkconfig –level 3 clvmd off
chkconfig –level 3 ccsd off
chkconfig –level 3 fenced off
***** GNBD stop 절차
umount /gfs
sleep 2
gnbd_import -r gnbd0
killall clvmd
fence_tool leave
killall fenced
sleep 2
cman_tool leave force
killall ccsd
rmmod gnbd
rmmod lock_dlm
rmmod gfs
rmmod dm-mod
**** GFS Stop 절차
umount /gfs
fence_tool leave
cman_tool leave
killall ccsd
rmmod lock_dlm
rmmod gfs
rmmod dm-mod
**** /etc/fstab 확인
/etc/fstab에 gfs 관련 마운트 정보를 입력해 두었다면 주석 처리를 한다.
*** 리부팅 ( rebooting )
**** GNBD Start 절차 (서버)
modprobe dm-mod
modprobe gfs
modprobe lock_dlm
modprobe gnbd
ccsd
cman_tool join
fence_tool join
gnbd_serv -v
gnbd_export -v -e gnbd0 -d /dev/hda4
**** GNBD Start 절차 (클라언트)
modprobe dm-mod
modprobe gfs
modprobe lock_dlm
modprobe gnbd
ccsd
cman_tool join
fence_tool join
gnbd_import -v -i node03
mount -t gfs /dev/gnbd/gnbd0 /gfs
**** GFS init start
chkconfig –level 3 gfs on
chkconfig –level 3 cman on
chkconfig –level 3 clvmd on
chkconfig –level 3 ccsd on
chkconfig –level 3 fenced on
8. GFS 의 적용 범위 및 고급 구성