[ libresys ]

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

 

Avertissement : Les documentations disponibles dans ce wiki sont tirées des documentations que j'ai rédigées dans le cadre de mon activité professionnelle, que j'ai ensuite adaptées afin d'en éliminer toute référence à un contexte spécifique du système d'information que j'administre et de les rendre plus facilement réutilisables. Cela implique que je ne les ai pas appliquées dans l'état où elles sont présentées dans ce wiki et qu'elles peuvent comporter des erreurs. Merci de me les signaler le cas échéant, et en cas de doute, n'hésitez pas à me questionner à travers l'article adéquat du blog.

Vous pouvez utiliser les informations, documentations et conseils diffusés à travers ce site à vos risques et périls. Je ne saurais être tenu pour responsable des conséquences que leur utilisation pourrait vous occasionner.

Sauf mention contraire, le contenu de ce wiki est placé sous la licence suivante : CC Attribution-Noncommercial-Share Alike 3.0 Unported