Installation d'un noeud du cluster pour machines virtuelles OpenVZ et KVM
Pré-requis
Gestion attachement Fiber Channel
Matériels équipés de cartes QLogic :
# apt-get install firmware-qlogic # update-initramfs -u
Gestion du SAN et du double attachement :
# apt-get install multipath-tools scsitools lsscsi
Réseau
Il s'agit de constituer :
- un agrégat de cartes réseau (channel bonding) en mode actif/passif, qui inclut les cartes eth0 et eth1 : bond0
- un bridge entre l'interface bond0 et les cartes ethernet virtuelles pour OpenVZ
Concernant le bridge pour OpenVZ, la section décrivant la configuration réseau dans Installation d'un serveur Debian - hôte OpenVZ + KVM n'est pas applicable telle quelle, car il faut combiner avec la configuration bonding des cartes réseau.
Taper
# apt-get install ifenslave-2.6 bridge-utils
Créer le fichier /usr/local/sbin/bridge-bonding avec le contenu suivant (version adaptée du script trouvé à cette adresse) :
#!/bin/sh
COMMAND=$1
BRIDGE=$2
BOND=$3
# Usage: transfer_addrs src dst
# Copy all IP addresses (including aliases) from device $src to device $dst.
transfer_addrs () {
local src=$1
local dst=$2
# Don't bother if $dst already has IP addresses.
if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then
return
fi
# Address lines start with 'inet' and have the device in them.
# Replace 'inet' with 'ip addr add' and change the device name $src
# to 'dev $src'.
ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
s/inet/ip addr add/
s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
s/${src}/dev ${dst}/
" | sh -e
# Remove automatic routes on destination device
ip route list | sed -ne "
/dev ${dst}\( \|$\)/ {
s/^/ip route del /
p
}" | sh -e
}
# Usage: transfer_routes src dst
# Get all IP routes to device $src, delete them, and
# add the same routes to device $dst.
# The original routes have to be deleted, otherwise adding them
# for $dst fails (duplicate routes).
transfer_routes () {
local src=$1
local dst=$2
# List all routes and grep the ones with $src in.
# Stick 'ip route del' on the front to delete.
# Change $src to $dst and use 'ip route add' to add.
ip route list | sed -ne "
/dev ${src}\( \|$\)/ {
h
s/^/ip route del /
P
g
s/${src}/${dst}/
s/^/ip route add /
P
d
}" | sh -e
}
# Usage: create_bridge bridge
create_bridge () {
local bridge=$1
# Don't create the bridge if it already exists.
if ! brctl show | grep -q ${bridge} ; then
brctl addbr ${bridge}
brctl stp ${bridge} off
brctl setfd ${bridge} 0
fi
ip link set ${bridge} up
}
# Usage: show_status dev bridge
# Print ifconfig and routes.
show_status () {
local dev=$1
local bridge=$2
echo '============================================================'
ip addr show ${dev}
ip addr show ${bridge}
echo ' '
brctl show ${bridge}
echo ' '
ip route list
echo ' '
route -n
echo '============================================================'
}
op_start () {
create_bridge $BRIDGE
wait_for_running_state $BOND
add_to_bridge $BRIDGE $BOND
transfer_addrs $BOND $BRIDGE
transfer_routes $BOND $BRIDGE
}
op_stop () {
transfer_routes $BRIDGE $BOND
ip link set $BRIDGE down
brctl delbr $BRIDGE
}
# Usage: add_to_bridge bridge dev
add_to_bridge () {
local bridge=$1
local dev=$2
# Don't add $dev to $bridge if it's already on a bridge.
if ! brctl show | grep -q ${dev} ; then
brctl addif ${bridge} ${dev}
fi
}
# waits for $dev to be in running state
wait_for_running_state() {
local dev=$1
local maxtries=10
echo -n "Waiting for ${dev} to negotiate link."
for i in `seq ${maxtries}` ; do
if ifconfig ${dev} | grep -q RUNNING ; then
break
else
echo -n '.'
sleep 1
fi
done
if [ ${i} -eq ${maxtries} ] ; then echo '(link isnt in running state)' ; fi
}
usage(){
echo "Usage: `basename $0` <command> [<bridge_if> <bond_if>]"
echo "Valid commands are: start, stop, status"
echo "bridge_if and bond_if should be specified if start or stop"
exit 1
}
case "$COMMAND" in
start)
op_start
;;
stop)
op_stop
;;
status)
show_status ${netdev} ${bridge}
;;
*)
usage
;;
esac
Puis le rendre éxecutable
# chmod +x /usr/local/sbin/bridge-bonding
dans /etc/network/interfaces
# The loopback network interface auto lo iface lo inet loopback auto bond0 iface bond0 inet static address x.x.x.x netmask x.x.x.x broadcast x.x.x.x gateway x.x.x.x up /sbin/ifenslave bond0 eth0 up /sbin/ifenslave bond0 eth1 up sysctl net.ipv4.conf.bond0.proxy_arp=1 up /usr/local/sbin/bridge-bonding start vzbr0 bond0 up sysctl net.ipv4.conf.vzbr0.proxy_arp=1 up sysctl net.ipv4.conf.vzbr0.forwarding=1 down /usr/local/sbin/bridge-bonding stop vzbr0 bond0
Debian 4 et 5
dans /etc/modprobe.d/arch/i386, ajouter :
alias bond0 bonding options bonding mode=1 miimon=100 downdelay=200 updelay=200
Debian 6
Créer le fichier /etc/modprobe.d/bonding.conf avec le contenu suivant :
alias bond0 bonding options bonding mode=1 miimon=100 downdelay=200 updelay=200
Note : mode 1 signifie active/backup http://www.karlesnine.com/spip.php?article99
mode 6 serait intéressant (adaptative load balancing) mais plante (en tout cas sur debian 4, à retester peut-être)
Paramétrage ssh des noeuds du cluster pour authentification par certificat
Certains des vzscripts s'appuient sur ssh pour réaliser les opérations à distances, comme le déplacement d'une machine virtuelle. Afin de facilité ces opérations, il est nécessaire de mettre en place une authentification par clé pour ssh.
Sur le premier noeud du cluster il faut générer, dans le répertoire /root/.ssh, et avec le compte root, un couple de clé public/privé pour chaque machine via la commande:
# ssh-keygen -t dsa
On obtient ainsi deux fichiers : id_dsa et id_dsa.pub Le contenu du fichier id_dsa.pub doit être présent dans le fichier authorized_keys des tous les noeuds du cluster de sorte que depuis ce noeud on puisse lancer des commandes sur tous les noeuds sans qu'un mot de passe soit demandé.
On commence par ce noeud :
# ssh-copy-id -i ~/.ssh/id_dsa.pub root@localhost
A partir de cet instant, il est beaucoup plus simple de recopier le répertoire /root/.ssh sur tous les noeuds plutôt que de créer des clés différentes sur chaque noeud qu'il faudrait intégrer sur tous, car le nombre d'opérations à faire pour intégrer un noeud serait fonction du nombre de noeuds déjà présents.
Sur tous les autres noeuds il suffit donc de recopier le répertoire /root/.ssh d'un noeud déjà intégré vers le noeud à intégrer :
# scp -r /root/.ssh root@nouveau_noeud:
Une première connexion d'une machine vers une autre doit permettre la mise à jour du fichier /root/.ssh/known_hosts et ensuite l'authentification se fait de façon transparente.
Mise à jour du fichier /etc/hosts
Afin que les commandes assurant la communication entre les noeuds du cluster OpenVZ fonctionnent en l'absence de serveur DNS, il faut que le fichier /etc/hosts de tous les noeuds contienne les adresses de tous les noeuds. Exemple de fichier /etc/hosts :
127.0.0.1 localhost 10.0.0.1 noeud1 10.0.0.2 noeud2 10.0.0.3 noeud3 10.0.0.4 noeud4 10.0.0.5 noeud5 10.0.0.6 noeud6 # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts
Préparation des scripts
- sur le nouveau noeud, créer le répertoire :
# mkdir /etc/vzcluster
- s'il s'agit du premier noeud, récupérer les scripts depuis cette documentation et placer les fichiers de configuration dans /etc/vzcluster et les scripts dans /usr/sbin/
- sinon, depuis un noeud déjà intégré, éditer le fichier de configuration /etc/vzcluster/vzclustermember.conf pour déclarer le nouveau noeud, puis faire :
# vzdiffuse_script # vzdiffuse_conf