Ziirish's Home :: Blog

Ziirish's Pub

 
 

Alors comme ça je t'ai manqué ami lecteur ? Ne t'en fais pas, je suis de retour (peut-être pas pour longtemps, je vais probablement passer mes prochains week-ends à faire les magasins pour rédiger ma lettre au père noël...).

Quoi qu'il en soit, je te présentais cette semaine une petite maquette fort sympathique à base de keepalived, nginx et haproxy. Éh bien figure toi que j'ai amélioré un peu cette maquette pour ton plus grand plaisir ;)

Concrètement, qu'ai-je fait ? J'ai ajouté du load-balancing DNS pour avoir une répartition de charge en amont de mes frontaux qui font ensuite du load-balancing sur les backends.

Alors, oui, comme ça avec des mots ça semble un peu tordu/compliqué. Sur un dessin ça devrait sembler plus clair... mais là j'ai un peu beaucoup la flemme de sortir mon joli dia.

Mais voici l'idée :

  • Je dispose de deux ip virtuelles que je vais enregistrer sous un même nom DNS
  • J'assigne une de ces ip virtuelle à chacun de mes load-balancer

En pratique, ça donne ça :


root@lb2:~# ip addr sh eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:3e:30:24:71 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.7/24 brd 172.25.0.255 scope global eth1
    inet 172.17.0.10/32 scope global eth1
    inet6 fe80::216:3eff:fe30:2471/64 scope link 
       valid_lft forever preferred_lft forever

root@lb1:~# ip addr sh eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:3e:20:4d:9b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.6/24 brd 172.25.0.255 scope global eth1
    inet 172.17.0.5/32 scope global eth1
    inet6 fe80::216:3eff:fe20:4d9b/64 scope link 
       valid_lft forever preferred_lft forever

ziirish@carbon:~$ dig lb.ziirish.info

; <<>> DiG 9.7.3 <<>> lb.ziirish.info
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30116
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;lb.ziirish.info.              IN      A

;; ANSWER SECTION:
lb.ziirish.info.       10800   IN      A       172.17.0.10
lb.ziirish.info.       10800   IN      A       172.17.0.5

;; AUTHORITY SECTION:
ziirish.info.           10800   IN      NS      yoda.ziirish.info.

;; ADDITIONAL SECTION:
yoda.ziirish.info.      10800   IN      A       10.0.0.30

;; Query time: 3 msec
;; SERVER: 10.0.0.3#53(10.0.0.3)
;; WHEN: Sat Nov 12 11:56:21 2011
;; MSG SIZE  rcvd: 101

Je ne reviendrais pas sur la configuration du DNS qui est relativement triviale... Je vous détaillerai juste les modifications apportées à keepalived et haproxy. En effet, pour utiliser ce mode de fonctionnement sans craindre de faire sauter les sessions (rendre le passage d'un lb à l'autre transparent pour le client final), il nous faut utiliser une petite fonctionnalité de haproxy qui n'est pas encore dans la branche stable : les pools. Nous couplerons cela aux stick-table qui étaient déjà présentes dans la version 1.4.

On commence donc par récupérer les dernières sources de haproxy à l'adresse suivante , puis nous le compilons :


% tar xvzf haproxy-1.5-dev7.tar.gz
% mv haproxy-1.5-dev7 /opt/
% cd /opt/haproxy-1.5-dev7
% make TARGET=linux26

J'avais installé la précédente version de haproxy via les paquets debian, j'ai donc à ma disposition le script init que je vais modifié comme ceci :


#HAPROXY=/usr/sbin/haproxy
HAPROXY=/opt/haproxy-1.5-dev7/haproxy

Notre nouveau haproxy est désormais utilisable.

Voici la nouvelle configuration :


global
        maxconn 30000
        ulimit-n 65536
        log     127.0.0.1 local0
        log     127.0.0.1 local1 debug


peers haproxy_pool
        peer ha1 10.0.0.6:1024
        peer ha2 10.0.0.7:1024


defaults
        balance leastconn
        retries 3
        option redispatch
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

 
listen stats 10.0.0.6:80 # remplacer par 10.0.0.7:80 sur le second lb
        mode http
        stats enable
        stats uri /stats
        stats realm HAProxy\ Statistics
        stats auth utilisateur:motdepasse 
 

backend http
        mode http
        balance roundrobin
        stick on src table https
        cookie SRV insert indirect nocache
        server s1 10.0.0.6:8080 cookie s1 check
        server s2 10.0.0.7:8080 cookie s2 check

backend https
        mode tcp
        balance roundrobin
        stick-table type ip size 200k expire 30m peers haproxy_pool
        stick on src
        server s1 10.0.0.6:4443 check
        server s2 10.0.0.7:4443 check


frontend public_http
        bind 172.17.0.5:80
        bind 172.17.0.10:80
        default_backend http

frontend public_https
        bind 172.17.0.5:443
        bind 172.17.0.10:443
        default_backend https

Enfin, il nous faut ajouter un nouveau paramètre au lancement de haproxy. On le renseignera dans le fichier /etc/default/haproxy :


EXTRAOPTS="-L ha1" # remplacer ha1 par ha2 sur le second lb

Nos deux instances de haproxy vont désormais communiquer entre-elles via le port 1024.

Il ne nous reste plus qu'à configurer keepalived.

Voici la conf sur le lb1 :


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 {
        interface eth1
        state MASTER
        virtual_router_id 51
        priority 101                    # 101 on master, 100 on backup
        virtual_ipaddress {
                172.17.0.15
        }
        track_script {
                chk_haproxy
        }
}

vrrp_instance VI_2 {
        interface eth1
        state BACKUP
        virtual_router_id 52
        priority 100                    # 101 on master, 100 on backup
        virtual_ipaddress {
                172.17.0.10
        }
        track_script {
                chk_haproxy
        }
}

Et celle sur le lb2 :


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 {
        interface eth1
        state BACKUP
        virtual_router_id 51
        priority 100                    # 101 on master, 100 on backup
        virtual_ipaddress {
                172.17.0.15
        }
        track_script {
                chk_haproxy
        }
}

vrrp_instance VI_2 {
        interface eth1
        state MASTER
        virtual_router_id 52
        priority 101                    # 101 on master, 100 on backup
        virtual_ipaddress {
                172.17.0.10
        }
        track_script {
                chk_haproxy
        }
}

Et voilà, enjoy !