커피닉스, 시스템 엔지니어의 쉼터 커피향이 나는 *NIX
커피닉스
시스템/네트웍/보안을 다루는 곳
* HanIRC의 #coffeenix 방
[ 장비 및 회선 후원 ]
HOME > 시스템 관리 / 서버운영 도움말
검색 : 사이트 WHOIS 웹서버 종류

최적화 / 튜닝 / 성능개선 (6, 글 1, 자료 3)
디스크 쿼터(quota) (3, 글 1, 자료 3)
디스크 관리 / 파일시스템 / mount (34, 글 13, 자료 12)
백업(backup) / 시스템 복구 (14, 글 6, 자료 11)
서버운영 (8, 글 2, 자료 9)
프린터 관리 / 프린팅 (7)
패키지 관리 / 패치 / rpm (10, 글 5, 자료 1)
부팅, boot / LILO / GRUB (10, 글 5, 자료 9)
서버 모니터링 (10, 글 5, 자료 2)
로그인 / 로그아웃 (1)
로그(log) / syslog (5, 글 3, 자료 3)
메모리, 스왑(swap), 램디스크(ramdisk) (3, 글 2)
사용자 관리(계정 관리) (1, 자료 1)

  FreeBSD에서 CARP와 HAProxy로 이중화(HA) 구성 작성일 : 2015/03/11 10:42
 
  • 글쓴이 : 좋은진호 ( http://coffeenix.net/ )
  • 조회수 : 5542
          [ 이전화면 / 수정 ]   비밀번호 :     인쇄용 화면
      제  목 : FreeBSD에서 CARP와 HAProxy로 이중화(HA) 구성
    작성자 : 좋은진호(truefeel, http://coffeenix.net/ )
    작성일 : 2015.2.17(화)


    1. CARP(Common Address Redundancy Protocol)란

    네트웍에서 VRRP(Virtual Router Redundancy Protocol)를 들어본 적 있는가?
    VRRP, CARP 이름에 Redundancy(리던던시)가 들어가 있는 것을 보면 용도가 무엇인지 짐작이 갈 것이다.
    라우터 1대만 운영할 때 이 라우터에 문제가 발생하면 서비스 장애가 발생한다. 이를 막고자 기본라우터 + 하나 이상의 백업 라우터를 구성한다. 그리고 VRRP로 라우터에 가상의 서비스 IP(VIP)를 부여한다. VIP로 서비스를 하다가 기본 라우터가 장애가 발생하면 백업 라우터로 VIP가 자동으로 넘어가므로 서비스 장애는 VIP가 넘어가는 아주 짧은 순간 뿐이다. 장애시간이 없다고 봐도 좋다.

    VRRP의 라이센스를 피해서 새롭게 구현한게 CARP다.

    이글은 다음과 같은 서버 환경에서 설명하겠다.

    - VIP(서비스 IP) : 10.10.10.10
    - 서버 1 : 10.10.10.1
    - 서버 2 : 10.10.10.2

    CARP 이중화(또는 다중화)는 Active-Active구성은 되지 않고, Active-Standby로 구성이 된다.
    서버 1과 서버 2 중에서 1대가 Active(CARP에서 MASTER라고 부름)가 되고 이 서버가 VIP 10.10.10.10을 갖게 된다. 따라서 외부에서 VIP로 요청하면 이 서버가 서비스를 받게 된다. 다른 1대는 Standby(CARP에서 BACKUP이라고 부름)가 된다. 만약 MASTER서버가 죽게되면, 1~3초내에 자동으로 BACKUP서버가 MASTER서버로 전환된다.





    내가 MASTER라는 것을 어떻게 알릴까? MASTER 또는 BACKUP서버에서 패킷을 모니터링해보면 MASTER가 224.0.0.18로 CARP 패킷을 broadcasting하는 것을 확인할 수 있다. 이 패킷을 통해 누가 MASTER인지 알게 된다. 패킷을 보내는 간격(초단위)은 advbase값과 advskew값의 조합으로 설정하는데, 이 부분은 뒤에서 설명하겠다.

     MASTER -> 224.0.0.18 CARP 패킷 broadcast 



    2-1. CARP 설정 (FreeBSD 9 이하)

    ifconfig 명령 2번으로 설정이 끝난다. 이렇게 간단한 이중화가 있어? 좋죠?

     
    1) 서버 1에서
    # ifconfig carp0 create
    # ifconfig carp0 vhid 1 advskew 0   pass <비밀번호> 10.10.10.10/24

    2) 서버 2에서
    # ifconfig carp0 create
    # ifconfig carp0 vhid 1 advskew 100 pass <위와 같은 비밀번호> 10.10.10.10/24
     


    - vhid : Virtual Host ID(VHID). 이중화 그룹(또는 다중화 그룹. 'virtual group' 또는 'redundancy group'이라고 부른다. 편의상 '이중화 그룹'이라고 하겠다.)에서 사용하는 번호다. 1~255까지 지정가능하고, 같은 그룹의 서버는 같은 번호를 사용해야 한다. 위에서는 1을 사용했고, 2대 서버 모두에서 1을 사용해야 한다. 3대로 다중화 구성한다면 3대 모두 같아야 한다.
    - advbase : 'advertisement base' 약자. 이중화 그룹에 몇 초간격으로 알릴 것(advertisement)인지를 지정한다. 지정하지 않으면 1초. 1~255까지 가능.
    - advskew : 'advertisement skew' 약자. 실제로 이중화 그룹에 알릴 때는 advbase + advskey값/256 초 간격으로 알린다. 100으로 지정했다면 1 + 100/256초, 약 1.39초가 된다. 0으로 지정했다면 advbase + 0초 = 1초 간격으로 알린다. 낮은 값일수록 MASTER로 선택될 가능성이 높다.
    - pass : 비밀번호. 같은 이중화 그룹끼리는 동일해야 한다.

     
    # ifconfig carp0 create
    # ifconfig
    ... 생략 ...
    lo0: flags=8049 metric 0 mtu 16384
       options=3
       inet 127.0.0.1 netmask 0xff000000
    carp0: flags=8 metric 0 mtu 1500         <-- carp0 인터페이스가 추가되었다.
    # ifconfig carp0 vhid 1 advskew 0 pass <비밀번호> 10.10.10.10/24
    # ifconfig carp0
    carp0: flags=49 metric 0 mtu 1500
       inet 10.10.10.10 netmask 0xffffff00
       carp: BACKUP vhid 1 advbase 1 advskew 0         <-- 처음은 BACKUP
    # ifconfig carp0
    carp0: flags=49 metric 0 mtu 1500
       inet 10.10.10.10 netmask 0xffffff00
       carp: MASTER vhid 1 advbase 1 advskew 0         <-- 바로 MASTER로 바뀜
     


    /var/log/messages에는 다음과 같은 로그가 남는다. link가 DOWN상태로 바뀌었다면 BACKUP 서버가 되었음을 말하고, UP 상태로 바뀌었다는 것은 MASTER 서버로 전환됐음을 의미한다. 3초만에 전환됐음을 알 수 있다.

     
    Feb 17 18:35:25 www1 kernel: bce0: promiscuous mode enabled
    Feb 17 18:35:25 www1 kernel: carp0: INIT -> BACKUP
    Feb 17 18:35:25 www1 kernel: carp0: link state changed to DOWN
    Feb 17 18:35:28 www1 kernel: carp0: link state changed to UP
     



    2-2. CARP 설정 (FreeBSD 10)

    FreeBSD 10은 ifconfig alias로 CARP를 설정한다. 넷마스크는 /32를 사용한다.

     
    # kldload carp
    # ifconfig em1 vhid 1 advskew 100 pass <비밀번호> alias 10.10.10.10/32
    #
    # ifconfig em1
    em1: flags=8943 metric 0 mtu 1500
       options=9b
       ether ... 생략 ...
       inet 10.10.10.11 netmask 0xffffff00 broadcast 10.10.10.255
       inet 10.10.10.10 netmask 0xffffffff broadcast 10.10.10.10 vhid 1
       media: Ethernet autoselect (1000baseT )
       status: active
       carp: BACKUP vhid 1 advbase 1 advskew 100
     


    em1은 CARP를 사용하게 될 인터페이스명이다. 본인의 서버 환경을 보고 변경해서 설정 할 것.


    3-1. rc.conf 설정 (FreeBSD 9 이하)

    CARP 커널 모듈이 로딩되도록 /boot/loader.conf에 다음을 추가한다.

     if_carp_load="YES"
     


    /etc/rc.conf 을 설정한다. advskew값은 서버 1, 2에 따라 적당히.

     
    cloned_interfaces="carp0"
    ifconfig_carp0="vhid 1 advskew 0 pass 비밀번호 10.10.10.10/24"
     



    3-2. rc.conf 설정 (FreeBSD 10)

    1) /boot/loader.conf 설정

     carp_load="YES"
     


    2) /etc/rc.conf 설정 (advskew값은 서버 1, 2에 따라 적당히. em1는 본인의 서버 환경에 맞게 변경할 것)

     
    ifconfig_em1="inet 10.10.10.11 netmask 255.255.255.0"            <-- 기존 설정
    ifconfig_em1_alias0="vhid 1 advskew 0 pass 비밀번호 alias 10.10.10.10/32"  <-- CARP 설정 추가
     



    4. MASTER를 BACKUP으로 전환

    서버 1이 현재 MASTER다. 서버가 죽거나 네트웍이 끊긴다면 자동으로 서버 2가 MASTER로 전환될 것이다. 그런데 서버 1에서 별도 작업이 필요해서 수동으로 서비스를 서버 2로 넘기고 싶다면 어떻게 해야 할까. 서버 1에서 다음 명령으로 상태를 BACKUP으로 전환할 수 있다. 변경 후에는 두 서버에서 ifconfig 명령으로 MASER와 BACKUP이 전환됐는지 확인한다.

     
    1) FreeBSD 9 이하
    # ifconfig carp0 state backup

    2) FreeBSD 10
    # ifconfig em1 vhid 1 state backup (em1은 본인의 인터페이스명에 맞게)
     


    서버의 messages 로그를 보면 DOWN이 된 후 서버 2에서 UP이 될 때까지 3초정도 시간이 걸렸다. 3초 동안은 서비스 연결이 문제있었을 것이다.

     
    1) 서버 1에서 로그
    Feb 17 18:40:49 www1 kernel: carp0: link state changed to DOWN

    2) 서버 2에서 로그
    Feb 17 18:40:52 www2 kernel: carp0: link state changed to UP
     


    상태 전환보다는 서버 1에서 CARP 인터페이스를 down시키는게 장애시간을 줄일 수 있다. 서버 2가 MASTER로 된 것을 확인했다면 CARP 인터페이스를 다시 up시켜준다.

     
    1) FreeBSD 9 이하
    # ifconfig carp0 down
    몇 초 후 다시 up시켜준다.
    # ifconfig carp0 up

    2) FreeBSD 10 (alias 삭제하는 것과 같은 방식이다. ifconfig em1 -alias 같은 실수를 하지 말자. CARP설정이 아닌 em1 설정 자체가 날라간다.)
    # ifconfig em1 inet 10.10.10.10 -alias
    몇 초 후 다시 설정한다.
    # ifconfig em1 vhid 1 advskew 100 pass <비밀번호> alias 10.10.10.10/32
     


    위 명령을 내리자마자 서버 1의 CARP link가 DOWN(상태는 MASTER -> INIT로 바뀜)되었고, 서버 2는 지체없이 BACKUP -> MASTER으로 전환되었다. (※ 바로 전환될 수도 있고 1~2초 걸릴 수도 있다.)

     
    1) 서버 1에서 로그
    Feb 17 18:44:24 www1 kernel: carp0: link state changed to DOWN

    2) 서버 2에서 로그
    Feb 17 18:44:24 www2 kernel: carp0: BACKUP -> MASTER (master timed out)
    Feb 17 18:44:24 www2 kernel: carp0: link state changed to UP
     



    5-1. CARP 설정 삭제 (FreeBSD 9 이하)

    ifconfig carp0 down은 상태만 MASTER, BACKUP -> INIT로 전환시킨다. delete는 VIP정보만 지운다. CARP 설정을 완전히 지우려면 destroy 파라미터를 사용한다.

     
    # ifconfig carp0 down
    # ifconfig carp0
    carp0: flags=8 metric 0 mtu 1500
       inet 10.10.10.10 netmask 0xffffff00
       carp: INIT vhid 1 advbase 1 advskew 100
    #
    # ifconfig carp0 delete
    # ifconfig carp0
    carp0: flags=8 metric 0 mtu 1500
       carp: INIT vhid 1 advbase 1 advskew 100
    #
    # ifconfig carp0 destroy
     



    5-2. CARP 설정 삭제 (FreeBSD 10)

    FreeBSD 10에서는 위에서 설명한대로 ifconfig alias를 삭제한다.

     
    # ifconfig em1
    em1: flags=8943 metric 0 mtu 1500
            ether ... 생략 ...
            inet 10.10.10.11 netmask 0xffffff00 broadcast 10.10.10.255
            inet 10.10.10.10 netmask 0xffffffff broadcast 10.10.10.10 vhid 1
            media: Ethernet autoselect (1000baseT )
            status: active
            carp: BACKUP vhid 1 advbase 1 advskew 100
    # ifconfig em1 inet 10.10.10.10 -alias
     



    6. HAProxy로 로드 밸런싱(Load Balancing, LB)하기

    CARP+HAProxy 구성으로 2대 또는 그 이상의 서버를 로드 밸런싱할 수 있다.
    CARP는 1대만 Active로 되고 나머지는 Standby 상태여야 해서 서버 효율성이 떨어진다. 일하는 서버는 열심히 일하고, 나머지는 구경꾼이 되는 것이다. CARP에 HAProxy까지 운영한다면 모든 서버가 함께 일하고 어느 한 서버가 아프면 나머지 서버가 한 서버의 몫까지 일을 하게 된다.

    서버 환경은 다음과 같다.

    - 웹서비스를 하고자 한다.
    - VIP    : 10.10.10.30
    - 서버 1 : 10.10.10.1
    - 서버 2 : 10.10.10.2
    - 서버 3 : 10.10.10.3

    각 서버에 CARP와 HAProxy 데몬을 설정한다. HAProxy는 서버마다 동일하게 설정한다. (HAProxy 설정은 '7. 참고자료'의 HAProxy 관련 글을 참고할 것)

    [ haproxy.cfg 일부 ]
     
    listen wwwlb 0.0.0.0:80
            balance roundrobin
            server  www1 10.10.10.1:8080 check inter 3000 rise 2 fall 1
            server  www2 10.10.10.2:8080 check inter 3000 rise 2 fall 1
            server  www3 10.10.10.3:8080 check inter 3000 rise 2 fall 1
     


    상황별로 어떻게 처리되는지 보자.

    (상황 1) 서버 1이 MASTER인 경우를 가정하자. (서비스 정상)
      1) MASTER : 서버 1
      2)---------+-----+-----+-----+
         상태    |서버1|서버2|서버3|
        ---------+-----+-----+-----+
        HAProxy  | OK  | OK  | OK  |
        WEB      | OK  | OK  | OK  |

    VIP로 웹접속을 하면, 서버 1로 요청이 들어온다. 서버 1의 HAProxy는 로드 밸런싱 설정(위에서 balance roundrobin)에 따라서 서버 1번으로 보낸다. 다음 요청을 받으면 서버 2번으로 보낸다. 이렇게 순차적으로 처리를 한다. 나 하나, 너하나, 형 하나. 사이 좋게.

    (상황 2) 서버 1이 과로로 down되었다. (서비스 정상)
      1) MASTER : 서버 2
      2)---------+-----+-----+-----+
         상태    |서버1|서버2|서버3|
        ---------+-----+-----+-----+
        HAProxy  | down| OK  | OK  |
        WEB      | down| OK  | OK  |

    VIP가 다음 서버로 넘겨진다. 서버 2 또는 서버 3이 MASTER가 될 것인데, CARP의 advskew 값이 낮은 서버가 MASTER가 될 가능성이 높다. 서버 2가 MASTER가 되었다고 가정하자. VIP로 웹접속을 하면, 서버 2로 요청이 들어온다. 서버 2의 HAProxy는 서버 1번이 죽은 것을 감지했다. 위에서는 3초간격으로 1번만 fail(inter 3000 rise 2 fall 1)이 발생해도 서비스에서 제외시킨다. HAProxy는 서버 2의 웹서버로 요청을 보낸다. 그 다음은 서버 3, ... 이렇게 순차처리한다.

    (상황 3) 서버 1을 살렸다. 그리고 서버 3의 웹서버 데몬만 죽었다. (서비스 정상)
      1) MASTER : 서버 2
      2)---------+-----+-----+-----+
         상태    |서버1|서버2|서버3|
        ---------+-----+-----+-----+
        HAProxy  | OK  | OK  | OK  |
        WEB      | OK  | OK  | down|

    여전히 서버 2가 MASTER다. VIP로 웹접속을 하면, 서버 2로 요청이 들어온다. HAProxy는 서버 1번의 웹서버가 살았음을, 3번이 죽었음을 감지했다. 서버 1번으로 요청을 보낸다. 다음은 2번으로 보낸다. 서버 1과 서버 2가 번갈아가면서 요청을 처리한다. 엔지니어는 서버 3의 웹서버 데몬 및 설정을 확인해서 문제없으면 start시킨다.

    (상황 4) 서버 3의 HAProxy가 죽었다. (서비스 정상)
      1) MASTER : 서버 2
      2)---------+-----+-----+-----+
         상태    |서버1|서버2|서버3|
        ---------+-----+-----+-----+
        HAProxy  | OK  | OK  | down|
        WEB      | OK  | OK  | OK  |

    서비스에 영향없다. 서버 2가 MASTER이므로 나머지 서버의 HAProxy는 요청을 받지 않는다. 죽어도 서비스에 영향이 없다. 엔지니어는 서버 3의 HAProxy가 이상없으면 start시킨다.

    (상황 5) 서버 2의 웹서버 데몬이 죽었다. (서비스 정상)
      1) MASTER : 서버 2
      2)---------+-----+-----+-----+
         상태    |서버1|서버2|서버3|
        ---------+-----+-----+-----+
        HAProxy  | OK  | OK  | OK  |
        WEB      | OK  | down| OK  |

    서버 2의 HAProxy는 서버 2의 웹서버가 죽었음을 감지하고 웹서비스에서 제외시킨다. 서버 1과 서버 3으로 웹서버 요청을 보낸다. 엔지니어는 서버 2의 웹서버가 이상없으면 start시킨다.

    (상황 6) 서버 2의 HAProxy 데몬이 죽었다. (장애 발생)
      1) MASTER : 서버 2
      2)---------+-----+-----+-----+
         상태    |서버1|서버2|서버3|
        ---------+-----+-----+-----+
        HAProxy  | OK  | down| OK  |
        WEB      | OK  | OK  | OK  |

    이 때는 장애가 발생한다. 서버 2가 MASTER이므로 서버 2의 HAProxy로 요청이 들어오는데, 데몬이 죽어있으니 웹서비스가 열리지 않는다. 서버 2의 HAProxy를 start시키거나 다른 서버로 MASTER서버를 넘기면 해결된다. 사실 이런 경우는 거의 없다. 이 점만 주의하면 된다. MASTER서버의 HAProxy 설정을 바꾸거나 stop시켜야할 때는 반드시 다른 서버로 MASTER서버를 념겨주고 작업하면 된다.

    한가지 더 주의할 것이 있다. MASTER서버를 리부팅할 때 미리 다른 서버로 MASTER를 넘겨주고 리부팅해야 몇초간의 장애 시간을 줄일 수 있다.
    리부팅할 때 데몬들이 하나씩 죽고, 네트웍이 끊긴다. MASTER 리부팅시 HAProxy는 stop되었는데, 네트웍은 연결된 상태가 몇 초간 유지될 수 있다. 이 시간동안 서비스 장애가 발생한다.


    7. 참고 자료

    * FreeBSD Handbook : 31.10. Common Address Redundancy Protocol (CARP)
      https://www.freebsd.org/doc/handbook/carp.html

    * ifconfig man page
      https://www.freebsd.org/cgi/man.cgi?ifconfig

    * CARP changes in FreeBSD 10-Release
      http://aaronrenoir.com/2014/02/12/carp-changes-FreeBSD-10.html

    * Set up CARP Fail-over and High Availability on FreeBSD
      https://www.youtube.com/watch?v=VjYb9mKB4jU

    * HAProxy로 로드밸런싱(LB, 이중화) 구성 (글 좋은진호, 2015.3)
      http://coffeenix.net/board_view.php?bd_code=1771
      커피닉스 카페 최근 글
    [01/11] 특정 안드로이드 WebView 버전에서 SSL 문제 (WebView 버그)
    [08/01] DNS forwarder (전달자) 서버를 통해서 쿼리하면 역방향을 받아오질 못합니다.
    [05/16] (주)후이즈 시스템엔지니어 (경력자) 모집
    [02/15] [AWS] Cloudfront edge 확인하기
    [01/20] Mobile Service/eCommerce 기업에서 Server / Java / PHP 개발자 구인
    [01/11] 탄탄한 퍼블리싱 모바일기업에서 Mobile 개발자를 모십니다.
    [01/11] 탄탄한 퍼블리싱 모바일기업에서 Web Front 개발자를 모십니다.
    [01/11] 탄탄한 퍼블리싱 모바일기업에서 Server 개발 팀장을 모십니다.
    [12/21] 브라우저별 SHA1 퇴출 시점
    [09/15] [구인] 시스템엔지니어 (경력)
    [08/05] Re: 칼리리눅스 텔넷관련
    [08/04] 칼리리눅스 텔넷관련
    [06/29] 또 다른 무료 SSL 인증서, Let's Encrypt
    [06/29] FreeBSD에서 Leap Second(윤초)는? 문제 없다.
    [06/25] [정규직/충무로] 경력직 서버 개발자를 모십니다
      New!   최근에 등록한 페이지
      KiCad EDA Suite project (Free/Libre/Open-Source EDA Suite) (CAD)
      오픈캐스케이드 캐드 (OpenCASCADE CAD)
      QCad for Windows --- GNU GPL (Free Software)
      The Hello World Collection
      IPMI를 활용한 리눅스 서버관리
      DNS 설정 검사
      nagiosgraph 설치 방법
      Slony-I 설치 방법 (postgresql replication tool)
      Qmail기반의 Anti spam 시스템 구축하기
      clusterssh

    [ 함께하는 사이트 ]




    운영진 : 좋은진호(truefeel), 야수(yasu), 범냉이, sCag
    2003년 8월 4일~