본문 바로가기
개발/Programming

HAProxy로 로드밸런싱

by 카루딘 2017. 5. 16.
반응형

http://d2.naver.com/helloworld/284659


제  목 : HAProxy로 로드밸런싱(LB, 이중화) 구성
작성자 : 좋은진호(truefeel, http://coffeenix.net/ )
작성일 : 2015.3.10(화)

HAProxy는 L4(TCP), L7(HTTP) 네트웍 스위치를 대체할 수 있는 로드 밸런싱(load balancing), HA(high availability)용 오픈소스다. 예를 들어 웹서버가 여러대가 있고, 이 서버를 로드 밸런싱한다면 웹서버 앞단에 HAProxy서버를 셋팅한다. 여러대 웹서버 중 1대가 장애발생해도 서비스에는 지장이 없다. HAProxy는 바로 서버 장애를 인지하고 해당서버를 서비스에서 제외시키기 때문이다.




1. HAProxy 기본 설정

 
global
   log 127.0.0.1   local1         # Linux
   # log /var/run/log   local1      # FreeBSD

   #
   maxconn 4096
   uid 99
   gid 99
   daemon

defaults
   log   global
   mode   http
   # option  httplog
   option  dontlognull

   retries   3
   redispatch
   maxconn   4000
   contimeout 5000

listen   wwwlb 0.0.0.0:80
   option   httpchk
   option   httpclose
   option   forwardfor

   balance   roundrobin
   server   www1 10.10.10.1:80 check inter 3000 rise 2 fall 1
   server   www2 10.10.10.2:80 check inter 3000 rise 2 fall 1
 



설정 중 몇가지만 살펴보자.

1) 로그 설정

 
global
   log 127.0.0.1   local1         # Linux
   # log /var/run/log   local1      # FreeBSD
defaults
   log   global
   # option  httplog
 



log 설정은 지정한 IP 또는 소켓(예. /dev/log 또는 /var/run/log)으로 로그를 보낸다. local1 뒤에는 로그레벨을 지정할 수 있는데, local1 notice라고 지정했다면 emerg~notice 레벨을 로그로 남긴다. notice 레벨만 syslog로 보내고 싶다면 local1 notice notice처럼 notice를 2번 적어주면 된다. 뒤에 있는 notice는 최소레벨을 의미한다. 즉, notice~notice 범위의 레벨을 의미하므로 오직 notice 레벨만 syslog로 보내는 것이다.
option httplog 설정은 클라이언트 IP, URL, 상태코드, bytes 등의 웹로그까지 syslog로 보내도록 한다.

syslog(또는 rsyslog)도 위와 매칭되도록 설정한다.

 
# local1.=info            /var/log/haproxy_access.log
local1.notice            /var/log/haproxy.log
 



HAProxy start/stop 정보와 서버가 DOWN, UP 등의 상태 변경 정보 등이 notice레벨에 해당한다. 웹로그는 info레벨이다. 요청이 너무 많을 경우 웹로그량(haproxy_access.log)이 급속히 커지므로 로그를 남길 것인지 잘 판단하길 바란다.

2) listen 설정

 
option   httpchk
option   forwardfor
 



option httpchk는 HTTP요청으로 서비스 헬스체크를 하겠다는 뜻이다. 추가설정없이 option httpchk만 설정하면 OPTIONS 메쏘드로 웹요청을 한다.
특정 URL을 체크하고 싶다면 아래처럼 설정하면 된다. OPTIONS 메쏘드 체크보다는 좀 더 나은 방법이다. HEAD 메쏘드로 체크하면 웹서버 응답이 없는 것 외에 404 에러가 발생하는 경우도 해당 서버를 서비스에서 제외시킨다.

 
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>

(예) option httpchk HEAD / HTTP/1.0
(예) option httpchk HEAD / HTTP/1.1\r\nHost:\ w.coffeenix.net
(예) option httpchk HEAD / HTTP/1.1\r\nUser-Agent:\ Health\ Check/HaProxy1\r\nHost:\ w.coffeenix.net
 



option forwardfor는 백단의 웹서버(위에서는 www1, www2)에 X-Forwarded-For 헤더를 넣어서 전달한다. X-Forwarded-For 헤더에 실제 요청한 클라이언트 IP가 저장된다.

 
server  www1 10.10.10.1:80 check inter 3000 rise 2 fall 1
 



www1 서버가 정상적으로 동작중인지를 3초(3000)간격으로 체크(check inter 3000)한다. 접속이 한번이라도 안된다면 해당 서버를 서비스에서 제외(fall 1)시킨다. 만약 두번 연속 체크해서 모두 정상적인 응답이 온다면 다시 서비스에 추가(rise 2)시킨다. rise를 지정하지 않으면 디폴트로 2를, fall을 지정하지 않으면 3이 디폴트 값이다.

 
(예) check inter 3000 fastinter 1000 rise 3 fall 2
 



평상시에는 inter 3000 설정에 따라 3초 간격으로 서비스를 체크한다. 해당 서버가 다운이 되었을 때, rise 3 설정에 따라 3번 연속 체크해서 정상이면 서비스에 추가한다. 이때 fastinter 1000이 실력발휘를 한다. 3번 체크하는 동안에 1초간격으로 서비스를 체크하게 된다. 따라서 좀 더 빨리 서비스에 추가될 수 있다.

balance 설정은 여러개가 있는데 자주 사용하는 2개만 살펴보면.
roundrobin은 순차적으로 요청을 넘겨준다. 첫번째 요청은 1번서버로, 다음은 2번서버로, 그 다음은 다시 1번서버로.
leastconn은 요청을 가장 적게 받은 서버로 요청을 넘겨준다. 1번 서버가 100개 요청받아 처리중이고, 2번서버가 80개 받아 처리중이라면, 요청이 들어올 때 2번서버로 보낸다.


2. 동일 클라이언트는 동일한 서버로 접속되도록 설정 (sticky 설정)

동일한 클라이언트가 항상 같은 서버로만 요청을 보낼 필요가 있을 때는 쿠키 체크와 클라이언트 IP 체크 등 2가지 방법으로 해결할 수 있다.

1) 쿠키로 세션 유지

 
listen   wwwlb 0.0.0.0:80
... 생략 ...
   balance   roundrobin
   cookie  SVID insert indirect nocache
   server   www1 10.10.10.1:80 cookie w1 check inter 3000 rise 2 fall 1
   server   www2 10.10.10.2:80 cookie w2 check inter 3000 rise 2 fall 1
 



클라이언트 요청이 들어오면, SVID 쿠키가 있는지를 검사한다. 클라이언트가 처음 요청할 때는 SVID 쿠키가 없을 것이므로 쿠키를 새로 만든다. 이 때 www1 서버로 접속하면 w1 쿠키값을 굽고, www2 서버로 접속하면 w2 쿠키값을 굽는다. 한번 요청했던 클라이언트에서 다음 요청을 할 때는 SVID 쿠키가 있으므로 쿠키값에 맞는 서버로 요청을 보낸다. 따라서 처음에 w1서버로 요청이 들어왔다면 다음에도 계속 w1서버로 요청을 보낼 수 있게 된다.

 
cookie  SVID insert indirect nocache maxlife 10m
 



동일한 서버로 접속하는 것을 10분만 유지하려면 위처럼 cookie 유지시간(maxlife 10m)을 지정할 수 있다.

HAProxy서버가 '클라이언트 -> HAProxy 서버 -> 웹서버들'과 같은 구성으로 되어 있을 때, SVID 쿠키는 클라이언트 <-> HAProxy 서버 구간에만 유지가 되고, 뒷단의 웹서버로는 전달되지 않는다. 로드밸런싱용으로만 사용하는 쿠키이므로 웹서버가 사용할 필요없으니깐.

 
클라이언트 <--- SVID 쿠키 ---> HAProxy <--- SVID 쿠키없음 ---> 웹서버들
 



2) 클라이언트 IP로 세션 유지

 
listen   wwwlb 0.0.0.0:80
... 생략 ...
   balance   source
   hash-type consistent
   server   www1 10.10.10.1:80 check inter 3000 rise 2 fall 1
   server   www2 10.10.10.2:80 check inter 3000 rise 2 fall 1
 



위처럼 balance와 hash-type을 설정하면 해시테이블을 사용해서 클라이언트 IP별로 특정서버로만 접속되도록 할 수 있다.


3. HAProxy의 통계 모니터링 페이지

 
listen   stats_page 0.0.0.0:8080
   stats   enable
   stats   uri /
   stats   auth ID:비밀번호
 



HAProxy의 통계 모니터링 페이지(Statistics Report, stats page)는 8080같이 서비스와는 별개의 포트로 설정하는게 보다 안전하다.


4. 웹서버 로그에 Proxy IP대신 클라이언트 IP 남기기

클라이언트 -> HAProxy 서버 -> 웹서버로 요청이 들어올 때, 웹서버 로그에는 HAProxy서버의 IP가 남게된다. 요청한 클라이언트 IP는 X-Forwarded-For 헤더에 들어있는데, nginx, apache 웹서버는 이 헤더값을 뽑아내 Proxy IP를 클라이언트 IP로 변경해주는 모듈이 있다.

1) nginx

http_realip 모듈은 기본으로 설치되지 않으므로 configure할 때 --with-http_realip_module 옵션을 추가한 후 컴파일한다.

 
set_real_ip_from  10.10.10.10;
real_ip_header    X-Forwarded-For;
 



10.10.10.10은 HAProxy서버의 IP이고, HAProxy서버가 여러대일 때는 IP를 한줄에 하나씩 추가해준다. 192.168.0.0/24처럼 대역폭으로 지정할 수도 있다.

2) apache

아파치에 mod_rpaf 모듈이 클라이언트 IP 변환기능을 제공한다. 자세한 설정법은 다음글을 읽어보시길.

* apache에서 Proxy IP를 real IP로 바꾸기 (글 좋은진호, 2010.2)
  http://coffeenix.net/board_view.php?bd_code=1701


5. 참고자료

* HAProxy version 1.5.11 Configuration Manual
  http://cbonte.github.io/haproxy-dconv/configuration-1.5.html

* Module ngx_http_realip_module
  http://nginx.org/en/docs/http/ngx_http_realip_module.html

* L4/L7 스위치의 대안, 오픈 소스 로드 밸런서 HAProxy
  http://helloworld.naver.com/helloworld/textyle/284659

* FreeBSD에서 CARP와 HAProxy로 이중화(HA) 구성 (글 좋은진호, 2015.2)
  http://coffeenix.net/board_view.php?bd_code=1770

반응형