Migration vers KVM avec WebVirtMgr

Une migration tournée vers l'open-source

Afin d'assuré la pérennité et la stabilité dans mon infrastructure, j'ai choisi KVM : standard ouvert, inter-opérable, aux fonctionna litées immenses. Plus précisément, ce nouveau projet s'inscrit dans m'a volonté d'être au plus proche de mon système Linux. KVM est présent dans les plus grands projets de cloud computing : openstack, opennebula, ovirt ainsi que bien d'autres.

En plus de KVM, il existe aussi ce fabuleux système de conteneur appelé docker, qui se base lui aussi intégralement sur Linux. Ils représentent à tous les deux de merveilleuse possibilités d'apprentissage pour comprendre le cloud. La gestion de KVM se fera en grande partie avec une interface en HTML5. Pour docker il existe : Shipyard que je n'évoquerai pas dans l'article.

L'ensemble de mon article ce base principalement sur le wiki de KVM, de WebVirtMgr ainsi que de libvirt.

La solution SaaS : WebVirtMgr

WebVirtMgr ce présente sous la forme d'une interface web développée en bootstrap. Elle utilise l'API libvirt pour la gestion du ou des hyperviseurs, des réseaux, des interfaces, des stockages et des VMs. WebVirtMgr ce présente sous la forme d'une interface web développée en bootstrap. L'accès à la VMs ce fera quand à elle via une console en VNC (novnc) ou html5 "spice". 
Plus d'information sur : webvirtmgr.

Voici une illustration de mon infrastructure :

WebVirtMgr et l'hyperviseur KVM/QEMU

KVM (Kernel Virtual Machine) est un module du noyau Linux qui permet à un programme de l'espace utilisateur d'utiliser les fonctionnalités de virtualisation matérielle de différents processeurs. Aujourd'hui, il prend en charge les processeurs Intel récents et processeurs AMD (x86 et x86_64), PPC 440, PPC 970, S / 390, ARM (Cortex A15), et MIPS32. (emulation processeur)

QEMU peut faire usage de KVM lors de l'exécution d'une architecture cible qui est la même que l'architecture de l'hôte. Par exemple, lors de l'exécution qemu-system-x86 sur un processeur compatible x86, vous pouvez profiter de l'accélération de KVM - donnant vous bénéficiez pour votre accueil et votre système invité. (émulation de machine virtuelle).

source : http://wiki.qemu.org/KVM

Pré-requis avant l’installation

  • Le processeur doit être compatible avec les technologies de virtualisation  :
egrep '^flags.*(vmx|svm)' /proc/cpuinfo

Si un résultat apparait alors votre processeur est opérationnel. Sinon c'est que votre processeur ne supporte pas la virtualisation.
Pas de panique ! il existe webvirtmgr avec lxc et docker bien-entendu : découvrez le !

  • Installer les paquets suivants :
apt-get install kvm libvirt-bin bridge-utils sasl2-bin
  • Télécharger le script de retspen et exécutez-le :
wget http://retspen.github.io/libvirt-bootstrap.sh 
sh libvirt-bootstrap.sh

Pour information, a la fin du script vous deviez avoir les services suivants en fonctionnement :

  • [ ok ] Starting system message bus: dbus.
  • [ ok ] Starting libvirt management daemon: libvirtd.

Installation de WebVirtMgr

WebVirtMgr à besoin des paquets suivants pour fonctionner :

apt-get install git python-pip python-libvirt python-libxml2 novnc supervisor

Durant (la longue) installation, différentes questions feront leurs apparitions :

faut-il installer une base de données pour NOVA : oui
faut-il configurer la base de données de nova-common avec dbconfig-common : oui
type de serveur de base de données à utiliser avec nova-common ! sqlite3

La prochaine étape consiste à configurer python et l'environnement "django" :

mkdir /var/www

Déplacer vous dans le répertoire "www" :

cd /var/www

Télécharger le "git" de WebVirtMgr :

git clone git://github.com/retspen/webvirtmgr.git

Rendez-vous dans le répertoire suivant :

cd webvirtmgr

L'outil pip est utilise car il installera rapidement et télécharge automatiquement les dépendances nécessaires :

sudo pip install -r requirements.txt

Downloading/unpacking django==1.5.5 (from -r requirements.txt (line 1))
  Downloading Django-1.5.5.tar.gz (8.1MB): 8.1MB downloaded
  Running setup.py (path:/tmp/pip_build_root/django/setup.py) egg_info for package django

    warning: no previously-included files matching '__pycache__' found under directory '*'
    warning: no previously-included files matching '*.py[co]' found under directory '*'
Downloading/unpacking gunicorn==18.0 (from -r requirements.txt (line 2))
  Downloading gunicorn-18.0.tar.gz (366kB): 366kB downloaded
  Running setup.py (path:/tmp/pip_build_root/gunicorn/setup.py) egg_info for package gunicorn

    warning: no previously-included files matching '*.pyc' found under directory 'docs'
    warning: no previously-included files matching '*.pyo' found under directory 'docs'
    warning: no previously-included files matching '*.pyc' found under directory 'tests'
    warning: no previously-included files matching '*.pyo' found under directory 'tests'
    warning: no previously-included files matching '*.pyc' found under directory 'examples'
    warning: no previously-included files matching '*.pyo' found under directory 'examples'
Downloading/unpacking lockfile>=0.9 (from -r requirements.txt (line 5))
  Downloading lockfile-0.10.2-py2-none-any.whl
Installing collected packages: django, gunicorn, lockfile
  Running setup.py install for django
    changing mode of build/scripts-2.7/django-admin.py from 644 to 755

    warning: no previously-included files matching '__pycache__' found under directory '*'
    warning: no previously-included files matching '*.py[co]' found under directory '*'
    changing mode of /usr/local/bin/django-admin.py to 755
  Running setup.py install for gunicorn

    warning: no previously-included files matching '*.pyc' found under directory 'docs'
    warning: no previously-included files matching '*.pyo' found under directory 'docs'
    warning: no previously-included files matching '*.pyc' found under directory 'tests'
    warning: no previously-included files matching '*.pyo' found under directory 'tests'
    warning: no previously-included files matching '*.pyc' found under directory 'examples'
    warning: no previously-included files matching '*.pyo' found under directory 'examples'
    Installing gunicorn_paster script to /usr/local/bin
    Installing gunicorn script to /usr/local/bin
    Installing gunicorn_django script to /usr/local/bin
  Found existing installation: lockfile 0.8
    Uninstalling lockfile:
      Successfully uninstalled lockfile
Successfully installed django gunicorn lockfile
Cleaning up...

Lancer la création de la base de données via django :

./manage.py syncdb
WARNING:root:No local_settings file found.
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table servers_compute
Creating table instance_instance
Creating table create_flavor

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Please enter either "yes" or "no": yes
Please enter either "yes" or "no": yes
Username (leave blank to use 'root'): kassianoff
Email address: postmaster@kassianoff.fr
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 6 object(s) from 1 fixture(s)

On recommence avec cette fois-ci "collectstatic" :

./manage.py collectstatic

Type 'yes' to continue, or 'no' to cancel: yes
75 static files copied

Donner les droits au serveur web dans le répertoire de WebVirtMgr :

chown -R www-data:www-data /var/www/webvirtmgr/

Modification du script et du lancement de VNC :

sudo service novnc stop
[ ok ] Stopping OpenStack NoVNC proxy: nova-novncproxy.

Suppression du script au lancement de notre distribution debian :

update-rc.d -f novnc remove
update-rc.d: using dependency based boot sequencing

Suppression du script dans init.d :

rm /etc/init.d/novnc

Renseigner des paramètres de lancement dans le fichier "webvirtmgr.conf" :

nano /etc/supervisor/conf.d/webvirtmgr.conf
[program:webvirtmgr]
command=/usr/bin/python /var/www/webvirtmgr/manage.py run_gunicorn -c /var/www/webvirtmgr/conf/gunicorn.conf.py
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/webvirtmgr.log
redirect_stderr=true
user=www-data

[program:webvirtmgr-console]
command=/usr/bin/python /var/www/webvirtmgr/console/webvirtmgr-console
directory=/var/www/webvirtmgr
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/webvirtmgr-console.log
redirect_stderr=true
user=www-data

On arréte le service supervisor et on le démarre :

service supervisor stop
service supervisor start

L'installation est terminé et nous pouvons désormais accédé à l'interface WebVirtMgr via le port 8000 de notre machine.

Le tunneling SSH sous linux

La méthode du tunnelling ssh permet la redirection des ports 8000 et 6080 (novnc) vers notre poste client (sécurisé) :

ssh root@webvirtmgr.kassianoff.fr:port -L localhost:8000:localhost:8000 -L localhost:6080:localhost:6080

Rendez-vous sur l'url : localhost:8000 et rentrer vos identifiants de connexion configuré lors du "./manage.py syncdb" :

Connexion entre WebVirtMgr et KVM/QEMU

Plusieurs étapes seront nécessaire avant de pouvoir configurer l'infrastructure.

  • Créer vos identifiants de connexion TCP comme ceci :
saslpasswd2 -a libvirt kassianoff.fr
Password: 
Again (for verification): 
  • Déclarer votre hyperviseur dans virsh :
virsh -c qemu+tcp://localhost/system nodeinfo
Please enter your authentication name: kassianoff.fr
Please enter your password:
CPU model:           x86_64
CPU(s):              8
CPU frequency:       1632 MHz
CPU socket(s):       1
Core(s) per socket:  4
Thread(s) per core:  2
NUMA cell(s):        1
Memory size:         32917020 KiB

Désormais ajoutons notre connexion TCP en cliquant sur le bouton : "Add connection"

Le résultat est le suivant :

 

Prise en main de la solution WebVirtMgr

Il me semble important de comprendre les différentes rubrique qui compose WebirtMgr :

  • Instances : Gestion et création de machines virtuelles ce sont nos instances.
  • Storages : Gestion et création des différents "pools" de stockage (repertoire, iso, nfs, lvm...).
  • Networks : Gestion et création des réseaux (bridge,route,nat...)
  • interfaces : Gestion et création des différentes interfaces que peuvent utiliser les réseaux.
  • secrets : (Je n'ai pas eu d'information la concernant, si un visiteur à des informations je suis preneur !)
  • Overview : Superviser l'ensemble de notre infrastructure : ressouces utilisées (cpu,mémoire etc...).

J'ai utilisé toute les rubriques (excepté "Secrets"), commencez par suivre les étapes ci-dessous pouvoir créer une instances.

Création des pools de stockage

Avant de démarrer la création d'une machine, nous aurons besoin de "pool de stockage", cliquez sur "Storages" puis sur "New storages" la configuration est la suivante :

  1. Création d'un repertoire "DIR" avec le chemin "/var/lib/libvirt/images"
  2. Création du répertoire "ISO" avec le chemin "/var/www/webvirtmgr/images" :
  3. Sur un dédié OVH, utiliser NFS-common, etcréez un répertoire "nfs" pour le connecter au NFS backup storage :
     
    apt-get install nfs-common
    mkdir /var/lib/libvirt/nfs/
    mount -t nfs ftpback-rbxX-XXX.ovh.net:/export/ftpbackup/nsXXXXXXX.ovh.net /var/lib/libvirt/nfs/
  4. Dans la création du "pool" il existe le mode NETFS compatible avec NFS, cependant le format n'est pas pris en compte !
    La solution consiste à utiliser  le mode "dir" en spécifiant le répertoire "nfs" précédemment monté :
  5. Vérifiez vos différents pool de storage dit : "nfs", "iso", "images" :

Je ne vais pas évoqué la création d'une machine dans le menu "images" ni même l'ajout d'un fichier ISO via WebVirtMgr.
La raison est simple j'utilise le terminal pour ses tâches là. Concentrons-nous sur les réseaux avant de créer notre VM.

La rubriques networks dans WebVirtMgr

L'ajout de réseaux ce fait via l'onglet "networks", ajoutez deux réseaux bridge "lbr0" et "lbr1" :

Reproduiser la manipulation ci-dessus pour créer la seconde interface bridge, ce qui donnera :

Interfaces et réseaux bridgé sous linux

La rubrique "interfaces" affiche le fichier de configuration "/etc/networks/interface" on y retrouvera "lo","br0", "lbr0", "lbr1".
Mais avant de configuer nos interfaces bridge,  voyons la configuration actuel :

ifconfig
eth0      Link encap:Ethernet  HWaddr 08:60:6e:e5:bd:47
          inet adr:XX.XXX.XXX.XXXX  Bcast:XX.XXX.XXX.XXX  Masque:255.255.255.0
          adr inet6: XXXX:XXXX:X:XXXX::/xx Scope:Global
          adr inet6: XXXX::XXX:XXXX:XXXX:XXXX/xx Scope:Lien
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Packets reçus:2243 erreurs:0 :0 overruns:0 frame:0
          TX packets:1618 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000
          Octets reçus:490019 (490.0 KB) Octets transmis:243883 (243.8 KB)

lo        Link encap:Boucle locale
          inet adr:127.0.0.1  Masque:255.0.0.0
          adr inet6: ::1/128 Scope:Hôte
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          Packets reçus:140 erreurs:0 :0 overruns:0 frame:0
          TX packets:140 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:0
          Octets reçus:22966 (22.9 KB) Octets transmis:22966 (22.9 KB)

virbr0    Link encap:Ethernet  HWaddr 22:e2:0b:e7:c2:d1
          inet adr:192.168.122.1  Bcast:192.168.122.255  Masque:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          Packets reçus:0 erreurs:0 :0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:0
          Octets reçus:0 (0.0 B) Octets transmis:0 (0.0 B)

On remarque la configuration suivante :  l'interface "eth0" qui représente l'adresse IP publique du serveur, l'interface loopback (logique) ainsi que l'interface "virbr0" qui est créer automatiquement en mode NAT.

Dans la mise en place de mon infrastructure, le réseau à une place importante. j'ai donc créer trois interfaces :

  • br0  = bridgé vers l'interface principale eth0 de mon hôte debian (utiliser pour mes ip failover OVH).
  • lbr1 = une interface bridge utiliser par vyos pour mes services web.
  • lbr2 = une interface bridge  utiliser par vyos pour mes dockers et VMs avec possibilité d'inter-connexion docker/kvm.

Mon routeur/pare-feu manage mes différentes interface "bro, lbr1,lbr2" : voici un schéma d'illustration

Commençons pas configurer l'interface "br0" : wiki de debian

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
        address XX.XXX.XXX.XXX
        netmask 255.255.255.0
        network XX.XXX.XXX.0
        broadcast XX.XXX.XXX.255
        gateway XX.XXX.XXX.254
        bridge_ports eth0
        bridge_stp off
        bridge_fd 0
        bridge_maxwait 0

iface eth0 inet6 static
        address XXXX:XXXX:X:XXXX::
        netmask 64
        post-up /sbin/ip -family inet6 route add XXXX:XXXX:X:XXXX:XX:XX:XX:XX dev eth0
        post-up /sbin/ip -family inet6 route add default via XXXX:XXXX:X:XXXX:XX:XX:XX:XX
        pre-down /sbin/ip -family inet6 route del default via XXXX:XXXX:X:XXXX:XX:XX:XX:XX
        pre-down /sbin/ip -family inet6 route del XXXX:XXXX:X:XXXX:XX:XX:XX:XX dev eth0

Redémarrer l'interface (le connexion en ssh avec votre serveur ne devrai pas être interrompue)  :

/etc/init.d/network restart

Vérifier la configuration de l'interface bridge sur l'hôte :

ifconfig br0
br0       Link encap:Ethernet  HWaddr 08:60:6e:e5:bd:47
          inet adr:XX.XXX.XXX.XXX  Bcast:XX.XXX.XXX.255  Masque:255.255.255.0
          adr inet6: XXXX::XXX:XXXX:XXXX:XXXX/xx Scope:Lien
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2344432 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1599970 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:0
          RX bytes:9383508945 (8.7 GiB)  TX bytes:312106046 (297.6 MiB)

La commande pour visualiser l'interface bridgé :

btctl show
br0             8000.08606ee5bd47       no              eth0

Le paquet bridge nous offre la possibilité de créer directement nos interfaces tel que :

brctl addbr lbr0
brctl addbr lbr1

Ensuite, il nous faut démarrer les interface bridgé "lbr0" et "lbr1" :

ip link set dev lbr0 up
ip link set dev lbr1 up

Cependant, la méthode de libvirt ne rend pas permanente nos interfaces ! ajouter les deux interface de façon définitives :

nano /etc/network/interface
auto lbr0
iface lbr0 inet manual
	bridge_ports none
	bridge_stp off

auto lbr1
iface lbr1 inet manual
    bridge_ports none
    bridge_stp off
/etc/init.d/network restart
brctl show

br0             8000.08606ee5bd47       no              eth0
lbr0            8000.fe5400047801       no              
lbr1            8000.fe54000a522b       no              
virbr0          8000.000000000000       yes

Le serveur hôte peut redémarrer sans crainte de perdre sa configuration désormais  ! Voici les différentes interfaces bridgé :

 

Vous avez la possibilités de désactiver l'interface au démarrage :

virsh net-autostart --disable default

Ou encore de supprimer définitivement l'interface "default" :

virsh net-destroy default

Création d'une instances dans WebVirtMgr

Dans la rubrique "instances", cliquer sur le bouton "New Instance" et plusieurs possibilités s'offre à vous !

  • Instance personnalisé, Template ou fichier de configuration XML.

Ci-dessous on retrouve aussi des "templates" pré-définis et numéroté de 1 à 6 qui permettent de créer une images.

Dans ce cas précis, je vais utiliser une instance personnalisée. Mais avant il faudra créer un disque pour la VM.
Comme expliquer précédemment je préfère utiliser le mode cli pour créer le disque de ma future machine :

qemu-img create -f qcow2 vdisk 10G

Pour ceux qui souhaite convertir une machine VMware vers KVM :

qemu-img convert vm1-flat.vmdk -O qcow2 vm1

Afficher des informations concernant notre machine :

qemu-img info vdisk

file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 136K
cluster_size: 65536

Utiliser maintenant le  HDD "vdisk" pour créer une VM "vdisk" :


Lancer la création en cliquant sur le bouton "create", puis apparait la gestion de la machine "vdisk" avec ses options :

A ce moment précis, libre à vous de découvrir les rubriques ci-dessus mais n'oubliez pas :

  1. "Access" pour sélectionner votre type de console, puis modifié la disposition du clavier (si mode : novnc).
  2. "Settings" pour l'ajout d'un "Media" ISO à la machine virtuelle.
  3. Dans "Settings" editer la configuration du xml de la machine "vdisk". Uniquement si vous souhaitez attribuer une Failover OVH à votre VM. La partie "interfaces" de la machine doit contenir (exemple sur mon routeur/pare-feu) :
     
    <interface type='bridge'>
    <mac address='xx:xx:xx:xx:xx:xx'/>
    <source bridge='br0'/>
    <target dev='vnet0'/>
    <alias name='net0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
  4. Lancement de la machine "Power" puis "Start", l'accès à la console ce fera via "Accès/Console"
  5. Une pop-up s'ouvre avec novnc et l'accès à la VM :

C'est terminé, vous êtes désormais prêt à utiliser les ressources de votre infrastructures et votre VM !
Mais avant... sauvegarder à chaud votre VM.

Sauvegarder vos machines KVM à chaud

La sauvegarde peut ce faire par clone via l'interface webvirtmgr ou encore via un simple "cp" : (vers NFS)

cp /var/lib/libvirt/images/vdisk /var/lib/libvirt/nfs/vdisk.02.03.2015

Vue d'ensemble de l'infrastructure

La charge d'utilisation de l'infrastructure est disponible dans la rubrique "overview" ce qui permet d'obtenir une vue d'ensemble en temps réel. Voici l'utilisation de mon infrastructure "webvirt-kassianoff" une fois en place :

Mise à jour de WebVirtMgr

Les mise à jours  technologiques et de sécurités sont bien entendu très importantes, pour cela rien de plus simple !
Rendez-vous dans le repertoire de WebVirtMgr :

cd /var/www/webvirtmgr

Puis lancez les commandes suivantes :

 remote: Counting objects: 27, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 27 (delta 7), reused 6 (delta 6), pack-reused 7
Unpacking objects: 100% (27/27), done.
From git://github.com/retspen/webvirtmgr
   ed176e4..c875e0d  master     -> origin/master
Updating ed176e4..c875e0d
Fast-forward
 console/views.py         |    3 ++-
 create/views.py          |    7 ++++---
 hostdetail/views.py      |    5 +++--
 instance/views.py        |   15 ++++++++-------
 interfaces/views.py      |    7 ++++---
 networks/views.py        |    9 +++++----
 secrets/views.py         |    3 ++-
 servers/views.py         |    9 +++++----
 storages/views.py        |    9 +++++----
 templates/base.html      |    2 +-
 templates/base_auth.html |    2 +-
 templates/login.html     |    2 +-
 12 files changed, 41 insertions(+), 32 deletions(-)
./manage.py collectstatic
WARNING:root:No local_settings file found.

You have requested to collect static files at the destination
location as specified in your settings.

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes

0 static files copied, 75 unmodified.
service supervisor stop

Je termine ma migration et j'espere que votre nouvelle infrastructure vous plait !

Commentaires