[클러스터] 리눅스 클러스터링 서버 구축하기 -아랑

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

동기화 방법에 대해 연구해 보도록 하겠다..

서진우

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

You may also like...

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