Introduction
C’est quoi Ansible ?
Ansible
est un outil open-source de gestion de configuration, de provisionnement de logiciels et de déploiement d’applications qui rend très simple l’automatisation des déploiements d’applications et des opérations d’infrastructure informatique. C’est une solution sans agent et facile à configurer contrairement à d’autres outils d’automatisation comme Puppet
ou Chef
.
Installation
Ansible s’appuie sur SSH et Python pour réaliser toute l’automatisation et il suffit donc d’installer Ansible sur le nœud de contrôle et de s’assurer qu’OpenSSH et Python sont installés à la fois sur le contrôle (l’endroit où Ansible est installé) et sur le nœud (l’hôte qui a besoin d’être configuré). Lors de la configuration d’équipements réseau, il existe une autre façon de configurer le nœud car il n’est pas possible d’installer Python (Python 3 recommandé) sur ces hôtes.
Voici quelques méthodes pour installer Ansible :
- via PIP
- via le fichier binaire
- via les dépôts
- docker
PIP
sudo apt install python3-pip
VERSION=3
pip install ansible==$VERSION
ansible --version
Fichier binaire
git clone https://github.com/ansible/ansible.bit
cd ansible
source ./hacking/env-setup
sudo apt install python3-pip
pip install --user -r ./requirements # Module installation for Jinja
Dépôts
apt-add-repository --yes --update ppa:/ansible/ansible-2.9
sudo apt install ansible
ansible --version
Notes et Recommendations
Même si vous pouvez utiliser l’utilisateur root dans Ansible pour exécuter des commandes Ad-Hoc et des playbooks, cela n’est pas considéré comme une bonne pratique en raison des risques de sécurité qui peuvent survenir en permettant à l’utilisateur root d’accéder à ssh. Pour cette raison, il est recommandé de créer un utilisateur Ansible dédié avec des privilèges sudo sur chaque nœud et sur le manager.
useradd -m aubin
echo "aubin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
Configurez maintenant la clé SSH pour accéder au nœud sans utiliser de mot de passe.
ssh-keygen
ssh-copy-id node[1-x]
Configurer Python3 comme interpreteur par défaut de Ansible. On pourra faire un lien de /usr/bin/python
vers python3
ou alors on doit configurer la valeur de ansible_python_interpreter=/usr/bin/python3
dans le fichier ansible.cfg
Introduction
Haproxy
est un outil utilisé pour faire du service discovery. Ses caractéristiques sont :
- il sert de
proxy
et eststateful
- il fait du
stickyness
en maintenant un client au même serveur de backend. - il sert de
Loadbalancer
et fait duHigh Availability
avec 9 algorithmes de LoadBalancing- Round Robin
- Least
- First
- Source
- URI
- HDR
- …
- il facilite ainsi la sécurisation et la mise en place du SSL
- il permet de faire de la
translation d'adresse et de port
- il est multi-protocole et facilite la configuration en terme de timeout
- il permet de faire du
forwarding
- il comprend un
système de monitoring
- il permet de faire du
service reload
- il permet de faire du
spof
avec l’outilkeepAlive
- il permet de faire du
slow start
- il permet de faire du
stickyness
- il permet de faire de la
réécriture d'url
- il est utilisé pour faire du
service discovery
Installation
L’installation sur un système Linux, on a :
apt-get install haproxy
La configuration se fait dans le fichier /etc/haproxy/haproxy.cfg
La commande de test suivant nous permettra de voir la version installé :
haproxy -v
Le fichier haproxy.cfg
permet de faire la configuration de haproxy, et il servira à faire à peu près 95% de la config. Il est sectionné en plusieurs parties :
- global
- default
- frontend
- backend
- listen (qui a pour vocation a remplacé frontend et backend)
Vous aurez plus d’information sur la note dédiée un peu plus en avant.
Les configurations à savoir sont :
- configuration du daemon : il se fait dans le fichier
/etc/sysconfig
- configuration du logrotate : il se fait en configurant le fichier
/etc/haproxy/haproxy.cfg
- Le repertoire de stockage des données est
/var/lib/haproxy
- Les templates d’erreurs de haproxy sont dans
/usr/share/haproxy
. Ces templates pourront nous aider à définir des formats de réponse automatique comme une réponse404
. On pourra dans un contexte de sécurisation camoufler une erreur404
avec une page légitime.
Configuration
Haproxy fonctionne en frontend et redirige les requêtes vers un ensemble de ressources en backend. Pour configurer ce service, il faudra tout d’abord lui demander d’écouter sur :
- une IP
- un Port
- une URL
Cette configuration est celle du frontend. Par la suite, il faudra configurer le backend où on précisera des ressources telles que les serveurs… On pourra préciser plusieurs services et définir le type de LoadBalancing qui sera appliqué. C’est également possible d’appliquer des règles spécifiques, de rajouter des headers sur les requêtes qui seront redirigées vers les services de backend. Le plus important à retenir jusqu’ici est le principe de frontend et de backend. Vous pouvez consulter plus de documentation sur le site officiel.
Exemple : Soit un client qui fait une requête sur le listener du Haproxy c’est-à-dire que la requête arrive sur le frontend. Cette requête sera redirigé vers un backend si elle vérifie certaines condition du frontend spécifique. Ensuite, on aura un chemin. Les étapes :
frontend : IP/URL/Port d’écout tel que défini dans la configuration du haproxy. C’est possible d’avoir plusieurs frontend. Ici, la requête est arrivée sur une URL ou un IP précis et sur un port précis (443, 80…)
application des règles : des règles sont appliquées pour déterminer le frontend correspondant à la requête cliente. Par la suite une décision sera faite :
- la requête peut être
bloquée
- la requête peut être
modifiée
c’est-à-dire que des entêtes peuvent être ajoutées ou enlevées ou modifiée… - …
- la requête peut être
une règle de redirection du frontend vers le backend
Dans le backend, une décision de LoadBalancing peut être appliquée. Des règles en place permettront de choisir le serveur vers qui redirigé la requête
un chemin retour
journalisation des échanges
Dans le fichier de configuration de Haproxy, on note 2 partie :
section
Global
section
Default
Global
Cette section correspond aux paramètres du service haproxy. Un exemple est définie comme suit :
global
log /dev/log local5 debug
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
Une pétite explication de ces paramètres :
- log : c’est la façon donc haproxy va s’occuper de la journalisation
- chroot : la sécurité de haproxy
- stats : pour permettre d’interargir avec haproxy avec des outils tiers notamment
hatop
pour configurer haproxy en GUI. Il permet aussi de définir le timeout qui est le temps de durer d’une connexion - user : l’utilisateur du service haproxy
- group : groupe correspondant
- daemon : ce mode permet à haproxy de s’exécuter en tant que service.
- eventuellement le ssl…
Default
Cette section s’applique si aucune configuration n’est précisée (définition d’un frontend et d’un backend pour une requête précise). Il est comme suit :
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
On a donc :
- log global : journalisation vers syslog ou suivant la définition de la section
global
- mode http : protocole de LoadBalancing. Il est possible de définir autre chose notamment tcp, smtp…
- option : permet de préciser la nécessité de journalisation de certaines options
- option httplog
- option dontlognull : spécifie qu’il ne faut pas journaliser lorsque les requêtes sont nulles
- timeout connect : spécifie le durée d’essaie de connexion avec le backend. Ce temps est en ms. Après ce temps, si le serveur ne répond pas, on considère le serveur indisponible.
- timeout client/server
- errorfile : permet de spécifier le fichier d’erreur qui devra être affichée en cas d’erreur
Lorsqu’on a rédiger un fichier de configuration haproxy, il est possible de tester la configuration avec la commande :
haproxy -c -f [myconfig_file.conf]
Exemple :
haproxy -c -f /etc/haproxy/haproxy.conf
C’est important de faire ce test pour un nouveau fichier de configuration haproxy avant de remplacer le fichier par défaut.
Exemple
Frontend
Avec Haproxy, on peut définir plusieurs frontend et cette capacité nous permet de mutualisé ce service. Un exemple de frontend minimaliste est :
frontend myapp_front
bind *:80
default_backend myapp_back
Le mot clé frontend
permet de définir un nouveau frontend. L’indentation est très important dans la rédaction d’un fichier Haproxy. Dans frontend, on pourra définir des paramètres dont les plus importants sont :
bind
: ici la valeur*:80
a été donné.*
spécifie qu’on souhaite écouter sur tous les ip de la machine sur lequel tourne le service haproxy. C’est également possible de définir un ip précis. On aura par exemple :bind 10.0.0.1:80
default_backend
: est une variable imposée, il spécifie le backend correspondant. La valeur donnée est le nom d’un backend qui a été défini
Backend
La définition d’un backend est comme suit :
backend myapp_back
server server1 10.0.0.1:80
Le mot clé backend
permet de définir un backend. Comme paramètre, on peut spécifier les serveurs qu’on aimerait lié avec le mot clé server
.
Dans le cas où on a plusieurs serveurs dans le backend, il est possible de spécifier un algorithme de loadbalancing avec le mot clé balance
. Dans cet exemple, nous allons utiliser un algorithme de Round Robin
On retrouve alors la configuration suivante :
backend myapp_back
balance roundrobin
server server1 10.0.0.1:80
server server2 10.0.0.2:5000
L’algorithme de Round Robin est l’algorithme par défaut utiliser lorsque ce paramètre n’est pas précisé.
Au final, nous obtenons le fichier suivant :
global
log /dev/log local5 debug
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
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
frontend myapp_front
bind *:80
default_backend myapp_back
backend myapp_back
balance roundrobin
server server1 10.0.0.1:80
server server2 10.0.0.2:5000
Options
Haproxy a beaucoup d’options que nous pouvons utilise, il s’agit notamment de :
- ACL qui permet de mieux gérer les requêtes entrantes et les regiriger vers certains server de backend
- Forwrad for qui permet de transporter l’IP du client responsable de la requête entre le serveur Haproxy et le serveur de backend. Dans ce cas, Haproxy ne remplamcera plus l’ip du client par son ip.
- …
Dans cette partie, nous allons juste voir comment implémenter des ACL, je vous recommande de vous rendre sur la documentation Haproxy pour plus d’informations sur ses fonctionnalités.
Une ACL permet un meilleur filtrage et redirection des requêtes reçues au niveau du frontend. On peut notamment les filtrer suivant l’URL, ce que nous allons faire dans cet exemple…
Pour un filtrage en fonction de 2 url à savoir : mct.aubinaso.fr
et www.aubinaso.fr
, on aura la configuration du frontend suivant :
frontend myapp_front
bind *:80
mode http
acl myapp_front1 hdr_dom(host) -i mct.aubinaso.fr
use_backend mybackend1 if myapp_front1
acl myapp_front2 hdr_dom(host) -i www.aubinaso.fr
use_backend mybackend2 if myapp_front2
La ligne mode http
informe qu’il s’agit d’une acl appliquée à la couche 7. Nous avons rajouté 2 entrées pour loadbalancer sur 2 ACL. Les urls sont mct.aubinaso.fr
et www.aubinaso.fr
. nous créons donc 2 règles acl avec pour nom myapp_front1 et myapp_front2. Le mot clé hdr_dom(host)
recupère les URL de la requête et en fonction de l’url, le client sera redirigé sur mybackend1 ou mybackend2.
Variable
NOM="John"
echo $NOM
echo "$NOM"
echo "${NOM}
Condition
if [[ -z "$chaine" ]]; then
echo "La chaine est vide"
elif [[ -n "$chaine" ]]; then
echo "La chaine est vide"
fi
Variable
NOM="John"
echo $NOM
echo "$NOM"
echo "${NOM}
Condition
if [[ -z "$chaine" ]]; then
echo "La chaine est vide"
elif [[ -n "$chaine" ]]; then
echo "La chaine est vide"
fi
Variable
NOM="John"
echo $NOM
echo "$NOM"
echo "${NOM}
Condition
if [[ -z "$chaine" ]]; then
echo "La chaine est vide"
elif [[ -n "$chaine" ]]; then
echo "La chaine est vide"
fi
Variable
NOM="John"
echo $NOM
echo "$NOM"
echo "${NOM}
Condition
if [[ -z "$chaine" ]]; then
echo "La chaine est vide"
elif [[ -n "$chaine" ]]; then
echo "La chaine est vide"
fi