The first, install keepalived to manage Virtual IP. My concept is use 2 Virtual IPs bind on 2 Nodes. Node 1 is MASTER on Virtual IP 1 and BACKUP on Virtual IP 2, Node 2 is MASTER on Virtual IP 2 and BACKUP on Virtual IP 1. DNS Round-robin to 2 Public IPs, every Public IP map to one Virtual IP.

I think this concept is working with both NGINX or HAProxy.

Insall KeepAlived

On both Nodes:

sudo dnf install -y keepalived
id -u keepalived &> /dev/null || useradd -s /usr/sbin/nologin -r keepalived_script
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf
firewall-cmd --add-rich-rule='rule protocol value="ah" accept' --permanent
firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent && sudo firewall-cmd --reload
firewall-cmd --add-port=112/udp --permanent && firewall-cmd --reload
firewall-cmd --add-port=112/tcp --permanent && firewall-cmd --reload

Edit /etc/keepalived/keepalived.conf:

On node 1:

global_defs {
   router_id NODE_01
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script chk_haproxy {           # Requires keepalived-1.1.13
        script "killall -0 haproxy"     # cheaper than pidof
        interval 2                      # check every 2 seconds
        weight 2                        # add 2 points of prio if OK
}

vrrp_instance VI_1 {
    state MASTER
    interface ens160 # change as your network interface
    virtual_router_id 51
    priority 101 # greater is more priority (99-100-101...)
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass hacluster
    }
    virtual_ipaddress {
        10.0.0.1 # Virtual IP 1
    }
	track_script {
        chk_haproxy
    }
}
vrrp_instance VI_2 {
    state BACKUP
    interface ens160
    virtual_router_id 52  # other ID
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass hacluster
    }
    virtual_ipaddress {
        10.0.0.2 # Virtual IP 2
    }
	track_script {
        chk_haproxy
    }
}

On node 2:

global_defs {
   router_id NODE_02
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_script chk_haproxy {           # Requires keepalived-1.1.13
        script "killall -0 haproxy"     # cheaper than pidof
        interval 2                      # check every 2 seconds
        weight 2                        # add 2 points of prio if OK
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens160
    virtual_router_id 51
    priority 101
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass hacluster
    }
    virtual_ipaddress {
        10.0.0.1 # Virtual IP 1
    }
	track_script {
        chk_haproxy
    }
}
vrrp_instance VI_2 {
    state MASTER
    interface ens160
    virtual_router_id 52  # other ID
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass hacluster
    }
    virtual_ipaddress {
        10.0.0.2 # Virtual IP 2
    }
	track_script {
        chk_haproxy
    }
}
systemctl enable --now keepalived
systemctl reload keepalived

Install somethings

sudo dnf -y install epel-release
sudo dnf -y groupinstall 'Development Tools'
sudo dnf install -y  wget git unzip perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel pcre-devel GeoIP GeoIP-devel

Install HAProxy community edition

Install from repo or source.

dnf -y install haproxy
setsebool -P haproxy_connect_any=1
sudo systemctl daemon-reload
sudo chkconfig haproxy on
systemctl enable --now haproxy
id -u haproxy &> /dev/null || useradd -s /usr/sbin/nologin -r haproxy

Open listen ports on firewall, or disable (for test):

sudo systemctl stop firewalld

Now, on both Nodes, update your haproxy with the same config. Your config files should be ascii, and have one new empty line.

In /etc/haproxy/haproxy.cfg:

# haproxy -c -V -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/  -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
global
   log /dev/log local0 warning
   log /dev/log local1 notice
   chroot /var/lib/haproxy
   stats timeout 30s
   user haproxy
   group haproxy
   daemon

defaults
	log global
	mode http
	option httplog
	option dontlognull
	timeout connect 5000
	timeout client 50000
	timeout server 50000
		
	stats enable   
	stats refresh 10s 
	stats uri /ha-stats 

In /etc/haproxy/conf.d, create a router file for listening:

/etc/haproxy/conf.d/router.cfg:

frontend listen_80
	mode http	
	bind :80	
	http-request add-header X-Forwarded-Proto https
	redirect scheme https if !{ ssl_fc }
frontend frontend_router		
	bind *:443 ssl crt /etc/haproxy/cert.pem	
	option http-server-close
	option forwardfor
	http-request add-header X-Forwarded-Proto https
	http-request add-header X-Forwarded-Port 443
	http-response add-header Strict-Transport-Security max-age=15768000	

	# WebSocket Check   
	acl is_websocket req.hdr(Upgrade) -i WebSocket && req.path_beg /ws

	# Router
	## check_dns for app1
	acl is_match_domain hdr_dom(host) -i app1.domain.com app1-test.domain.com
	use_backend app1_backend_socket if is_match_domain is_websocket
	use_backend app1_backend if is_match_domain
	## check_dns for app2
	acl is_match_domain hdr_dom(host) -i app2.domain.com app2-test.domain.com
	use_backend app2_backend_socket if is_match_domain is_websocket
	use_backend app2_backend if is_match_domain

/etc/haproxy/conf.d/app1.cfg:

# if app1 listen on custom Port
frontend app1_frontend_other_port
	mode http	
	bind :3003
	bind *:3003 ssl crt /etc/haproxy/cert.pem
	acl is3003 dst_port 3003
	
	acl is_app1_main hdr_dom(host) -i app1.domain.com
	acl is_app1_test hdr_dom(host) -i app1-test.domain.com
	
	http-request redirect prefix https://app1.domain.com code 301 if is3003 is_app1_main 
	http-request redirect prefix https://app1-test.domain.com code 301 if is3003 is_app1_test 
   
backend app1_backend
	mode http	
	balance roundrobin   
	server node1 10.5.10.202:3000 ssl verify none #if backend has SSL
	server node2 10.5.10.202:3001 ssl verify none

backend app1_backend_socket
    mode http    
	balance roundrobin   
	server node1 10.5.10.202:3200 ssl verify none #if backend has SSL
	server node2 10.5.10.202:3201 ssl verify none
	server node3 10.5.10.202:3202 ssl verify none
	server node4 10.5.10.202:3203 ssl verify none

/etc/haproxy/conf.d/app2.cfg:

backend app2_backend
	mode http	
	balance roundrobin   
	server node1 10.5.10.203:3000 #if backend has no SSL
	server node2 10.5.10.203:3001

backend app2_backend_socket
    mode http    
	balance roundrobin   
	server node1 10.5.10.203:3200
	server node2 10.5.10.203:3201

Recheck config and apply

# haproxy -c -V -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/  -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

Reload your keepalived again.

Test

Config your DNS (example.domain.com) to 2 public IP.

In both nodes, run terminal server test:

python3 -m http.server -b 0.0.0.0 3009
# install python3 if does not install

On browser, connect http://example.domain.com/?ha-test then refresh. Show your terminal.

DMCA.com Protection Status


Leave a Reply

Your email address will not be published. Required fields are marked *