====== Cluster HA entre deux dedibox ======
Sauf mention contraire, toutes les commandes sont à lancer sur les deux hyperviseurs. Seule la gestion de gluster peut se faire depuis un seul des deux
===== But =====
Le but de ce how-to est de monter un cluster qui hébergera des machines virtuelles. Il utilisera deux serveurs de chez [[http://online.net|Online]] (on a pas d'action chez eux, c'est juste que leurs offres sont très agressives ^^) en tant qu'hyperviseurs. Il doit être possible de:
* Migrer à chaud des machines virtuelles de l'un vers l'autre (pour maintenance planifiée, répartition de charge etc...), sans perte de connectivité
* Attribuer des IP publiques à des invités (via les IP Failovers de Online.net), sans aucun filtrage, ni NAT: les VM ont leur adresse IP publique directement connectée à Internet
* La possibilité d'attribuer plusieurs IP Failover à une seule machine virtuelle
* Créer des réseaux virtuels isolés (une partie publique, et autant de réseaux privés que nécessaire, tous parfaitement étanches entre eux)
* Les réseaux virtuels ne doivent pas être liés aux hyperviseurs (si deux invités sont reliés au même réseau logique, ils peuvent se contacter peu importe sur quel hyperviseur ils tournent)
* Redémarrer rapidement des invités en cas de crash d'un des hyperviseurs
* Perdre aucune donnée en cas de crash d'un hyperviseur
* Empêcher le démarrage de la même machine virtuelle sur les deux hyperviseurs en même temps (ce qui corromprait presque immédiatement le disque de l'invité)
Une toute petite partie est vraiment spécifique aux serveurs d'Online, la majorité peut être ré-utilisée pour monter un cluster sur des serveurs hébergés chez vous
===== Composants =====
* Deux serveurs [[http://www.online.net/fr/serveur-dedie|dedibox]] PRO (hyperviseur et serveur de stockage)
* [[http://www.centos.org|CentOS]] 6 x86_64 (système hôte)
* [[http://libvirt.org|libvirt]] (API de gestion de la virtualisation)
* [[http://wiki.qemu.org/|qemu]]-kvm (l'hyperviseur)
* [[http://virt-manager.org/|virt-manager]] (l'interface graphique de gestion des machines virtuelles)
* [[http://www.gluster.org/|GlusterFS]] (solution de stockage distribué)
* [[http://openvpn.net/index.php/open-source.html|OpenVPN]] (pour créer les tunnels entre les deux hyperviseurs)
* [[https://fedorahosted.org/sanlock/|sanlock]] (gère les verrous sur les disques et empêche de démarrer la même machine virtuelle sur les deux hyperviseurs en même temps)
* Quelques notions en réseau et virtualisation (bien maitriser une installation simple de libvirt + KVM + virt-manager vous sera probablement utile)
* Un peu d'huile de coude
* Quelques pack de bières et/ou une grande cafetière selon vos préférences
===== Schéma global =====
Voilà une représentation schématique de ce qu'on cherche à obtenir:
{{:tuto:virtualisation:dedibox_ha.png|Schéma global de l'installation}}
===== Prérequis =====
==== À préparer sur la console online.net ====
* Deux serveur dedibox PRO (ou supérieur, l'important étant de disposer de l'option RPN)
* Accès iLO / iDRAC sur les deux serveurs (pour installer CentOS via le média virtuel)
* Créer un groupe RPN, et y assigner les deux serveurs, rendez-vous sur [[http://documentation.online.net/fr/serveur-dedie/tutoriel/rpn-by-online.net|cette page]] pour savoir comment faire
Il est vivement recommandé de prendre l'option RPN-G (pour avoir du gigabit sur le réseau RPN), sinon par défaut, c'est du 100M, ce qui impactera les performances des invités puisqu'il y a une réplication synchrone entre les deux hyperviseurs
===== Installation des systèmes hôtes =====
La première étape est d'installer une CentOS 6 (6.4 étant la dernière version actuellement) en édition x86_64. CentOS n'étant plus supportée par l'installateur d'Online ((CentOS 6.4 est de nouveaux disponible maintenant, mais l'installation via le média virtuelle reste possible)), il faut d'abord installer n'importe quel système (une debian par exemple), puis, une fois installé, on peut accéder à l'interface iLO (ou iDRAC selon la marque du serveur, iLO pour les IBM, iDRAC pour les Dell). On peut ensuite charger un applet java (oui, beurk, mais c'est toujours mieux que de l'activeX :-) ) pour prendre la main sur la console du serveur (une sorte de KVM sur IP) ainsi qu'un lecteur CD virtuel. Il faut simplement connecter une ISO netinstall de CentOS dans ce lecteur virtuel et redémarrer le serveur, qui va s'amorcer dessus. L'amorce peut prendre du temps selon la vitesse de votre connexion, puisque l'image netinstall sera streamée depuis votre poste.
La suite de ce how-to considère que:
* Les deux hyperviseurs sont installés, avec les noms hyp1 et hyp2 respectivement
* L'IP publique de hyp1 est 88.190.30.8
* l'IP privée (réseau RPN) de hyp1 est 10.25.9.46
* l'IP publique de hyp2 est 88.190.30.9
* l'IP privée (réseau RPN) de hyp2 est 10.25.9.47
* LVM a été utilisé pour gérer le partitionnement, et l'unique groupe de volumes (VG) se nomme **main**
===== Désactivation des services =====
Certains services ne sont pas nécessaires et sont donc désactivés maintenant.
chkconfig ip6tables off
chkconfig iptables off
/etc/init.d/iptables stop
/etc/init.d/ip6tables stop
Ne prenez pas peur, on va remettre du filtrage dans la suite bien entendu, mais c'est en général plus simple de monter la base sans avoir à s'embêter avec un firewall
===== Optimisations des hyperviseurs =====
==== Réglages systèmes ====
Pour éviter des chutes de performances, il faut éviter à tout prix de swapper, quitte à exploiter moins de cache. On désactive aussi l'IPv6 puisqu'on ne s'en servira pas dans notre cas
echo "vm.swappiness=0" >> /etc/sysctl.conf
echo "vm.vfs_cache_pressure=10000" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
sysctl -p
Avec cette configuration, le swap ne devrait être utilisé que pour éviter un OOM (dans la pratique, il semble que le swap soit toujours un peu utilisé, même si moins qu'avant. La version 6.4 de CentOS semble utiliser beaucoup plus facilement le swap, espérons que ce comportement soit corrigé dans la 6.5)
===== Préparation de l'environnement =====
Dans cette étape, nous allons, sur chacun des hyperviseurs, créer quelques fichiers texte simples, qui contiennent des variables. Ça simplifiera la suite
mkdir /etc/install
chmod 700 /etc/install
echo hyp1 > /etc/install/hostname
echo hyp2 > /etc/install/peer_hostname
echo firewall-services.com > /etc/install/dnsdomainname
echo 10.25.9.46 > /etc/install/rpn_ip
echo B4:B5:2F:51:9B:61 > /etc/install/rpn_mac
echo 10.25.8.47 > /etc/install/rpn_peer_ip
echo 1 > /etc/install/host_id
echo 37651 > /etc/install/online_sdx
echo xxxxxxxxxxxxxxxxxxxxx > /etc/install/api_key
Faites la même chose sur hyp2, en adaptant les valeurs.
la valeur de host_id doit impérativement être différente entre hyp1 et hyp2. C'est cet identifiant qui sera utilisé pour la gestion des verrous sur les disquesDans cet exemple, 37651 est l'identifiant de votre serveur Online (vu dans votre console comme sd-37651). Adaptez cette valeur à l'identifiant de votre dediboxxxxxxxxxxxxxxxxxxxxxx est votre clé pour l'accès à l'API Online, vous pouvez la trouver sur cette page: https://console.online.net/fr/api/access
Gardez cette clé secrète, elle permet de gérer à distance vos serveurs, y compris les redémarrer
===== Configuration des dépôts =====
Il va falloir ajouter quelques dépôts, certains composants logiciels n'étant pas disponibles dans les dépôts de base, ou leur version étant trop ancienne
==== Dépôt EPEL ====
Le dépôt EPEL contient de nombreux logiciels, et sera utilisé pour openvpn, ainsi que quelques outils de base
rpm -Uvh http://fr2.rpmfind.net/linux/epel/6/i386/epel-release-6-8.noarch.rpm
=== Installation d'outils de base ===
Maintenant que le dépôt EPEL est configuré, on peut en profiter pour installer quelques outils de base que je juge indispensables ;-)
yum install htop screen strace pbzip2 iftop iptraf man rsync bash-completion wget openssh-clients vim acpid tcpdump pciutils patch sysstat
==== Dépôt GlusterFS ====
La version de GlusterFS dans les dépôts de base est un peu vieillotte, et surtout, ne permet pas un recovery pendant que les fichiers sont ouverts. On va donc utiliser le dépôt RHEL fourni par gluster.org pour avoir une version plus récente.
wget -P /etc/yum.repos.d/ \
http://download.gluster.org/pub/gluster/glusterfs/3.4/LATEST/RHEL/glusterfs-epel.repo
===== Installation des outils de virtualisation =====
Il faut maintenant installer les outils de base pour virtualiser tout notre petit monde
yum install libvirt qemu-kvm \
bridge-utils policycoreutils-python
On va appliquer une configuration minimale, mais fonctionnelle de libvirt. Le but est de:
* Gérer l'accès à libvirt uniquement via ssh (qemu+ssh://hyp1/system par exemple)
* Donner cet accès à un utilisateur non privilégié, appelé **fws**
==== Activer KSM ====
KSM ((**K**ernel **S**ame page **M**erging)) est un mécanisme permettant de mettre en commun des pages mémoire identiques (y compris entre plusieurs invités). En utilisant un peu de CPU, on peut donc récupérer de la mémoire. Au plus vous faites tourner des systèmes identiques ou proche, au plus vous avez de chance d'voir des pages identiques, et donc d’économiser de la RAM. Le démon ksmtuned permet quand à lui de surveiller la pertinence et KSM (démarrage quand la mémoire vient à manquer, ajustement de l'agressivité du scan en fonction de la pression sur la RAM, désactivation quand ce n'est plus nécessaire etc...)
chkconfig ksm on
chkconfig ksmtuned on
mv /etc/ksmtuned.conf /etc/ksmtuned.conf.default
cat <<'EOF' > /etc/ksmtuned.conf
KSM_MONITOR_INTERVAL=10
KSM_SLEEP_MSEC=5
KSM_NPAGES_BOOST=600
KSM_NPAGES_DECAY=-200
KSM_NPAGES_MIN=64
KSM_NPAGES_MAX=4094
KSM_THRES_COEF=45
KSM_THRES_CONST=9144
LOGFILE=/var/log/ksmtuned.log
DEBUG=1
EOF
cat <<'EOF' > /etc/logrotate.d/ksmtuned
/var/log/ksmtuned.log {
weekly
missingok
rotate 4
compress
delaycompress
copytruncate
minsize 100k
}
EOF
/etc/init.d/ksm start
/etc/init.d/ksmtuned start
vous pouvez ajuster la configuration de ksmtuned, regardez le fichier /etc/ksmtuned.conf.default pour avoir une explication sur les différents paramètres
==== Configuration de base de libvirt ====
mv /etc/libvirt/libvirtd.conf \
/etc/libvirt/libvirtd.conf.default
cat < /etc/libvirt/libvirtd.conf
listen_tls = 0
listen_tcp = 0
mdns_adv = 0
unix_sock_group = "libvirt"
unix_sock_rw_perms = "0770"
auth_unix_ro = "none"
auth_unix_rw = "none"
EOF
On va aussi empêcher le marquage des machines virtuelles pour un démarrage automatique. Si pour un hyperviseur simple c'est une fonction intéressante, dans le cas d'un cluster, c'est plutôt dangereux, il vaut mieux maîtriser cette phase.
mkdir -p /etc/libvirt/qemu/autostart/
chattr +i /etc/libvirt/qemu/autostart/
==== Création d'un compte utilisateur non privilégié ====
useradd fws
passwd fws
groupadd libvirt
usermod -a -G libvirt fws
==== Configuration SELinux ====
Une variable SELinux doit être activée pour certains types de sauvegardes utilisant rsync.
setsebool -P rsync_export_all_ro=1
===== Configuration des interfaces privées (réseau RPN) =====
Sur les deux hyperviseurs, il faut maintenant configurer l'interface privée (celle connectée sur le réseau RPN, normalement eth1):
cat <<'EOF' > /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
HWADDR=__MAC__
ONBOOT=yes
NM_CONTROLLED=no
TYPE=Ethernet
BOOTPROTO=dhcp
MTU=9000
EOF
sed -i -e "s/__MAC__/$(cat /etc/install/rpn_mac)/g" \
/etc/sysconfig/network-scripts/ifcfg-eth1
/etc/init.d/network restart
Si tout se passe bien, vous devriez pouvoir pinguer les deux hyperviseurs entre eux via le réseau RPN. Ça ne sert à rien d'aller plus loin tant que ça n'est pas le cas.
Les interfaces du réseau RPN doivent être configurée via le protocole DHCP, n'essayez pas de les mettre en IP fixe, ça ne fonctionnera pas
===== Ajustement du fichier /etc/hosts =====
Il faut que les deux hyperviseurs puissent toujours se joindre, même en cas de problème de DNS, le plus simple est donc de rajouter quelques alias dans /etc/hosts
cat <<'EOF' > /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 __HOSTNAME__ __HOSTNAME__.__DOMAINNAME__
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
__PEER_IP__ peer __PEER_HOSTNAME__ __PEER_HOSTNAME__.__DOMAINNAME__
EOF
sed -i -e "s/__HOSTNAME__/$(cat /etc/install/hostname)/g" \
-e "s/__DOMAINNAME__/$(cat /etc/install/dnsdomainname)/g" \
-e "s/__PEER_IP__/$(cat /etc/install/rpn_peer_ip)/g" \
-e "s/__PEER_HOSTNAME__/$(cat /etc/install/peer_hostname)/g" /etc/hosts
===== GlusterFS =====
GlusterFS sera utilisé pour fournir l'espace de stockage accessible depuis les deux hyperviseurs en simultané.
==== Installer les paquets nécessaires ====
yum install glusterfs-fuse glusterfs \
glusterfs-server
==== Créer un volume GlusterFS pour le stockages des images ====
=== Créer un volume LVM ===
Les données exportées par GlusterFS seront stockées sur un volume LVM sur chaque hyperviseur. Dans cet exemple, on va créer un volume de 800Go. Vous pouvez ajuster en fonction de l'espace disponible sur vos serveurs.
Pensez à garder un peu d'espace libre sur votre VG, pour les autres volumes (voir suite du how-to) et pour la prise de snapshots LVM)GlusterFS sera utilisé en mode réplication, il faut donc créer des volumes de tailles égales sur les deux hyperviseurs
lvcreate -L 800G -n vmstore main
=== Formater ce volume ===
Red Hat recommande l'utilisation du système de fichier XFS pour l'utilisation de Gluster. Ext4 fonctionne aussi, à vous de voir celui que vous préférez
yum install xfsprogs
mkfs.xfs -f -i size=512 -L VMSTORE /dev/main/vmstore
=== Monter ce nouveau volume ===
Les volumes qui stockeront les données Gluster seront montés dans /mnt/bricks/
* Créer le point de montage
mkdir -p /mnt/bricks/vmstore
* Ajouter une ligne à fstab pour le montage automatique, et monter immédiatement le volume
echo "/dev/main/vmstore /mnt/bricks/vmstore xfs noatime 0 0" \
>> /etc/fstab
mount -a
mount
=== Activer et démarrer le démon gluserd ===
chkconfig glusterd on
/etc/init.d/glusterd start
Faites la même chose (lvcreate, mkfs.ext4, montage etc...) sur le deuxième hyperviseur avant d'aller plus loin
=== Contacter l'hyperviseur distant ===
Depuis un hyperviseur (peu importe lequel), on va vérifier la connectivité avec l'hyperviseur distants, via un //**probe**//
gluster peer probe hyp2
=== Créer le volume GlusterFS "vmstore" ===
À faire sur un seul hyperviseur (peu importe lequel)
gluster volume create vmstore replica 2 \
hyp1:/mnt/bricks/vmstore hyp2:/mnt/bricks/vmstore
=== Démarrer le volume "vmstore" ===
À faire sur un seul hyperviseur (peu importe lequel)
gluster volume start vmstore
=== Réglage du volume ===
On peut faire quelques réglages sur ce volume pour améliorer les performances
gluster volume set vmstore nfs.disable on
gluster volume set vmstore network.ping-timeout 5
gluster volume set vmstore network.frame-timeout 300
Autres réglages recommandés pour optimiser les performances
gluster volume set vmstore performance.stat-prefetch off
gluster volume set vmstore performance.io-cache off
gluster volume set vmstore performance.read-ahead off
gluster volume set vmstore remote-dio on
gluster volume set vmstore cluster.eager-lock on
=== Ajout du point de montage ===
Ce nouveau volume GlusterFS sera monté dans /var/lib/libvirt/images, on pourra ensuite définir plusieurs pool de stockage:
echo "localhost:/vmstore /var/lib/libvirt/images glusterfs defaults,_netdev 0 0" \
>> /etc/fstab
chkconfig netfs on
mount -a
=== Autoriser les VM à utiliser des systèmes de fichiers FUSE ===
GlusterFS étant basé sur FUSE, il faut autoriser les VM à accéder aux systèmes de fichiers FUSE (SELinux le bloque par défaut):
setsebool -P virt_use_fusefs=1
===== Sanlock =====
le démon sanlock va permettre de poser des verrous sur les images disques, et ainsi d'empêcher la même machine virtuelle de démarrer en même temps sur les deux hyperviseurs (ce qui corromprait les données à coup sûre)
==== Installer les paquets ====
yum install libvirt-lock-sanlock
==== Démarrer le démon watchdog pour sanlock ====
wdmd agit comme un watchdog et forcera l'hyperviseur à redémarrer en cas de problème
chkconfig wdmd on
/etc/init.d/wdmd start
==== Créer un volume GlusterFS pour sanlock ====
sanlock doit pouvoir écrire sur un répertoire commun entre les deux hyperviseurs. Le plus simple est donc de créer un nouveau volume GlusterFS pour le stockage des verrous.
Il faut compter 1Mo pour chaque verrous, soit pour chaque disque virtuel utilisé (si une VM utilise 3 disques -> 3 verrous), pensez donc à dimensionner correctement ce volume
=== Préparation des bricks ===
lvcreate -L 10G -n sanlock main
mkfs.xfs -f -i size=512 -L SANLOCK /dev/main/sanlock
mkdir -p /mnt/bricks/sanlock
chown :sanlock /mnt/bricks/sanlock
chmod 770 /mnt/bricks/sanlock
echo "/dev/main/sanlock /mnt/bricks/sanlock xfs noatime 0 0" >> /etc/fstab
mount -a
=== Création du volume GlusterFS ===
À faire sur un seul hyperviseur (peu importe lequel)
gluster volume create sanlock replica 2 \
hyp1:/mnt/bricks/sanlock hyp2:/mnt/bricks/sanlock
gluster volume start sanlock
gluster volume set sanlock nfs.disable on
gluster volume set sanlock network.ping-timeout 5
gluster volume set sanlock network.frame-timeout 10
=== Configurer pour un montage automatique ===
echo "localhost:/sanlock /var/lib/libvirt/sanlock glusterfs defaults,_netdev 0 0" \
>> /etc/fstab
mount -a
Si vous utilisez ext3 ou ext4 à la place de xfs pour ce volume, il vaut mieux supprimer le répertoire /var/lib/libvirt/sanlock/lost+found sinon, il va générer des messages d'erreur dans les journaux de sanlock
=== Démarrer le démon sanlock ===
chkconfig sanlock on
/etc/init.d/sanlock start
=== Configurer le plugin sanlock de libvirt ===
mv /etc/libvirt/qemu-sanlock.conf \
/etc/libvirt/qemu-sanlock.conf.default
cat <<'EOF' > /etc/libvirt/qemu-sanlock.conf
auto_disk_leases = 1
host_id = __HOST_ID__
user= "sanlock"
group = "sanlock"
EOF
sed -i -e "s/__HOST_ID__/$(cat /etc/install/host_id)/g" \
/etc/libvirt/qemu-sanlock.conf
mv /etc/libvirt/qemu.conf \
/etc/libvirt/qemu.conf.default
cat <<'EOF' > /etc/libvirt/qemu.conf
lock_manager = "sanlock"
EOF
=== Autoriser l'utilisation de sanlock au niveau de SELinux ===
setsebool -P virt_use_sanlock=1
setsebool -P sanlock_use_fusefs=1
=== Redémarrer libvirt ===
chkconfig libvirtd on
/etc/init.d/libvirtd restart
À partir de maintenant, vous devriez pouvoir ajouter les connexions vers hyp1 et hyp2 dans virt-manager. Ne créez pas de machine virtuelle pour l'instant, vérifier juste que la connexion est OK (avec l'URI qemu+ssh://fws@hyp1/system)
=== Nettoyage des verrous ===
Dans certains cas, un verrou peut se perdre (crash d'une VM, crash du démon sanlock etc...), on va donc mettre en place une tâche cron qui va nettoyer les verrous qui ne devraient plus être là. Ces cas sont suffisamment rares pour que la tâche ne s'exécute qu'une fois par jour (une fois par semaine serait même probablement suffisant)
cat <<'EOF' > /etc/cron.daily/sanlock-cleanup
#!/bin/bash
# Sleep between 0 second and 30 minutes
# So hypervisors do not cleanup at the same time
sleep $[ $RANDOM % 1800 ]
/usr/sbin/virt-sanlock-cleanup >/dev/null 2>&1
EOF
chmod +x /etc/cron.daily/sanlock-cleanup
=== Déclaration des pools de stockage libvirt ===
On peut maintenant définir un premier pool de stockage pour les images ISO
mkdir -p /var/lib/libvirt/images/iso
cat <<'EOF' > iso.xml
iso/var/lib/libvirt/images/iso075500
EOF
virsh pool-define iso.xml
virsh pool-start iso
virsh pool-autostart iso
On va aussi créer un second pool pour le stockage des images des VM. Vous pouvez créer autant de pool que nécessaire, par exemple, un pool (aka répertoire dans le volume Gluster) par client
mkdir -p /var/lib/libvirt/images/firewallservices
cat <<'EOF' > firewallservices.xml
firewallservices/var/lib/libvirt/images/firewallservices075500
EOF
virsh pool-define firewallservices.xml
virsh pool-start firewallservices
virsh pool-autostart firewallservices
===== Création d'un espace commun pour les dumps mémoire =====
Libvirt peut utiliser une fonction de sauvegarde sur disque pour suspendre un invité en sauvegardant son état dans un fichier sur disque. Par défaut, ces dumps mémoire sont stockés dans /var/lib/libvirt/qemu/save. L'idéal est donc de créer un volume partagé entre les deux hyperviseurs (ainsi une VM suspendue sur l'un peu être réveillée sur l'autre).
lvcreate -L50G -n save main
mkfs.xfs -L QEMU -i size=512 -f /dev/main/save
mkdir -p /mnt/bricks/save
echo "/dev/main/save /mnt/bricks/save xfs noatime 0 0" \
>> /etc/fstab
mount -a
Maintenant, on crée un volume gluster
À faire sur un seul hyperviseur
gluster volume create save replica 2 hyp1:/mnt/bricks/save hyp2:/mnt/bricks/save
gluster volume start save
gluster volume set save nfs.disable on
gluster volume set save network.ping-timeout 5
gluster volume set save network.frame-timeout 300
Puis on monte ce volume
echo "localhost:/save /var/lib/libvirt/qemu/save glusterfs defaults,_netdev 0 0" \
>> /etc/fstab
mount -a
===== Création des réseaux =====
On va maintenant créer deux réseaux pour les VM. Le premier, nommé **wan** sera utilisé pour connecter les VM à Internet (avec une IP publique), l'autre, nommé **lan** sera isolé et permettra de disposer d'un réseau privé. Les hyperviseurs n'ont pas d'accès à ces réseau, le routage entre le **lan** et le **wan** sera donc à charge d'une VM (qui aura une interface dans chaque réseau). Ces réseaux seront reliés à leur homologue entre les deux hyperviseurs via des tunnels OpenVPN, permettant de migrer une VM d'un hyperviseur à l'autre sans perte de connexion.
Tout le trafic entre les deux hyperviseurs se faisant sur le réseau privé (RPN), OpenVPN sera utilisé sans aucune authentification, ni chiffrement, afin d'économiser des ressources CPU.
==== Suppression du réseau "default" ====
Les réseau par défaut ne seront pas utilisés:
virsh net-destroy default
virsh net-undefine default
==== Réseau wan ====
On crée un bridge nommé brwan sur les hyperviseurs. Ce bridge n'aura pour l'instant aucune interface esclave:
cat <<'EOF' > /etc/sysconfig/network-scripts/ifcfg-brwan
DEVICE=brwan
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=none
IPV6INIT=no
EOF
==== Réseau lan ====
Même manipulation, pour le réseau lan avec un bridge brlan
cat <<'EOF' > /etc/sysconfig/network-scripts/ifcfg-brlan
DEVICE=brlan
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=none
IPV6INIT=no
IPV6_AUTOCONF=no
EOF
==== Redémarrer la pile réseau ====
/etc/init.d/network restart
==== Tunnels entre les hyperviseurs ====
Il faut maintenant créer des tunnels entre les deux hyperviseurs pour relier les deux brwan entre eux, ainsi que les deux brlan (mais les deux réseau lan et wan resteront parfaitement étanches)
=== Script "up" pour OpenVPN ===
Ce script sera appelé par OpenVPN au démarrage de chaque tunnel, et il se chargera d'ajouter l'interface tap du tunnel au bridge correspondant (par exemple taplan sera ajouté automatiquement à brlan)
mkdir -p /etc/openvpn/bin
cat <<'EOF' > /etc/openvpn/bin/up
#!/bin/bash
sleep 2
TAP=$1
ID=${TAP#tap}
/sbin/ifconfig $1 0.0.0.0 up promisc
/usr/sbin/brctl addif br$ID $TAP
EOF
chmod +x /etc/openvpn/bin/up
restorecon -Rv /etc/openvpn
=== Ajustement SELinux ===
Par défaut, SELinux va empêcher OpenVPN de faire appel à brctl, il faut donc créer une politique de sécurité personnalisée.
cat <<'EOF' > mycluster.te
module mycluster 1.0;
require {
type openvpn_t;
type brctl_exec_t;
class file { read execute open getattr execute_no_trans };
}
#============= openvpn_t ==============
allow openvpn_t brctl_exec_t:file { read execute open getattr execute_no_trans };
EOF
checkmodule -M -m -o mycluster.mod mycluster.te
semodule_package -o mycluster.pp -m mycluster.mod
mkdir -p /usr/share/selinux/packages/mycluster/
mv mycluster.pp /usr/share/selinux/packages/mycluster/
semodule -i /usr/share/selinux/packages/mycluster/mycluster.pp
=== Configuration des tunnels OpenVPN ===
Même si les deux hyperviseurs seront parfaitement équivalent, pour OpenVPN, il faut en définir un qui jouera le rôle de serveur, et l'autre de client. Dans cet exemple, hyp1 sera le serveur, et hyp2 le client
yum install openvpn
== Sur hyp1 ==
cat <<'EOF' > /etc/openvpn/wan.conf
lport 1195
proto udp
dev tapwan
user openvpn
group openvpn
up bin/up
persist-key
persist-tun
cipher none
ping 5
ping-restart 20
EOF
cat <<'EOF' > /etc/openvpn/lan.conf
lport 1194
proto udp
dev taplan
user openvpn
group openvpn
up bin/up
persist-key
persist-tun
cipher none
ping 5
ping-restart 20
EOF
semanage port -a -t openvpn_port_t -p udp 1195
== Sur hyp2 ==
cat <<'EOF' > /etc/openvpn/wan.conf
rport 1195
proto udp
dev tapwan
nobind
remote __PEER_IP__
up bin/up
user openvpn
group openvpn
chroot /etc/openvpn/
persist-key
persist-tun
cipher none
ping 5
ping-restart 60
EOF
cat <<'EOF' > /etc/openvpn/lan.conf
rport 1194
proto udp
dev taplan
nobind
remote __PEER_IP__
up bin/up
user openvpn
group openvpn
chroot /etc/openvpn/
persist-key
persist-tun
cipher none
ping 5
ping-restart 60
EOF
sed -i -e "s/__PEER_IP__/$(cat /etc/install/rpn_peer_ip)/g" \
/etc/openvpn/wan.conf
sed -i -e "s/__PEER_IP__/$(cat /etc/install/rpn_peer_ip)/g" \
/etc/openvpn/lan.conf
=== Activer et démarrer openvpn ===
chkconfig openvpn on
/etc/init.d/openvpn start
Si tout se passe comme prévu, les deux tunnels se monteront (vous pouvez vérifier dans /var/log/messages), et les deux bridges **brwan** et **brlan** auront une interface esclave chacune: respectivement **tapwan** et **taplan**
Il est possible de créer autant de réseaux isolés entre eux que nécessaire, en suivant la même procédure que pour le réseau **lan**
====== Échange des clés SSH entre hyperviseurs ======
Cette étape est optionnelle, puisque toutes les migrations, créations, etc... pourront se faire depuis l'outil graphique virt-manager. Cependant, si vous voulez aussi pouvoir gérer les migrations en ligne de commande, le mieux est de générer quelques clés SSH et de les échanger entre les différents hyperviseurs. Sur chaque hyperviseur, il faut:
* Générer une clé SSH pour le compte root (ssh-keygen -t rsa -b 4096)
* Déposer cette clé sur le compte fws de l'hyperviseur distant (ssh-copy-id fws@hyp2)
====== Configuration du par feu sur les hyperviseurs ======
Maintenant que la majorité est en place, il est temps de se préoccuper du par feu sur les hyperviseurs. Étant le cœur de l'infrastructure, inutile de préciser que leur sécurité est primordial. L'accès ne doit être possible que depuis des IP de confiances, et uniquement par SSH. Shorewall sera utilisé pour définir les règles de par feu.
yum install shorewall
===== Définition des interfaces =====
Shorewall utilise la notion de zones pour établir des règles de filtrage, en général, une zone correspond à une réseau accessible depuis une interface donnée. Dans notre configuration, chaque hyperviseur à 3 zones sur lesquels un filtrage doit/peut être appliqué:
* eth0: cette interface relie l'hyperviseur au réseau publique, et doit faire l'objet d'une politique strict. On nommera cette zone **wan**
* brwan: cette interface relie les machines virtuelles disposant d'une IP publique. Les hyperviseurs ne doivent pas réellement faire de filtrage entre eth0 et brwan, mais simplement passer les paquets dans un sens comme dans l'autre. Cette zone sera appelée **pwan** (pour proxy wan)
* eth1: cette interface relie l'hyperviseur au réseau privé RPN, ce réseau étant isolé physiquement, il n'y a pas de filtrage à appliquer, on peut donc autoriser tout le trafic. Cette zone sera appelée **rpn**
Contenu du fichier /etc/shorewall/interfaces:
#
# Shorewall version 4 - Interfaces File
#
# For information about entries in this file, type "man shorewall-interfaces"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-interfaces.html
#
###############################################################################
FORMAT 2
###############################################################################
#ZONE INTERFACE OPTIONS
wan eth0
rpn eth1
pwan brwan bridge
===== Définitions des zones =====
Il faut maintenant définir le type de chaque zone. Dans notre cas assez simple, nous ne voulons que du trafic IPv4, nous allons donc éditer le fichier /etc/shorewall/zones:
#
# Shorewall version 4 - Zones File
#
# For information about this file, type "man shorewall-zones"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-zones.html
#
###############################################################################
#ZONE TYPE OPTIONS IN OUT
# OPTIONS OPTIONS
fw firewall
wan ipv4
rpn ipv4
pwan ipv4
===== Définitions des politiques par défaut =====
Le fichier **/etc/shorewall/policy** permet de définir l'action du par feu si aucune règle définie ne correspond au paquet:
#
# Shorewall version 4 - Policy File
#
# For information about entries in this file, type "man shorewall-policy"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-policy.html
#
###############################################################################
#SOURCE DEST POLICY LOG LIMIT: CONNLIMIT:
# LEVEL BURST MASK
$FW rpn ACCEPT
rpn $FW ACCEPT
wan pwan ACCEPT
pwan wan ACCEPT
all all DROP info
Ici:
* Tout le trafic initié par l'hyperviseur à destination du réseau RPN est autorisé par défaut
* De même, tout le trafic provenant du réseau RPN à destination de l'hyperviseur est également autorisé. Ces deux règles sont nécessaires pour que les deux hyperviseurs puissent communiquer tranquillement entre eux (établissement des tunnels VPN, trafic GlusterFS, migration des VM etc...)
* Tout le trafic entre les zones wan et pwan est autorisé
* Tout le trafic entre pwan et wan l'est également (les hyperviseurs ne filtrent rien, ils transmettent simplement les paquets aux VM concernées, selon leurs IP Failover attribuées. À charge des VM de faire du filtrage sur leur interface connectée à ce réseau)
* Tout le reste est interdit, et les blocages sont journalisés
===== Définitions des variables =====
Le fichier **/etc/shorewall/params** permet de définir des variables, qui peuvent ensuite être utilisées dans les règles de filtrage. Ça facilite la maintenance des règles. Dans ce fichier, on peut y placer les IP de confiances qui seront les seules à pouvoir se connecter en SSH aux hyperviseurs par exemple
#
# Shorewall version 4 - Params File
#
# /etc/shorewall/params
#
# Assign any variables that you need here.
#
# It is suggested that variable names begin with an upper case letter
# to distinguish them from variables used internally within the
# Shorewall programs
#
# Example:
#
# NET_IF=eth0
# NET_BCAST=130.252.100.255
# NET_OPTIONS=routefilter,norfc1918
#
# Example (/etc/shorewall/interfaces record):
#
# net $NET_IF $NET_BCAST $NET_OPTIONS
#
# The result will be the same as if the record had been written
#
# net eth0 130.252.100.255 routefilter,norfc1918
#
###############################################################################
IP_BDX=11.12.13.14
IP_MRS=74.5.236.77,198.20.21.22
IP_RBX=57.26.2945
IP_TRUST=$IP_BDX,$IP_MRS,$IP_RBX
IP_ZBX=62.33.89.127
#LAST LINE -- DO NOT REMOVE
Dans cette exemple, on a définie les adresses IP des différents locaux de la société, qui pourront accéder gérer les hyperviseurs. La variable $IP_TRUST rassemble toutes les IP définies
===== Définition des règles de filtrage =====
Le fichier le plus important est probablement **/etc/shorewall/rules**. C'est dans ce fichier qu'on va définir nos règles spécifiques de filtrage. Il va falloir adapter ce fichier à votre environnement, voici un exemple:
#
# Shorewall version 4 - Rules File
#
# For information on the settings in this file, type "man shorewall-rules"
#
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-rules.html
#
######################################################################################################################################################################################
#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS SWITCH
# PORT PORT(S) DEST LIMIT GROUP
#SECTION ALL
#SECTION ESTABLISHED
#SECTION RELATED
SECTION NEW
# OUTPUT
ACCEPT $FW wan UDP 53
ACCEPT $FW wan UDP 123
ACCEPT $FW wan TCP 80,443,20,21
ACCEPT $FW all ICMP 8
# INPUT
ACCEPT any $FW ICMP 8
ACCEPT wan:$IP_TRUST $FW TCP 22
ACCEPT wan:$IP_ZBX $FW TCP 10050
Dans cet exemple:
* Connexions sortantes (initiées par l'hyperviseur)
* L'hyperviseur peut envoyer ses requêtes DNS via l'interface eth0 (UDP port 53)
* Il peut envoyer ses requêtes NTP via eth0 également (UIDP port 123)
* Il peut initier des connexions TCP sur les ports 80 (HTTP), 443 (https), 20 et 21 (FTP). Ces connexions sortantes sont nécessaires pour les mises à jour et l'installation de paquets depuis les dépôts
* Il peut émettre des icmp echo request (ping, aka icmp 8) vers n'importe qui toujours via eth0
* Connexion entrante (reçu par l'hyperviseur)
* N'importe qui peut le pinguer sur son IP publique. Vous pouvez le restreindre aux IP de confiance si nécessaire, mais en général, une réponse au ping ne pose aucun problème de sécurité
* Seules les IP de confiances ($IP_TRUST) peuvent ouvrir une connexion SSH (TCP port 22)
* Le serveur de monitoring ($IP_ZBX) peut se connecter sur le port 10050 (pour les curieux, c'est un serveur [[http://www.zabbix.com|Zabbix]] qui contact l'agent Zabbix sur ce port :-))
===== Activation du par feu =====
Avec une installation par défaut, shorewall refusera de démarrer, il faut éditer le fichier **/etc/shorewall/shorewall.conf** et remplacer STARTUP_ENABLED=No par STARTUP_ENABLED=Yes
sed -i -e "s/STARTUP_ENABLED=.*/STARTUP_ENABLED=Yes/g" \
/etc/shorewall/shorewall.conf
===== Démarrer le par feu =====
Attention, roulement de tambours, on va maintenant appliquer nos règles de filtrage.
Avant d'aller plus loin, assurez-vous de pouvoir récupérer l'accès à l'hyperviseur en cas d'erreur sur une règle qui vous couperait l'accès. Vous pouvez soit avoir à porté la console virtuelle depuis l'interface Online.net, soit vous créer un petit watchdog simpliste: dans une fenêtre, lancez la commande sleep 300 && reboot puis activez le par feu depuis une autre fenêtre. Si tout est OK, vous pouvez annuler la commande de redémarrage, mais si vous vous êtes coupé l'accès, le serveur redémarrera au bout de 5 minutes (et les règles de par feu ne s'appliqueront pas automatiquement puisqu'on a pas encore activé le démarrage de shorewall)
/etc/init.d/shorewall start
Si tout se passe bien, shorewall ne devrait loguer aucune erreur, et commencer son filtrage. Vous pouvez suivre les paquets bloqués dans **/var/log/messages**.
Vous pouvez maintenant faire exactement la même chose sur le deuxième hyperviseur.
Une fois que vous vous êtes assuré que les règles de filtrages sont fonctionnelles, il ne reste plus qu'à activer shorewall au démarrage:
chkconfig shorewall on
====== Définition des règles de proxy ARP ======
On y est presque, il ne manque plus qu'à définir les règles de proxy ARP. Ce n'est pas du par feu à proprement parler, mais Shorewall permet de simplifier cette mise en place (activation du mode proxy sur l'interface brwan, ajout des règles de routage etc...) alors pourquoi s'en priver ;-)
Les hyperviseurs ne feront pas de routage du trafic, excepté entre les réseaux **wan** et **pwan**. L'interface physique des hyperviseurs (eth0) recevra les trames à destinations des IP publiques des VM (les IP failovers), et les transmettra sur le réseau **pwan** (via le pont **brwan**) grâce à une configuration en proxy ARP. Cette technique présente plusieurs avantages par rapport à du bridging simple:
* Pas de risque de diffuser une MAC non déclarée sur le réseau Online, et donc pas de risque d'une mise en sécurité du port de l'hyperviseur.
* Possibilité d'attribuer plusieurs IP publiques à une seule VM (ce qui n'est pas possible avec le bridging, puisqu'on doit déclarer à l'avance une MAC générée aléatoirement à chaque IP Failover)
* Grâce au tunnel OpenVPN mis en place, les VM se chargeant du routage peuvent également être migrées d'un hyperviseur à l'autre sans perte de connectivité.
Dans le fichier **/etc/shorewall/proxyarp**, nous allons ajouter une ligne par IP Failover qui sera attribuée à une machine virtuelle:
#
# Shorewall version 4 - Proxyarp File
#
# For information about entries in this file, type "man shorewall-proxyarp"
#
# See http://shorewall.net/ProxyARP.htm for additional information.
#
###############################################################################
#ADDRESS INTERFACE EXTERNAL HAVEROUTE PERSISTENT
88.190.23.99 brwan eth0 No Yes
88.191.89.16 brwan eth0 No Yes
Dans cet exemple, **88.190.23.99** et **88.191.89.16** sont deux IP failovers redirigées vers un des deux hyperviseurs (et la beauté de tout ce système, c'est qu'on s'en fou sur lequel des deux l'IP est redirigée).
Ajoutez sur chaque hyperviseurs uniquement les adresses IP Failovers qui lui sont redirigées dessus.
===== Automatiser les mises à jour des règles de prox ARP =====
On vient de voir comment mettre en place les règles de proxy ARP, mais ça serait quand même plus classe si nos deux hyperviseurs pouvaient mettre à jour automatiquement ces règles: ainsi plus besoin de toucher aux hyperviseurs, on ajoute une IP failover sur un des deux, et il modifiera sa configuration automatiquement en conséquence. Non seulement ça serait plus classe, mais en plus, c'est possible :-)
==== Création d'un script de re-configuration des interfaces wan ====
En cas de changement d'une IP failover d'un hyperviseur vers l'autre, il fat re-configurer les deux interfaces eth0 et brwan. Plutôt que de relancer toute la stack réseau (qui couperait l'accès aux volumes gluster), on va créer un script qui ne re-configure que les deux interfaces nécessaires:
cp -a /etc/init.d/network /etc/init.d/wan
cat <<'EOF' > wan.patch
--- /etc/init.d/network 2013-01-09 12:13:29.000000000 +0100
+++ /etc/init.d/wan 2013-07-21 16:13:06.526176211 +0200
@@ -40,12 +40,7 @@
# find all the interfaces besides loopback.
# ignore aliases, alternative configurations, and editor backup files
-interfaces=$(ls ifcfg* | \
- LANG=C sed -e "$__sed_discard_ignored_files" \
- -e '/\(ifcfg-lo$\|:\|ifcfg-.*-range\)/d' \
- -e '/ifcfg-[A-Za-z0-9#\._-]\+$/ { s/^ifcfg-//g;s/[0-9]/ &/}' | \
- LANG=C sort -k 1,1 -k 2n | \
- LANG=C sed 's/ //')
+interfaces="brwan eth0"
rc=0
# See how we were called.
@@ -60,9 +55,6 @@
apply_sysctl
- # bring up loopback interface
- action $"Bringing up loopback interface: " ./ifup ifcfg-lo
-
case "$VLAN" in
yes)
if [ ! -d /proc/net/vlan ] && ! modprobe 8021q >/dev/null 2>&1 ; then
@@ -213,10 +205,6 @@
)
done
- action $"Shutting down loopback interface: " ./ifdown ifcfg-lo
-
- sysctl -w net.ipv4.ip_forward=0 > /dev/null 2>&1
-
# IPv6 hook (post IPv4 stop)
if [ -x /etc/sysconfig/network-scripts/init.ipv6-global ]; then
/etc/sysconfig/network-scripts/init.ipv6-global stop post
EOF
patch /etc/init.d/wan wan.patch
==== Mise en place du script failover_updater ====
On va créer un petit script perl sur chaque hyperviseur. Ce script demandera à intervalles régulières quelles IP Failovers lui sont redirigées dessus, et il pourra ainsi mettre à jour la configuration de shorewall.
Placez ce script dans /usr/local/bin/failover_updater.pl
#!/usr/bin/perl -w
use strict;
use LWP;
use JSON;
use Getopt::Long;
use File::Compare;
use File::Copy;
my ($key, $id) = '';
GetOptions(
"key=s" => \$key,
"id=s" => \$id
);
if ($key eq '' || $id eq ''){
print "Usage: $0 --key= --id=\n";
exit(1);
}
# Used to hide api key
$0 = 'failover updater';
my $c = LWP::UserAgent->new;
my $r = $c->get("https://api.online.net/api/v1/server/info/$id",
"Authorization" => "Authorization: Bearer $key",
);
unless ($r->is_success){
print "an error occured while querying the API" .
"The error is: " . $r->status_line;
exit(2);
}
my $data = from_json($r->content);
open TMP, ">/tmp/proxyarp" || die "Cannot open /tmp/proxyarp";
# Print the file header
print TMP <<"EOF";
###############################################################################
##ADDRESS\t\tINTERFACE\tEXTERNAL\tHAVEROUTE\tPERSISTENT
EOF
# Now add one arp proxy rule per failover IP
# redirected to ourself
foreach my $ip ( @{$data->{'network'}->{'ipfo'}} ){
print TMP "$ip\t\tbrwan\t\teth0\t\tNo\t\tYes\n";
}
close TMP;
if (compare("/etc/shorewall/proxyarp", "/tmp/proxyarp") != 0){
# Looks like IP Failover changed, we need to update shorewall
# # config, reload it and flush the ARP cache
print "Updating ARP Proxy config and flushing cache...\n";
move ("/tmp/proxyarp", "/etc/shorewall/proxyarp");
system("/sbin/restorecon -R /etc/shorewall >/dev/null 2>&1");
# Wait a few second for the new routing rules to take place
# It will result in more down time if we update too early
sleep(90);
system("/etc/init.d/wan restart >/dev/null 2>&1");
system("/etc/init.d/shorewall reload >/dev/null 2>&1");
}
else{
unlink "/tmp/proxyarp";
}
Donnez les droits d'exécution:
chmod +x /usr/local/bin/failover_updater.pl
Installez les dépendances perl:
yum install perl-JSON perl-libwww-perl
Ajoutez une tâche cron:
cat <<'EOF' > /etc/cron.d/failover_updater
* * * * * root /usr/local/bin/failover_updater.pl --key=__API_KEY__ --id=__ONLINE_ID__
EOF
chmod 640 /etc/cron.d/failover_updater
sed -i -e "s/__API_KEY__/$(cat /etc/install/api_key)/g" \
-e "s/__ONLINE_ID__/$(cat /etc/install/online_sdx)/g" \
/etc/cron.d/failover_updater
Et voilà, tout est prêt. Toutes les minutes, les hyperviseurs vont demander quelles IP Failover leur sont attribuées, et re-configurer ce qui est nécessaire. En cas de bascule d'une IP Failover d'un hyperviseur vers l'autre (pour maintenance par exemple), il faut compter entre 1 et 2 minutes de coupure le temps que le nouveau routage se mette en place, que les hyperviseur récupèrent la nouvelle configuration et re-configure le nécessaire.
====== Migration des invités à l'arrêt ======
Pour finir, on va mettre un petit script sur les deux hyperviseurs. Il va permettre de migrer automatiquement les VM sur le deuxième hyperviseur pendant l'arrêt du serveur. Si le deuxième hyperviseur n'est pas joignable, alors on va simplement sauvegarder l'état des VM (virsh managedsave)
* Placez ce script dans /usr/local/bin/migrate_all.pl
#!/usr/bin/perl -w
use strict;
use Sys::Virt;
my ($local,$remote) = undef;
eval { $local = Sys::Virt->new( uri => 'qemu:///system' ); };
if ($@){
# No connection to the local libvirt
# We can't do anything
die 'Error connecting to libvirt on URI: qemu:///system: '. $@;
}
eval { $remote = Sys::Virt->new( uri => 'qemu+ssh://fws@peer/system' ); };
if ($@){
# No connection to the remote server
# Let's try to managed save all running domain
foreach my $dom ($local->list_all_domains()){
next unless $dom->is_active;
$dom->managed_save();
}
}
else{
# We have a connection to both the local and
# the remote libvirt. Lets try to migrate
# all our running domain to our friend
foreach my $dom ($local->list_all_domains()){
next unless $dom->is_active;
$dom->migrate($remote, Sys::Virt::Domain::MIGRATE_LIVE | Sys::Virt::Domain::MIGRATE_PEER2PEER | Sys::Virt::Domain::MIGRATE_TUNNELLED);
}
}
* Rendez-le exécutable
chmod +x /usr/local/bin/migrate_all.pl
* Créez un script d'init rc.shutdown
cat <<'EOF' > /etc/init.d/rc.shutdown
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
case "$1" in
stop)
if [ -x /etc/rc.shutdown ]; then
logger "Running local shutdown scripts (/etc/rc.shutdown)"
/etc/rc.shutdown
fi
;;
start)
# nothing to do
;;
*)
echo "Usage: $0 start|stop" >&2
exit 3
;;
esac
EOF
chmod +x /etc/init.d/rc.shutdown
ln -sf /etc/rc.d/init.d/rc.shutdown /etc/rc0.d/K00rc.shutdown
ln -sf /etc/rc.d/init.d/rc.shutdown /etc/rc6.d/K00rc.shutdown
* Créez le fichier /etc/rc.shutdown, qui appelera notre petit script perl responsable de la migration
cat <<'EOF' > /etc/rc.shutdown
#!/bin/sh
/usr/local/bin/migrate_all.pl
EOF
chmod +x /etc/rc.shutdown
* Enlevez le script libvirt-guests
chkconfig --del libvirt-guests
si ce script fonctionne très bien en exécution manuelle, il ne contact pas l'hyperviseur distant pendant un arrêt (il est pourtant appelé au tout début de la phase d'arrêt) et se contente de mettre les VM en pause. Elles peuvent être réveillées immédiatement sur le second, mais ça demande une intervention manuelle, et c'est justement pas le but :-/ Si quelqu'un à une idée, je suis preneur
====== Créer un invité ======
On peut maintenant s'attaquer à la création d'un invité sur notre nouveau cluster tout neuf. La création est assez simple, pensez simplement à utiliser le pool **iso** pour stocker les ISO d'installation, et un autre pool pour les VM (pas obligatoire, mais plus propre)
* Au niveau réseau, vous pouvez connecter les interfaces des invités au pont **brlan** ou **brwan**. Les interfaces connectées sur **brwan** disposeront d'une IP publique (voir la suite). Les machines connectées uniquement à **brlan** sont complètement isolés. Il vous faudra probablement créer une passerelle virtuelle ayant une interface sur **brwan** et une autre sur **brlan** qui servira de passerelle. [[http://wiki.contribs.org|SME Server]] et [[http://pfsense.org|PfSense]] sont d'excellents candidats :-)
* Au niveau des disques, il faut mettre le cache à "**none**" (par défaut, il a la valeur "default", qui correspond à "passthrough"). Les migrations à chaud entre les deux hyperviseurs ne seront pas possibles tant que le cache ne sera pas mis à "none"
===== Configuration d'une IP publique dans un invité =====
Pour donner une IP publique à un invité, et donc faire en sorte qu'il soit directement connecté à Internet (sans aucun NAT ou filtrage), il faut:
* Rediriger une IP failover sur un de vos deux hyperviseurs depuis la console Online (peut importe sur quel hyperviseur l'IP est redirigée)
* Pendant l'installation, vous n'aurez probablement pas la possibilité de mettre la configuration réseau définitive, il va donc falloir jouer avec le masque réseau. Pour faire court:
* L'adresse IP à configurer est l'IP failover
* La passerelle est la passerelle de l'hyperviseur sur lequel l'IP failover est redirigée
* ajustez le masque réseau pour que l'IP failover soit dans le même réseau que la passerelle (avec un peu de chance un 255.255.255.0 suffit, mais on peut augmenter jusqu'au 255.0.0.0 si nécessaire, selon les IP failover dont vous disposez)
* Une fois que l'installation est terminée, on va pouvoir mettre en place la configuration définitive. En gros, il faut:
* Mettre un masque réseau de 255.255.255.255 sur l'interface externe
* Ajouter une route statique vers la passerelle (qui est la passerelle de l'hyperviseur sur lequel est attribué l'IP failover), par exemple:
ip route add 88.190.47.1 dev eth1
voir [[http://documentation.online.net/fr/serveur-dedie/reseau/ip-failover#configuration_de_votre_serveur|cette page]] pour plus d'information sur la configuration réseau
====== Réinstallation d'un serveur ======
En cas de crash important, nécessitant une ré-installation complète d'un des deux hyperviseurs, la plupart de ce tuto peut être suivit sans actions particulière, sauf pour la partie GlusterFS. Voilà les étapes à suivre pour re-synchroniser les 3 volumes:
* Re-créez les bricks à leur emplacement normal (/mnt/bricks/sanlock, /mnt/bricks/save et /mnt/bricks/vmstore)
* Installez les composants glusterfs
* Récupérez l'UUID de l'hôte qui vient d'être réinstallé (cet UUID peut se récupérer sur le serveur encore fonctionnel dans le répertoire /var/lib/glusterd/peers
* Restaurez cet UUID sur le nouveau serveur dans le fichier /var/lib/glusterd/glusterd.info. Ce fichier doit ressembler à quelques chose comme ça:
UUID=34de250b-fba2-462f-8f68-e19cdee31111
operating-version=2
* Depuis le nouveau serveur, faites un peer probe de l'ancien, exemple:
gluster peer probe hyp2
* On re-synchronise les informations de volumes depuis l'ancien serveur encore fonctionnel
gluster volume sync hyp1 all
* On restaure les attributs étendus utilisé par GlusterFS sur les bricks. Sans cette étape, point de synchro. On lance cette commande depuis l'ancien serveur (hyp1)
rsync -dvPt --xattrs /mnt/bricks/ root@hyp2:/mnt/bricks/
* On remonte les 3 volumes GlusterFS à leurs emplacements
* On force une synchronisation des données:
find /var/lib/libvirt/
====== TODO ======
* Ajouter codes couleurs (hyp1, hyp2 ou les deux)
* Verrous sur les disques (sanlock ?) (voir http://libvirt.org/locking.html)
* Ajouter une tâche cron pour nettoyer les leases (virt-sanlock-cleanup)
* Mesure perf GlusterFS sur du Gigabit
* Migrer automatiquement les VM vers l'autre hyperviseur pendant l'arrêt ?
* Solution de sauvegardes à chaud des VM
* Scripts d'ajout des interfaces OpenVPN tab au bridge correspondant
* Script d'ajout de nouveau réseau privé
* Crée un réseau isolé libvirt
* Crée une configuration OpenVPN qui va bien
* Relance OpenVPN pour connexion immédiate
* Config firewall hyperviseurs
* Pas de communication entre les VM et les hyperviseurs
* Config proxy ARP hyperviseurs / attribution d'IP failover aux VM sans NAT
* Lors du redémarrage d'un hyperviseur surlequel des IP failover sont redirigées, il faut désactiver le proxy arp sur brwan de l'autre hyperviseur pour que le routage revienne (echo 0 > /prox/sys/net/ipv4/conf/brwan/proxy_arp && sleep 3 && echo 1 > /prox/sys/net/ipv4/conf/brwan/proxy_arp)
* Il semble qu'il faille relancer openvpn sur les deux hyperviseurs après un redémarrage de l'un des deux (même si les tunnels s'établissent proprement, pas de lien ethernet)
* Empêcher le démarrage auto des VM au démarrage de l'hôte (via un script hook de libvirt ?)
* Créer un volume gluster indépendant pour stocker les ISO d'install
* Depuis Gluster 3.4, il peut y avoir des conflits entre les ports utilisés par glusterfsd et les ports utilisés pour la migration simple (plain TCP) des VM. Il faut trouver comment modifier la plage de port de l'un ou de l'autre (au pire, une migration tunnelée (--tunnelled) de libvirt fonctionne toujours, mais ça serait plus élégant si les options de migrations par défaut de virt-manager fonctionnaient à tous les coups)