Haproxy + Keepalived
HAProxy + Keepalived
Install package
sudo apt update
sudo apt install haproxy keepalived -y
touch /etc/keepalived/check_haproxy.sh && chmod +x /etc/keepalived/check_haproxy.sh
Configure keepalived
/etc/keepalived/check_haproxy.sh
#!/bin/bash
pidof haproxy > /dev/null 2>&1
if [ $? -ne 0 ]; then
exit 1
fi
exit 0
/etc/keepalived/keepalived.conf
master
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 2
weight -10
fall 1
rise 2
}
vrrp_instance VI_1 {
state MASTER
interface enp1s0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 12345
}
virtual_ipaddress {
192.168.122.10
}
track_script {
chk_haproxy
}
}
backup
vrrp_script chk_haproxy {
script "/etc/keepalived/check_haproxy.sh"
interval 1
weight -10
fall 1
rise 1
}
vrrp_instance VI_1 {
state BACKUP
interface enp1s0
virtual_router_id 51
priority 95
advert_int 1
authentication {
auth_type PASS
auth_pass 12345
}
virtual_ipaddress {
192.168.122.10
}
track_script {
chk_haproxy
}
}
Configure haproxy
/etc/haproxy/haproxy.cfg
For all servers
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
maxconn 2000
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
#timeout connect 5000
#timeout client 50000
#timeout server 50000
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
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
frontend http_front
bind *:80
# Stick table
stick-table type ip size 1m expire 10s store http_req_rate(10s)
# ip associate with stick table
tcp-request connection track-sc1 src
# Rate limit: max 100 request per 10 seconds
http-request deny if { sc_http_req_rate(0) gt 100 }
default_backend http_back
backend http_back
balance roundrobin
server node01 192.168.122.226:80 check
server node02 192.168.122.185:80 check
# enable haproxy stats http://<server>:9000/stats
listen stats
bind *:9000
mode http
stats enable
stats uri /stats
stats refresh 10s
stats realm Haproxy\ Statistics
stats auth admin:adminpassword123
stats admin if TRUE
Check config
haproxy -c -f -V /etc/haproxy/haproxy.cfg
Restart services
systemctl restart haproxy
systemctl restart keepalived
Check correct work
Stop some service
systemctl stop haproxy
# or
systemctl stop keepalive
ip 192.168.122.10 must be assigned to backup server
Script for manage haproxy
#!/bin/bash
SOCKET="/run/haproxy/admin.sock"
COMMAND="socat $SOCKET stdio"
function check_args {
if [ "x$1" == "x" ]
then
echo "unknown backend for drain $0 drain <backend> <server>"
exit 1
elif [ "x$2" == "x" ]
then
echo "unknown server for drain $0 drain $1 <server>"
exit 1
fi
}
case $1 in
help|--help|-h)
echo "help" | $COMMAND
;;
status)
echo "Server states"
echo "show servers state" | $COMMAND
;;
drain)
check_args $2 $3
echo "set server $2/$3 state drain" | $COMMAND
while true; do
SESS=$(echo "show stat" | $COMMAND | grep "$2,$3" | cut -d',' -f5)
echo "Active sessions: $SESS"
[ "$SESS" -eq 0 ] && break
sleep 2
done
STATUS=$(echo "show stat" | $COMMAND | grep "$2,$3" | cut -d',' -f18)
echo "$2 $2 is $STATUS"
;;
ready)
check_args $2 $3
echo "set server $2/$3 state ready" | $COMMAND
sleep 1
STATUS=$(echo "show stat" | $COMMAND | grep "$2,$3" | cut -d',' -f18)
echo "$2 $2 is $STATUS"
;;
maint)
check_args $2 $3
echo "set server $2/$3 state maint" | $COMMAND
sleep 1
STATUS=$(echo "show stat" | $COMMAND | grep "$2,$3" | cut -d',' -f18)
echo "$2 $2 is $STATUS"
;;
*)
echo "$*" | socat $SOCKET stdio
;;
esac
or using python lib for manage haproxy