multi masters의 단일 진입점인 LoadBalancer(LB) 구성 → 사실상 HA 클러스터 구성
192.168.0.100 IP를 사용하는 서버에 Nginx를 이용하여 LB 구성
Nginx docker 이미지를 이용하여 LB 사용 → docker 컨테이너 운영 관리에 쉬움
1. nginx 구성 파일을 만들어서 master들의 단일 진입점을 구성
# nginx로 Load Balancer할 수 있게 nginx.conf 파일 생성
$ mkdir /etc/nginx
$ cat << END > /etc/nginx/nginx.conf
events {}
stream {
upstream stream_backend {
least_conn;
server 192.168.0.200:6443;
server 192.168.0.201:6443;
server 192.168.0.202:6443;
}
server {
listen 6443;
proxy_pass stream_backend;
proxy_timeout 300s;
proxy_connect_timeout 1s;
}
}
END
2. 도커 컨테이너로 NGINX를 실행하면서 LB를 운영
# nginx 컨테이너 실행
$ docker run --name proxy -v /etc/nginx/nginx.conf:/etc/nginx/nginx.cof:ro --restart=always -p 6443:6443 -d nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
b380bbd43752: Pull complete
fca7e12d1754: Pull complete
745ab57616cb: Pull complete
a4723e260b6f: Pull complete
1c84ebdff681: Pull complete
858292fd2e56: Pull complete
Digest: sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36
Status: Downloaded newer image for nginx:latest
4324e6beaef0bd05d76af525fa415c4bcdf34fb807e4280e952108bf0a957630
# nginx 컨테이너가 실행 중 확인
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4324e6beaef0 nginx "/docker-entrypoint.…" 54 seconds ago Up 53 seconds 80/tcp, 0.0.0.0:6443->6443/tcp, :::6443->6443/tcp proxy
# 통신이 되는지 확인
$ curl 192.168.0.100:6443
전역 옵션(global) 섹션과 기본 옵션(defaults) 섹션, 프록시 옵션 섹션(listen)의 주요 옵션에 관한 설명
global # 전역 옵션 섹션
daemon → 백그라운드 모드(background mode)로 실행
log → syslog 설정
log-send-hostname → hostname 설정
uid → 프로세스의 userid를 number로 변경
user → 프로세스의 userid를 name으로 변경
node → 두 개 이상의 프로세스나 서버가 같은 IP 주소를 공유할 때 name 설정(HA 설정)
maxconn → 프로세스당 최대 연결 개수
Defaults # 기본 옵션 섹션
log → syslog 설정
maxconn → 프로세스당 최대 연결 개수
listen
listen webfarm 10.101.22.76:80→ listen haproxy name ip:port
mode http → 연결 프로토콜
option httpchk → health check
option log-health-checks → health 로그 남김 여부
option forwardfor → 클라이언트 정보 전달
option httpclose → keep-alive 문제 발생 시 off 옵션
cookie SERVERID rewrite → 쿠키로 서버 구별 시 사용 여부
cookie JSESSIONID prefix → HA 구성 시 prefix 이후에 서버 정보 주입 여부
balance roundrobin → 순환 분배 방식
stats enable → 서버 상태 보기 가능 여부
stats uri /admin → 서버 상태 보기 uri
server xvadm01.ncli 10.101.22.18:80 cookie admin_portal_1 check inter 1000 rise 2 fall 5 → real server 정보(server [host명] [ip]:[port] cookie [서버쿠키명] check inter [주기(m/s)] rise [서버구동여부점검횟수], fall [서비스중단여부점검횟수])
3. balance 옵션
로드 밸런싱의 경우 round robin 방식을 일반적으로 사용하지만 다른 여러 방식이 있음 → 옵션에 적용할 수 있는 로드 밸런싱 알고리즘
roundrobin → 순차적으로 분배(최대 연결 가능 서버 4128개)
static-rr → 서버에 부여된 가중치에 따라서 분배
leastconn → 접속 수가 가장 적은 서버로 분배
source → 운영 중인 서버의 가중치를 나눠서 접속자 IP를 해싱(hashing)해서 분배
uri → 접속하는 URI를 해싱해서 운영 중인 서버의 가중치를 나눠서 분배(URI의 길이 또는 depth로 해싱)
url_param → HTTP GET 요청에 대해서 특정 패턴이 있는지 여부 확인 후 조건에 맞는 서버로 분배(조건 없는 경우 round robin으로 처리)
hdr → HTTP 헤더 에서 hdr()으로 지정된 조건이 있는 경우에 대해서만 분배(조건 없는 경우 round robin으로 처리)
4. Keepalived 설치와 설정 파일 수정을 통해 node 1과 node 2에 대한 HA 구성
Keepalived를 node1, node2에 설치
설치를 마친 후, Keepalived의 설정 파일을 수정
4.1. Keepalived 설정 내용 → 설정 내용 적용 후 Keepalived 서비스를 node1, node2에 실행
MASTER 서버의 Priority는 200으로 설정, BACKUP 서버의 Priority는 100 설정 → Priority 값이 높은 쪽이 MASTER 서버가 됨
auth_pass 및 virtual_router 값은 MASTER 서버와 BACKUP 서버 모두 동일해야함 → 해당 값은 default 값으로 그대로 유지
auth_pass는 간단하게 '1010'으로 설정
auth_pass 값도 MASTER 서버와 BACKUP 서버가 동일하게 설정해야함
virtual_ipaddress에는 VIP(192.168.100.250)로 설정해야함
4.2. node 1 (MASTER 서버)
MASTER 서버의 Keepalived 패키지 설치 및 실행
$ yum -y update
# Keepalived 패키지 설치
$ yum -y install keepalived
# Keepalived 설정 파일 수정
$ vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
vrrp_instance VI_1 {
state MASTER
interface eth1
virtual_router_id 51
priority 200
advert_int 1
authentication {
auth_type PASS
auth_pass 1010
}
virtual_ipaddress {
192.168.100.250
}
}
# keepalived 실행
$ systemctl start keepalived
$ systemctl enable keepalived
# keepalived 실행 상태 확인
$ systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2021-07-30 15:40:41 UTC; 11s ago
Main PID: 1081 (keepalived)
CGroup: /system.slice/keepalived.service
├─1081 /usr/sbin/keepalived -D
├─1082 /usr/sbin/keepalived -D
└─1083 /usr/sbin/keepalived -D
Jul 30 15:40:43 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:43 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:43 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:43 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:48 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:48 master1 Keepalived_vrrp[1083]: VRRP_Instance(VI_1) Sending/queueing gratuitous...250
Jul 30 15:40:48 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:48 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:48 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:40:48 master1 Keepalived_vrrp[1083]: Sending gratuitous ARP on eth1 for 192.168.100.250
Hint: Some lines were ellipsized, use -l to show in full.
4.3.node 2 (BACKUP 서버)
BACKUP 서버의 Keepalived 패키지 설치 및 실행
$ yum -y update
# Keepalived 패키지 설치
$ yum -y install keepalived
# Keepalived 설정 파일 수정
$ vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
vrrp_instance VI_1 {
state BACKUP
interface eth1
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1010
}
virtual_ipaddress {
192.168.100.250
}
}
# keepalived 실행
$ systemctl start keepalived
$ systemctl enable keepalived
# keepalived 실행 상태 확인
$ systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2021-07-30 15:40:41 UTC; 11s ago
Main PID: 1075 (keepalived)
CGroup: /system.slice/keepalived.service
├─1075 /usr/sbin/keepalived -D
├─1076 /usr/sbin/keepalived -D
└─1077 /usr/sbin/keepalived -D
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: Registering Kernel netlink reflector
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: Registering Kernel netlink command channel
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: Registering gratuitous ARP shared channel
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: Opening file '/etc/keepalived/keepalived.conf'.
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) removing protocol VIPs.
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: Using LinkWatch kernel netlink reflector...
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jul 30 15:40:41 master2 Keepalived_vrrp[1077]: VRRP sockpool: [ifindex(3), proto(112), unicast...1)]
Jul 30 15:40:41 master2 Keepalived_healthcheckers[1076]: Initializing ipvs
Jul 30 15:40:41 master2 Keepalived_healthcheckers[1076]: Opening file '/etc/keepalived/keepaliv...'.
Hint: Some lines were ellipsized, use -l to show in full.
5. 첫 번째 테스트 → Keepalived가 잘 실행되는지 확인
node 1, node 2와 같은 Private Subnet(192.168.100.0/24 대역) 안에 있는 테스트 서버(192.168.100.201) 1대를 구성
생성한 VIP(192.168.100.250)로 PING 테스트를 하는 도중에, node 1(MASTER server)을 shut down
5.1. 테스트 서버(192.168.100.201)에서 VIP(192.168.100.250)로 PING 테스트 진행
# 테스트 서버(192.168.100.201)에서 ping 테스트
$ ping 192.168.100.250
PING 192.168.100.250 (192.168.100.250) 56(84) bytes of data.
64 bytes from 192.168.100.250: icmp_seq=1 ttl=64 time=0.335 ms
64 bytes from 192.168.100.250: icmp_seq=2 ttl=64 time=0.392 ms
64 bytes from 192.168.100.250: icmp_seq=3 ttl=64 time=0.477 ms
64 bytes from 192.168.100.250: icmp_seq=4 ttl=64 time=0.469 ms
64 bytes from 192.168.100.250: icmp_seq=5 ttl=64 time=0.337 ms
64 bytes from 192.168.100.250: icmp_seq=6 ttl=64 time=0.322 ms
64 bytes from 192.168.100.250: icmp_seq=7 ttl=64 time=0.720 ms <----- Node1(MASTER 서버)에서 Node2 (BACKUP서버)로 fail-over
64 bytes from 192.168.100.250: icmp_seq=8 ttl=64 time=0.330 ms
64 bytes from 192.168.100.250: icmp_seq=9 ttl=64 time=0.417 ms
64 bytes from 192.168.100.250: icmp_seq=10 ttl=64 time=0.407 ms
64 bytes from 192.168.100.250: icmp_seq=11 ttl=64 time=0.314 ms
64 bytes from 192.168.100.250: icmp_seq=12 ttl=64 time=0.270 ms
64 bytes from 192.168.100.250: icmp_seq=13 ttl=64 time=0.404 ms
64 bytes from 192.168.100.250: icmp_seq=14 ttl=64 time=0.346 ms
64 bytes from 192.168.100.250: icmp_seq=15 ttl=64 time=0.271 ms
5.2. node2 (Backup 서버)에서 /var/log/messages 확인 결과, node 1(Master 서버)의 VIP(192.168.100.201)를 Take-Over 한것 확인 가능
# node2에서 확인
$ tail -f /var/log/messages
Jul 30 15:50:45 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Entering MASTER STATE
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) setting protocol VIPs.
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth1 for 192.168.100.250
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:46 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:51 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:51 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth1 for 192.168.100.250
Jul 30 15:50:51 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:51 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:51 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:50:51 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 15:51:03 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Received advert with higher priority 200, ours 100
Jul 30 15:51:03 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jul 30 15:51:03 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) removing protocol VIPs.
6. 두 번째 테스트 → Keepalived가 잘 실행되는지 확인
node 1, node 2와 같은 Private Subnet(192.168.100.0/24 대역) 안에 있는 테스트 서버(192.168.100.201) 1대를 구성
생성한 VIP(192.168.100.250)로 PING 테스트를 하는 도중에, node 1(MASTER server)의 keepalived 서비스 down 후 트래픽 확인
node 1(MASTER server)의 keepalived 서비스 restart 후 트래픽 확인
6.1. 테스트 서버(192.168.100.201)에서 VIP(192.168.100.250)로 PING 테스트 진행
# 테스트 서버(192.168.100.201)에서 ping 테스트
$ ping 192.168.100.250
PING 192.168.100.250 (192.168.100.250) 56(84) bytes of data.
64 bytes from 192.168.100.250: icmp_seq=1 ttl=64 time=0.332 ms
64 bytes from 192.168.100.250: icmp_seq=2 ttl=64 time=0.250 ms
64 bytes from 192.168.100.250: icmp_seq=3 ttl=64 time=0.443 ms
64 bytes from 192.168.100.250: icmp_seq=4 ttl=64 time=0.517 ms
64 bytes from 192.168.100.250: icmp_seq=5 ttl=64 time=0.373 ms
64 bytes from 192.168.100.250: icmp_seq=6 ttl=64 time=0.481 ms
64 bytes from 192.168.100.250: icmp_seq=7 ttl=64 time=0.442 ms
64 bytes from 192.168.100.250: icmp_seq=8 ttl=64 time=0.382 ms
64 bytes from 192.168.100.250: icmp_seq=9 ttl=64 time=0.445 ms
6.2. 일반적인 상황에서 테스트 서버에서 보낸 트래픽이 node1 (Master 서버)의 VIP(eth1:0)로만 트래픽 인입 확인 → node 2(Backup 서버)에는 트래픽 전송 X
# node1 (Master 서버)의 VIP로만 트래픽 인입 확인
$ tcpdump -i eth1:0
16:52:20.057581 IP worker > master1: ICMP echo request, id 19909, seq 1, length 64
16:52:20.057609 IP master1 > worker: ICMP echo reply, id 19909, seq 1, length 64
16:52:20.292151 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
16:52:21.061380 IP worker > master1: ICMP echo request, id 19909, seq 2, length 64
16:52:21.061402 IP master1 > worker: ICMP echo reply, id 19909, seq 2, length 64
16:52:21.293746 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
16:52:22.062916 IP worker > master1: ICMP echo request, id 19909, seq 3, length 64
16:52:22.062938 IP master1 > worker: ICMP echo reply, id 19909, seq 3, length 64
16:52:22.295863 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
# node2 (Backup 서버)는 대기 -> master에서 상태 체크만 함
$ tcpdump -i eth1:0
16:02:23.931301 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
6.3. node1 (Master 서버)의 keepalived 서비스 down→ node 2(Backup 서버)에 트래픽 인입 확인
$ systemctl stop keepalived
# node1 (Master 서버)는 대기 -> backup에서 상태 체크만 함
$ tcpdump -i eth1:0
16:54:00.591586 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simp
# node1 (Master 서버)의 /var/log/messages 내용 -> HA Master 종료 확인
$ tail -f /var/log/messages
Jul 30 16:55:02 master1 kernel: device eth1 left promiscuous mode
Jul 30 16:55:29 master1 systemd: Stopping LVS and VRRP High Availability Monitor...
Jul 30 16:55:29 master1 Keepalived[4960]: Stopping
Jul 30 16:55:29 master1 Keepalived_vrrp[4962]: VRRP_Instance(VI_1) sent 0 priority
Jul 30 16:55:29 master1 Keepalived_vrrp[4962]: VRRP_Instance(VI_1) removing protocol VIPs.
Jul 30 16:55:29 master1 Keepalived_healthcheckers[4961]: Stopped
Jul 30 16:55:30 master1 Keepalived_vrrp[4962]: Stopped
Jul 30 16:55:30 master1 Keepalived[4960]: Stopped Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2
Jul 30 16:55:30 master1 systemd: Stopped LVS and VRRP High Availability Monitor.
# node2 (Backup 서버)의 VIP로만 트래픽 인입 확인
$ tcpdump -i eth1:0
16:53:30.532423 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
16:53:30.548001 IP worker > master2: ICMP echo request, id 19910, seq 18, length 64
16:53:30.548028 IP master2 > worker: ICMP echo reply, id 19910, seq 18, length 64
16:53:31.549477 IP worker > master2: ICMP echo request, id 19910, seq 19, length 64
16:53:31.549499 IP master2 > worker: ICMP echo reply, id 19910, seq 19, length 64
16:53:31.549530 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
16:53:32.549784 IP worker > master2: ICMP echo request, id 19910, seq 20, length 64
16:53:32.549824 IP master2 > worker: ICMP echo reply, id 19910, seq 20, length 64
16:53:32.549972 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
# node2 (Backup 서버)의 /var/log/messages 내용 -> HA Backup 시작 확인
$ tail -f /var/log/messages
Jul 30 16:55:29 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Entering MASTER STATE
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) setting protocol VIPs.
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth1 for 192.168.100.250
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:55:30 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:55:35 master2 Keepalived_vrrp[1077]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:55:35 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth1 for 192.168.100.250
6.4. node1 (Master 서버)의 keepalived 서비스 restart → node 1(Master 서버)에 트래픽 다시 인입 확인
$ systemctl restart keepalived
# node1 (Master 서버)의 VIP로만 트래픽 다시 인입 확인
$ tcpdump -i eth1:0
16:54:17.656150 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
16:54:18.626524 IP worker > master1: ICMP echo request, id 19910, seq 66, length 64
16:54:18.626563 IP master1 > worker: ICMP echo reply, id 19910, seq 66, length 64
16:54:18.657517 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
16:54:19.628842 IP worker > master1: ICMP echo request, id 19910, seq 67, length 64
16:54:19.628864 IP master1 > worker: ICMP echo reply, id 19910, seq 67, length 64
16:54:19.658916 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
# node1 (Master 서버)의 /var/log/messages 내용 -> HA Master 재시작 확인
$ tail -f /var/log/messages
Jul 30 16:58:51 master1 Keepalived[4985]: Starting Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2
Jul 30 16:58:51 master1 Keepalived[4985]: Opening file '/etc/keepalived/keepalived.conf'.
Jul 30 16:58:51 master1 Keepalived[4986]: Starting Healthcheck child process, pid=4987
Jul 30 16:58:51 master1 systemd: Started LVS and VRRP High Availability Monitor.
Jul 30 16:58:51 master1 Keepalived[4986]: Starting VRRP child process, pid=4988
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: Registering Kernel netlink reflector
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: Registering Kernel netlink command channel
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: Registering gratuitous ARP shared channel
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: Opening file '/etc/keepalived/keepalived.conf'.
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: VRRP_Instance(VI_1) removing protocol VIPs.
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: Using LinkWatch kernel netlink reflector...
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: VRRP sockpool: [ifindex(3), proto(112), unicast(0), fd(10,11)]
Jul 30 16:58:51 master1 Keepalived_healthcheckers[4987]: Opening file '/etc/keepalived/keepalived.conf'.
Jul 30 16:58:51 master1 Keepalived_vrrp[4988]: VRRP_Instance(VI_1) Transition to MASTER STATE
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: VRRP_Instance(VI_1) Entering MASTER STATE
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: VRRP_Instance(VI_1) setting protocol VIPs.
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth1 for 192.168.100.250
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:52 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:57 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:57 master1 Keepalived_vrrp[4988]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth1 for 192.168.100.250
Jul 30 16:58:57 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:57 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:57 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
Jul 30 16:58:57 master1 Keepalived_vrrp[4988]: Sending gratuitous ARP on eth1 for 192.168.100.250
# node2 (Backup 서버)는 대기 -> master에서 상태 체크만 함
$ tcpdump -i eth1:0
16:54:37.679862 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
# node2 (Backup 서버)의 /var/log/messages 내용 -> HA backup이 Master로 빼았김 확인
$ tail -f /var/log/messages
Jul 30 16:58:51 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Received advert with higher priority 200, ours 100
Jul 30 16:58:51 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) Entering BACKUP STATE
Jul 30 16:58:51 master2 Keepalived_vrrp[1077]: VRRP_Instance(VI_1) removing protocol VIPs.
7. 세 번째 테스트 → Keepalived가 잘 실행되는지 확인
master 네트워크 절단시 backup으로 인입 OK, master 네트워크 재시동 이후 트래픽이 자동으로 master에 오지 않음(keepalived 서비스 재시작 필요)
node 1, node 2와 같은 Private Subnet(192.168.100.0/24 대역) 안에 있는 테스트 서버(192.168.100.201) 1대를 구성
생성한 VIP(192.168.100.250)로 PING 테스트를 하는 도중에, node 1(MASTER server)의 네트워크를 down
일정 시간 지난 후 다시 네트워크를 up한 후 eth1:0 VIP를 구성
네트워크가 up되어도 backup으로 계속 트래픽 발생 → master 서버로 돌아오지 않음
7.1. 테스트 서버(192.168.100.201)에서 VIP(192.168.100.250)로 PING 테스트 진행
# 테스트 서버(192.168.100.201)에서 ping 테스트
$ ping 192.168.100.250
PING 192.168.100.250 (192.168.100.250) 56(84) bytes of data.
64 bytes from 192.168.100.250: icmp_seq=1 ttl=64 time=0.335 ms
64 bytes from 192.168.100.250: icmp_seq=2 ttl=64 time=0.392 ms
64 bytes from 192.168.100.250: icmp_seq=3 ttl=64 time=0.477 ms
64 bytes from 192.168.100.250: icmp_seq=4 ttl=64 time=0.469 ms
64 bytes from 192.168.100.250: icmp_seq=5 ttl=64 time=0.337 ms
64 bytes from 192.168.100.250: icmp_seq=6 ttl=64 time=0.322 ms
64 bytes from 192.168.100.250: icmp_seq=7 ttl=64 time=0.720 ms <----- Node1(MASTER 서버)에서 Node2 (BACKUP서버)로 fail-over
64 bytes from 192.168.100.250: icmp_seq=8 ttl=64 time=0.330 ms
64 bytes from 192.168.100.250: icmp_seq=9 ttl=64 time=0.417 ms
64 bytes from 192.168.100.250: icmp_seq=10 ttl=64 time=0.407 ms
64 bytes from 192.168.100.250: icmp_seq=11 ttl=64 time=0.314 ms
64 bytes from 192.168.100.250: icmp_seq=12 ttl=64 time=0.270 ms
64 bytes from 192.168.100.250: icmp_seq=13 ttl=64 time=0.404 ms
64 bytes from 192.168.100.250: icmp_seq=14 ttl=64 time=0.346 ms
64 bytes from 192.168.100.250: icmp_seq=15 ttl=64 time=0.271 ms
64 bytes from 192.168.100.250: icmp_seq=16 ttl=64 time=0.314 ms
7.2. 일반적인 상황에서 테스트 서버에서 보낸 트래픽이 node1 (Master 서버)의 VIP(eth1:0)로만 트래픽 인입 확인 → node 2(Backup 서버)에는 트래픽 전송 X
# node1 (Master 서버)의 VIP로만 트래픽 인입 확인
$ tcpdump -i eth1:0
15:58:09.214853 IP worker > master1: ICMP echo request, id 1015, seq 1, length 64
15:58:09.214893 IP master1 > worker: ICMP echo reply, id 1015, seq 1, length 64
15:58:10.121214 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
15:58:10.216097 IP worker > master1: ICMP echo request, id 1015, seq 2, length 64
15:58:10.216121 IP master1 > worker: ICMP echo reply, id 1015, seq 2, length 64
15:58:11.122587 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
15:58:11.216543 IP worker > master1: ICMP echo request, id 1015, seq 3, length 64
15:58:11.216564 IP master1 > worker: ICMP echo reply, id 1015, seq 3, length 64
15:58:12.123952 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
15:58:12.218872 IP worker > master1: ICMP echo request, id 1015, seq 4, length 64
15:58:12.218894 IP master1 > worker: ICMP echo reply, id 1015, seq 4, length 64
# node2 (Backup 서버)는 대기 -> master에서 상태 체크만 함
$ tcpdump -i eth1:0
16:02:23.931301 IP master1 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 200, authtype simple, intvl 1s, length 20
7.5. 테스트 서버(192.168.100.201)에서 VIP(192.168.100.250)로 기존의 PING 테스트 세션을 종료 후 다시 진행해도 그대로 유지
# 테스트 서버(192.168.100.201)에서 ping 테스트
$ ping 192.168.100.250
PING 192.168.100.250 (192.168.100.250) 56(84) bytes of data.
64 bytes from 192.168.100.250: icmp_seq=1 ttl=64 time=0.335 ms
64 bytes from 192.168.100.250: icmp_seq=2 ttl=64 time=0.392 ms
64 bytes from 192.168.100.250: icmp_seq=3 ttl=64 time=0.477 ms
64 bytes from 192.168.100.250: icmp_seq=4 ttl=64 time=0.469 ms
64 bytes from 192.168.100.250: icmp_seq=5 ttl=64 time=0.337 ms
64 bytes from 192.168.100.250: icmp_seq=6 ttl=64 time=0.322 ms
64 bytes from 192.168.100.250: icmp_seq=7 ttl=64 time=0.720 ms
64 bytes from 192.168.100.250: icmp_seq=8 ttl=64 time=0.330 ms
64 bytes from 192.168.100.250: icmp_seq=9 ttl=64 time=0.417 ms
64 bytes from 192.168.100.250: icmp_seq=10 ttl=64 time=0.407 ms
64 bytes from 192.168.100.250: icmp_seq=11 ttl=64 time=0.314 ms
64 bytes from 192.168.100.250: icmp_seq=12 ttl=64 time=0.270 ms
64 bytes from 192.168.100.250: icmp_seq=13 ttl=64 time=0.404 ms
64 bytes from 192.168.100.250: icmp_seq=14 ttl=64 time=0.346 ms
64 bytes from 192.168.100.250: icmp_seq=15 ttl=64 time=0.271 ms
64 bytes from 192.168.100.250: icmp_seq=16 ttl=64 time=0.314 ms
64 bytes from 192.168.100.250: icmp_seq=17 ttl=64 time=0.491 ms
64 bytes from 192.168.100.250: icmp_seq=18 ttl=64 time=0.480 ms
64 bytes from 192.168.100.250: icmp_seq=19 ttl=64 time=0.389 ms
64 bytes from 192.168.100.250: icmp_seq=20 ttl=64 time=0.362 ms
64 bytes from 192.168.100.250: icmp_seq=21 ttl=64 time=0.392 ms
64 bytes from 192.168.100.250: icmp_seq=22 ttl=64 time=0.399 ms
64 bytes from 192.168.100.250: icmp_seq=23 ttl=64 time=0.381 ms
64 bytes from 192.168.100.250: icmp_seq=24 ttl=64 time=0.277 ms
64 bytes from 192.168.100.250: icmp_seq=25 ttl=64 time=0.570 ms
[...생략]
^C
--- 192.168.100.250 ping statistics ---
908 packets transmitted, 889 received, 2% packet loss, time 910037ms
rtt min/avg/max/mdev = 0.151/0.452/6.065/0.216 ms
# 테스트 서버(192.168.100.201)에서 다시 ping 테스트
$ ping 192.168.100.250
PING 192.168.100.250 (192.168.100.250) 56(84) bytes of data.
64 bytes from 192.168.100.250: icmp_seq=1 ttl=64 time=0.446 ms
64 bytes from 192.168.100.250: icmp_seq=2 ttl=64 time=0.608 ms
64 bytes from 192.168.100.250: icmp_seq=3 ttl=64 time=0.395 ms
64 bytes from 192.168.100.250: icmp_seq=4 ttl=64 time=0.452 ms
64 bytes from 192.168.100.250: icmp_seq=5 ttl=64 time=0.504 ms
64 bytes from 192.168.100.250: icmp_seq=6 ttl=64 time=0.483 ms
7.6. node 1(Master 서버)의 VIP(192.168.100.250)에 트래픽 다시 인입 확인
# node1 (Master 서버)는 대기 -> backup에서 상태 체크만 함
$ tcpdump -i eth1:0
16:41:59.321344 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
# node2 (Backup 서버)의 VIP로만 트래픽 인입 확인
$ tcpdump -i eth1:0
16:42:06.024044 IP worker > master2: ICMP echo request, id 19904, seq 45, length 64
16:42:06.024077 IP master2 > worker: ICMP echo reply, id 19904, seq 45, length 64
16:42:06.343284 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
16:42:07.033519 IP worker > master2: ICMP echo request, id 19904, seq 46, length 64
16:42:07.033543 IP master2 > worker: ICMP echo reply, id 19904, seq 46, length 64
16:42:07.346173 IP master2 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
기본적인 옵션만 아래 설명 → 여러 섹션으로 나누어져 있으며 섹션 하단에 파라미터를 추가하는 방식으로 구성
2.1. global 구간
-daemon
백그라운드에서 HAproxy 서비스 실행
데몬형식 fork 하면서 실행 하는 파라미터
만약 daemon을 추가 하지 않을 경우 포그라운드에서 실행 → 실행할 때 &를 추가하여 명시적으로 백그라운드에서 실행되게 해야함
-maxconn
최대 연결 수를 지정
(ulimit -n) 을 통해 해당 서버의 기본 프로세스가 오픈 할 수 있는 갯수 만큼 지정 가능
2.2. defaults 구간
-mode (http,tcp,health)
tcp→ 해당 포트에 대한 어플리케이션 프록시
http→ http 인스턴스에서 작동
health→ 단순한 health check 모드
-timeout connect
전체 외부 클라이언트에서 실제 real 서버 까지의 time out 설정
-timeout client
외부 클라이언트에서 vip(virtual IP)까지의 timeout 설정
-timeout server
vip(virtual IP) 서버에서 실제 real 서버 까지의 timeout 설정
2.3. frontend 구간
-bind
bind 는 apache 의 binding 설정과 비슷 하며, 해당 서버로 listening 되는 아이피와 포트를 지정
-default_backend
frontend 에서 받은 정보를 backend server로 보낼 이름을 지정
servers 라는 backend 설정된 아이피로 포워딩
2.4. backend servers 구간 → server <name> <address>[:[port]][param*]
위 형태로 명시된 아이피와 포트로 데이터를 전송
2.5. listen 구간
frontend + backend 한번에 설정 가능한 섹션
3. HAproxy balance 옵션
backend 에서 사용 할 balancing 알고리즘을 설정 가능
3.1. roundrobin
순서대로 데이터를 전송
3.2. static-rr
서버에 weight 가중치를 부여해, 부여된 가중치에 따라 데이터 전송
3.3. balance_url_param
HTTP GET 요청에 대해서 특정 패턴이 있는지 여부 조사후 조건에 맞는 서버로 트래픽 전송
조건이 없는 경우 roundrobin 으로 트래픽 전송
3.4. balance hdr
HTTP Header 에서 hdr(name) 으로 지정된 조건이 있는 경우에 대해서만 트래픽 전송
조건이 없는경우 roundrobin 으로 트래픽 전송
4. HAproxy 패키지 설치
4.1. 첫번째 방법. yum으로 haproxy 패키지 설치
HAproxy는 버전에 따라 설정이 약간씩 다르기에 필요한 버전을 수동으로 다운받는게 좋음
$ yum -y install haproxy
4.2. 두번째 방법. HAproxy 패키지 수동으로 설치 → HAproxy 2.3.9 버전 설치
아래 명령어를 입력하여 haproxy 2.3.9 버전 설치 파일을 다운로드
$ cd /usr/local/lib
# haproxy 2.3.9 버전 파일 설치
$ curl -O http://www.haproxy.org/download/2.3/src/haproxy-2.3.9.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2860k 100 2860k 0 0 564k 0 0:00:05 0:00:05 --:--:-- 672k
# 다운받은 haproxy 2.3.9 버전 설치 파일 확인
$ ls /usr/local/lib
haproxy-2.3.9.tar.gz
설치파일을 압축해제
$ tar zxf haproxy-2.3.9.tar.gz
$ ls -al /usr/local/lib
total 2868
drwxr-xr-x. 3 root root 55 Aug 1 13:09 .
drwxr-xr-x. 12 root root 131 Apr 30 2020 ..
drwxrwxr-x 11 root root 4096 Mar 30 16:38 haproxy-2.3.9
-rw-r--r-- 1 root root 2928660 Aug 1 13:08 haproxy-2.3.9.tar.gz
TARGET=linux-glibc → HAProxy 2.0 부터는 "linux2628" 대신에 "linux-glibc" 로 "TARGET"이 변경
USE_OPENSSL=1 → SSL 인증서를 활성화 하기 위해서 USE_OPENSSL를 활성화
USE_PCRE=1 → 펄(PERL) 호환 정규 표현식을 사용하기 위해 활성화
USE_ZLIB=1 → http 압축을 이용하기 위해 활성화
USE_SYSTEMD=1 → systemd 를 통해서 서비스를 컨트롤 하기 위해서 USE_SYSTEMD도 활성화
$ cd /usr/local/lib/haproxy-2.3.9
$ make TARGET=linux-glibc USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1 USE_SYSTEMD=1
CC src/ev_poll.o
CC src/ev_epoll.o
CC src/ssl_sample.o
CC src/ssl_sock.o
[...생략]
$ /usr/local/sbin/haproxy -v
HA-Proxy version 2.3.9-53945bf 2021/03/30 - https://haproxy.org/
Status: stable branch - will stop receiving fixes around Q1 2022.
Known bugs: http://www.haproxy.org/bugs/bugs-2.3.9.html
Running on: Linux 3.10.0-1160.36.2.el7.x86_64 #1 SMP Wed Jul 21 11:57:15 UTC 2021 x86_64
HAProxy 서비스 예제 파일을 다운로드
$ curl "http://git.haproxy.org/?p=haproxy-2.3.git;a=blob_plain;f=contrib/systemd/haproxy.service.in" -o /etc/systemd/system/haproxy.service
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1405 0 1405 0 0 550 0 --:--:-- 0:00:02 --:--:-- 550
HAproxy 서비스 예제 파일 수정
$CONFIG 값 설정 → /etc/haproxy/haproxy.cfg
$EXTRAOPTS 값 설정 → /run/haproxy-master.sock
$PIDFILE 값 설정 → /run/haproxy.pid
$ vi /etc/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=network-online.target
Wants=network-online.target
[Service]
EnvironmentFile=-/etc/default/haproxy
EnvironmentFile=-/etc/sysconfig/haproxy
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock"
# 수정 전 내용 아래
ExecStartPre=@SBINDIR@/haproxy -f $CONFIG -c -q $EXTRAOPTS
ExecStart=@SBINDIR@/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS
ExecReload=@SBINDIR@/haproxy -Ws -f $CONFIG -c -q $EXTRAOPTS
# 수정 후 내용 아래
ExecStartPre=/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q -S /run/haproxy-master.sock
ExecStart=/usr/local/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
ExecReload=/usr/local/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -c -q -S /run/haproxy-master.sock
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=always
SuccessExitStatus=143
Type=notify
# The following lines leverage SystemD's sandboxing options to provide
# defense in depth protection at the expense of restricting some flexibility
# in your setup (e.g. placement of your configuration files) or possibly
# reduced performance. See systemd.service(5) and systemd.exec(5) for further
# information.
# NoNewPrivileges=true
# ProtectHome=true
# If you want to use 'ProtectSystem=strict' you should whitelist the PIDFILE,
# any state files and any other files written using 'ReadWritePaths' or
# 'RuntimeDirectory'.
# ProtectSystem=true
# ProtectKernelTunables=true
# ProtectKernelModules=true
# ProtectControlGroups=true
# If your SystemD version supports them, you can add: @reboot, @swap, @sync
# SystemCallFilter=~@cpu-emulation @keyring @module @obsolete @raw-io
[Install]
WantedBy=multi-user.target
$ vi /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2 # syslog. UDP 514번 포트 Open 필요
chroot /var/lib/haproxy # 모든 동작은 /var/lib/haproxy에서 수행, 보안 상승
pidfile /var/run/haproxy.pid # 실행 pid명
maxconn 4000 # 프로세스 당 최대 연결 수치
user haproxy # haproxy 서비스 사용자
group haproxy # harpoxy 서비스 그룹
daemon # background로 실행될 수 있도록 설정
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults # front, back, listen에 관련 설정 부분
mode http # http 프로토콜을 사용하는 로드벨런싱 모드
log global # 로그는 global에 설정한 방법으로 사용
option httplog # 기본 Log는 SIP, DIP와 Name만 표기됨, 해당 옵션을 사용하면 디테일하게 Log 표시
option dontlognull # Log 비대화 방지 -> Probe(정찰, 스캔과 같은 불필요한 기록을 HAProxy Log 기록 X
option http-server-close # 클라이언트와 리얼 서버 연결 종료시, 디폴트로 유휴 대기하지 않고, 서버에서 Handshake를 종료
# 더 빠른 새로운 세션을 준비할 수 있도록 해줌
# 디폴트 옵션에 선언되어 있어도, 인스턴스 별로 no 옵션으로 제외처리 가능
option forwardfor except 127.0.0.0/8 # 서버에 대한 응답을 HAProxy가 받기 때문에(VIP), 리얼 서버 IP를 HTTP 헤더에 표기하는 옵션
option redispatch # mode HTTP에서 Cookie에 지정된 Real 서버가 다운되면, 외부 클라이언트가 쿠키를 플로시하기 전에 서비스에 문제 발생 가능
# redispatch 옵션을 통해 프로시 지속성을 무시하고 쿠키, 세션 재분재를 실행 -> retries값이 0보다 커야함
retries 3 # redispatch 횟수 결정
timeout http-request 10s # Request시의 헤더에만 적용. Dos 방어를 위해, HTTP 요청 타임 아웃시간 설정 -> 클라이언트의 연결 타임아웃과는 관계 X, HAProxy의 옵션
timeout queue 1m # 서버의 maxconn에 도달시, 무한정 보류 상태로 두지 않고 HTTP 503 응답을 보내면서 연결을 버리기까지의 시간
timeout connect 10s # TCP 패킷 손실을 막기 위한 Real 서버로의 연결 최대 지연시간 설정 -> Backend에 적용, 전역에도 적용 가능
timeout client 1m # 외부 클라이언트의 요청이나 데이터와의 연결 최대 시 -> http-request가 선행, 서버 안정성에 기여
timeout server 1m # 서버가 데이터를 승인하거나, 전송해야 할 때의 연결 최대 시간
timeout http-keep-alive 10s # 클라이언트의 요청에 따른 응답 전송 후, 다음 요청까지의 대기 시간 -> http-request가 선행 필수
timeout check 10s # timeout server와 동일하거나 작은 값을 가져야함
maxconn 3000 # 프로세스당 최대 연결 개수
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend http
bind: *:80 # haproxy 구동시 사용할 포트를 지정 -> 클라이언트의 연결을 받는 부분(WAF 기능과 유사)
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static # ACL에서 정의한 style들을 backend static으로 전송
default_backend static # 아래 backend 중에서 static 부분을 사용 -> 미리 여러개 설정해놓고 선택
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static # 실제 접속시 로드밸런싱하는 서버
balance roundrobin # roundrobin은 무조건 한번씩 번갈아 접속시키는 방식 -> source 값을 이용
server static 192.168.100.201:80 check # 포워딩할 서버 IP와 포트 설정
server static 192.168.100.202:80 check # 포워딩할 서버 IP와 포트 설정
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check
#listen # 프론트/백엔드 연결의 포트/옵션등 정의 -> TCP 제어나 Proxy에 주로 사용
#listen stats # "stats"라는 이름으로 listen 지정
# bind *:9000 # 접속 포트 지정
# stats enable
# stats realm Haproxy Statistics # 브라우저 타이틀
# stats uri /haproxy_stats # stat 를 제공할 URI
# #stats auth Username:Password # 인증이 필요하면 추가
9.1. rsyslog 에 HAproxy 용 로그를 남기도록 설정 → /etc/rsyslog.d/haproxy.conf 파일 구성
$ vi /etc/rsyslog.d/haproxy.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
$template Haproxy, "%msg%\n"
#rsyslog 에는 rsyslog 가 메세지를 수신한 시각 및 데몬 이름같은 추가적인 정보가 prepend 되므로, message 만 출력하는 템플릿 지정
# 이를 haproxy-info.log 에만 적용한다.
# 모든 haproxy 를 남기려면 다음을 주석해재, 단 access log 가 기록되므로, 양이 많다.
#local0.* /var/log/haproxy/haproxy.log
# local0.=info 는 haproxy 에서 에러로 처리된 이벤트들만 기록하게 됨 (포맷 적용)
local0.=info /var/log/haproxy/haproxy-info.log;Haproxy
# local0.notice 는 haproxy 가 재시작되는 경우와 같은 시스템 메세지를 기록하게됨 (포맷 미적용)
local0.notice /var/log/haproxy/haproxy-allbutinfo.log
9.2. logroate에 HAproxy 설정을 추가 → /etc/logrotate.d/haproxy 파일 구성
# /etc/haproxy/haproxy.cfg 파일 가장 아래에 추가
$ vi /etc/haproxy/haproxy.cfg
listen monitor
mode http
bind *:8020
stats enable
stats auth root:hello
stats uri /monitor
13.2. HAProxy.cfg 파일 검증 및 재시작
# 위 내용이 적합한지 검증
$ haproxy -f /etc/haproxy/haproxy.cfg -c
Configuration file is valid
$ systemctl restart haproxy