Linux,Unix,BSD

HAProxy-2.4.2 설치하기 on Ubuntu 20.04

채윤아빠 2021. 8. 1. 19:34
728x90
반응형

Ubuntu 20.04 호스트에 HAProxy를 설치하고 운영하는 것에 대하여 정리한 문서입니다.

HAProxy 설치하기

HAProxy를 Ubuntu에서 설치하는데는 크게 두 가지 방법이 있습니다. "apt"을 이용하는 방법과 소스를 이용하여 직접 빌드하고 설치하는 방법이 있습니다.

본 문서에서는 "HAProxy" 최신 소스를 이용하여 직접 설치하는 방법에 대하여 주로 설명합니다.

apt 를 통한 간편 설치

"apt" 명령을 이용해 haproxy 패키지를 손쉽게 설치할 수 있습니다.

$ sudo apt install haproxy

하지만 위와 같이 설치하면, 2.0.13 버전이 설치됩니다.

$ haproxy -vv
HA-Proxy version 2.0.13-2ubuntu0.1 2020/09/08 - https://haproxy.org/

가장 최신 버전을 설치하기 위해서는 "haproxy.org":http://www.haproxy.org/ 에서 최신 소스를 받아서 직접 빌드하고 설치를 해야만 합니다.

소스를 이용한 직접 빌드 설치

빌드를 위한 패키지 설치

아래와 같이 HAProxy를 빌드하는데 필요한 패키지들을 다운로드 받습니다.

$ sudo apt-get install -y build-essential \
    libssl-dev \
    libpcre2-dev libpcre3-dev \
    libsystemd-dev \
    zlib1g-dev

HAProxy 최신 소스 다운로드

"haproxy.org":http://www.haproxy.org/ 에서 최신 소스 URL을 확인하고, 아래와 같이 다운로드 받습니다.

본 문서를 작성하는 시점에서 haproxy의 최신버전은 2.4.2 입니다.

$ mkdir -p ~/work ; cd ~/work
$ wget https://www.haproxy.org/download/2.4/src/haproxy-2.4.2.tar.gz
--2021-07-27 16:46:06--  https://www.haproxy.org/download/2.4/src/haproxy-2.4.2.tar.gz
Resolving www.haproxy.org (www.haproxy.org)... 51.15.8.218, 2001:bc8:35ee:100::1
Connecting to www.haproxy.org (www.haproxy.org)|51.15.8.218|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3579220 (3.4M) [application/x-tar]
Saving to: ‘haproxy-2.4.2.tar.gz’

haproxy-2.4.2.tar.gz     100%[=================================>]   3.41M  1.93MB/s    in 1.8s

2021-07-27 16:46:10 (1.93 MB/s) - ‘haproxy-2.4.2.tar.gz’ saved [3579220/3579220]

HAProxy 소스 빌드

다음과 같이 HAProxy 최신 소스의 압축을 풀고, 소스를 빌드합니다.

# tar xf haproxy-2.4.2.tar.gz && cd haproxy-2.4.2
# make TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1

HAProxy 2.0 부터는 "linux2628" 대신에 "linux-glibc" 로 "TARGET"이 변경됩니다.

빌드된 HAProxy 소스를 다음과 같이 설치합니다.

$ sudo make install
`haproxy' -> `/usr/local/sbin/haproxy'
`doc/haproxy.1' -> `/usr/local/share/man/man1/haproxy.1'
install: creating directory `/usr/local/doc'
install: creating directory `/usr/local/doc/haproxy'
`doc/configuration.txt' -> `/usr/local/doc/haproxy/configuration.txt'
`doc/management.txt' -> `/usr/local/doc/haproxy/management.txt'
`doc/architecture.txt' -> `/usr/local/doc/haproxy/architecture.txt'
`doc/peers-v2.0.txt' -> `/usr/local/doc/haproxy/peers-v2.0.txt'
`doc/regression-testing.txt' -> `/usr/local/doc/haproxy/regression-testing.txt'
`doc/cookie-options.txt' -> `/usr/local/doc/haproxy/cookie-options.txt'
`doc/lua.txt' -> `/usr/local/doc/haproxy/lua.txt'
`doc/WURFL-device-detection.txt' -> `/usr/local/doc/haproxy/WURFL-device-detection.txt'
`doc/proxy-protocol.txt' -> `/usr/local/doc/haproxy/proxy-protocol.txt'
`doc/linux-syn-cookies.txt' -> `/usr/local/doc/haproxy/linux-syn-cookies.txt'
`doc/network-namespaces.txt' -> `/usr/local/doc/haproxy/network-namespaces.txt'
`doc/DeviceAtlas-device-detection.txt' -> `/usr/local/doc/haproxy/DeviceAtlas-device-detection.txt'
`doc/51Degrees-device-detection.txt' -> `/usr/local/doc/haproxy/51Degrees-device-detection.txt'
`doc/netscaler-client-ip-insertion-protocol.txt' -> `/usr/local/doc/haproxy/netscaler-client-ip-insertion-protocol.txt'
`doc/peers.txt' -> `/usr/local/doc/haproxy/peers.txt'
`doc/close-options.txt' -> `/usr/local/doc/haproxy/close-options.txt'
`doc/SPOE.txt' -> `/usr/local/doc/haproxy/SPOE.txt'
`doc/intro.txt' -> `/usr/local/doc/haproxy/intro.txt'

기본적인 설치가 완료된 후에 다음과 같이 설치된 haproxy의 버전을 확인합니다.

$ /usr/local/sbin/haproxy -vv
HAProxy version 2.4.2-553dee3 2021/07/07 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.2.html
Running on: Linux 5.8.0-63-generic #71~20.04.1-Ubuntu SMP Thu Jul 15 17:46:08 UTC 2021 x86_64
Build options :
  TARGET  = linux-glibc
  CPU     = generic
  CC      = cc
  CFLAGS  = -O2 -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-address-of-packed-member -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-cast-function-type -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference
  OPTIONS = USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1
  DEBUG   =

Feature list : +EPOLL -KQUEUE +NETFILTER +PCRE -PCRE_JIT -PCRE2 -PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED +BACKTRACE -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H +GETADDRINFO +OPENSSL -LUA +FUTEX +ACCEPT4 -CLOSEFROM +ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL +SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS -OT -QUIC -PROMEX -MEMORY_PROFILING

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=8).
Built with OpenSSL version : OpenSSL 1.1.1f  31 Mar 2020
Running on OpenSSL version : OpenSSL 1.1.1f  31 Mar 2020
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with network namespace support.
Built with zlib version : 1.2.11
Running on zlib version : 1.2.11
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE version : 8.39 2016-06-14
Running on PCRE version : 8.39 2016-06-14
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Encrypted password support via crypt(3): yes
Built with gcc compiler version 9.3.0

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
              h2 : mode=HTTP       side=FE|BE     mux=H2       flags=HTX|CLEAN_ABRT|HOL_RISK|NO_UPG
            fcgi : mode=HTTP       side=BE        mux=FCGI     flags=HTX|HOL_RISK|NO_UPG
       <default> : mode=HTTP       side=FE|BE     mux=H1       flags=HTX
              h1 : mode=HTTP       side=FE|BE     mux=H1       flags=HTX|NO_UPG
       <default> : mode=TCP        side=FE|BE     mux=PASS     flags=
            none : mode=TCP        side=FE|BE     mux=PASS     flags=NO_UPG

Available services : none

Available filters :
        [SPOE] spoe
        [CACHE] cache
        [FCGI] fcgi-app
        [COMP] compression
        [TRACE] trace

HAProxy 서비스를 정상적으로 실행하기 위해서는 haproxy 계정을 시스템 계정으로 등록되어 있어야 합니다.
다음과 같이 "haproxy" 계정을 등록합니다.

$ sudo groupadd --gid 980 haproxy ; \
sudo useradd --gid 980 --uid 980 -r haproxy

HAProxy 설정 파일을 초기화합니다.

$ sudo mkdir -p /etc/haproxy \
&& sudo touch /etc/haproxy/haproxy.cfg \
&& sudo touch /etc/haproxy/domain2backend.map \
&& sudo chown -R haproxy:haproxy /etc/haproxy/

HAProxy 라이브러리 디렉토리 및 상태 파일을 초기화합니다.

$ sudo mkdir -p /var/lib/haproxy \
&& sudo touch /var/lib/haproxy/stats \
&& sudo chown -R haproxy:haproxy /var/lib/haproxy

"haproxy"에 대한 심볼릭 링크를 설정합니다.

$ sudo ln -s /usr/local/sbin/haproxy /usr/sbin/haproxy

HAProxy 서비스를 설치합니다.

$ chkconfig haproxy off # 기존 설치된 설정 제거
알림: 'systemctl disable haproxy.service'에 요청을 전송하고 있습니다.

$ sudo rm -f /etc/init.d/haproxy
$ cd ~/work/haproxy-2.4.2/admin/systemd
$ make
$ sudo cp haproxy.service /lib/systemd/system/
$ sudo systemctl daemon-reload ; sudo systemctl enable haproxy
Created symlink from /etc/systemd/system/multi-user.target.wants/haproxy.service to /usr/lib/systemd/system/haproxy.service.

$ systemctl status haproxy
● haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
   Active: inactive (dead)

환경설정

HAPorxy 기본 설정

일반적으로 "home1.wb.com", "home2.wb.com"와 같이 두 도메인에 대한 매핑 설정을 위하여 아래와 같이 "haproxy.cfg" 파일을 작성합니다.

$ vi /etc/haproxy/haproxy.cfg
global
    log         127.0.0.1 local2 info

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    stats socket           /var/run/haproxy.sock mode 666 level admin
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    #no option               http-use-htx # HTTP2 표준처럼 헤더를 모두 lower로 처리하는 것 방지
    option                  forwardfor
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

listen stats
    bind :::8888 v4v6
    mode http
    stats enable
    stats hide-version
    stats uri /
    stats realm Haproxy\ Statistics
    stats auth hunature:bns0705

frontend  main
    bind :::80 v4v6
    option                      http-server-close
    use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/domain2backend.map,default)]
    default_backend             default


frontend  https-in
    bind :::443 v4v6 ssl crt /etc/haproxy/ssl/ ciphers !EDH:!RC4:!ADH:!DSS:HIGH:+AES128:+AES256-SHA256:+AES128-SHA256:+SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
    mode                        http
    option                      forwardfor
    option                      http-server-close
    #http-response add-header   Strict-Transport-Security "max-age=31536000; includeSubDomains"
    #http-response add-header   Strict-Transport-Security "max-age=31536000"
    #http-response add-header   X-Frame-Option "DENY"
    use_backend %[ssl_fc_sni,lower,map_dom(/etc/haproxy/domain2backend.map,default)]
    default_backend             default


backend default
    balance     roundrobin
    server  home1 192.168.0.10:8080 check
    server  home2 192.168.0.11:8080 check

환경설정값이 유효한지 확인한다.

$ /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c
Configuration file is valid

HAProxy 서비스를 시작합니다.

$ sudo systemctl start haproxy

서비스가 정상적으로 구동하고 있는지 *:8888 포트로 접속하여 확인합니다.

동적으로 도메인 매핑 추가하는 방법

HAProxy를 이용하여 서비스해야할 backend 및 도메인이 동적으로 변경된다면 앞서 작성한 기본 설정과 같은 정적 구성으로는 불가능합니다.
동적으로 도메인을 매핑하여 처리하기 위해서는 "frontend main" 단에서 "acl" 및 "use_backend" 항목들을 다음과 같이 변경하고, 도메인에 대한 실질적인 매핑은 설정한 매핑 파일에 설정하여 동적으로 동작할 수 있도록 합니다.

frontend  main
    bind :::80 v4v6
    option                      http-server-close
    use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/domain2backend.map,default)]
    default_backend             default

하지만, 도메인에 매핑될 backend 정보가 변경되면, "haproxy.cfg" 파일에 추가해 줄 수밖에는 없습니다.

backend backend_4
    balance roundrobin
    server  server1 192.168.56.204:8004 check
    server  server2 192.168.56.205:8004 check

backend backend_5
    balance roundrobin
    server  server1 192.168.56.204:8005 check
    server  server2 192.168.56.205:8005 check

haproxy.cfg에서 설정한 것과 같이, 도메인별 매핑을 위한 파일(domain2backend.map)을 다음과 같이 작성합니다.

$ vi /etc/haproxy/domain2backend.map

#domainname  backendname
home1.hbesthee.com    backend_1
home2.hbesthee.com    backend_2
test4.hbesthee.com    backend_4
shop5.hbesthee.com    backend_5

위와 같이 "haproxy.cfg"에 신규 backend를 추가하고 도메인별 매핑을 위한 파일(domain2backend.map)에 신규 도메인을 추가한 이후에는 HAProxy 서비스를 재시작하지 않고, 동적으로 설정 다시 읽기는 다음과 같이 수행합니다.

$ sudo systemctl reload haproxy

위와 같이 하면 서비스의 중단없이 새로운 도메인 매핑이 바로 적용되어 신규 도메인으로의 연결도 정상적으로 연결이 가능합니다.

HAProxy 설치 관련 참고글