High Availbility Proxy의 약자로 Reverse Proxy 역할을 수행하는 소프트웨어입니다.
HAProxy는 네트워크 스위치에서 제공하는 L4, L7 기능 및 로드 밸런서 기능을 제공합니다.
우리가 흔히 프록시라고 하면 포워드 프록시를 많이 의미하곤 합니다.
클라이언트가 서버로 요청할 때 직접 요청하지 않고 먼저 프록시 서버를 통해 요청하는 방식입니다.
클라이언트와 인터넷, 서버가 있을 때 클라이언트와 인터넷 사이에 프록시 서버가 위치함으로써 서버로 하여금 클라이언트로부터 온 요청이 정확히 누구에게서 온건지 알 수 없습니다.
리버스 프록시는 클라이언트가 서버를 호출할 때 리버스 프록시를 호출하게 되고 프록시 서버가 서버를 요청하여 받은 응답을 클라이언트에게 전달하는 방식입니다.
포워드 프록시랑은 반대로 클라이언트와 인터넷, 서버가 있을 때 인터넷과 서버 사이에 프록시가 위치함으로써 클라이언트가 서버에게서 받은 응답이 정확히 어떤 서버로부터 받은건지 알 수 없는 형태의 프록시를 의미합니다.
로드밸런싱이란 하나의 서비스에 대한 부하를 여러 서버로 분산하는 것을 의미합니다.
서비스에 부하가 발생하면 두가지 해결 방법이 있습니다.
scale-up: 서버의 성능을 높인다.
scale-out: 부하를 여러 서버에 분산한다.
로드밸런싱은 scale out에 속합니다.
HAProxy는 정말 다양한 기능을 오픈소스로 제공하고 있습니다.
1. SSL 지원
2. Load Balancing
3. Active Health Check
4. KeepAlived(프록시 이중화)
등등...
HAProxy와 비슷한 기능을 수행하는 소프트웨어로 nginx가 있습니다.
nginx또한 http 나 reverse proxy 같은 기능 외에도 load balancer 기능 또한 강력합니다.
HAProxy가 Nginx와 다른 점은 Active Health Check 기능이라고 볼 수 있는데, 요청을 건내주기 전 서버 상태를 점검하고, 문제가 있으면 다른 node 로 트래픽을 넘겨줄 수 있는 기능을 nginx에서는 유료 버전을 사용해야 하지만 HAProxy에서는 기본적으로 기능을 제공하고 있습니다!!!
주의해야할 점이 컨테이너를 그냥 띄우면 컨테이너를 띄울 때마다 컨테이너 아이피가 변경이 됩니다. 아이피가 변경된다는 말은 컨테이너간 통신이 불가능하다는 말을 의미하겠죠. docker container간 통신을 하기 위해서 통신이 필요한 컨테이너 끼리 같은 docker network로 묶어주면 컨테이너 이름으로 서로 통신할 수 있습니다.
docker network를 하나 생성해주고 컨테이너를 띄울 때 --net haproxy-net 와 같이 옵션을 주어 네트워크를 지정해 컨테이너를 실행해줍니다.
FROM haproxy:2.3
USER root
haproxy:lts 이미지를 pull 받고 컨테이너 상 사용자를 root로 지정한다는 내용입니다.
sudo docker build -t my-haproxy .
haproxy 컨테이너가 실행될 때마다 외부 볼륨에서 설정 파일을 가져와 사용하도록 haproxy 디렉토리를 홈 디렉토리에 생성해줍니다. 저는 root 디렉토리에 생성했습니다.
mkdir ~/haproxy
SSL 인증서가 위치할 디렉토리 또한 생성해줍니다.
mkdir ~/haproxy/certs
SSL 인증서를 발급 받아 해당 디렉토리에 위치해주고 설정파일에서 지정해주어야 합니다.
cd ~/haproxy
vi ./haproxy.cfg
global
log 127.0.0.1 local2
#chroot /var/lib/haproxy # 서비스 제일 경로, 슈퍼유저로 프로세스 실행 시 모든 동작은 이 안에서 수행
pidfile /var/run/haproxy.pid # 실행피드명
stats socket /var/run/haproxy.sock mode 666 level admin
maxconn 4000
tune.ssl.default-dh-param 4000 # ssl 적용시 항목, maxconn이랑 맞추자
user root
group root
daemon
defaults
mode http # http 프로토콜 사용
log global # 로그는 global 설정을 따른다
option httplog # 로그 디텔일을 높임
option dontlognull # 로그 비대화 방지를 위해 probe같은 잡다한 기록은 남기지 않음
option forwardfor
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
# front
frontend http_front # http 프론트엔드
bind *:80
http-request set-header X-Forwarded-Proto http
default_backend default
frontend https_front
bind *:443 ssl crt usr/local/etc/haproxy/certs/ # 발급한 인증서 적용해주자 자동으로 도메인 인식해서 잡아줌
http-request set-header X-Forwarded-Proto https
#accongbox.com으로 들어오는 요청은 host_home이라는 그룹으로 보낸다.
acl host_home hdr(host) -i accongbox.com
#sync.accongbox.com으로 들어오는 요청은 host_sync로 보낸다.
acl host_sync hdr(host) -i sync.accongbox.com
#host_home의 경우 web이라는 이름을 가진 backend를 사용
use_backend web if host_home
#host_sync의 경우 sync_server이라는 이름을 가진 backend 사용
use_backend sync_server if host_sync
#이외에는 기본으로 default라는 이름을 가진 백엔드 사용
default_backend default
resolvers docker # docker 컨테이너간 통신을 하기 위해 resover설정, 같은 다커 네트워크 상에 있으면 이름으로 통신 가능
nameserver dns1 127.0.0.11:53
#backend
backend default
redirect scheme https if !{ ssl_fc } # http접근인 경우 https로 리다이렉트
balance roundrobin
server server accongbox-front:5000 check resolvers docker # accongbox-front는 같은 다커 네트워크 상에 있는 컨테이너 이름이다.
backend web
redirect scheme https if !{ ssl_fc }
balance roundrobin
server home_server accongbox-front:5000 check resolvers docker # 포트 지정하기
backend sync_server
redirect scheme https if !{ ssl_fc }
balance roundrobin # 라운드 로빈 방식으로 컨테이너 3개에 로드밸런싱
server server1 accongbox-spring1:8080 check resolvers docker
server server2 accongbox-spring2:8080 check resolvers docker
server server3 accongbox-spring3:8080 check resolvers docker
#listen #프론트/밴엔드의 연결의 포트/옵션을 정의함. tcp제어나 proxy에 주로 사용
listen stats # stats란 이름으로 리슨 지정
bind *:9000 # 접속포트 지정
stats enable
stats realm Haproxy Statistics
stats uri /haproxy_stats # stat을 제공할 url
#stats auth Username:Password # 인증이 필요하면 추가한다
haproxy는 클라이언트와 haproxy 사이를 frontend라 하고 haproxy와 서버 사이를 backend라고 합니다.
sudo docker run -d --name my-haproxy --net haproxy-net -p 80:80 -p 443:443 -p 9000:9000 --restart always -v /root/haproxy:/usr/local/etc/haproxy my-haproxy:latest
외부의 80포트, 443포트, 9000포트를 해당 컨테이너의 각각의 포트로 바인딩 해주었습니다.
-v옵션으로 외부에서 설정한 설정파일을 적용해주었습니다.
--net 옵션으로 docker network를 지정해주었습니다. 모든 통신이 필요한 컨테이너는 해당 네트워크를 지정해주어야 합니다.
haproxy는 서버 상태 페이지를 기본적으로 제공합니다.
ip....com:9000/haproxy_stats로 이동해보면 현재 서버 상태를 한번에 확인할 수 있습니다.
예시 보기: https://github.com/suhongkim98/accongbox-haproxy
위에서 앞단에 HAProxy
로 프록시서버를 두었고, 뒷단에 2개의 백엔드 애플리케이션을 두었으며 HAProxy
에서 헬스체크를 통해 살아있는 백엔드 애플리케이션에 트래픽을 라우팅하도록 구성하였습니다.
헬스체크를 통해 살아있는 서버에만 트래픽이 전달 될테니 몇몇 서버는 껏다 킬 수 있게 되었네요. 이를 이용해 무중단 배포를 하시면 됩니다.
무중단 배포에는 다양한 전략이 존재합니다. 롤링
, 카나리
, 블루-그린
등이 대표적입니다. 배포 전략에 따라 새로운 버전의 백엔드 애플리케이션을 배포하시면 됩니다..!