HA con Keepalived + HAProxy + Apache

    La combinación de Keepalived + HAProxy nos permite tener un entorno con alta disponibilidad (HA) para diferentes servicios al balancear su carga. En este caso, lo usaremos para un servidor web basado en Apache.

    Para ello, podemos instalar y configurar 2 Raspberry Pi por igual, con diferente IP:

  • RP01 – 10.0.1.71
  • RP02 – 10.0.1.72
  • También necesitaremos una IP virtual (10.0.1.70) que irá balanceando entre los nodos en función de su disponibilidad

    Mi recomendación es usar siempre 3 nodos como mínimo, pero en un entorno LAB, con 2 es suficiente. Usar 3.

    Lo primero, será instalar el producto y librarías necesarias en ambos equipos:

    apt-get install haproxy slirp4netns keepalived ipset libipset-dev -y
    apt install apache2 software-properties-common ca-certificates apt-transport-https gpg lsb-release openssl
    apt-get install apache2 php7.3 php7.3-mysql php7.3-curl php7.3-gd php7.3-imap php7.3-recode php7.3-tidy php7.3-xmlrpc -y
    

    En RPI01 ejecutaremos:

    cat <<'EOF' > /etc/keepalived/keepalived.conf
    global_defs {
        lvs_id LB01                    # UNIQUE ID
        router_id LB01                 # UNIQUE ID
        enable_script_security
        script_user root 
    }
    
    vrrp_sync_group SyncGroup01 {
        group {
            VI_1
        }
    }
    
    vrrp_script chkhaproxy {
        script "/usr/bin/killall -0 haproxy"
        script "/usr/sbin/service haproxy start"
        interval 9
        timeout 3
        weight 20
        rise 2
        fall 3
    }
    
    vrrp_script chkmysql {
        script "pidof mysqld"
        interval 2 # every 2 seconds
        weight 2
    }
    
    vrrp_instance VI_1 {
        interface wlan0
        state MASTER
        virtual_router_id 1
        priority 101                    # MAX PRIORITY
        advert_int 5
        #debug 2
    
        virtual_ipaddress {
            10.0.1.70
        }
    
        unicast_src_ip 10.0.1.71         # MASTER_IP_VALUE
        unicast_peer {    
            10.0.1.72                    # BACKUP_IP_VALUE
        }
    
        track_script {
            chkhaproxy
            chkmysql
        }
        notify "/scripts/keepalived.sh INFO"
        notify_master "/scripts/keepalived.sh MASTER"
        notify_backup "/scripts/keepalived.sh BACKUP" 
        notify_fault "/scripts/keepalived.sh FAULT" 
    }
    EOF
    
    service haproxy restart
    service keepalived restart
    

    En RPI02 ejecutaremos:

    cat <<'EOF' > /etc/keepalived/keepalived.conf
    global_defs {
        lvs_id LB02                       # UNIQUE ID
        router_id LB02                    # UNIQUE ID
        enable_script_security
        script_user root 
    }
    
    vrrp_sync_group SyncGroup01 {
        group {
            VI_1
        }
    }
    
    vrrp_script chkhaproxy {
        script "/usr/bin/killall -0 haproxy"
        script "/usr/sbin/service haproxy start"
        interval 9
        timeout 3
        weight 20
        rise 2
        fall 3
    }
    
    vrrp_script chkmysql {
        script "pidof mysqld"
        interval 2 # every 2 seconds
        weight 2
    }
    
    vrrp_instance VI_1 {
        interface wlan0
        state BACKUP
        virtual_router_id 1
        priority 100             # MIN PRIORITY
        advert_int 5
        #debug 2
    
        virtual_ipaddress {
            10.0.1.70
        }
    
        unicast_src_ip 10.0.1.73         # MASTER_IP_VALUE
        unicast_peer {    
            10.0.1.72                    # BACKUP_IP_VALUE
        }
    
        track_script {
            chkhaproxy
            chkmysql
        }
    
        notify "/scripts/keepalived.sh INFO"
        notify_master "/scripts/keepalived.sh MASTER"
        notify_backup "/scripts/keepalived.sh BACKUP" 
        notify_fault "/scripts/keepalived.sh FAULT" 
    }
    EOF
    
    service haproxy restart
    service keepalived restart
    

    En ambos equipos, ejecutaremos:

    groupadd -r keepalived_script
    useradd -r -s /sbin/nologin -g keepalived_script -M keepalived_script
    
    mkdir -p touch /scripts
    
    cat <<'EOF' > /scripts/keepalived.sh
    #!/bin/bash
    echo "$(hostname -s) change STATE: $1"
    EOF
    
    chmod +x /scripts/keepalived.sh
    chown root.root /scripts/keepalived.sh
    
    service haproxy restart
    service keepalived restart
    
    ip a show wlan0
    ip neighbour show
    
    haproxy -c -f /etc/haproxy/haproxy.cfg
    

    Hasta aquí ya tenemos el servicio funcionando.

    Para visualizar estado y estadísticas podemos ejecutar lo siguiente, también en ambos nodos:

    cat <<'EOF' >> /etc/haproxy/haproxy.cfg
    
    listen stats
        bind :8080
        mode http
        stats enable
        stats hide-version
        stats refresh 30s
        stats realm Haproxy\ Statistics
        stats show-node
        stats auth admin:123456
        stats uri  /haproxy?stats
    EOF
    
    service haproxy restart
    
    echo "" > /var/www/html/node.php
    

    Ahora, configuraremos la alta disponibilidad para Apache:

    En RPI01 ejecutaremos:

    cat <<'EOF' >> /etc/haproxy/haproxy.cfg
    
    frontend apache
       bind 10.0.1.71:81
       mode tcp
       option tcplog
       option  dontlognull
       default_backend apache2
    
    backend apache2
       balance roundrobin
       mode tcp
       option tcpka
       server RP01 10.0.1.71:80 check weight 1
       server RP02 10.0.1.72:80 check weight 1
    EOF
    
    service haproxy restart
    

    En RPI02 ejecutaremos:

    cat <<'EOF' >> /etc/haproxy/haproxy.cfg
    
    frontend apache
       bind 10.0.1.72:81
       mode tcp
       option tcplog
       option  dontlognull
       default_backend databases
    
    backend apache2
       balance roundrobin
       mode tcp
       option tcpka
       server RP01 10.0.1.71:80 check weight 1
       server RP02 10.0.1.72:80 check weight 1
    EOF
    
    service haproxy restart
    

    Para validar, tendremos 2 accesos. El primero, de forma nativa. El segundo uno creado de forma manual:

    http://10.0.1.71:8080/haproxy?stats
    http://10.0.1.72:8080/haproxy?stats
    
    http://10.0.1.71/node.php
    http://10.0.1.72/node.php
    

    y por la IP virtual, podremos saber en que nodo está en un momento determinado:

    http://10.0.1.70:8080/haproxy?stats
    
    http://10.0.1.70/node.php
    

    Leave a Reply

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