Menu

Infrastructure entièrement redondée

29 janvier 2017 - Stockage, Virtualisation
Infrastructure entièrement redondée

 


I.   Présentation

Avoir des serveurs disponible le plus souvent possible est très important pour les clients. Ici nous allons monter une petite infrastructure ayant une très haute disponibilité et tolérance de panne.

On va prendre l’exemple de clients qui se connectent à un site internet. Ici nous allons utiliser un Worpdress. Ce qui signifie que nous avons besoin d’une base de donnée en plus de serveurs web ainsi que du stockage pour le contenu du WordPress. Voici schématiquement ce que nous allons mettre en place.

 

Fonctionnement d'une haute disponibilité  L'adressage IP

 

 

Nous allons découper ce projet en plusieurs étapes. On commencera par la base c’est à dire les bases SQL puis nous remonteront pour ajouter petit à petit une nouvelle brique.

 

Toutes les machines sont basé sur Debian 8 jessie.

Voici le listing des machines avec leurs noms (hostname) et leurs IPs:

 

 

 

 

 

Comme vous pouvez le constater notre infrastructure est basé sur 2 sous réseaux. De ce fait les clients qui sont en 192.168.1.x  n’ont pas d’accès direct au serveurs qui sont en 172.20.0.x de plus le stockage partagé pour les serveurs web sont dans un autre sous réseau, ce qui offre une autre protection et surtout permet de ne pas polluer le réseau utilisé par les serveurs par les réplications.

 


II.   Base SQL

 

Nous utiliseront 3 machines SQL et nous allons en faire un cluster, c’est à dire que nos 3 SQL seront vu comme un seul et unique. Une synchronisation sera effective entre les 3 machines.

 

a. MariaDB

 

Tout d’abord sur nos 3 serveurs nous allons installer:

 

On ajout le dépôt mariadb:

[SQL1, SQL2, SQL3]

apt-get install software-properties-common
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://fr.mirror.babylon.network/mariadb/repo/10.1/debian jessie main'

 

Puis on installe nos 3 paquets:

apt-get update
apt-get install rsync galera-3 mariadb-server-10.1

 

On sécurise notre installation sql:

mysql_secure_installation
Entrez votre mot de passe root Change root password? comme vous voulez
Remove anonymous users? Y
Disallow root login remotely N
Remove test database and access to it? Y
Reload privilege tables now? Y

 

b. GaleraDB

 

On configure GaleraDB, on va créer le fichier suivant et y mettre cela:

[SQL1]

nano /etc/mysql/conf.d/galera.cnf

[mysqld]
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0

# Configuration de Galera par le fournisseur
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so

# Configuration du cluster Galera
wsrep_cluster_name="sql_cluster"
wsrep_cluster_address="gcomm://172.20.0.1,172.20.0.2,172.20.0.3"

# Configuration de la synchronisation Galera
wsrep_sst_method=rsync
# Configuration des noueds de Galera
wsrep_node_address="172.20.0.1"
wsrep_node_name="sql1"

 

On crée ce fichier sur les autres serveurs SQL en n’oubliant pas de changer wsrep_node_address par l’IP su serveur sur lequel on se trouve ainsi que le wsrep_node_name

[SQL2, SQL3]

# Configuration des noueds de Galera
wsrep_node_address="172.20.0.1"
wsrep_node_name="sql1"

 

Une fois cela fait, nous pouvons démarrer le cluster, on commence par arreter le service sql sur les 3 serveurs

[SQL1, SQL2, SQL3]

service mysql stop

 

puis sur le serveur SQL1 seulement:

[SQL1]

service mysql start --wsrep-new-cluster
[ ok ] Starting MariaDB database server: mysqld . . ..
[info] Checking for corrupt, not cleanly closed and upgrade needing tables..

 

On vérifie le nombre de nœud dans le cluster:

mysql -u root -p -e 'SELECT VARIABLE_VALUE as "cluster size" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME="wsrep_cluster_size"'

+————–+
| cluster size |
+————–+
| 1 |
+————–+

 

Sur les serveur 2 et 3 on démarre mariadb:

[SQL2, SQL3]

service mysql start
[ ok ] Starting MariaDB database server: mysqld . . . . . ..
[info] Checking for corrupt, not cleanly closed and upgrade needing tables..
root@SQL3:~# ERROR 1045 (28000): Access denied for user 'debian-sys-maint'@'localhost' (using password: YES)

ERREUR normale sur debian

 

Sur le serveur 1 on vérifie de nouveau le nombre de nœud dans le cluster:

[SQL1]

mysql -u root -p -e 'SELECT VARIABLE_VALUE as "cluster size" FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME="wsrep_cluster_size"'

+————–+
| cluster size |
+————–+
| 3 |
+————–+

 

Correction de l’erreur précédente, ouvrez le fichier suivant:

[SQL1]

nano /etc/mysql/debian.cnf

# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host = localhost
user = debian-sys-maint
password = jmzDsSHOLgTCUIpB
socket = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host = localhost
user = debian-sys-maint
password = jmzDsSHOLgTCUIpB
socket = /var/run/mysqld/mysqld.sock
basedir = /usr

 

Copier les deux lignes suivantes sur les serveurs 2 et 3:

[SQL2, SQL3]

password = jmzDsSHOLgTCUIpB
password = jmzDsSHOLgTCUIpB

 

 

c. Test de réplication

 

Afficher les bases données présente sur les 3 serveurs

[SQL1, SQL2, SQL3]

mysql -p -e "show databases"

+——————–+
| Database |
+——————–+
| information_schema |
| mysql |
| performance_schema |
+——————–+

 

Sur le serveur 2 créons une base de donnée:

[SQL2]

mysql -p -e "create database replication"

 

Sur le serveur 3 affichons les bases:

[SQL1, SQL2, SQL3]

mysql -p -e "show databases"

+——————–+
| Database |
+——————–+
| information_schema |
| mysql |
| performance_schema |
| replication |
+——————–+

 

Sur le serveur 1 supprimons la base que nous venons de créer:

[SQL1]

mysql -p -e "drop database replication"

 

Sur le serveur 2 affichons de nouveau les bases:

[SQL2]

mysql -p -e "show databases"

+——————–+
| Database |
+——————–+
| information_schema |
| mysql |
| performance_schema |
+——————–+

 

Nous voila de retour à l’état initiale.

Petit résumé:

Synchronisation OK

 

 

 


III.   HAPROXY

Nous allons maintenant créer notre load balancer qui sera le point d’entrée unique pour les bases sql.

 

a. haproxy

 

Commençons par installer haproxy en ajoutant les sources

[HA1 , HA2]

nano /etc/apt/sources.list
deb http://ftp.debian.org/debian/ jessie-backports main
apt-get update
apt-get install haproxy

 

Modifions le fichier de configuration pour indiquer l’IP virtuelle et quels sont les serveurs vers lesquels ont renverra les requêtes sql:

nano /etc/haproxy/haproxy.cfg

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon

# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private

# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RS$
ssl-default-bind-options no-sslv3

defaults
log global
mode http
# option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

# Configuration de l'ip virtuelle
listen cluster_db
bind 172.20.0.4:3306

# Mariadb
mode tcp

# Mode de balancement Round Robin
balance roundrobin

# Les serveurs mariadb
server SQL1 172.20.0.1:3306 check
server SQL2 172.20.0.2:3306 check
server SQL3 172.20.0.3:3306 check

 

 

b. heartbeat

 

Maintenant installons heartbeat qui permettra de check à interval régulier sir les serveurs sont en fonctionnement ou non.

[HA1 , HA2]

apt-get install heartbeat

 

Passons à sa configuration, il y aura 3 fichiers à modifier:

 

[HA1 , HA2]

nano /etc/ha.d/ha.cf

keepalive 2
deadtime 10
udpport 694
bcast eth0
mcast eth0 225.0.0.1 694 1 0
ucast eth0 172.20.0.6
udp eth0
logfacility local0
node HA1
node HA2

 

[HA1]

nano /etc/ha.d/haresources

HA1 172.20.0.4

 

[HA2]

nano /etc/ha.d/haresources

HA2 172.20.0.5

 

[HA1 , HA2]

nano /etc/ha.d/authkeys

auth 3
3 md5 P@$$w0rd

### permissions

chmod 600 /etc/ha.d/authkeys

 

[HA1 , HA2]

On désactive le démarrage automatique de haproxy

insserv -r haproxy

 

On ajoute dans le fichier hosts nos deux serveurs

[HA1 , HA2]

nano /etc/hosts

172.20.0.5 HA1
172.20.0.6 HA2

 

Enfin on démarre nos services

[HA1 , HA2]

/etc/init.d/heartbeat start
/etc/init.d/haproxy start

 

c. test

 

Il suffit de faire un ifconfig pour vérifier que nous avons bien notre IP virtuelle accrochée sur l’un des serveurs

[HA1 , HA2]

ifconfig

 

[HA1]

ha 1
eth0:0 Link encap:Ethernet HWaddr 3e:13:6a:aa:19:01
inet addr:172.20.0.4 Bcast:172.20.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

 

Maintenant on arrête le service heartbeat sur HA1 pour simuler la panne:

[HA1]

/etc/init.d/heartbeat stop

 

On vérifie que l’IP virtuelle est maintenant accrochée sur HA2:

[HA2]

ifconfig

eth0:0 Link encap:Ethernet HWaddr 8a:25:38:f1:65:fc
inet addr:172.20.0.4 Bcast:172.20.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

 

 


IV.   GlusterFS Stockage

 

Maintenant nous allons créer notre espace de stockage partagé. Pour cela on allons créer deux serveurs avec un raid5 sur chaque.

 

a. raid5

 

Sur nos deux VMs nous ajoutons 3 disques de 10 Go. On vérifie qu’ils sont bien reconnu par le système:

[GLUSTER1, GLUSTER2]

fdisk -l | grep "10 GiB"

Disque /dev/sdb : 10 GiB, 10737418240 octects, 20971520 secteurs
Disque /dev/sdc : 10 GiB, 10737418240 octects, 20971520 secteurs
Disque /dev/sds : 10 GiB, 10737418240 octects, 20971520 secteurs

 

On va partitionner les disques:

[GLUSTER1, GLUSTER2]

fdisk /dev/sdb

Bienvenue dans fdisk (util-linux 2.25.2).
Les modifications resteront en mémoire jusqu'à écriture.
Soyez prudent avant d'utiliser la commande d'écriture.

Le périphérique ne contient pas de table de partitions reconnue.
Created a new DOS disklabel with disk identifier 0xb6d67229.

Commande (m pour l'aide) : m

Aide :

DOS (secteur d'amorçage)
a modifier un indicateur d'amorçage
b éditer l'étiquette BSD imbriquée du disque
c basculer l'indicateur de compatibilité DOS

Générique
d supprimer la partition
l afficher les types de partitions connues
n ajouter une nouvelle partition
p afficher la table de partitions
t modifier le type d'une partition
v vérifier la table de partitions

Autre
m afficher ce menu
u modifier les unités d'affichage et de saisie
x fonctions avancées (réservées aux spécialistes)

Sauvegarder et quitter
w écrire la table sur le disque et quitter
q quitter sans enregistrer les modifications

Créer une nouvelle étiquette
g créer une nouvelle table vide de partitions GPT
G créer une nouvelle table vide de partitions SGI (IRIX)
o créer une nouvelle table vide de partitions DOS
s créer une nouvelle table vide de partitions Sun
Commande (m pour l'aide) : n
Type de partition
p primaire (0 primaire, 0 étendue, 4 libre)
e étendue (conteneur pour partitions logiques)
Sélectionnez (p par défaut) : p
Numéro de partition (1-4, 1 par défaut) : 1
Premier secteur (2048-20971519, 2048 par défaut) :
Dernier secteur, +secteurs ou +taille{K,M,G,T,P} (2048-20971519, 20971519 par défaut) :

Une nouvelle partition 1 de type « Linux » et de taille 10 GiB a été créée.

Commande (m pour l'aide) : w
La table de partitions a été altérée.
Appel d'ioctl() pour relire la table de partitions.
Synchronisation des disques.

 

On vérifie que les partions sont bien présentes:

[GLUSTER1, GLUSTER2]

fdisk -l | grep 10G

/dev/sdb1 2048 20971519 20969472 10G 83 Linux
/dev/sdc1 2048 20971519 20969472 10G 83 Linux
/dev/sdd1 2048 20971519 20969472 10G 83 Linux

 

 

Nous pouvons installer le paquet nous permettant de réaliser le raid:

[GLUSTER1, GLUSTER2]

apt-get install mdadm

 

Puis nous le créons:

 

[GLUSTER1, GLUSTER2]

mdadm --create /dev/md0 --level=5 --assume-clean --raid-devices=3 /dev/sdb /dev/sdc /dev/sdd

mdadm: /dev/sdb appears to be part of a raid array:
level=raid0 devices=0 ctime=Thu Jan 1 01:00:00 1970
mdadm: partition table exists on /dev/sdb but will be lost or
meaningless after creating array
mdadm: /dev/sdc appears to be part of a raid array:
level=raid0 devices=0 ctime=Thu Jan 1 01:00:00 1970
mdadm: partition table exists on /dev/sdc but will be lost or
meaningless after creating array
mdadm: /dev/sdd appears to be part of a raid array:
level=raid0 devices=0 ctime=Thu Jan 1 01:00:00 1970
mdadm: partition table exists on /dev/sdd but will be lost or
meaningless after creating array
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

 

On configure le montage du raid en mode daemon (service sous windows):

[GLUSTER1, GLUSTER2]

mdadm --monitor --daemonise /dev/md0
mdadm: Monitor using email address "root" from config file
4676

 

On formate le raid:

[GLUSTER1, GLUSTER2]

mkfs.ext4 /dev/md0

 

On modifie le fichier pour que le raid soit monté au démarrage du système:

[GLUSTER1, GLUSTER2]

nano /etc/fstab
/dev/md0 /mnt/gluster ext4 defaults 0 1

 

On crée le repertoire que nous avons déclarer dans le raid:

[GLUSTER1, GLUSTER2]

mkdir /mnt/gluster

 

puis on monte tout ce qu’il y a de lister dans fstab:

[GLUSTER1, GLUSTER2]

mount -a

 

On vérifie que le raid est monté:

[GLUSTER1, GLUSTER2]

mount | grep md0
/dev/md0 on /mnt/gluster type ext4 (rw,relatime,stripe=256,data=ordered)

 

On vérifie la taille total du raid en regardant la taille du dossier créé précédemment:

[GLUSTER1, GLUSTER2]

df -H /dev/md0

Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/md0 21G 47M 20G 1% /mnt/gluster

 

On vérifie l’état du raid:

[GLUSTER1, GLUSTER2]

mdadm --detail /dev/md0

/dev/md0:
Version : 1.2
Creation Time : Sat Jan 21 12:38:06 2017
Raid Level : raid5
Array Size : 20955136 (19.98 GiB 21.46 GB)
Used Dev Size : 10477568 (9.99 GiB 10.73 GB)
Raid Devices : 3
Total Devices : 3
Persistence : Superblock is persistent
Update Time : Sat Jan 21 12:40:20 2017
State : clean
Active Devices : 3
Working Devices : 3
Failed Devices : 0
Spare Devices : 0

Layout : left-symmetric
Chunk Size : 512K

Name : WP1:0 (local to host WP1)
UUID : 609a3aec:a4294637:af1c5358:7c24edb1
Events : 2

Number Major Minor RaidDevice State
0 8 16 0 active sync /dev/sdb
1 8 32 1 active sync /dev/sdc
2 8 48 2 active sync /dev/sdd

 

 

b. glusterfs-server

 

Installons GlusterFS pour faire notre cluster de données:

[GLUSTER1, GLUSTER2]

apt-get install glusterfs-server

 

 

On ajoute dans le fichier de configuration une sécurité, on indique gluster n’écoutera que sur la carte réseau ayant le réseau 10.0.0.x

[GLUSTER1]

nano /etc/glusterfs/glusterd.vol

# ecoute seulement sur l'interface privee 10.0.0.1
option transport.rdma.bind-address 10.0.0.1
option transport.socket.bind-address 10.0.0.1
option transport.tcp.bind-address 10.0.0.1

 

[GLUSTER2]

nano /etc/glusterfs/glusterd.vol

# ecoute seulement sur l'interface privee 10.0.0.2
option transport.rdma.bind-address 10.0.0.2
option transport.socket.bind-address 10.0.0.2
option transport.tcp.bind-address 10.0.0.2

 

 

Puis on démarre le service:

[GLUSTER1, GLUSTER2]

service glusterfs-server start

 

 

On va indiquer quelle probe (serveur) ajouter à notre cluster:

[GLUSTER1]

gluster peer probe 10.0.0.2
peer probe: success.

Inutile de dire au GLUSTER1 de s’ajouter lui même: vous auriez une erreur indiquant le fait qu’il y est déjà.

 

 

On vérifie le status du cluster:

[GLUSTER1]

gluster peer status
Number of Peers: 1
Hostname: 10.0.0.2
Uuid: 4a4351d0-1097-4f2b-a7c4-bfbebdbb3122
State: Peer in Cluster (Connected)

 

[GLUSTER2]

gluster peer status
Number of Peers: 1
Hostname: 10.0.0.1
Uuid: e3715142-dce3-4f4e-8757-4b1cec958e8e
State: Peer in Cluster (Connected)

 

 

Nous créons le volume partagé:

[GLUSTER1]

gluster volume create gfsvol replica 2 10.0.0.1:/mnt/gluster 10.0.0.2:/mnt/gluster force
volume create: gfsvol: success: please start the volume to access data

 

 

On vérifié le status du volume:

[GLUSTER1]

gluster volume info

Volume Name: gfsvol
Type: Replicate
Volume ID: ef58ca67-ecb4-4195-8efa-223ef699c0c6
Status: Created
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: 10.0.0.1:/mnt/gluster
Brick2: 10.0.0.2:/mnt/gluster

 

[GLUSTER2]

gluster volume info

Volume Name: gfsvol
Type: Replicate
Volume ID: ef58ca67-ecb4-4195-8efa-223ef699c0c6
Status: Created
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: 10.0.0.1:/mnt/gluster
Brick2: 10.0.0.2:/mnt/gluster

 

 

On démarre le volume:

[GLUSTER1]

gluster volume start gfsvol
volume start: gfsvol: success

 

 

On vérifie de nouveau le status du volume:

[GLUSTER1]

gluster volume info

Volume Name: gfsvol
Type: Replicate
Volume ID: ef58ca67-ecb4-4195-8efa-223ef699c0c6
Status: Started
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: 10.0.0.1:/mnt/gluster
Brick2: 10.0.0.2:/mnt/gluster

 

[GLUSTER2]

gluster volume info

Volume Name: gfsvol
Type: Replicate
Volume ID: ef58ca67-ecb4-4195-8efa-223ef699c0c6
Status: Started
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: 10.0.0.1:/mnt/gluster
Brick2: 10.0.0.2:/mnt/gluster

PS: regardez la section Status, elle est passée de Created à Started

 

 

 


V.   Nginx

 

 

Nous allons préparer nos deux serveurs web.

 

Commençons par installer nginx et php:

[WP1 , WP2]

apt-get install php5-fpm php5-mysql nginx -y

 

On va créer notre fichier de configuration correspondant à notre site et supprimer celui par défaut:

[WP1 , WP2]

cd /etc/nginx/sites-available
rm ../sites-enabled/default
nano wordpress

server {
listen 80;

root /var/www/html/;
index index.php index.html index.htm;

server_name localhost;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to index.html
try_files $uri $uri/ /index.html;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
include /etc/nginx/fastcgi.conf;
fastcgi_index index.php;
}

}

 

On active notre site:

[WP1 , WP2]

cd ../sites-enabled/
ln -s ../sites-available/wordpress

 

On vérifie la configuraiton de nginx puis on redémarre le service:

[WP1 , WP2]

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

service nginx restart

 

On crée un fichier de test en php pour voir si tout fonctionne:

[WP1 , WP2]

nano /var/www/html/index.php

<?php
phpinfo();
?>

 

On test l’adresse http://votre_ip/index.php

 

 


VI.   GlusterFS client

 

On reste sur nos serveurs web. Nous allons monter sur chacun d’eux le stockage partagé.

 

On va installer le paquet gluster-client permettant de monter ce type de montage:

[WP1 , WP2]

apt-get install glusterfs-client -y

 

On crée le répertoire où sera hébergé notre site:

[WP1 , WP2]

mkdir /var/www/html/wordpress

Puis on place dans fstab le montage à effectuer au démarrage:

[WP1]

nano /etc/fstab
10.0.0.1:/gfsvol /var/www/html/wordpress glusterfs _netdev,fetch-attempts=10 0 0

 
[WP2]

nano /etc/fstab
10.0.0.2:/gfsvol /var/www/html/wordpress glusterfs _netdev,fetch-attempts=10 0 0

 

Et on monte se montage:

[WP1 , WP2]

mount -a

On vérifie que la taille de se montage correspond bien à celui de notre raid5:

[WP1]

df -h /var/www/html/wordpress/
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
10.0.0.1:/gfsvol 20G 44M 19G 1% /var/www/html/wordpress

 
[WP2]

df -h /var/www/html/wordpress/
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
10.0.0.2:/gfsvol 20G 44M 19G 1% /var/www/html/wordpress

 

 


VII. WordPress

 

a. WordPress

 

On télécharge WordPress et on le décompresse:

[WP1]

cd /tmp
wget --no-check-certificate https://fr.wordpress.org/wordpress-4.7.1-fr_FR.tar.gz
tar -xvf wordpress-4.7.1-fr_FR.tar.gz

 

On se place dans le dossier wordpress créé par la décompression de l’archive et on déplace tout vers notre répertoire du site:

[WP1]

cd /tmp/wordpress
mv * /var/www/html/wordpress/

 

On vérifie que tout y est:

[WP1]

ls -l /var/www/html/wordpress/
total 181
-rw-r--r-- 1 1001 1001 418 sept. 25 2013 index.php
-rw-r--r-- 1 1001 1001 19935 janv. 2 19:51 license.txt
drwx------ 2 root root 16384 janv. 21 17:16 lost+found
-rw-r--r-- 1 1001 1001 9106 janv. 13 13:00 readme.html
-rw-r--r-- 1 1001 1001 5447 sept. 27 23:36 wp-activate.php
drwxr-xr-x 9 1001 1001 4096 janv. 13 13:00 wp-admin
-rw-r--r-- 1 1001 1001 364 déc. 19 2015 wp-blog-header.php
-rw-r--r-- 1 1001 1001 1627 août 29 14:00 wp-comments-post.php
-rw-r--r-- 1 1001 1001 3581 janv. 13 13:00 wp-config-sample.php
drwxr-xr-x 5 1001 1001 4096 janv. 13 13:00 wp-content
-rw-r--r-- 1 1001 1001 3286 mai 24 2015 wp-cron.php
drwxr-xr-x 18 1001 1001 12288 janv. 13 13:00 wp-includes
-rw-r--r-- 1 1001 1001 2422 nov. 21 03:46 wp-links-opml.php
-rw-r--r-- 1 1001 1001 3301 oct. 25 05:15 wp-load.php
-rw-r--r-- 1 1001 1001 33939 nov. 21 03:46 wp-login.php
-rw-r--r-- 1 1001 1001 8048 janv. 11 06:15 wp-mail.php
-rw-r--r-- 1 1001 1001 16250 nov. 29 06:39 wp-settings.php
-rw-r--r-- 1 1001 1001 29896 oct. 19 06:47 wp-signup.php
-rw-r--r-- 1 1001 1001 4513 oct. 14 21:39 wp-trackback.php
-rw-r--r-- 1 1001 1001 3065 août 31 18:31 xmlrpc.php

 

On vérifie par la même occasion que sur WP2 les fichier sont bien présent, pour valider notre stockage partagé:

[WP2]

ls -l /var/www/html/wordpress/
total 181
-rw-r--r-- 1 1001 1001 418 sept. 25 2013 index.php
-rw-r--r-- 1 1001 1001 19935 janv. 2 19:51 license.txt
drwx------ 2 root root 16384 janv. 21 17:16 lost+found
-rw-r--r-- 1 1001 1001 9106 janv. 13 13:00 readme.html
-rw-r--r-- 1 1001 1001 5447 sept. 27 23:36 wp-activate.php
drwxr-xr-x 9 1001 1001 4096 janv. 13 13:00 wp-admin
-rw-r--r-- 1 1001 1001 364 déc. 19 2015 wp-blog-header.php
-rw-r--r-- 1 1001 1001 1627 août 29 14:00 wp-comments-post.php
-rw-r--r-- 1 1001 1001 3581 janv. 13 13:00 wp-config-sample.php
drwxr-xr-x 5 1001 1001 4096 janv. 13 13:00 wp-content
-rw-r--r-- 1 1001 1001 3286 mai 24 2015 wp-cron.php
drwxr-xr-x 18 1001 1001 12288 janv. 13 13:00 wp-includes
-rw-r--r-- 1 1001 1001 2422 nov. 21 03:46 wp-links-opml.php
-rw-r--r-- 1 1001 1001 3301 oct. 25 05:15 wp-load.php
-rw-r--r-- 1 1001 1001 33939 nov. 21 03:46 wp-login.php
-rw-r--r-- 1 1001 1001 8048 janv. 11 06:15 wp-mail.php
-rw-r--r-- 1 1001 1001 16250 nov. 29 06:39 wp-settings.php
-rw-r--r-- 1 1001 1001 29896 oct. 19 06:47 wp-signup.php
-rw-r--r-- 1 1001 1001 4513 oct. 14 21:39 wp-trackback.php
-rw-r--r-- 1 1001 1001 3065 août 31 18:31 xmlrpc.php

 

 

On va modifier notre fichier de configuration pour aller pointer sur notre répertoire wordpress:

[WP1 , WP2]

nano /etc/nginx/sites-available/wordpress

 

modifier

root /var/www/html;

en

root /var/www/html/wordpress;

 

Puis on redémarre le service nginx:

[WP1 , WP2]

service nginx restart

 

On vérifie l’accès au worpdress:

http://votre_ip_wp1/

 

 

b. Petites modifications

 

Avant de commencer l’installation du wordpress, nous devons créer une base de donnée et un utilisateur autorisé à accéder à distance au serveurs sql.

 

On se connecte au sql, puis on crée un base de donnée, un utilisateur et on lui donne les droits sur cette base:

[SQL1]

mysql -u root -p

create database wordpress;
create user jdoe@localhost identified by 'P@$$w0rd';
grant all privileges on wordpress.* to jdoe@localhost identified by 'P@$$w0rd';
flush privileges;
exit;

 

On se place sur cette nouvelle base de donnée et on donne l’accès à notre utilisateur depuis les serveurs WP1 et WP2:

[SQL1]

use wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO 'jdoe'@'172.20.0.5' IDENTIFIED BY 'P@$$w0rd' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON wordpress.* TO 'jdoe'@'172.20.0.6' IDENTIFIED BY 'P@$$w0rd' WITH GRANT OPTION;

 

On peut faire l’installation du WordPress. (Je ne le détail pas).

 


IX.  Nginx Frontend & keepalived

 

Dernière partie de notre projet, le point d’entrée unique de nos utilisateurs. C’est ici que nos utilisateur seront redirigé vers les serveurs WP1 ou WP2.

 

a. nginx load balancer

 

On installe nginx :

[FRONTEND1 , FRONTEND2]

apt-get install nginx -y

 

On supprime la configuration du site par défaut et on crée le notre:

[FRONTEND1 , FRONTEND2]

cd /etc/nginx/sites-available
rm ../sites-enabled/default
nano lbwp

 
upstream lbwp {
server 172.20.0.7:80;
server 172.20.0.8:80;
}

server {
location / {
proxy_pass http://lbwp;
}
}

 

On active notre site:

[FRONTEND1 , FRONTEND2]

cd ../sites-enabled/
ln -s ../sites-available/lbwp

 

On vérifie la configuration et on redémarre nginx:

[FRONTEND1 , FRONTEND2]

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

service nginx restart

 

 

On affiche les logs d’acces en temps réel et on vérifie que tous fonctionne en accédant au FRONTEND1 et FRONTEND2:

[FRONTEND1 , FRONTEND2]

tail -f /var/log/nginx/access.log

 

 

b. Correction des logs

 

Si on affiche les logs d’accès  sur WP1 ou WP2, on s’apercoit qu’on ne voit que l’ip des FRONTEND1 ou FRONTEND2 qui apparaissent, ce qui n’est pas le mieux pour le troubleshooting.

Pour régler ça, on modifie notre fichier de configuration de site:

[FRONTEND1 , FRONTEND2]

nano /etc/nginx/sites-available/lbwp
 
upstream lbwp {
server 172.20.0.7:80;
server 172.20.0.8:80;
}

server {
location / {
proxy_pass http://lbwp;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}

 

Puis on redémarre nginx en vérifiant la configuration:

[FRONTEND1 , FRONTEND2]

nginx -t
service nginx restart

 

 

c. Keepalived

 

Nous devons créer notre IP unique et surtout avoir une redondance.

 

On installe donc keepalived:

[FRONTEND1 , FRONTEND2]

apt-get install keepalived -y

 

On modifie le fichier deconfiguration:

[FRONTEND1]

nano /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "killall -0 nginx"
interval 2
weight 2
}

vrrp_instance VI_1 {
interface eth1
state MASTER
virtual_router_id 1
priority 101 # 101 on master, 100 on backup
virtual_ipaddress {
192.168.1.99
}
track_script {
chk_nginx
}
}

 

[FRONTEND2]

nano /etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "killall -0 nginx"
interval 2
weight 2
}

vrrp_instance VI_1 {
interface eth1
state MASTER
virtual_router_id 1
priority 100 # 101 on master, 100 on backup
virtual_ipaddress {
192.168.1.99
}
track_script {
chk_nginx
}
}

 

On redémarre keepalived:

[FRONTEND1 , FRONTEND2]

service keepalive restart

 

Et voila nos clients peuvent accéder à notre site sur l’url: http://192.168.1.99

 

 


X.   Conclusion

 

Nous avons donc mis en place une infrastructure qui répond à la haute disponibilité et à la tolérance de panne. En effet dans le pire des cas nous avons le droit de perdre:

 

Ce qui statistiquement est très faible. Mais cela permet également de faire une maintenance sur les serveurs plus facilement sans interruption de service.

 

 


Laisser un commentaire

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