HAProxy + Ubuntu14.04

소개



Ubuntu14.04에서 HAProxy1.5.9를 구축하고 SSL 가속기를 사용해 보았으므로 설명합니다.

구성


HAProxy
├── Nginx1
└── Nginx2

환경 정보


  • OS: Ubuntu14.04
  • HAProxy: 1.5.9

  • Step1: HAProxy 설치



    먼저 HAProxy make에 필요한 패키지를 설치합니다.
    $ sudo apt-get update
    $ sudo apt-get install build-essential make g++ libssl-dev
    

    그런 다음 최신 소스를 가져옵니다.
    2014/12/8 현재 최신 안정 버전은 1.5.9입니다.
    $ cd /usr/local/src
    $ sudo wget http://www.haproxy.org/download/1.5/src/haproxy-1.5.9.tar.gz
    $ 
    

    가져온 패키지를 배포하고 설치합니다.
    $ sudo tar zxvf haproxy-1.5.9.tar.gz
    $ cd haproxy-1.5.9
    $ sudo make TARGET=linux2628 USE_OPENSSL=yes 
    $ sudo make install # /usr/local/sbin/haproxyがインストールされる
    

    Step2: haproxy 그룹, 사용자 생성


    $ sudo groupadd -g 2001 haproxy # haproxy用グループ作成
    $ sudo useradd -u 2001 -g 2001 -s /sbin/nologin haproxy # haproxy用ユーザー作成
    

    Step3: 필요한 디렉토리 만들기



    설정 파일, 로그 파일, pid 파일을 저장할 디렉토리를 만듭니다.
    $ sudo mkdir -p /var/run/haproxy /etc/haproxy/ssl /var/log/haproxy /var/lock/haproxy
    $ sudo chown -R haproxy:haproxy /var/run/haproxy /etc/haproxy /var/log/haproxy
    

    Step4: 설정 파일 편집



    여기는 전부를 읽을 수 없습니다만, 크게 나누면 이하 2개로 구성되어 있는 것 같습니다.
  • global 섹션
  • Proxies: defaluts 섹션, frontend 섹션, backend 섹션, listen 섹션 세트.

  • 각 섹션의 대략적인 의미는 다음과 같습니다.


    섹션 이름
    역할


    global
    전체 프로세스 및 OS 특정 설정을 수행하는 섹션. 프로세스 관리, 보안 및 성능 조정을 위한 키워드를 설명하는 섹션.

    defaults
    다른 섹션 (frontend, backend, listen)에 대한 기본값을 설정하는 섹션

    frontend
    청취중인 소켓의 정의를 설명하는 섹션

    백엔드
    요청한 연결을 던지는 서버 정보를 설명하는 섹션

    청취
    frontend 및 backend 설정을 연결하는 섹션.


    여기 각각에서 지정 가능한 키워드는 HAProxy 매뉴얼 를 참조해 주세요.

    /etc/haproxy/haproxy.cfg
    global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        maxconn 4096 # 一つのプロセスで張れる最大のコネクション数
        pidfile     /var/run/haproxy.pid
        user haproxy
        group haproxy
        daemon # background設定
        ssl-server-verify  none # オレオレ証明書のためnoneに設定
        tune.ssl.cachesize 20000 # ssl session cacheの容量。200B * 20000程度の容量
        ssl-default-bind-options no-sslv3
        tune.ssl.default-dh-param 2048 # こちら設定しないとWarning出ます。
    
    # Proxies #
    defaults
        log global # globalセクションの設定した方法でログ出力。
        mode    http # 起動時のモードを選択。tcp|http|heakthが選択可能。
        option  httplog # httpリクエストのログを出力。
        retries 3 # 接続失敗時にリトライする回数。 
        maxconn 2000 # frontendで同時に張れるコネクション数
        timeout connect 5000 # リトライまでの待ち時間。単位はmillisecond。
        timeout client  5000 # クライアントとの間のタイムアウト時間。単位はmillisecond
        timeout server  50000 # サーバーとの間のタイムアウト時間。単位はmillisecond
    
    frontend  ssl_proxy
        bind *:443 ssl crt /etc/haproxy/ssl/server.pem # frontedでlisteningしているIPアドレス、ポートを指定。crtでは証明書とprivate keyが記載されたpemファイルを指定。
        use_backend      nginx # 転送するbackend名を指定する。
    
    backend nginx
        balance roundrobin # ロードバランスのアルゴリズムを指定。
        server nginx1 10.3.0.29:80 check inter 2000 # 転送先のサーバー定義。checkを付けることでhealthチェックをしてくれる。この場合は2000millisecond。
        server nginx2 10.3.0.93:80 check inter 2000 # 転送先のサーバー定義。checkを付けることでhealthチェックをしてくれる。この場合は2000millisecond。
    

    /etc/init.d/haproxy
    #!/bin/bash
    #
    # chkconfig: - 85 15
    # description: HA-Proxy is a TCP/HTTP reverse proxy which is particularly suited \
    #              for high availability environments.
    # processname: haproxy
    # config: /etc/haproxy/haproxy.cfg
    # pidfile: /var/run/haproxy.pid
    
    # Source function library.
    if [ -f /etc/init.d/functions ]; then
      . /etc/init.d/functions
    elif [ -f /etc/rc.d/init.d/functions ] ; then
      . /etc/rc.d/init.d/functions
    elif [ -f /lib/lsb/init-functions ] ; then
      # Ubuntu用
      . /lib/lsb/init-functions
    else
      exit 0
    fi
    
    # This is our service name
    BASENAME=`basename $0`
    if [ -L $0 ]; then
      BASENAME=`find $0 -name $BASENAME -printf %l`
      BASENAME=`basename $BASENAME`
    fi
    
    [ -f /etc/$BASENAME/$BASENAME.cfg ] || exit 1
    
    RETVAL=0
    LOCK_DIR='/var/lock/haproxy';
    if [ -f /usr/sbin/$BASENAME ] ; then
      CMD=/usr/sbin/$BASENAME;
    elif [ -f /usr/local/sbin/$BASENAME ] ; then
      CMD=/usr/local/sbin/$BASENAME;
    fi
    start() {
      ${CMD} -c -q -f /etc/$BASENAME/$BASENAME.cfg
    
      if [ $? -ne 0 ]; then
        echo "Errors found in configuration file, check it with '$BASENAME check'."
        return 1
      fi
    
      echo -n "Starting $BASENAME: "
    #  daemon ${CMD} -D -f /etc/$BASENAME/$BASENAME.cfg -p /var/run/$BASENAME.pid
      start_daemon ${CMD} -D -f /etc/$BASENAME/$BASENAME.cfg -p /var/run/$BASENAME.pid
      RETVAL=$?
      echo
      [ $RETVAL -eq 0 ] && touch ${LOCK_DIR}/$BASENAME
      return $RETVAL
    }
    
    stop() {
      echo -n "Shutting down $BASENAME: "
      killproc $BASENAME -USR1
      RETVAL=$?
      echo
      [ $RETVAL -eq 0 ] && rm -f ${LOCK_DIR}/$BASENAME
      [ $RETVAL -eq 0 ] && rm -f /var/run/$BASENAME.pid
      return $RETVAL
    }
    
    restart() {
      ${CMD} -c -q -f /etc/$BASENAME/$BASENAME.cfg
    
      if [ $? -ne 0 ]; then
        echo "Errors found in configuration file, check it with '$BASENAME check'."
        return 1
      fi
      stop
      start
    }
    
    reload() {
      ${CMD} -c -q -f /etc/$BASENAME/$BASENAME.cfg
      if [ $? -ne 0 ]; then
        echo "Errors found in configuration file, check it with '$BASENAME check'."
        return 1
      fi
      ${CMD} -D -f /etc/$BASENAME/$BASENAME.cfg -p /var/run/$BASENAME.pid -sf $(cat /var/run/$BASENAME.pid)
    }
    
    check() {
      ${CMD} -c -q -V -f /etc/$BASENAME/$BASENAME.cfg
    }
    
    rhstatus() {
      status $BASENAME
    }
    
    condrestart() {
      [ -e ${LOCK_DIR}/$BASENAME ] && restart || :
    }
    
    # See how we were called.
    case "$1" in
      start)
        start
        ;;
      stop)
        stop
        ;;
      restart)
        restart
        ;;
      reload)
        reload
        ;;
      condrestart)
        condrestart
        ;;
      status)
        rhstatus
        ;;
      check)
        check
        ;;
      *)
        echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|check}"
        exit 1
    esac
    
    exit $?
    

    /etc/haproxy/ssl/server.pem
    -----BEGIN PRIVATE KEY-----
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    3fOpcu73aVjofSld6lcAyj3cVd2qfKro8BDsXAtyZGmTDS2VgzqEk+LNUZJtVfwE
    6RzFDjsh2e31hX9RAgZpR1uk9534Hw1YcSBMbgAnW2hTqcV0/mESVYn1+1zPNlfy
    2sHgs2dzAdujp0Cvm6T14SmHKqOgDt6XuexuQRZNonJ4dB04eSVyJVj47CRo6NqX
    ZOBBfHN9R6dIRz1BnjUeRttdj13qljhJ0E+u4MnCRNbghpGrzwxLMvWwp320f3AZ
    qrtPEQ8gH97PEwx7baU7Z+wltRzSXGxqEdvNILSdjMnGjFIVwX2iKsXcrKz9A2SK
    RbksYX/hAgMBAAECggEAPvBecxhKMjp+zXuzlVALLxgXJpxD9hUntAwljulci59u
    JZ3LtZ5vQhv1ks36w+34d17APtrkxYBgMHUSB8A3lFSyo/6PWyzTsJ0PRuO53D2p
    08SyfnbrqaVD3Erl4GHRDVcJIzevZqUnMaNSw9XCAKd8YXoiD5wcFkAJ/ZODUVX0
    unsQVSRLVpjP3LxbkLA1behgUbYfe6IgQY3PdgU6ddZgFKMYo901AOAc6GT43c0B
    33ehGO+rZohMPUKLME0LbfsLscPztL2ZNXf6K3iA67bTrOfK+L4LiVnJllf4WWDU
    YyQaE+BP2jqfPBtzidHqtDo5uSowpQx9j6wpupum7QKBgQDeezBt49CZWTyWWfF7
    XkbNC6DIavbtJCtDmxlAiPw+6de8O9UJpe64jXBX1n3C7T2MvZh2hYN+hOxOUS0M
    YMncyxQ8AJpeUn/qxjvdZ82iR96YxZrtw1A9EL66hQQAY1MfLPnlgBRzj9S1KZf7
    BtDkwZIbaY2aNounQSUjo9msswKBgQDDrqVD5c2l2BQZglJ1TRstSLQOwQl/6EbK
    Cohi2sOZ+6znL37ta8UCN4OGnV8q+hNnegGc+UUZcPXsx6Omou0qkjy0IKEqepZC
    1On9OXcoyXBn7i5K2kIycJ+Ztw0OBewD8BJzSbKuRB9k1JHOiGAZpszurjpGPJJJ
    w8CudHkTGwKBgFfEhWB0pRA58frmVKt0j73IPo+SEwOOZzrubtHUuJ4hJiht+icq
    PLi1o4Ijbc1+Re/Fw+XN2ggJbCehQoJFlJzzyHG7UyqupSP7PBamIqtIavodynbN
    vFO6zWNLoj588Ie1+IefNXI5ZZJqbDhtge8cpgUGaQRTTFiZDIu40eCdAoGADVNk
    X8ZThdq8K6yLTv+sPR45XNPagMJhp7ql5Q1+yoqwEKJUY3i2VttO8qje5T9YePB/
    EaCMCxp9NN23kE6CFicVSTL7prfoaa60LJFwQu/M3tcCgghw/5xZ0g78LZtLok0E
    BKPdLi7ncGdlcooo+TY5uHtW7peLYsiY44h9AkcCgYArW6zrNr3ASfJ/xjG0FItv
    ltzQUa/vBm+H2q0QKq4LWw0u542rymEXpRIyV/67EWxfUBo8xkik7IvNrnzzt/jC
    4mUarfHuRHrXXcvU8joSalaj7/B7h/ps1y43mjOfwgXPtoi2tE8yx2fL4kETvQBP
    TbHkZz8FCRsVN7cEfVUAcg==
    -----END PRIVATE KEY-----
    -----BEGIN CERTIFICATE-----
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    SlAxDjAMBgNVBAgMBVRva3lvMRIwEAYDVQQHDAlTaGluanl1a3UxGjAYBgNVBAoM
    EUlEQyBGcm9udGllcixpbmMuMSkwJwYDVQQLDCBUZWNobmljYWwgRGV2ZWxlcG1l
    bnQgRGVwYXJ0bWVudDETMBEGA1UEAwwKVWVubyBBa2l0bzEcMBoGCSqGSIb3DQEJ
    ARYNYXVlbm9AaWRjZi5qcDAeFw0xNDA4MjQwNTQwMTdaFw0xNDA5MjMwNTQwMTda
    MIGrMQswCQYDVQQGEwJKUDEOMAwGA1UECAwFVG9reW8xEjAQBgNVBAcMCVNoaW5q
    eXVrdTEaMBgGA1UECgwRSURDIEZyb250aWVyLGluYy4xKTAnBgNVBAsMIFRlY2hu
    aWNhbCBEZXZlbGVwbWVudCBEZXBhcnRtZW50MRMwEQYDVQQDDApVZW5vIEFraXRv
    MRwwGgYJKoZIhvcNAQkBFg1hdWVub0BpZGNmLmpwMIIBIjANBgkqhkiG9w0BAQEF
    AAOCAQ8AMIIBCgKCAQEAqg+dPwdkKEiKpN3zqXLu92lY6H0pXepXAMo93FXdqnyq
    6PAQ7FwLcmRpkw0tlYM6hJPizVGSbVX8BOkcxQ47Idnt9YV/UQIGaUdbpPed+B8N
    WHEgTG4AJ1toU6nFdP5hElWJ9ftczzZX8trB4LNncwHbo6dAr5uk9eEphyqjoA7e
    l7nsbkEWTaJyeHQdOHklciVY+OwkaOjal2TgQXxzfUenSEc9QZ41HkbbXY9d6pY4
    SdBPruDJwkTW4IaRq88MSzL1sKd9tH9wGaq7TxEPIB/ezxMMe22lO2fsJbUc0lxs
    ahHbzSC0nYzJxoxSFcF9oirF3Kys/QNkikW5LGF/4QIDAQABMA0GCSqGSIb3DQEB
    BQUAA4IBAQA+C5SzaN+cRfaMxjWuWlxMLDSQ2jVg9oyS9XY4CfME6GWyU4DWMyhe
    NJ+H4r+MxSJb9nJs1N5weR7hObvZCM/K2qh7P+d+UGa2qfZeq1PJq6HZqVPgzKBc
    rsuFEfDgnx2OS0MsfxWZc4kamZb6W5d46tYaFI0aCutcRQg2wF5+VQvfPYtPG27T
    h7lYMA8Rw4lys55hOiMx1BxJgZX6o1RhV8UJp/+hIAQ9pQ64uU/UzJRm6jvHxAo2
    4iBMw8qoZV42/Oh/ZsKJcS1FEYqCHa9nnr1ogsYijsQxDG2jP/dmoOAXcXt/LCqP
    vPPyDdcONycVadjAWZgVZ0HsquCrHMtb
    -----END CERTIFICATE-----
    

    Step5: HAProxy 시작


    $ sudo chmod +x /etc/init.d/haproxy
    $ sudo /etc/init.d/haproxy start
    

    Step6: 액세스해 보기



    모처럼이므로 tcpdump를 취하고, HTTP 통신이 되어 있는지 어떤지를 확인해 본다.
    $ sudo tcpdump -i eth0 -s 2048K -w /tmp/tcpdump port 80
    
    $ curl -k https://${haproxy_server}
    $ curl -k https://${haproxy_server}
    $ curl -k https://${haproxy_server}
    $ curl -k https://${haproxy_server}
    $ curl -k https://${haproxy_server}
    

    Step7: 확인해 보기



    얻은 tcpdump를 Wireshark에서 살펴보십시오.10.3.0.9310.3.0.20 에 교대로 요청이 던지고 있는 것을 알 수 있다.



    결론


    HAProxy를 사용하면 상당히 쉽게 SSL 가속 LB를 만들 수 있다는 것을 알았습니다.
    단지 설정할 수 있는 keyword가 많이 본격적으로 이용하려면 우선 문서의 로드가 필요할 것 같습니다^^;

    끝.

    좋은 웹페이지 즐겨찾기