Configurazione AWstat per webserver in load balancing

In questo articolo affrontiamo un problemino che si incontra utilizzando più web server dietro ad un load balancer: la generazione delle statistiche.

Ammettiamo una situazione in cui abbiamo quattro web server apache con indirizzo IP 192.168.20.101-102-103-104 dietro ad un load balancer con indirizzo IP pubblico che rigira ai 4 server le richieste HTTP provenienti dalla rete internet. I quattro server leggono il contenuto dei siti web (pagine html, php, immagini…) da un disco condiviso comune con una qualsiasi tecnica (NFS, GlusterFS, MooseFS, iSCSI/OCFS2, ecc.). In questo caso ciascun server genererà i propri log di accesso indipendentemente: come fare per far si che un programma che genera statistiche (in questo caso AWstats) faccia il suo compito a dovere?

Le soluzioni sono principalmente due: la più immediata è condividere la directory con i log di Apache tra i quattro server in modo che tutti scrivano su un unico file di log. Questo, però, può generare facilemente problemi in quanto la situazione più complessa da gestire per un disco condiviso sono le scritture multiple contemporanee su uno stesso file.

La seconda soluzione, quella che adotteremo in questo articolo, è di far salvare i log a ciascun server in una sua directory e creare una nuova macchina che periodicamente copierà i file di log da ciascun server, li aggregherà e genererà le statistiche con awstat per ciascun website.

Partiamo quindi da una nuova installazione linux su cui installeremo AWstats. Su Debian/Ubuntu:

apt-get install awstats

Ora montiamo la directory condivisa con i siti web come fosse un comune web server: questo ci servirà per far si che awstats scriva le pagine con le statistiche all’interno della directory “web/stats” di ciascun virtualhost. Nella mia configurazione (ISPConfig) all’interno della directory /var/www c’è una directory per ogni sito web al cui interno c’è, appunto, una sottodirectory web con le pagine del sito e, ad un livello ancora inferiore, la sottodirectory stats che conterrà le statistiche.
Nel mio caso si tratta di un filesystem di rete NFS (/mnt/www sul server 192.168.20.253), per cui mi è sufficiente aggiungere la seguente riga nel file hosts del server AWstats:

<strong>/etc/fstab</strong>
192.168.20.253:/mnt/www                /var/www                nfs   rsize=32768,wsize=32768,intr,noatime,_netdev  0 0

Quindi lancio i seguenti comandi per montare il filesystem:

mkdir /var/www
apt-get install nfs-kernel-server nfs-client
mount /var/www

Ora creo una directory per ciascun server in cui salvare i log:

mkdir -p /var/log/httpd-1
mkdir -p /var/log/httpd-2
mkdir -p /var/log/httpd-3
mkdir -p /var/log/httpd-4

A questo punto possibile creare uno script che tramite scp copi i file in locale periodicamente, però l’utilizzo della rete sarebbe molto significativo per cui preferisco usare NFS ed esportare le 4 nuove directory verso i webserver. Per lo stesso motivo evito di esportare la directory con i log dei 4 webserver con NFS: meglio che awstats lavori con i file in locale.
Quindi modifico il file /etc/exports per esportare le quattro directory:

<strong>/etc/exports</strong>
/var/log/httpd-1        192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-2      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-3      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-4      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)

e lancio il comando per avviare l’esportazione:

exportfs -a

Ora, su ciascun server web, monto la directory esportata dal server AWstats. Modifico il file /etc/fstab:

<strong>/etc/fstab</strong>
192.168.20.44:/var/log/httpd-1                /var/log/httpd                nfs   rsize=32768,wsize=32768,intr,noatime,_netdev  0 0

In questo caso sono sul server “1” e quindi monto la directory /var/log/httpd-1; bisogna agire di conseguenza sugli altri server.

mount /var/log/httpd

Ora, sui nostri quattro web server andiamo a modificare la configurazione di apache.
Innanzi tutto creaiamo un alias per la directory awstats-icon aggiungendo le seguenti righe:

<strong>/etc/httpd/httpd.conf</strong>
Alias /awstats-icon/ "/usr/share/awstats/awstats-icon/"

    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all

E copiamo su ciascun webserver la directory con le icone di awstats in /usr/share/awstats/awstats-icon.
Inoltre dobbiamo modificare la configurazione dei Virtualhost in modo che i log vengano salvati in una diversa directory per ciascun sito. Questa configurazione rispecchia il comportamento di default di ISPConfig.

Ora veniamo allo script che farà il lavoro vero e proprio. I commenti sono autoesplicativi, in qualsiasi caso lo script prende in esame tutte le directory presenti in /var/www assumendo che ciascuna di queste contenga un virtualhost.
La riga di configurazione più importante è echo "LogFile=\"${mergepath} ${logdir}/${dominio}/${filelog} |\"" > $configfile: in questa riga si indica dove sono i file di log relativi al virtualhost. Si usa lo script di awstats “logresolvemerge.pl” per fare il merge di tutti i file di log relativi al giorno precedente: tale script viene lanciato “al volo” e genera il file che sarà utilizzato da awstats in ram.

<strong>/usr/local/bin/crea-statistiche.sh</strong>
#!/bin/bash

# Variabili da configurare
# ---------------------------
# Directory con i siti web
webdir="/var/www"
# Sottodirectory per l'output dei file di report
reportdir="web/stats"
# Directory con i log
logdir="/var/log/httpd-*"
# Directory con le configurazioni di awstats
awstatsdir="/etc/awstats"
# Path allo script per realizzare il merge dei log
mergepath="/usr/share/doc/awstats/examples/logresolvemerge.pl"
# ---------------------------
# Elaboro il nome del file sul quale generare i log
data=`date +%Y%m%d`
filelog="$(($data - 1))-access.log.gz"

# Eseguo il ciclo per tutte le directory in "webdir"
j="${webdir}/*"
for directory in $j
do
    # Nel caso in cui si tratti effettivamente di una directory
    if [ -d ${direcroty} ]
    then
    # Estraggo il nome dominio dalla path
    dominio=${directory##*/}

    # Genero i file di configurazioni di AWStats
    configfile="${awstatsdir}/awstats.${dominio}.conf"
    echo "LogFile=\"${mergepath} ${logdir}/${dominio}/${filelog} |\"" > $configfile
    echo "SiteDomain=${dominio}" >> $configfile
    echo "LogFormat=1" >> $configfile
    echo "DirIcons=\"/awstats-icon\"" >> $configfile
    fi

    # Eseguo AWStats
    /usr/lib/cgi-bin/awstats.pl -config=$dominio -update
    /usr/lib/cgi-bin/awstats.pl -config=$dominio -output -staticlinks > ${webdir}/${dominio}/${reportdir}/awstats.html
done