HAProxy 로드밸런싱 심화

HAProxy란?

HAProxy는 고성능 TCP/HTTP 로드밸런서이자 리버스 프록시입니다. C로 작성되어 단일 프로세스에서 수십만 동시 연결을 처리하며, GitHub, Stack Overflow, Reddit 등 대규모 서비스의 트래픽 분산에 사용됩니다. Nginx 리버스 프록시가 웹 서버 겸 프록시라면, HAProxy는 로드밸런싱에 특화된 전문 도구입니다.

Nginx vs HAProxy 비교

항목 Nginx HAProxy
주요 역할 웹 서버 + 프록시 전용 로드밸런서
L4 로드밸런싱 stream 모듈 네이티브 지원
헬스체크 기본 (Plus에서 고급) 다양한 방식 내장
Stats 대시보드 stub_status 실시간 상세 통계
설정 리로드 nginx -s reload 무중단 리로드 (SO_REUSEPORT)
ACL 라우팅 location/map 강력한 ACL 엔진

기본 구조 — frontend/backend

HAProxy 설정은 global, defaults, frontend, backend 4개 섹션으로 구성됩니다.

global
    maxconn 50000
    log stdout format raw local0
    stats socket /var/run/haproxy.sock mode 660 level admin
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
    ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11
    tune.ssl.default-dh-param 2048

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option forwardfor
    option http-server-close
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    timeout http-keep-alive 10s
    timeout check 5s
    default-server init-addr last,libc,none

frontend http_front
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
    
    # HTTP → HTTPS 리다이렉트
    http-request redirect scheme https unless { ssl_fc }
    
    # HSTS 헤더
    http-response set-header Strict-Transport-Security "max-age=63072000"
    
    # ACL 기반 라우팅
    acl is_api path_beg /api/
    acl is_ws hdr(Upgrade) -i websocket
    acl is_static path_end .css .js .png .jpg .svg .woff2
    
    use_backend api_servers if is_api
    use_backend ws_servers if is_ws
    use_backend static_servers if is_static
    default_backend web_servers

backend web_servers
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    
    cookie SERVERID insert indirect nocache
    server web1 10.0.1.10:3000 check cookie web1 weight 100
    server web2 10.0.1.11:3000 check cookie web2 weight 100
    server web3 10.0.1.12:3000 check cookie web3 weight 50  # 스펙 낮은 서버

로드밸런싱 알고리즘

# 1. roundrobin — 순차 분배 (기본, 동적 weight 변경 가능)
balance roundrobin

# 2. leastconn — 최소 연결 (DB 커넥션 풀, 긴 요청에 적합)
balance leastconn

# 3. source — 소스 IP 해싱 (세션 고정)
balance source
hash-type consistent  # 서버 추가/제거 시 최소 재분배

# 4. uri — URI 해싱 (캐시 서버에 적합)
balance uri
hash-type consistent

# 5. hdr — 특정 헤더 기반 (테넌트별 라우팅)
balance hdr(X-Tenant-Id)
hash-type consistent

고급 헬스체크

HAProxy의 헬스체크는 단순 TCP 연결 확인부터 HTTP 응답 본문 검사까지 지원합니다.

backend api_servers
    balance leastconn
    
    # HTTP 헬스체크 — 상태코드 + 본문 검사
    option httpchk
    http-check send meth GET uri /health/ready ver HTTP/1.1 hdr Host api.example.com
    http-check expect rstatus ^2[0-9]{2}
    
    # 연속 실패/성공 횟수로 판정
    default-server inter 3s fall 3 rise 2
    
    # slowstart: 복구된 서버에 트래픽 점진적 증가
    server api1 10.0.2.10:8080 check slowstart 30s
    server api2 10.0.2.11:8080 check slowstart 30s
    server api3 10.0.2.12:8080 check slowstart 30s backup  # 백업 서버

backend db_tcp
    mode tcp
    balance leastconn
    
    # MySQL 프로토콜 헬스체크
    option mysql-check user haproxy
    server db1 10.0.3.10:3306 check
    server db2 10.0.3.11:3306 check backup

ACL 기반 고급 라우팅

frontend http_front
    bind *:443 ssl crt /etc/haproxy/certs/
    
    # 카나리 배포 — 헤더 기반
    acl is_canary hdr(X-Canary) -i true
    acl is_canary_cookie cook(canary) -i true
    
    # A/B 테스트 — 쿠키 없으면 10% 확률로 canary 쿠키 설정
    acl no_ab_cookie cook(canary) -m len 0
    http-request set-var(txn.rand) rand(100) if no_ab_cookie
    http-request add-header Set-Cookie "canary=true; Path=/; Max-Age=86400" if no_ab_cookie { var(txn.rand) -m int lt 10 }
    http-request add-header Set-Cookie "canary=false; Path=/; Max-Age=86400" if no_ab_cookie { var(txn.rand) -m int ge 10 }
    
    use_backend canary_servers if is_canary
    default_backend prod_servers
    
    # Rate Limiting — IP당 초당 20 요청
    stick-table type ip size 200k expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 200 }
    
    # 지역 기반 라우팅
    acl is_kr src -f /etc/haproxy/maps/kr-ips.lst
    use_backend kr_servers if is_kr

backend canary_servers
    balance roundrobin
    server canary1 10.0.4.10:3000 check

backend prod_servers
    balance roundrobin
    server prod1 10.0.4.20:3000 check
    server prod2 10.0.4.21:3000 check

Stats 대시보드와 Runtime API

# Stats 페이지 활성화
frontend stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if TRUE  # 서버 drain/disable UI 제공
    stats auth admin:securepass123

# Runtime API로 동적 제어
# 서버 drain (신규 연결 차단, 기존 연결 유지)
echo "set server web_servers/web1 state drain" | socat stdio /var/run/haproxy.sock

# 서버 weight 동적 변경
echo "set server web_servers/web2 weight 50" | socat stdio /var/run/haproxy.sock

# 백엔드 상태 확인
echo "show stat" | socat stdio /var/run/haproxy.sock | cut -d, -f1,2,18,37

SSL/TLS 최적화

global
    # OCSP Stapling
    ssl-default-bind-options ssl-min-ver TLSv1.2
    tune.ssl.cachesize 100000
    tune.ssl.lifetime 600

frontend https
    bind *:443 ssl crt-list /etc/haproxy/crt-list.txt alpn h2,http/1.1
    
    # 클라이언트 인증서 (mTLS)
    bind *:8443 ssl crt /etc/haproxy/certs/server.pem ca-file /etc/haproxy/certs/ca.pem verify required
    
    # SSL 오프로딩 후 백엔드는 HTTP
    http-request set-header X-Forwarded-Proto https
    http-request set-header X-Real-IP %[src]
    http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)] if { ssl_fc_has_crt }

Docker Compose 운영 예시

# docker-compose.yml
services:
  haproxy:
    image: haproxy:3.0-alpine
    ports:
      - "80:80"
      - "443:443"
      - "8404:8404"
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
      - ./certs:/etc/haproxy/certs:ro
    restart: unless-stopped
    sysctls:
      - net.ipv4.ip_unprivileged_port_start=0
    ulimits:
      nofile:
        soft: 65536
        hard: 65536
    networks:
      - backend

  # 무중단 설정 리로드
  # docker kill -s HUP haproxy

Prometheus 메트릭 연동

frontend stats
    bind *:8404
    http-request use-service prometheus-exporter if { path /metrics }
    stats enable
    stats uri /stats

Grafana 대시보드와 연동하면 백엔드별 응답 시간, 에러율, 커넥션 수를 실시간으로 모니터링할 수 있습니다.

운영 팁

  • 무중단 배포: Runtime API로 서버를 drain → 배포 → ready로 블루-그린 배포 구현
  • maxconn 튜닝: 백엔드 서버의 처리 능력에 맞게 server ... maxconn 100으로 과부하 방지
  • 로그 분석: %Tr/%Tw/%Tc/%Tt 타이밍 필드로 병목 구간 파악
  • stick-table 동기화: Active-Active 구성 시 peers 섹션으로 세션/레이트 테이블 동기화

정리

HAProxy는 단순 로드밸런싱을 넘어 ACL 라우팅, 카나리 배포, Rate Limiting, mTLS까지 제공하는 트래픽 관리 플랫폼입니다. Runtime API를 통한 동적 제어와 상세한 Stats 대시보드는 프로덕션 운영에서 큰 강점입니다. Nginx와 경쟁 관계가 아니라 — Nginx는 정적 파일 서빙과 웹 서버로, HAProxy는 L4/L7 로드밸런싱 전문 도구로 함께 사용하는 것이 이상적입니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux