In questa guida vedremo come configurare un load balancer utilizzando Pound su Ubuntu Server 20.04.1.
Pound è un software opensource sviluppato principalmente come reverse proxy e application firewall, utilizzato spesso per realizzare load balancer. Tra le caratteristiche salienti ci sono la capacità di rilevare lo stato di un server di backend, la possibilità di tradurre richieste in HTTPS su HTTP e un forte accento sulla sicurezza. Quando un server di backend non è raggiungibile Pound è in grado di rilevarlo, scegliendo tra gli altri server accessibili secondo criteri predefiniti a distribuzione casuale. Il tutto avviene tenendo traccia delle sessioni attive, che tipicamente permangono verso il medesimo server di backend di partenza.
La struttura che andremo a realizzare assomiglierà alla seguente:
Detto questo installiamo Ubuntu Server su tutte e tre le macchine e configuriamo opportunamente gli indirizzi di rete.
1. Configurazione rete
Questa operazione dovrà essere ripetuta in modo uguale su tutte le macchine. Procediamo con la prima. Prima di andare avanti vediamo la configurazione che vogliamo avere.
Creeremo una rete 192.168.0.0/24
nella quale le tre macchine saranno configurate nella maniera seguente:
1 2 3 |
load-balancer-server 192.168.0.5 webserver-1 192.168.0.6 webserver-2 192.168.0.7 |
Per visualizzare la configurazione di rete corrente (comincio dalla prima macchina) digitiamo
1 |
ip a |
Comparirà qualcosa di simile:
Nel mio caso sto utilizzando una macchina virtuale con VirtualBox e la scheda di rete è enp0s3. Tipicamente al suo posto si trova eth1. L’indirizzo configurato dal DHCP è il 192.168.0.4.
La configurazione di rete si trova in /etc/netplan
Per vedere tutti i file di configurazione presenti digitiamo:
1 |
ls /etc/netplan |
dovremmo vedere un file tipo 00-installer-config.yaml
Creiamone un backup del file digitando:
1 |
sudo cp /etc/netplan/00-installer-config.yaml /etc/netplan/00-installer-config.yaml.bck |
Adesso andiamo a modificare il file, bisogna fare attenzione all’identazione, che prevede 2 spazi vuoti per ciascuna sottosezione. Digitiamo:
1 |
sudo nano /etc/netplan/00-installer-config.yaml |
Il file originale dovrebbe contenere qualcosa di simile:
1 2 3 4 5 6 |
# This is the network config written by 'subiquity' network: ethernets: enp0s3: dhcp4: true version: 2 |
Modifichiamolo nella maniera seguente:
1 2 3 4 5 6 7 8 9 10 |
# This is the network config written by 'subiquity' network: ethernets: enp0s3: dhcp4: no addresses: [192.168.0.5/24] gateway4: 192.168.0.1 nameservers: addresses: [8.8.8.8, 8.8.4.4] version: 2 |
Il mio gateway è il 192.168.0.1, per scoprirlo tramite DHCP possiamo digitare ip r
Una volta modificata la configurazione salviamo il file e testiamola digitando:
1 |
sudo netplan try |
Se va tutto bene possiamo applicare la modifica, digitando:
1 |
sudo netplan apply |
Verifichiamo infine la configurazione con:
1 |
ip a |
Se tutto è andato bene vedremo qualcosa del genere:
Se dovessimo cambiare il nome della macchina possiamo digitare:
1 |
sudo hostnamectl set-hostname webserver-1 |
Per assegnare alla macchina il nome webserver-1. Una volta modificato il nome sarà sufficiente riavviare.
2. Installazione di Pound
Adesso procediamo ad installare Pound su load-balancer-server. Per farlo digitiamo:
1 |
sudo apt-get install pound |
Per configurare Pound procediamo a modificare il file /etc/pound/pound.cfg
. Digitiamo quindi:
1 |
sudo nano /etc/pound/pound.cfg |
Troveremo di default una struttura simile alla seguente nel file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
ListenHTTP Address 127.0.0.1 Port 8080 ## allow PUT and DELETE also (by default only GET, POST and HEAD)?: xHTTP 1 Service BackEnd Address 127.0.0.1 Port 80 End End End |
Questo significa che Pound è in ascolto sulla porta 8080 e utilizza come servizio un server di backend sempre all’indirizzo locale (qui si suppone si sia installato apache sul medesimo server). Adesso i servizi possono essere definiti in modo globale oppure relativamente ad uno specifico listener. In questo caso sono definiti all’interno di un listener. Ogni servizio ha dentro i server di backend ai quali può essere data una priorità. La priorità di predefinito è impostata su 5, i valori possibili sono da 1 a 9.
Riorganizziamo il nostro file di configurazione per ottenere il seguente risultato:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
## Minimal sample pound.cfg ## ## see pound(8) for details ###################################################################### ## global options: User "www-data" Group "www-data" #RootJail "/chroot/pound" ## Logging: (goes to syslog by default) ## 0 no logging ## 1 normal ## 2 extended ## 3 Apache-style (common log format) LogLevel 3 # <-- impostiamo il log level a 3 ## check backend every X secs: Alive 30 ## use hardware-accelleration card supported by openssl(1): #SSLEngine "<hw>" # poundctl control socket Control "/var/run/pound/poundctl.socket" ###################################################################### ## listen, redirect and ... to: ## redirect all requests on port 8080 ("ListenHTTP") to the local webserver (see "Service" below): ListenHTTP Address 127.0.0.1 Port 80 # <-- cambiamo la porta da 8080 su 80 ## allow PUT and DELETE also (by default only GET, POST and HEAD)?: #xHTTP 1 # <-- commentiamo questa riga End # configuriamo anche l'ascolto sul HTTPs, lasciamo commentato se non abbiamo il certificato #ListenHTTPS # Address 127.0.0.1 # Port 443 # Cert "/etc/ssl/pound.pem" #End Service BackEnd Address 192.168.0.6 Port 80 End BackEnd Address 192.168.0.7 Port 80 Priority 5 End End |
Se volessimo configurare dei servizi di emergenza, anziché usare il TAG BackEnd
potremmo utilizzare Emergency
. Tutto il resto rimarrebbe identico. Un server di emergenza interverrebbe solo qualora tutti gli altri backend fallissero.
Salviamo il file e modifichiamo il meccanismo di startup digitando:
1 |
sudo nano /etc/default/pound |
Modifichiamo il file nella maniera seguente:
1 2 3 4 5 6 7 |
# Defaults for pound initscript # sourced by /etc/init.d/pound # installed at /etc/default/pound by the maintainer scripts # prevent startup with default configuration # set the below varible to 1 in order to allow pound to start startup=1 |
A questo punto riavviamo Pound. Digitiamo:
1 |
sudo service pound restart |
3. Installazione di Apache sui backend
Sui server di backend sarà sufficiente installare Apache, senza ulteriori configurazioni. Ricordiamoci che Pound, anche se interrogato in HTTPS si connetterà ai server di backend in HTTP.
Per farlo digitiamo semplicemente:
1 |
sudo apt-get install apache2 |
Una volta installato Apache modifichiamo l’output predefinito del webserver. Per farlo cancelliamo il file originale e creiamone uno nuovo.
1 2 |
sudo rm /var/www/html/index.html sudo nano /var/www/html/index.html |
In questo caso ci scriverò dentro il nome del WebServer, per esempio:
1 |
Ciao dal WebServer1 |
Configuriamo ora il backend affinché effettui il log per le richieste X-Forwarded-For.
Anzitutto abilitiamo l’estensione remoteip
di apache.
1 |
sudo a2enmod remoteip |
Modifichiamo il file di configurazione digitando:
1 |
sudo nano /etc/apache2/apache2.conf |
Modifichiamo il seguente paragrafo del file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# # The following directives define some format nicknames for use with # a CustomLog directive. # # These deviate from the Common Log Format definitions in that they use %O # (the actual bytes sent including headers) instead of %b (the size of the # requested file), because the latter makes it impossible to detect partial # requests. # # Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. # Use mod_remoteip instead. # RemoteIPHeader X-Forwarded-For RemoteIPInternalProxy 192.168.0.5 LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %O" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent |
Faccio notare che l’IP 192.168.0.5 è quello della macchina col Pound.
Riavviamo Apache:
1 |
sudo service apache2 restart |
Ripetiamo questa procedura su ogni backend.
4. Prova di funzionamento
A questo punto colleghiamoci al nostro server con Pound, nel mio caso si trova all’indirizzo http://192.168.56.1/
Aggiornando più volte la pagina vedremo comparire, in modo casuale, la risposta del webserver-1 oppure del webserver-2
Oppure: