HAProxy & Keepalived
HAProxy 이중화를 위해 Keepalived를 사용한 테스트이다. (Keepalived도 IPVS를 사용한 L4 Level의 LoadBalancing을 할 수 있다.)
설치
Test 환경
-
OS : Ubuntu 18.04
-
Node
-
VIP : 192.168.219.253
-
Master IP : 192.168.219.125
-
Slave IP : 192.168.219.126
-
Web01 : 192.168.219.128
-
Web02 : 192.168.219.129
-
HAProxy Version : 1.8.8
-
Keepalived Version : 1.3.9
HAProxy
# apt install -y haproxy
-> Ubuntu 18.04에서 기본 Repo로 설치시 1.8.8 버전이 설치된다.
현재 (2020-01) 2.1버전이 최신버전이며 1.5버전부터 SSL을 지원하기 때문에 기본설치방법으로도 SSL 사용이 가능하지만 최신 버전을 사용하고 싶다면 wget을 사용하여 다운로드 후 컴파일하거나 별도 Repo를 추가시켜준다.
# apt-add-repository ppa:vbernat/haproxy-2.1
# apt update
# apt install -y haproxy 또는 apt install -y haproxy=2.1
-> 위와 같은 방법으로 Repo 추가 후 설치하면 2.1.2 버전이 설치된다.
Keepalived
# apt install -y keepalived
설정
HAProxy (Master&Slave)
# vim /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 4000
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
option httpclose
timeout http-request 10s
timeout http-keep-alive 10s
timeout connect 10s
timeout client 1m
timeout server 1m
timeout queue 1m
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen stats_page
bind 192.168.219.253:8080
stats enable
stats realm HAProxy Statistics
stats uri /
stats auth admin:admin
frontend haproxy
bind 192.168.219.253:80
mode http
default_backend server
backend server
mode http
balance roundrobin
cookie SVID insert indirect nocache maxlife 10m
option httpchk GET /
http-check expect status 200
server web01 192.168.219.128:80 cookie web01 check inter 2000 rise 2 fall 5
server web02 192.168.219.129:80 cookie web02 check inter 2000 rise 2 fall 5
Keepalived
# vim /etc/keepalived/keepalived.conf (Master)
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 200
advert_int 1
authentication {
auth_type PASS
auth_pass 7388
}
virtual_ipaddress {
192.168.219.253
}
}
# vim /etc/keepalived/keepalived.conf (Slave)
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 7388
}
virtual_ipaddress {
192.168.219.253
}
}
커널 파라미터 변경
Kernel Parameter Default List
net.ipv4.ip_forward = 1
-
Kernel이 패킷을 전달하게 하는 경우 사용한다.
-
Keepalived가 네트워크 패킷을 실제 서버에 정상적으로 전달하려면 각 라우터 노드가 커널에서 IP Forward를 설정해야한다.
net.ipv4.ip_nonlocal_bind = 1
-
HAProxy 및 Keepalived의 로드밸런싱은 동시에 로컬이 아닌 IP 주소에 바인딩할 수 있어야한다.
-
즉, 네트워크 인터페이스에 없는 주소로 바인딩할 수 있도록 해주는 커널 값이다. (네트워크 인터페이스가 지정된 정적 IP가 아닌 동적 IP를 바인딩할 수 있다.)
-
해당 옵션이 비활성화 되어 있어도 서비스가 시작하면서 인터페이스에 특정 IP를 바인딩할 수 있으나 FailOver시 문제 발생
참고 URL
HAProxy Kernel Parameter Best Practices
가장 중요한 Paramater
net.ipv4.ip_local_port_range = "1025 65534"
net.ipv4.tcp_max_syn_backlog = 100000
net.core.netdev_max_backlog = 100000
net.core.somaxconn = 65534
ipv4.tcp_rmem = "4096 16060 64060"
ipv4.tcp_wmem = "4096 16384 262144"
작업량에 따라 조절
tcp_slow_start_after_idle = 0
iptables tuning
net.netfilter.nf_conntrack_max = 131072
주의 사항
conntrack이 잘못 구성되면 HAProxy가 최대 성능을 발휘하지 못한다.
또한 iptables가 활성화 되어 있으면 connection tracking 작업을 위해 iptables에 규칙이 없더라도 20%의 CPU를 소모한다.
참고 URL
테스트
아래 테스트는 커널 파라미터 중 기본값만 변경한 테스트이다.
1. 커널 파라미터 변경전 FailOver
# curl 192.168.219.253 (VIP)
외부에서 HAProxy의 VIP로 curl 명령 실행시 뒷단의 Web 서버로 LoadBalancing이 되는 것이 확인된다.
앞단에서 HAProxy Master역할을 하는 것은 Keepalived의 Master로 설정된 노드이다.
이제 Master VM 장애 발생을 가정하고 Failover 테스트를 진행한다.
Slave에는 Haproxy Service가 실행 중이다.
(기본 커널 파라미터가 셋팅이 안된상태에서 Slave의 HAProxy 데몬은 실행에 실패한다. 테스트를 위해 Master를 Off후 서비스를 올린 뒤에 다시 Master를 On 시켜 테스트 환경을 만든 것이다.
데몬이 실패한 이유는 haproxy에 의해 VIP가 네트워크 인터페이스에 바인딩되어야하는데 커널파라미터가 비활성화 값이므로 실패하였다.)
Master VM을 Poweroff 하였을때 Keepalived에 의해 Slave VM이 Master로 승격되었다.
외부에서 HAProxy로 curl 명령 실행시 무중단으로 실행되는 것도 확인되었다.
이제 다시 Master VM을 실행시켜 FailBack을 할 예정이다.
Slave는 정상이나 Master가 다시 정상으로 돌아왔을 경우 HAProxy에 대한 응답은 실패했다.
Master에서 확인해보니 아래와 같이 HAProxy Service가 실패하였다.
실패 원인
haporxy는 haproxy.cfg에 있는 VIP를 바인딩해야하는데 VIP가 현재 로드밸런서에 없으므로 오류를 발생시킨다. (오류 내용 - 프록시 : 소켓을 바인드 할 수 없음)
Master -> Slave로 FailOver하는 경우 Keepalived에 의해 VIP가 옮겨간다. Slave에서 서비스 구동을 하다가 Master가 정상으로 돌아오면 Keepalived는 가중치에 의해 다시 Master가 트래픽을 받도록 변경한다.
이 상태에서 VIP도 Master로 옮겨오는데 Keepalived가 VIP를 Master의 네트워크 인터페이스에 바인딩하고 HAProxy가 서비스가 실행되면 커널파라미터에 상관없이 HAProxy에서 VIP를 네트워크 인터페이스에서 인식하여 정상적으로 FailBack이 된다.
# vim /lib/systemd/system/haproxy.service
위 방법은 Service의 Boot Type에서 notify를 idle로 변경한 것이다.
notify의 경우 simple과 동일하나 unit이 구동되면 systemd에 시그널을 보낸다. (unit이 시작된 즉시 systemd는 유닛의 시작이 완료되었다고 판단한다. 그런데 다른 유닛과 통신하기 위해 소켓을 사용하는 경우 이 설정을 사용하면 안된다.)
HAProxy의 경우 Keepalived와 통신하기 때문에 HA를 구성하기 위해서는 Type이 notify가 되어서는 안된다. 이런 부분을 해결해주는 것이 net.ipv4.ip_nonlocal_bind 파라미터이다.
Master에서 Type을 notify -> idle로 변경하였을 경우 net.ipv4.ip_nonlocal_bind=0 이더라도 정상적으로 FailBack이 진행된다.
하지만 Slave의 경우 Unit의 Type을 변경하더라도 서비스는 실패가 된다. (실패한 이유는 Keepalived의 VIP가 Master에 있기때문에 통신할 소켓이 없어서 발생한다. 네트워크 인터페이스의 바인딩 문제)
net.ipv4.ip_nonlocal_bind=1 일경우 Unit의 Type에 상관없이 HAProxy 서비스는 정상 시작된다.
2. 커널 파라미터 변경후 FailOver
net.ipv4.ip_nonlocal_bind=1 로 변경한 경우 정상적으로 FailOVer & FailBack이 진행된다. 다면 FailBack 과정에서 짧은시간동안 순단이 발생할 수 있으며 순단시에는 HTTP Code 503을 발생한 후 정상적으로 HTTP Code 200을 반환한다.
실제 운영환경에서는 자동 FailBack이 아닌 수동으로 FailBack을 진행하는 것을 권장한다. 잠시동안이라도 발생하는 네트워크 순단현상을 최대한 방지하기 위해서이다.
3. 정리
Master & Slave 구성에서 Master는 Service Unit의 Type 값을 변경해 정상적인 FailBack을 할 수 있고 Slave에서는 커널 파라미터를 변경하여 FailOver 환경을 만들수 있으나 정상적인 방법은 아니므로 기본 커널 파리미터 값을 변경하여 HA를 구성하는 것을 권장한다.
'Web' 카테고리의 다른 글
SNI(Server Name Indication) (0) | 2020.10.25 |
---|---|
HAProxy (2) | 2020.01.17 |
Keepalived & VRRP (0) | 2020.01.17 |
부하분산 테스트 설명 및 용어 (0) | 2019.04.09 |
PinPoint (0) | 2019.04.09 |