[클러스터] 리눅스 클러스터링 서버 구축하기 -아랑
LVS (Linux Virtaul Server) INSTALL
작성자 : 서진우 ( alang at sysmng.com )
————————————————————————–
1. 시스템 환경
* Master Server ( real_server 1 ) :
Redhat 7.1 ( kernel 2.4.2 )
랜카드 1개
활당 아이피 3개
– 실제 아이피 : 211.47.64.151 ( eth0 )
– 내부 아이피 : 192.168.0.1 ( eth0:0 )
– 가상 아이피 : 211.47.64.153 ( eth0:1 )
* Real Server 2
Redhat 7.1 ( kernel 2.4.2 )
랜카드 1개
활당 아이피 3개
– 실제 아이피 : 211.47.64.145 ( eth0 )
– 내부 아이피 : 192.168.0.2 ( eth0:0 )
– 가상 아이피 : 211.47.64.153 ( lo:0 )
로드밸랜싱 서버와 리얼서버가 같은 허브에 연결되어진 상태에서
위의 환경으로 구축되어질것이다.
그럼..설치를 시작해 보자.
2. 커널 패치
먼저 커널에 ipvs 패치와 arp 캐싱 문제를 해결하는 패치를 해 주어야 한다.
참고로 ipvs 패치는 http://linuxvirtualserver.org/software/index.html
에 있다. 이곳에서 ipvs-0.2.7.tar.gz 를 다운 받는다. 커널은 2.4.5 로
설치하겠다.
ipvs 패치는 로드밸랜싱 서버에만 해주면 되지만 arp 패치는 로드,리얼서버
모두 해준다.
IPVS module 의 설치 방법에는 두가지가 있다. 우선 하나는 모듈로 올리는
방법과 커널에 추가 하는 방법이다.
모듈에 올리는 방법 :
// <path-name> 은 ipvs patch directory
cd <path-name>/ipvs
make
make -C ipvsadm
make install
insmod ip_vs_wlc.o
커널에 적재하는 방법 :
/usr/src 디렉토리에 아무 패치가 되지 않은 커널 linux-2.4.2.tar.gz
의 압축을 푼다.
# tar xzvf linux-2.4.2.tar.gz
# mv linux-2.4.2 linux
ipvs-0.2.7.tar.gz 압축을 해제한다.
# tar xzvf ipvs-0.2.7.tar.gz
# cd linux
// ipvs 패치
# cat ../ipvs-0.2.7/linux_kernel_ksyms_c.diff | patch -p1
# cat ../ipvs-0.2.7/linux_net_Makefile.diff | patch -p1
# cat ../ipvs-0.2.7/linux_net_ipv4_Config_in.diff | patch -p1
# cat ../ipvs-0.2.7/linux_ip_fw_compat_c.diff | patch -p1
# cp -rp ../ipvs-0.2.7/ipvs/ net/ipv4
# mv net/ipv4/ipvs/linux_net_ipv4_ipvs_Makefile net/ipv4/ipvs/Makefile
// arp 패치
# cat ../hidden-2.4.2-1.diff | patch -p1
커널 컴파일
# make menuconfig
Code maturity level options —>
[*] Prompt for development and/or incomplete code/drivers
Networking options —>
//* Networking options 에서 제대로 ipvs 패치가 이루어 졌으면
IP: Netfilter Configuration —>
IP: Virtual Server Configuration —>
이 두가지 항목이 모두 있게 된다. 만일 이 두가지가 없다면 커널패치가
정상적으로 이루어 지지 않은 것이다.
<*> Packet socket
[*] Packet socket: mmapped IO
[*] Kernel/User netlink socket
[*] Routing messages
<*> Netlink device emulation
[*] Network packet filtering (replaces ipchains)
[*] Network packet filtering debugging
[ ] Socket Filtering
<*> Unix domain sockets
[*] TCP/IP networking
[*] IP: multicasting
[*] IP: advanced router
[*]IP: policy routing
[*] IP: use netfilter MARK value as routing key
[ ] IP: fast network address translation
[ ]IP: equal cost multipath
[ ]IP: use TOS value as routing key
[ ]IP: verbose route monitoring
[ ]IP: large routing tables
[ ] IP: kernel level autoconfiguration
<*> IP: tunneling
< > IP: GRE tunnels over IP
[*] IP: multicast routing
[ ]IP: PIM-SM version 1 support
[ ]IP: PIM-SM version 2 support
[ ] IP: ARP daemon support (EXPERIMENTAL)
[ ] IP: TCP Explicit Congestion Notification support
[*] IP: TCP syncookie support (disabled per default)
IP: Netfilter Configuration —>
IP: Virtual Server Configuration —>
< > The IPv6 protocol (EXPERIMENTAL)
< > Kernel httpd acceleration (EXPERIMENTAL)
[ ] Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)
—
< > The IPX protocol
< > Appletalk protocol support
———————————————————
IP: Netfilter Configuration —>
<*> Connection tracking (required for masq/NAT)
<*> FTP protocol support
< > Userspace queueing via NETLINK (EXPERIMENTAL)
<*> IP tables support (required for filtering/masq/NAT)
<*> limit match support
<*> MAC address match support
<*> netfilter MARK match support
<*> Multiple port match support
<*> TOS match support
<*> Connection state match support
<*> Unclean match support (EXPERIMENTAL)
<*> Owner match support (EXPERIMENTAL)
<*> Packet filtering
<*> REJECT target support
< > MIRROR target support (EXPERIMENTAL)
<*> Full NAT
<*> MASQUERADE target support
<*> REDIRECT target support
<*> Packet mangling
<*> TOS target support
<*> MARK target support
< > LOG target support
——————————————————-
IP: Virtual Server Configuration —>
<*> virtual server support (EXPERIMENTAL)
[*] IP virtual server debugging
(12) IPVS connection table size (the Nth power of 2)
— IPVS scheduler
<*> round-robin scheduling
<*> weighted round-robin scheduling
<*> least-connection scheduling scheduling
<*> weighted least-connection scheduling
<*> locality-based least-connection scheduling
<*> locality-based least-connection with replication scheduling
— IPVS application helper
< > FTP protocol helper
——————————————————
이와 같이 설정하고 커널 컴파일을 한다.
# make dep
# make clean
# make bzImage
# make modules
# make modules_install
커널 컴파일이 끝나면…새로운 커널이미지를 lilo 에 적용시키고
새로운 커널로 재부팅을 한다.
이제…처음에 말했던…시스템 환경을 구축해 보자..
* master_server (로드밸랜싱)
# ifconfig eth0 211.47.64.151 netmask 255.255.255.0 up
# route add -host 211.47.64.151 dev eth0
# ifconfig eth0:0 192.168.0.1 netmask 255.255.255.0 up
# route add -host 192.168.0.1 dev eth0:0
# ifconfig eth0:1 211.47.64.153 netmask 255.255.255.255 broadcast 211.47.64.153 up
# route add -host 211.47.64.153 dev eth0:1
// arp 캐쉬 제거를 위해서 …
인터넷은 tcp/ip 기반으로 되어 있지만 한번 접속된 서버의 ip 주소에 대한
arp 태쉬라는것이 얼마간 남게 된다. 그래서 그 캐시가 지워지기 전에는 처
음 접속후 arp 캐시를 따라서 접속하게 된다. 때문에 위와 같이 arp 캐시를
숨김으로해서 클라이언트에 arp 캐시가 저장이 된지 않고 매번 서버를 찾도
록 하는 것이다.
echo 1 > /proc/sys/net/ipvs/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/all/hidden
echo 1 > /proc/sys/net/ipv4/conf/eth0/hidden
* real_server 1
# ifconfig eth0 211.47.64.145 netmask 255.255.255.0 up
# route add -host 211.47.64.145 dev eth0
# ifconfig eth0:0 192.168.0.2 netmask 255.255.255.0 up
# route add -host 192.168.0.2 dev eth0:0
# ifconfig lo:0 211.47.64.153 netmask 255.255.255.255 broadcast 211.47.64.153 up
# route add -host 211.47.64.153 dev lo:0
echo 1 > /proc/sys/net/ipvs/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/all/hidden
echo 1 > /proc/sys/net/ipv4/conf/lo/hidden
이와 같이 설정이 모두 무사히 마쳤으면 확인을 해본다.
# ifcofig
# route
이제 ipvsadm 을 이용하여 클러스터를 시켜 보자
물런 이설정은 로드밸랜싱 서버인 master_server 에만 행한다.
설정에 앞서 ipvsadm 명령어에 사용되는 옵션에 대해 알아보자.
-A : 서비스를 추가 한다.
-s : 스케줄러 선택 ( wlc : weight least connection scheduling )
-a : add server ( -e : EDIT , -d : Delete )
-t : TCP service 추가 ( -u : UDP , -f : Firewall )
-r : 옵션 다음에 Real Server ip address 를 적는다.
-i : 패킷전달 방식 (ip tunneling 방식) , -g : Direct Routing 방식
-w : wlc 방식에서 가중치
* master_server
# ipvsadm -A -t 211.47.64.153:80 -s wlc
# ipvsadm -a -t 211.47.64.153:80 -r 192.168.0.1 -g -w 1
# ipvsadm -a -t 211.47.64.153:80 -r 192.168.0.2 -g -w 2
여기서 -w 뒤의 숫자는 요청분배 가중치를 둔것이다. -w 1 은 한번의 요청,
-w 2 는 두번의 요청을 의미하는것으로 위의 설정되로 라면…
1st connection -> 192.168.0.1
2st connection -> 192.168.0.2
3st connection -> 192.168.0.2
4st connection -> 192.168.0.1
5st connection -> 192.168.0.2
6st connection -> 192.168.0.2
7st connection -> 192.168.0.1
이와 같은 순서로 요청이 분배되게 된다.
리얼서버를 몇개를 늘리더라도 master_server 에 ipvsadm 명령어를 통해
리얼서버설정만 추가해 주면된다.
# ipvsadm -a -t 211.47.64.153:80 -r 192.168.0.3 -g -w 2
# ipvsadm -a -t 211.47.64.153:80 -r 192.168.0.4 -g -w 2
# ipvsadm -a -t 211.47.64.153:80 -r 192.168.0.5 -g -w 2
.
.
.
일단 여기까지면 작업분배가 이루어 진다. 하지만 리얼서버 한대가 과부하
에 의해 죽게 되면 그래도 로드밸랜싱 서버에 설정된 스케줄 대로 작업이
분배되어진다. 몇번은 살아 있는 서버로..몇번은 죽어 있는 서버로…
여기서 리얼서버가 죽으면 …ipvsadm 에서 죽은 리얼서버의 정보를 제거
하여 더이상 그리고 작업을 분배해 주어서는 안된다. 이와 같은 작업을
위해서는 mon 이란 프로그램을 설치 해야 한다.
자 mon 을 설치 하여 보자..
mon 프로그램은 http://www.kernel.org/software/mon/ 에서 다운 받으면 된다.
mon-0.38.21.tar.gz
mon 을 설치하기 위해서는 몇가지 perl 모듈이 필요한데…다음과 같다.
-Time::Period
-Time::HiRes
-Convert::BER
-Mon::*
이는 ftp://ftp.bora.net/pub/CPAN 디렉토리및에서 다운 받을수 있다.
Perl 모듈을 설치 전에 C 헤더 파일에 대응하는 perl 헤더 파일을 만들어야 한다.
# cd /usr/include
# h2ph *.h sys/*.h asm/*.h
xxx.h -> xxx.ph 등의 메세지와 함께 변환이 되어진다.
perl 모듈은 다음과 같은 방법으로 설치 할수 있다.
# tar xzvf Time-Hires-01.20.tar.gz
# cd Time-Hires-01-20
# perl Makefile.PL
# make
# make test
# make install
fping 프로그램 정도는 기본으로 깔아 두세요…
mon 소스를 /usr/local 에 압축을 풀어 모든 파일들을 /usr/local/mon 에 둔다.
# mv /usr/local/mon-0.38 /usr/local/mon
# cd /usr/local/mon
# mkdir /etc/mon
# cp etc/example.cf /etc/mon/mon.cf
# cp etc/auth.cf /etc/mon/auth.cf
이와 같이 옮겼으면 /etc/service 파일을 열어서 mon 이 사용할 포트를 지정해
준다. (제일 끝에다가…)
mon 2583/tcp # MON
mon 2583/udp # MON traps
이제 /etc/mon/mon.cf 를 열어서 간단한 mon 설정 파일을 만들고 테스트 해보자.
# vi /etc/mon/mon.cf
————————————————————————
cfbasedir = /etc/mon
alertdir = /usr/local/mon/alert.d
mondir = /usr/local/mon/mon.d
maxprocs = 20
histlength = 100
randstart = 30s
authtype = getpwnam
hostgroup node_2 192.168.0.2
watch node_2
service ping
description ping to node_2 group
interval 10s
monitor fping.monitor
period wd {Mon-Fri} hr {7am-10pm}
alert mail.alert alang at sysmng.com
alert page.alert alang at sysmng.com
alert echo.alert “real02 server is down!!”
upalert echo.alert “real02 server is live!!”
———————————————————————–
echo.alert 란 파일은 없으므로 만들어 준다.
# vi /usr/local/mon/alert.d/echo.alert
———————————————————————–
#!/bin/sh
echo “`date`$*” >> /var/log/echo.alert.log;
———————————————————————–
파일 퍼미션은 755 로 둔다.
mon 을 실행 시켜 보자..
/usr/local/mon -f -c /etc/mon/mon.cf
이제 real02 서버의 LAN 선을 뽑아 보자..
/var/log/echo.alert.log 에 real02 server is down 이란 로그가 쌓이게 된다.
이와 같이 되었다면..성공이다..
지금까지는 테스트 였다.. 이제 실질적으로 mon.cf 파일을 설정하여 보자.
# vi /etc/mon/mon.cf
————————————————————————
cfbasedir = /etc/mon
alertdir = /usr/local/mon/alert.d
mondir = /usr/local/mon/mon.d
maxprocs = 20
histlength = 100
randstart = 30s
authtype = getpwnam
hostgroup node_1 192.168.0.1
hostgroup node_2 192.168.0.2
watch node_1
service http
interval 5s
monitor http.monitor
period wd {Sun-Sat}
alert lvs.alert -P tcp -V 211.47.64.153:80 -R 192.168.0.1 -W 1 -F dr -X down
upalert lvs.alert -P tcp -V 211.47.64.153:80 -R 192.168.0.1 -W 1 -F dr
watch node_2
service http
interval 5s
monitor http.monitor
period wd {Sun-Sat}
alert lvs.alert -P tcp -V 211.47.64.153:80 -R 192.168.0.2 -W 1 -F dr -X down
upalert lvs.alert -P tcp -V 211.47.64.153:80 -R 192.168.0.2 -W 1 -F dr
————————————————————————-
테스트에서 처럼 단순히 ping 으로 real 서버들을 감시하는것이 아니라 http 접속
을 계속 확인하여 httpd 가 정상 작동을 하지 않을때 별도 처리를 해주도록 하였다.
서버가 살아 있다고 하더라도..httpd 데몬이 죽으면 웹서비스는 할수 없기 때문이
다.. 이제는 ..
mon 에서 사용하는 ipvsadm 을 마음대로 제어할수 있는 스크립터를 만들어 보자.
이 mon 에서 계속 감시 하여 real 서버가 죽을때 자동으로 죽은 real 서버로는
작업을 못보내게 하는 스크립터가 되겠다.
# vi /usr/local/mon/alert.d/lvs.alert
————————————————————————-
#!/usr/bin/perl
#
# lvs.alert – Linux Virtual Server alert for mon
#
# It can be activated by mon to remove a real server when the
# service is down, or add the server when the service is up.
#
#
use Getopt::Std;
getopts (“s:g:h:t:l:P:V:R:W:F:X:u”);
$ipvsadm = “/sbin/ipvsadm”;
$protocol = $opt_P;
$virtual_service = $opt_V;
$remote = $opt_R;
$status = $opt_X;
if ($status eq “down”){
# <“udp 를 사용 하시려면 이 부분에 프로토콜 체크를 한번 더 하셔야
합니다.”>
system(“$ipvsadm -d -t $virtual_service -r $remote”);
exit 0;
}
else {
$weight = $opt_W;
if ($opt_F eq “nat”) {
$forwarding = “-m”;
}
elsif ($opt_F eq “tun”) {
$forwarding = “-i”;
}
else {
$forwarding = “-g”;
}
if ($protocol eq “tcp”) {
system(“$ipvsadm -a -t $virtual_service -r $remote -w $weight
$forwarding”);
exit 0;
}
else {
system(“$ipvsadm -a -u $virtual_service -r $remote -w $weight
$forwarding”);
exit 0;
}
exit 0;
};
——————————————————————————-
퍼미션을 755 로 준다.
이제 지금까지 만들어 수동으로 하나하나 작업한 환경을 한번에 제어할수 있는
init 스크립트를 만들어 보자
# vi /etc/rc.d/init.d/puck
——————————————————————————
#!/bin/sh
#
# load balancer daemon scripts
#
PATH=/bin:/usr/bin:/sbin:/usr/sbin
export PATH
IPVSADM=/sbin/ipvsadm
MON=/usr/local/mon/mon
RETVAL=0
#Source function library.
. /etc/rc.d/init.d/functions
case “$1” in
start)
if [ -x $IPVSADM ]
then
#
# ipvs system 설정 부분
#
echo 1 > /proc/sys/net/ipv4/ip_forward
ifconfig eth0:1 211.47.64.153 netmask 255.255.255.255 broadcast 211.47.64.153 up
route add -host 211.47.64.153 dev eth0:1
echo 1 > /proc/sys/net/ipv4/conf/all/hidden
echo 1 > /proc/sys/net/ipv4/conf/eth0/hidden
$IPVSADM -A -t 211.47.64.153:80 -s wlc
$IPVSADM -a -t 211.47.64.153:80 -R 192.168.0.1 -g -w 1
$IPVSADM -a -t 211.47.64.153:80 -R 192.168.0.2 -g -w 1
echo -n “started loadbalancer daemon:”
daemon $MON -f -c /etc/mon/mon.cf
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/punk
echo
fi
;;
stop)
if [ -x $IPVSADM ]
then
echo -n “puck daemon stopping…”
$IPVSADM -C
ifconfig eth0:1 down
killproc mon
rm -f /var/lock/subsys/punk
killall http.monitor
echo -n “puck daemon killed”
echo
fi
;;
*)
echo “Usage : puck {start|stop}”
exit 1
esac
exit 0
——————————————————————————-
이로써 모든 설정이 완료 되었다.
시스템에서 일어 나는 변화를 확실하게 하기 위해서 웹서버의 KeepAlive 를 off
시키고 MaxKeepAliveRequest 값을 1 로 변환한다.
인터넷 익스플로러의 도구 -> 인터넷 옵션 -> 임시 인터넷 파일 ->
페이지를 열때 마다 체크
설정을 하고 각 서버마다 각기 다른 초기 화면을 띄워 놓자..
이제 테스트를 한번 해보자 ..
로드 밸랜싱 서버에서
# /etc/rc.d/init.d/puck start
브라우져를 열어서 새로 고침을 할때 마다 인덱스 화면이 변화는가…변환다면..
성공이다..축하한다.
어느 하나의 리얼서버를 죽여 놓고…계속 새로고침을 해보자..죽은 real 서버
의 초기화면을 제외한 다른 서버들의 초기화면들만 스케줄에 따라서 나타나는
지를 확인하라… 죽은 서버를 다시 살리면…한동안은 새로 살아난 서버 화면
만 보일것이다. 이는 wlc 스케줄 방식을 이해하면 금방알수 있다. wlc 방식은
가중치도 줄수 있지만…그와 동시에 각 리얼서버별로 처리 요청 비중을 고려
하여 분배하게 되는 것이다. 즉 한 서버가 죽은 동안 다른 서버에서 요청을
많이 처리 했으므로다른 서버가 자신의 일을 처리해 준만큼 자기도 다른 서버의
일을 대신 처리해준다고 보면된다. 이와 같은 방식은 ipvsadm 으로 요청 처리
사항을 보면 알수 있다.
[root@www1 alert.d]# ipvsadm
IP Virtual Server version 0.2.7 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 211.47.64.153:http wlc
-> 192.168.0.2:http Route 1 5 0
-> 192.168.0.3:http Local 1 5 0
-> 192.168.0.4:http Local 1 5 0
-> 192.168.0.5:http Local 1 4 0
이로써 LVS_INSTALL 을 마치도록 하겠다. 앞으로 High Avaliability 와 disk
동기화 방법에 대해 연구해 보도록 하겠다..