Archivi tag: bilanciatore

Nginx e CentOS: creare un load balancer per i Websocket di nodejs

In questo post ho riportato il codice bash (di mia stesura) necessario per eseguire l’applicativo nodejs come demone (senza avvelersi quindi di tool esterni quali nohup o screen). In soldoni, esso non fa altro che tirare su (o stoppare/riavviare) 8 istanze di nodejs (ciascuna delle quali è in ascolto su una porta TCP dedicata, dalla 9001 alla 9008), il cui compito è quello di gestire le connessioni Websocket in ingresso (tramite la libreria socket.io ed il metodo HTTP Upgrade).

Nel caso in cui vi fosse la necessità di distribuire le istanze di nodejs su più macchine (per questioni di ridondanza e di suddivisione del carico), è indispensabile avvalersi di un bilanciatore in grado di gestire la suddetta tipologia di traffico (Websocket).

A tal proposito, se si vuole optare per una soluzione “software”, non si hanno tantissime alternative e le più gettonate sono sicuramente HAProxy e Nginx. Il primo è un bilanciatore a tutti gli effetti, mentre il secondo è un server Web (a detta di molti più performante e malleabile di Apache), che però può essere configurato a mo’ di load balancer.

La scelta è ricaduta proprio su Nginx perchè si è rivelato essere molto più stabile rispetto ad HAProxy (quest’ultimo crashava inesorabilmente se le richieste di connessione provenivano dal browser Safari).

Di seguito riporto la configurazione di Nignx, supponendo che vi siano 3 frontend da bilanciare, ciascuno dei quali dotato di 8 istanze nodejs:

upstream node_app {
    ip_hash;
    server node1.domain.com:9001;
    server node1.domain.com:9002;
    server node1.domain.com:9003;
    server node1.domain.com:9004;
    server node1.domain.com:9005;
    server node1.domain.com:9006;
    server node1.domain.com:9007;
    server node1.domain.com:9008;
    server node2.domain.com:9001;
    server node2.domain.com:9002;
    server node2.domain.com:9003;
    server node2.domain.com:9004;
    server node2.domain.com:9005;
    server node2.domain.com:9006;
    server node2.domain.com:9007;
    server node2.domain.com:9008;
    server node3.domain.com:9001;
    server node3.domain.com:9002;
    server node3.domain.com:9003;
    server node3.domain.com:9004;
    server node3.domain.com:9005;
    server node3.domain.com:9006;
    server node3.domain.com:9007;
    server node3.domain.com:9008;
}

server {
    server_name lblive.domain.com;
    listen 80;
    location / {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://node_app;
    }
}

La configurazione è abbastanza intuitiva: nella prima parte viene definito l’elenco dei frontend e la politica di bilanciamento (stickyip_hash), mentre nella seconda parte vengono definite le regole per la gestione del traffico (soprattutto per ciò che concerne gli header HTTP).

A configurazione completata avviamo Nginx:

[root@loadbalancer ~]# service nginx start

e facciamo in modo che venga eseguito automaticemente dopo ogni riavvio:

[root@loadbalancer ~]# chkconfig nginx on

E’ tutto. Alla prossima.

Sincronizzazione dei contenuti Web tramite rsync

Supponiamo che vi siano in produzione N frontend Web dietro bilanciatore e che quindi, ad ogni release, si renda necessario caricare i contenuti su ciascuno di essi (rendendo la vita difficile agli sviluppatori).

Ho deciso quindi di automatizzare tale procedura mediante l’uso di rsync. In soldoni, i contenuti Web verranno caricati manualmente su un unico frontend (che fungerà da server) mentre le altre macchine fungeranno da client (ovvero aggiorneranno i loro contenuti ogni X minuti consultando direttamente la macchina server).

rsyncConfigurazione della macchina server

Tale attività si articola in due fasi: la prima consiste nell’installazione e nella corretta configurazione del demone xinetd (evoluzione del celeberrimo inetd), mentre la seconda riguarda solo ed esclusivamente rsync.

Procediamo dunque con l’installazione di xinetd:

[root@front1 ~]# yum install xinetd

ed impostiamo l’avvio automatico del demone in questione per i diversi runlevel:

[root@front1 ~]# chkconfig --levels 2345 xinetd on

Posizioniamoci nella dir /etc/xinetd.d ed apriamo in scrittura il file rsync, sostituendo la direttiva:

disable = yes

con

disable = no

In definitiva, il suddetto file, dovrà avere il seguente contenuto:

service rsync
{
        disable = no
        flags           = IPv6
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/rsync
        server_args     = --daemon
        log_on_failure  += USERID
}

Passiamo ora al secondo step relativo alla configurazione della macchina server, ovvero la creazione del file rsyncd.conf nella directory /etc:

[root@front1 ~]# touch /etc/rsyncd.conf

All’interno del suddetto file creeremo dei moduli ad-hoc contenenti tutte le direttive necessarie per la sincronizzazione dei contenuti tra server e client, ad esempio:

log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
[images]
   path = /var/www/html/images
   uid = root
   gid = root
   read only = no
   list = yes
   host allow = 10.12.66.0/24

Salviamo il file ed avviamo xinetd:

[root@front1 ~]# service xinetd start

Configurazione delle macchine client

Tale configurazione consiste esclusivamente nella creazione di una entry crontab del tipo:

*      *   * * *     root          rsync -avr root@10.12.66.1::images /var/www/html/images/

ovvero ogni minuto viene contattato il server (10.12.66.1, modulo images che punta a /var/www/html/images/) e viene sincronizzato il contenuto della dir del client /var/www/html/images/.

Fine del post, alla prossima.

LVS e Nagios: script bash per controllare lo stato dell’interfaccia virtuale

Ho realizzato il seguente script bash (da integrare a Nagios) per verificare lo stato dell’interfaccia virtuale presente su ciascun frontend dietro bilanciatore LVS (configurato in direct routing).

nagios

#!/bin/bash

if [ -n "$1" ];then
        status=`/sbin/ifconfig | grep $1 2> /dev/null`

        if [ -n "$status" ]; then
                echo "OK"
                exit 0
        else
                echo "CRITICAL"
                exit 2
        fi

else
        echo "Usage: check_if_status <IP>"
fi

exit 0

Lo script è abbastanza semplice. Per prima cosa lancio il comando ifconfig facendo un grep sull’IP specificato nella configurazione di Nagios. Se tale comando genera un output diverso dalla stringa vuota significa che l’interfaccia virtuale è attiva e quindi esco (exit 0), altrimenti genero un errore di tipo critico (exit 2).

Alla fine dello script ho inserito anche la parte relativa allo usage.

Alla prossima.