18 mai 2022

Mise en œuvre de frontaux Web Nginx en haute disponibilité avec Keepalived

Dans cet article, nous allons mettre en place les premières VMs de notre infrastructure KVM, infra présentée ici : Tuto Virtualisation V 2022 : Debian 11, KVM et Openvswitch

Cet article prendra place également dans un futur « méga tuto » dédié à la mise en œuvre d’une Infra Web. Mais ce n’est pas pour tout de suite !

Présentement, nous allons simplement mettre en place un service Nginx en haute disponibilité.

 

I – Présentation

Rappel de la topologie que l’on va adopter :

 

Nous allons nous concentrer ici sur les VMs Frontweb1 et Frontweb2.

 

II – Mise en place des VMs

Je me sers de mon script fait maison (Tuto Virtualisation avec KVM, partie VIII : Scripts d’automatisation)

Au niveau de la configuration  :

# Options
size_swap=1
size_var=3
size=3
ram=512
cpu=2

A – Création des VMs

Tout simplement  :

# ./create.sh -n frontweb1 -i 11 -s 1
# ./create.sh -n frontweb2 -i 12 -s 0

Avant de les démarrer, un peu de configuration…

B – Ajout des interfaces réseaux

Nous allons attacher les interfaces supplémentaires, à savoir un port trunk vlansext (les vlans 10 et 20) sur chaque serveur.

Dans l’article Haute Disponibilité de routeurs sous Linux avec Keepalived, je présente comment ajouter une interface par CLI. Méthode qui présente un inconvénient car on ne peut pas spécifier le VLAN, ce qui nous oblige donc à éditer la configuration à posteriori pour l’ajouter.

Là, nous allons utiliser la méthode « injection de fichier XML », permettant du coup la définition du réseau au complet avec son VLAN en une étape.

Créez donc un fichier : networkfrontweb1.xml

<interface type='network'>
      <source network='intern-vlans' portgroup='vlansext'/>
      <target dev='frontweb1.1'/>
      <model type='virtio'/>
      <driver name='vhost'/>
</interface>

et un fichier : networkfrontweb2.xml

<interface type='network'>
      <source network='intern-vlans' portgroup='vlansext'/>
      <target dev='frontweb2.1'/>
      <model type='virtio'/>
      <driver name='vhost'/>
</interface>

Et on ajoute :

# virsh attach-device frontweb1 networkfrontweb1.xml --config
# virsh attach-device frontweb2 networkfrontweb2.xml --config

Pour mémoire, le flag –config indique qu’on rend la modification pérenne (maintient au reboot).

C – Configuration réseaux

On va éditer les fichiers d’interfaces avant de démarrer :

# mount /dev/mapper/vg1-frontweb1p1 /root/mountlvm/

On édite le fichier /root/mountlvm/etc/network/interfaces pour y ajouter les interfaces eth1.10 et eth1.20 :

auto lo
iface lo inet loopback

auto eth0.99
iface eth0.99 inet static
 address 10.99.1.11
 netmask 255.255.255.0

auto eth0.250
iface eth0.250 inet static
 address 10.250.1.11
 netmask 255.255.255.0

auto eth1.10
iface eth1.10 inet static
 address 10.10.1.11
 netmask 255.255.255.0
 gateway 10.10.1.254

auto eth1.20
iface eth1.20 inet static
 address 10.20.1.11
 netmask 255.255.255.0

On démonte :

# umount /root/mountlvm

 

La même chose pour le Frontweb2 :

# mount /dev/mapper/vg0-frontweb2p1 /root/mountlvm/

On édite le fichier /root/mountlvm/etc/network/interfaces :

auto lo
iface lo inet loopback

auto eth0.99
iface eth0.99 inet static
 address 10.99.1.12
 netmask 255.255.255.0

auto eth0.250
iface eth0.250 inet static
 address 10.250.1.12
 netmask 255.255.255.0

auto eth1.10
iface eth1.10 inet static
 address 10.10.1.12
 netmask 255.255.255.0
 gateway 10.10.1.254

auto eth1.20
iface eth1.20 inet static
 address 10.20.1.12
 netmask 255.255.255.0

On démonte :

# umount /root/mountlvm

 

Et on peut démarrer les VMS :

# virsh start frontweb1
# virsh start frontweb2

Puis se connecter dessus :

# ssh user@frontweb1
# ssh user@frontweb2

 

III – NGINX

Bon, pour le moment, on va faire au plus simple et juste installer NGINX.

Dans d’autres articles, nous verrons comme l’optimiser, lui adjoindre un WAF (Web Application Firewall), lui mettre un certificat et également comme synchroniser nos configurations….

Pour l’installer (sur les deux serveurs) :

frontwebX# apt install nginx-extras

Le package nginx-extras embarque des modules dont on aura besoin par la suite.

 

IV – Keepalived

Passons maintenant à la mise en haute disponibilité de notre service Front Web. Comme pour mes routeurs, j’utilise Keepalived, qui va mettre à disposition une IP flottante 10.10.1.10.

Sur les deux machines :

frontwebX# apt install keepalived

On va tout d’abord créer notre petit script de check : /srv/check_nginx.sh

#!/bin/bash

HOST=$(ip a show dev eth1.10 | grep -w "inet" | xargs | cut -d ' ' -f 2 | sed 's/.\{3\}$//')
curl=$(curl http://$HOST -o /dev/null -w '%{http_code}\n' -s)

if [ $curl != 200 ]
then
  exit 1
else
  exit 0
fi

On le rend exécutable :

frontwebX# chmod +x /srv/check_nginx.sh

Ensuite, on passe au fichier de configuration de Keepalived, sur le Frontweb1 :

vrrp_script check_nginx {
  script "/srv/check_nginx.sh"
  interval 2
}

vrrp_instance FRONTWEB {
  state MASTER
  preempt 1
  interface eth1.10
  virtual_router_id 10
  priority 200
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass password
  }
  unicast_src_ip 10.10.1.11
  unicast_peer {
    10.10.1.12
  }
  virtual_ipaddress {
    10.10.1.10
  }
  track_script {
    check_nginx
  }
}


et sur le 2 :

vrrp_script check_nginx {
  script "/srv/check_nginx.sh"
  interval 2
}

vrrp_instance FRONTWEB {
  state BACKUP
  interface eth1.10
  virtual_router_id 10
  priority 50
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass password
  }
  unicast_src_ip 10.10.1.12
  unicast_peer {
    10.10.1.11
  }
  virtual_ipaddress {
    10.10.1.10
  }
  track_script {
    check_nginx
  }
}

Puis, sur les deux VMs :

frontwebX# service keepalived stop
frontwebX# service keepalived start

Et on peut vérifier avec

frontwebX# tail -f /var/log/syslog

 

V – DNAT sur les routeurs

Pour terminer, on va mettre en place la règle de DNAT  sur nos routeurs pour que notre cluster NGINXreçoive bien les paquets pour les ports 80 (http) et 443 (https).

Sur nos deux routeurs (mis en place ici : Haute Disponibilité de routeurs sous Linux avec Keepalived), on va éditer le fichier /srv/firewallup.sh  pour y ajouter ce qui est en gras :

#!/usr/sbin/nft -f
flush ruleset
define external_ip = 66.66.66.66
define frontweb = 10.10.1.10
define if_v10 = "eth1"

table ip filter {
  chain input {
    type filter hook input priority 0; policy accept;
  }
  chain output {
    type filter hook output priority 0; policy accept;
  }
  chain forward {
    type filter hook forward priority 0; policy accept;
  }
}

table ip nat {
  chain prerout {
    type nat hook prerouting priority -100; policy accept;
    ip daddr $external_ip tcp dport { http, https } counter dnat to $frontweb
  }
  chain postrout {
    type nat hook postrouting priority 100; policy accept;
    iifname $if_v10 snat $external_ip
  }
}

 

La règle

ip daddr $external_ip tcp dport { http, https } counter dnat to $frontweb

stipule que les paquets qui ont en destination (daddr) notre IP externe et comme port de destination (dport) en tcp http et https sont comptés (counter) puis subissent un DNAT (Destination Network Address Translation) avec comme nouvelle destination l’IP de notre frontal web, 10.10.1.10, défini par la variable frontweb.

Rien de sorcier…

 

VI – Tests et conclusion

Et bien, il n’y a plus qu’a tester ! Déjà que notre NGINX réponde bien aux requêtes externes, puis ensuite, que la coupure de l’un entraine bien la bascule de l’IP virtuelle…

Et si tout est bon, on revient à la feuille de route et on poursuit !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *