par Nicolas · Publié · Mis à jour
Dans cette série d’articles, nous allons étudier un peu KVM, il parait que c’est à la mode !
Un ami m’a dit il y a quelque temps : « tu devrais tester, c’est pas mal »…
A l’occasion du projet de nouveau serveur V2020 en Debian 10, je me suis alors souvenu que j’avais ceci sur la liste des nombreuses choses à tester. Ce fut donc l’occasion de m’y mettre.
Pour faire ce que je fais avec Xen (à savoir créer une image en une commande), j’ai du rester motivé car ce n’est pas aussi « tout en un ».
J’ai donc bien défriché et vous propose un « petit tour » de KVM.
Table des matières
Virtualisation avec KVM, la série de tutos
Installation et préparation du réseau
Installation d’une VM à partir d’une ISO
C – Création du pool LVM dans KVM
II – Ajout d’une interface à la VM
A – Modification vlan pour l’hyperviseur
IV – Spécifier les VLANs lors de la création
VM avec Debootstrap et noyau de l’hyperviseur
Préparation d’un template pour les VMs
Je ne fais pas faire un cours magistral sur la virtualisation, il y a pléthore de ressources à ce sujet sur le grand internet, mais pour résumer, on trouve deux types d’hyperviseurs :
– Type 1, ou « bare metal » : l’hyperviseur est l’OS de la machine, directement sur le hardware.
Des noms ? KVM, Xen, Vmware ESXi, Hyper-V, Xen-Server (la version « Citrix de Xen »).
– Type 2, ou « hosted » : l’hyperviseur est un logiciel qui tourne sur l’OS de la machine.
Encore des noms ? Vmware Workstation, Qemu, Virtual Box. Bref, un logiciel installé sur un OS.
Ceci dit, de nos jours, type I, type II, cela devient de plus en plus confus… On va voir pourquoi avec KVM, et d’ailleurs pour être plus précis, on devrait dire KVM/Qemu.
Qemu, techniquement, c’est du type II. C’est un soft qui tourne sur l’OS et qui permet d’émuler une machine. Cela permet de faire tourner par exemple, une archi ARM sur un host en X86, bref un émulateur tout à fait classique.
KVM (Kernel-based Virtual Machine), c’est un module du noyau Linux (intégré depuis la 2.6.20) qui permet de transformer Linux en hyperviseur.
C’est bien beau tout ça, mais ça interagit comment ?
Et bien avec l’aide de Libvirt, une API de virtualisation. Cette API open source peut être utilisée avec d’autres solutions de virtualisation, mais on la retrouve le plus souvent associée avec KVM/Qemu.
Elle va faire « le lien » entre tout ceci et propose également des commandes pour faciliter la manipulations des VMS (les lignes de commandes Qemu brutes sont imbitables…)
Et y’a une astuce, c’est que ce trio malicieux peut bosser comme un hyperviseur de type I si l’architecture que doit émuler Qemu est identique à l’architecture de l’hôte. Pour résumer (grossièrement), il n’émule plus les instructions processeurs, vu qu’il peut les passer directement, d’où performances accrues, etc..
Impeccable !
Ceci dit, il faut s’assurer avant que votre processeur hôte supporte bien les instructions de virtualisation.
Ceci avec la commande
# cat /proc/cpuinfo
Dans les flags, vous devez voir vmx (Intel) ou svm (AMD)
Pour voir facilement :
# egrep --color 'vmx|svm' /proc/cpuinfo
Si ils n’y sont pas, vous pourrez quand même virtualiser, mais Qemu restera de « type 2 » et les performances ne seront pas extraordinaires.
Petit truc aussi au passage :
A l’occasion d’un cat /proc/cpuinfo sur un Xen, j’ai constaté que le flag n’apparaissait pas. Inquiet sur le bon fonctionnement du proc, c’est en fait normal, il faut taper :
# cat /sys/hypervisor/properties/capabilities
Pour le voir sous la forme :
hvm-X.0-x86_32 hvm-X.0-x86_32p hvm-X.0-x86_64
Bref, voila pour la petit introduction sur KVM et les hyperviseurs en général.
J’ai fait court et concis, n’hésitez pas à poser des questions si quelque chose n’est pas clair.
On commence par les bases :
# apt install qemu-kvm libvirt-clients libvirt-daemon-system --no-install-recommends
Dans le cadre d’un serveur headless, le –-no-install-recommends est, justement, recommandé …
A la différence de Xen, KVM ne nécessite pas de booter sur un noyau particulier, donc rien d’autre à faire.
Pour voir si ça tourne :
# service libvirtd status
A y est, c’est prêt… 🙂
Pour le management des VMs, on trouve deux solutions :
•.En mode graphique, avec virt-manager. Je ne traite pas ceci dans mes articles car d’une, c’est déjà fort bien documenté, de deux, je suis en headless, de trois, si vous savez le faire en ligne de de commande, vous saurez le faire dans une GUI 😉
•.En mode ligne de commande donc, avec virsh.
Virsh, c’est un peu l’équivalent de la commande xl de Xen et ça se lance ainsi :
# virsh
On arrive alors dans la console virsh.
On peut taper par exemple :
virsh# help
Et pour quitter :
virsh# exit
Et on peut aussi passer le tout en une ligne :
# virsh node-info
Vous affiche les infos de l’host.
# virsh list
Cette commande vous affiche les VMs qui tournent.
Pour voir à la fois celles qui tournent et celles à l’arrêt, ce sera :
# virsh list --all
On reviendra de toute façon sur virsh en temps et en heure. Pour les impatients : https://linux.die.net/man/1/virsh
Pour le réseau, comme à mon habitude, j’utilise Openvswitch car c’est le bien.
# apt install openvswitch-switch
Et on va ajouter le premier bridge
# ovs-vsctl add-br br0
Nous allons modifier le fichier interfaces /etc/network/interfaces de l’hyperviseur :
allow-ovs br0
iface br0 inet static
address IP_PUBLIQUE
netmask 255.255.255.0
gateway GATEWAY
ovs_type OVSBridge
ovs_ports eth0
allow-br0 eth0
iface eth0 inet manual
ovs_bridge br0
ovs_type OVSPort
ceci afin de le brancher directement sur le br0, etc…
Si votre port est nommé autrement (avec le nouveau système de Debian), vous adaptez, bien évidement.
Un p’tit reboot (on pourrait faire sans, mais ainsi, je valide que mon fichier est sans erreurs)
# reboot
Et voila, l’hyperviseur est connecté sur le bridge br0 pour sortir, et ce bridge permettra à d’autres machines de sortir directement.
On va confier la gestion du réseau des VMs au système de pools de KVM. C’est optionnel, mais pratique.
Pour voir ce qu’il y a en place :
# virsh net-list --all
Et ce truc par défaut, on le supprime :
# virsh net-undefine default
On va maintenant lui dire de prendre en compte notre tout nouveau switch br0.
Cela se fait en le définissant dans un fichier xml, nommé, par exemple, front.xml :
<network>
<name>ovs-front</name>
<forward mode='bridge'/>
<bridge name='br0'/>
<virtualport type='openvswitch'/>
</network>
Il faut ensuite l’insérer et l’activer :
# virsh net-define front.xml
# virsh net-start ovs-front
# virsh net-autostart ovs-front
Pour voir si tout est ok :
# virsh net-list
Voila, c’est prêt !
KVM/Qemu est en place, le réseaux est prêt. Il ne reste plus qu’a créer nos VMS et vous allez voir que par rapport à Xen où je n’expliquais qu’une seule façon de faire (je reviendrais d’ailleurs dessus), ici, on va balayer plusieurs méthodes et comprendre ainsi un peu mieux les arcanes du boot de linux.
Et pour commencer, on va se faire une petite VM en partant d’une ISO de Debian, la méthode la plus simple
On va commencer par télécharger l’ISO que l’on veut installer, au hasard … une Debian :
# mkdir /img
# cd /img
# wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-10.3.0-amd64-netinst.iso
# mv debian-10.3.0-amd64-netinst.iso debian.iso
# cd
On pourrait tout à fait choisir de tester FreeBSD, CentOS, Fedora ou tout autre distribution.
Pour créer les VMs, on va utiliser virt-install qui s’installe de la sorte :
# apt install virtinst --no-install-recommends
Niveau stockage, KVM peut utiliser différents formats.
Son format à lui, c’est le qcow2, mais il gère aussi les disques virtuels venant de Vmware, le stockage en NFS, etc, … et également ce que j’affectionne : LVM.
Dans mes articles, j’utilise exclusivement LVM, mais pour info, si vous voulez utiliser qcow2, il faut déjà installer ceci :
# apt install qemu-utils
Puis pour créer votre fichier image :
# qemu-img create -f qcow2 /imgvms/test1.qcow2 5G
Et ensuite, dans les commande virt-inst, vous remplacez les LVs par vos fichiers qcow2 avec par ex :
--file /imgvms/test1.qcow2
Comme on part sur du LVM, on va déjà devoir l’installer :
# apt install lvm2
Virsh permet de builder automatiquement PV, VG, etc.. mais je préfère le faire à la main avant.
Admettons que ce soit la partition sda2 qui va servir.
On va la marquer comme LVM (8E) avec cfdisk par ex :
# cfdisk /dev/sda
La, vous changez le type, puis écrivez les modifications.
Ensuite, on créé le PV et le VG :
# pvcreate /dev/sda2
# vgcreate vg0 /dev/sda2
Maintenant, on peut passer à la définition du VG dans virsh :
# virsh pool-define-as kvm-lvm logical --source-name vg0 --target /dev/vg0
Notez bien que le nom de mon VG dans virsh est différent de son vrai nom.
Ensuite, on active :
# virsh pool-start kvm-lvm
# virsh pool-autostart kvm-lvm
On peut lister
# virsh pool-list
Les autres pools ne gênent pas, on va les garder (le img sert pour indexer les ISOs, je n’ai pas encore eu le temps de creuser cet aspect…)
Avoir un pool de stockage défini dans KVM est tout à fait optionnel. On pourrait tout à fait s’en passer et créer les LVs à la main mais pour certaines manipulations qu’on verra plus tard (clone par exemple, c’est nécessaire, enfin, si on passe par le clonage via virsh… bref, ça ne mange pas de pain…)
On peut enfin lancer la création et l’installation de notre première VM avec :
virt-install --name debianmano \
--vcpus 1 \
--cpu host \
--ram 1024 \
--location /img/debian.iso \
--disk pool=kvm-lvm,size=4,bus=virtio \
--network network:ovs-front,model=virtio,mac=52:54:00:11:11:11,target=debianmano.0 \
--graphics none \
--console pty,target_type=serial \
--extra-args='console=ttyS0' \
--os-variant debian10
Au niveau des paramètres :
•.name : sérieusement ?
•.vcpus : indique le nombre de cpus virtuels
•.cpu host : permet de passer tout le jeu d’instruction du processeur hôte vers le(s) vcpu(s).
•.location : indique où se trouve notre ISO
•.disk : permet de créer directement le LV dans le pool. On aurait pu créer le LV avant et donner ici son chemin
•.network : indique le réseau KVM sur lequel est branché la VM, le driver, l’adresse MAC et le nom de l’interface qui sera connectée à openvswitch (sans, ce serait du genre vnet0…)
•.graphic : none désactive la console graphique
•.console et extra-args : active la console série
•.os-variant : permet d’activer des fonctions avancées durant l’install (acpid par exemple)
Plus d’infos ici : https://linux.die.net/man/1/virt-install
WARNING MAC :
Si vous êtes sur un serveur dédié, voyez avec votre prestataire comment gérer les Macs. Chez Online par ex, il faut la générer et faire en sorte que l’interface de VM qui sort avec l’IP FO soit bien configurée avec la MAC générée au préalable.
Chez soi, on s’en « cogne, » mais on peut tout à fait donc forcer une MAC (sans, ce sera au hasard, avec cependant toujours 52:54:00 qui correspond à KVM.
Une fois lancé et passé les messages de boot, on se retrouve avec un installeur Debian classique.
Choix de langue : C, puis on définit sa localisation.
Configuration du réseau (votre VM sera donc dans le même network que l’hyperviseur, par exemple une IP publique en cas de serveur dédié ou une IP en 192.168… si vous êtes chez vous).
Pour le partitionnement, on va prendre auto mais sans LVM, et on poursuit l’installation.
A la question GRUB : on l’installe sur /dev/vda.
Il se peut qu’à la fin, la VM ne se relance pas (je n’ai pas compris pourquoi, vu que ça ne le fait pas systématiquement)
La commande qui permet de se connecter à la console :
# virsh console debianmano
vous dira que le domaine est coupé.
Dans ce cas, pour le démarrer :
# virsh start debianmano
Et si vous voulez la console en même temps.
# virsh start debianmano --console
On voit Grub puis le chargement initial. Les autres messages ne s’affichent pas (configuration par défaut de Grub)
Et à un moment, on arrive sur l’invite de connexion.
Vous pouvez alors vous connecter sur votre VM et cette dernière doit communiquer correctement sur le réseau (ping, etc…)
Pour quitter la console, c’est CTRL + ] (en physique car en ssh, je dois faire CTRL ¤)
Au passage, une liste (non exhaustive) de commande utile :
# virsh autostart debianmano
Active le démarrage automatique de la VM.
# virsh reboot debianmano
Reboot de la machine (via ACPI)
# virsh shutdown debianmano
Shutdown de la machine (via ACPI)
# virsh destroy debianmano
Simule le coup de la prise…
# virsh suspend debianmano
# virsh resume debianmano
Met en pause et réactive la VM
# virsh edit debianmano
Permet d’éditer le fichier de conf de la VM
# virsh dumpxml debianmano > file.xml
Dump la configuration de la VM dans un fichier
# virsh define file.xml
Créer une nouvelle machine selon un fichier
# virsh create file.xml
La même chose, mais démarre en plus la machine.
# virsh undefine debianmano
Supprime la VM (mais ne l’arrête pas si elle tourne…)
Pour supprimer aussi le LV créé automatiquement :
# virsh vol-delete debianmano kvm-lvm
Bon que remarque t’on avec cette VM ?
Contrairement aux VMs de Xen qui, si on n’utilise pas PyGrub (ou PVGRUB), utilisent le kernel/initramfs de l’hyperviseur, ici, on a une machine « complète » : Grub, chargement du noyau…
Une machine en quelque sorte plus « autonome ». Il sera ainsi possible de faire des modifications du noyau directement dans la VM.
En parlant de Grub, sur la VM, on va éditer le fichier /etc/default/grub pour y modifier les deux lignes :
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0"
GRUB_TERMINAL="serial console"
Puis :
debianmano# update-grub
Ceci nous permettra de voir les messages du kernel au boot.
Au niveau Openvswitch :
# ovs-vsctl show
nous montre bien le port nommé debianmano.0 connecté sur le br0
Et en ce qui concerne le LV :
# virsh vol-list kvm-lvm
Qu’on peut le voir aussi avec :
# lvs
Tout est en ordre.
Et si vous voulez voir le fichier de configuration de la VM :
#virsh edit debianmano
Ho, le joli XML… (je ne suis pas fan, mais ca n’engage que moi…)
Admettons que la VM soit coupée et que vous souhaitiez accéder à ses fichiers.
Avec Xen et mon système de VMS, le FS (ext4) est directement sur le LV, je peux donc le monter directement :
# mount /dev/vg0/monvol /mnt
Mais ici, ce n’est pas le cas. Le LV contient la(les) partitions créées pendant l’installation de la Debian.
On verra plus tard comment s’y connecter de façon « bas niveau », mais en attendant, voila un outil pratique …
Cela s’installe avec :
# apt install libguestfs-tools --no-install-recommends
On va couper la VM :
virsh shutdown debianmano
Puis :
# guestmount -d debianmano -i /mnt
La, on patiente un peu..
Et on a le FS de la VM monté dans /mnt… Tada…
Pour démonter :
# guestunmount /mnt
On peut relancer la VM, on va en avoir besoin pour la suite :
# virsh start debianmano
Voila, vous savez maintenant comment créer une VM à partir d’une ISO. Simple non ?
Avant de voir l’autre façon de faire à l’aide de debootstrap, nous allons discuter réseau dans la partie suivante.
Notre première VM est branchée directement sur le bridge br0 d’Openvswitch, elle est au même « niveau réseau » que l’hyperviseur.
Admettons que nous voulions aussi avoir la possibilité d’avoir des VMs sur un réseau interne, ne disposant donc pas directement d’une « sortie » via l’eth0/br0 de l’hyperviseur.
C’est ce que nous allons voir dans cet article.
Tout d’abord, nous allons créer un nouveau bridge au sein d’Openvswitch.
# ovs-vsctl add-br brint
Nouveau bridge sobrement appelé brint.
Dans KVM, on va le définir dans un fichier back.xml :
<network>
<name>ovs-back</name>
<forward mode='bridge'/>
<bridge name='brint'/>
<virtualport type='openvswitch'/>
</network>
Puis :
# virsh net-define back.xml
# virsh net-start ovs-back
# virsh net-autostart ovs-back
Sur l’hyperviseur, on va lui offrir la possibilité de communiquer sur ce bridge en passant par l’interface interne créée automatiquement.
Pour se faire :
# ip addr add 10.99.1.250 dev brint
# ip link set brint up
# ip route add 10.99.1.0/24 dev brint
Pour tester, nous allons brancher à chaud une nouvelle interface réseau à notre première VM. L’avantage de la virtualisation, car aller brancher une carte réseau sur une vrai machine qui tourne, je ne m’y risquerais pas…
Pour voir déjà l’existant :
# virsh domiflist debianmano
On lui ajoute l’interface ainsi :
# virsh attach-interface debianmano network ovs-back --model virtio --target debianmano.1 --mac 52:54:00:11:11:12 --persistent
Au passage, pour détacher, c’est :
# virsh detach-interface debianmano bridge --mac 52:54:00:11:11:12 --config
Si on regarde le fichier de configuration :
# virsh edit debianmano
On peut voir la section pour cette interface qui a été ajoutée :
...
<interface type='network'>
<mac address='52:54:00:11:11:12'/>
<source network='ovs-back'/>
<target dev='debianmano.1'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</interface>
...
Puis dans la VM debianmano :
# virsh console debianmano
On va regarder la nouvelle interface ajoutée :
debianmano# ip a
Ici, c’est enp7s0 qui est ajoutée. Donc :
debianmano# ip addr add 10.99.1.1 dev enp7s0
debianmano# ip link set enp7s0 up
debianmano# ip route add 10.99.1.0/24 dev enp7s0
On teste un ping vers l’hyperviseur :
debianmano# ping 10.99.1.250
Et dans l’hyperviseur :
# ping 10.99.1.1
Ceci doit fonctionner sans encombres.
On va faire une petite pause pour voir comment utiliser au mieux tout cela.
Très souvent, dans le cas ou l’on a besoin d’isoler un réseau de VMs sur un hyperviseur, le plus simple est d’effectuer l’interconnexion des réseaux (externe et interne) au niveau de l’hyperviseur. Typiquement ce qui est utilisé avec les hyperviseurs de type II si on ne cherche pas à complexifier.
Ici, on pourrait le faire en autorisant le forward IP sur l’hyperviseur, plus le lien sur le bridge interne crée auparavant, les régles de NAT…
Coté VM, on les connecterait au brint, en déclarant l’adresse IP de l’hyperviseur sur ce bridge en gateway.
Ok, cela fonctionne….
…mais je n’aime pas.
Quand je virtualise, je veux que l’hyperviseur ne fasse que cela.
Pour le routage vers le réseau interne des VMS, j’utilise une VM spécifique avec un lien sur le br0 (et donc une IP « externe ») et un lien sur le brint. C’est elle qui s’occupera du forward, du nat, etc…
L’hyperviseur garde son IP « principale » uniquement pour l’administration. Et il garde aussi le contact avec les VM mais uniquement pour de la gestion.
Ce qu’on va faire pour tester, c’est transformer notre première VM en routeur :
debianmano# echo 1 > /proc/sys/net/ipv4/ip_forward
Puis
debianmano# iptables -t nat -A POSTROUTING -s 10.99.1.0/24 -j SNAT --to 192.168.1.100
Son IP « externe » étant, vous l’aurez compris 192.168.1.100
On va donc maintenant faire une machine uniquement branchée sur brint :
# virt-install --name newvm \
--vcpus 1 \
--cpu host \
--ram 1024 \
--location /img/debian-10.2.0-amd64-netinst.iso \
--disk pool=kvm-lvm,size=4,bus=virtio \
--network network:ovs-back,model=virtio,target=newvm.0 \
--graphics none \
--console pty,target_type=serial \
--extra-args='console=ttyS0' \
--os-variant debian10
On fait l’installation avec pour le réseau, une IP du genre 10.99.1.2, Gateway 10.99.1.1 (la première VM).
Une fois l’installation effectuée et la VM démarrée :
#virsh console newvm
On doit pouvoir pinguer debianmano :
newvm# ping 10.99.1.1
Également l’hyper (qui est encore présent sur le même réseau) :
newvm# ping 10.99.1.250
Par contre, la route passe bien par la premiere VM :
newvm# ip route
renvoie :
default via 10.99.1.1 dev enp1s0 onlink
10.99.1.0/24 dev enp1s0 proto kernel scope link src 10.99.1.2
Depuis debianmano et l’hyperviseur, on doit également pouvoir pinguer newvm sur son IP 10.99.1.2.
Le réseau interne est fonctionnel, nous avons la seconde VM qui communique avec l’extérieur par le biais de la VM routeur. L’hyperviseur ne gère en rien le routage.
C’est bien, mais pas top, car j’aime utiliser les VLANs et nous allons voir justement comment les intégrer dans l’article suivant.
Je gère mes réseaux ainsi :
Une VM routeur avec une ip « externe » sur le bridge et plusieurs ips sur plusieurs réseaux internes :
Un premier réseau 10.10.1.0/24 qui est utilisé pour les communications Extérieur -> VMs (frontal web, postfix, vpn, etc…) et aussi pour les communications VMs -> extérieur (mise à jour, etc…).
Les VMs pour communiquer entres elles utilisent un réseau 10.20.1.0/24. Par exemple, frontal web vers serveurs backweb, postfix vers ldap, serveur divers vers stockage en cluster…
Bon, techniquement, j’utilise encore un autre réseau pour l’intercommunication dans les clusters, mais j’en parle déjà dans l’article sur ….
Et pour terminer, pour les communications Hyperviseur – VMs (ssh, ntp, etc..), j’utilise encore un autre réseau, le 10.99.1.0/24
Compliqué ? Oui, mais utile (facilite grandement le traitement avec Netflow, Ipfix, etc…, mais on reviendra plus tard sur cela dans une autre série d’articles.
Et pour gérer tout cela, au lieu de monter un nouveau bridge par réseau, on va simplement utiliser le principe des VLANs.
Pour mémoire, nous avions brancher l’hyperviseur sur le brint à l’aide des commandes suivantes :
# ip addr add 10.99.1.250 dev brint
# ip link set brint up
# ip route add 10.99.1.0/24 dev brint
Il n’y a qu’une chose à faire, c’est indiquer le VLAN à utiliser sur le port.
Et cela se fait ainsi :
# ovs-vsctl set port brint tag=99
On peut voir
# ovs-vsctl show
indique :
...
Port brint
tag: 99
Interface brint
type: internal
...
Dans un fichier ovs-vlans.xml :
<network>
<name>ovs-vlans</name>
<forward mode='bridge'/>
<bridge name='brint'/>
<virtualport type='openvswitch'/>
<portgroup name='vlandef' default='yes'>
</portgroup>
<portgroup name='vlan99'>
<vlan>
<tag id='99'/>
</vlan>
</portgroup>
<portgroup name='vlans1020'>
<vlan trunk='yes'>
<tag id='10'/>
<tag id='20'/>
</vlan>
</portgroup>
</network>
Toujours sur le brint, mais on y ajoute la notion de portgroup.
Un qui trunk les VLANs 10 et 20 (toutes mes machines en ont besoin, autant mettre les deux sur un seul port) et un qui dessert le vlan 99.
Je garde le 99 sur une autre interface, question d’habitude et de cloisonnement.
On injecte et on démarre :
# virsh net-define ovs-vlans.xml
# virsh net-start ovs-vlans
# virsh net-autostart ovs-vlans
On va modifier les VMS :
On va lui attacher une nouvelle interface :
# virsh attach-interface debianmano network ovs-vlans --model virtio --target debianmano.2 --mac 52:54:00:11:11:13 --config
Ceci afin de créer automatiquement l’entrée dans le fichier de configuration, configuration qu’on modifiera juste après, la commande virsh attach-interface ne permettant pas de spécifier les portgroups.
On édite donc son fichier de configuration pour y ajouter les portgroup :
# virsh edit debianmano
Vous éditez :
...
première interface qu'on ne tripote pas...
...
<interface type='network'>
<mac address='52:54:00:11:11:12'/>
<source network='ovs-vlans' portgroup='vlans1020'/>
<target dev='debianmano.1'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</interface>
<interface type='network'>
<mac address='52:54:00:11:11:13'/>
<source network='ovs-vlans' portgroup='vlan99'/>
<target dev='debianmano.2'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>
</interface>
Il faut ajouter les portgroup dans <source network>.
Un sur le trunk 10-20 et l’autre sur le vlan99.
On ne touche pas à la première interface.
On retourne dans la VM :
# virsh console debianmano
On va modifier /etc/default/grub :
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
afin de récupérer les noms classiques (eth0, eth1, etc…)
Puis :
debianmano# update-grub
On va éditer le fichier /etc/network/interfaces :
auto eth0
iface eth0
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.254
auto eth1.10
iface eth1.10 inet static
address 10.10.1.1
netmask 255.255.255.0
auto eth1.20
iface eth1.20 inet static
address 10.20.1.1
netmask 255.255.255.0
auto eth2
iface eth2 inet static
address 10.99.1.1
netmask 255.255.255.0
Ne reste plus qu’à arrêter la machine.
# virsh shutdwon debianmano
De la même manière que pour le routeur…
On va lui attacher une nouvelle interface :
# virsh attach-interface newvm network ovs-vlans --model virtio --target newvm.1 --mac 52:54:00:11:11:21 --config
On édite son fichier de configuration pour y ajouter les portgroup :
# virsh edit newvm
Et vous éditez :
<interface type='network'>
<mac address='52:54:00:62:ec:4c'/>
<source network='ovs-vlans' portgroup='vlans1020'/>
<target dev='newvm.0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
<interface type='network'>
<mac address='52:54:00:11:11:21'/>
<source network='ovs-vlans' portgroup='vlan99'/>
<target dev='newvm.1'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</interface>
La, on change les deux interfaces. La première passe sur le ovs-vlans sur le trunk 10-20, la seconde, sur le vlan99.
On retourne dans la VM :
# virsh console newvm
On va modifier /etc/default/grub :
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
Puis :
newvm# update-grub
On va éditer le fichier /etc/network/interfaces :
auto eth0.10
iface eth0.10 inet static
address 10.10.1.2
netmask 255.255.255.0
gateway 10.10.1.1
auto eth0.20
iface eth0.20 inet static
address 10.20.1.2
netmask 255.255.255.0
auto eth1
iface eth2 inet static
address 10.99.1.2
netmask 255.255.255.0
Ne reste plus qu’à arrêter la machine.
# virsh shutdwon newvm
On relance les deux VMs :
# virsh start debianmano
# virsh start newvm
Puis on va déjà regarder :
# virsh domiflist debianmano
# virsh domiflist newvm
On doit bien voir ce qu’on s’attendait à voir 😉
On peut donc supprimer l’ancienne définition de brint dans KVM :
# virsh net-destroy ovs-back
# virsh net-undefine ovs-back
Sur le routeur (debianmano), on va réactiver le routage :
# virsh console debianmano
Puis :
debianmano# echo 1 > /proc/sys/net/ipv4/ip_forward
debianmano# iptables -t nat -A POSTROUTING -s 10.10.1.0/24 -j SNAT --to 192.168.1.100
Et depuis newvm, on doit pouvoir pinguer le monde entier.
Rien de compliqué au final.
Comme je l’ai expliqué, la commande virsh attach-interface ne permet pas de passer le paramètre portgroup.
Par contre, pour la création avec virt install, on peut tout à fait spécifier les portgroup de la sorte :
--network network:ovs-vlans,portgroup=vlans1020,model=virtio,mac=52:54:00:AA:BB:CC,target=newvm.1
Et voila, vous savez utilisez les VLANs avec KVM et Openvswitch. Bien évidement, libre à vous de faire plus simple, mais au moins, s’il faut faire compliqué, vous saurez 😉
Dans la partie suivante, nous allons voir la première méthode pour créer une VM à partir de debootsrap.
Dans cette cinquième partie de la série sur KVM, nous allons commencer à creuser un peu car faire des machines à partir d’une ISO, c’est rigolo, mais ce n’est pas pratique. Question automatisation, on a vu mieux.
Il est tout a fait possible de l’automatiser avec la fonction de preseed. C’est un fichier qui simule ce que vous pourriez taper au clavier. C’est mieux, mais bon, ça reste pas terrible terrible à mon gout.
On va donc tenter de faire quelque chose qui va nous rapprocher de ce que Xen permet avec xen-create-image, en utilisant debootstrap.
Debootstrap, c’est un truc tout bête qui vous permet de préparer une Debian depuis une autre Debian.
Et avec cette façon de faire, on peut encore procéder de deux façons…
La première, qu’on va voir ici et qui est similaire aux machines Xen par défaut, où une VM va utiliser le noyau de l’hyperviseur pour booter.
On va créer le LV en passant par virsh :
# virsh vol-create-as kvm-lvm debiandeboot 4G
On peut le voir dans :
# virsh vol-list kvm-lvm
Ensuite, on va simplement le formater :
# mkfs.ext4 /dev/vg0/debiandeboot
Puis on le monte :
# mount /dev/vg0/debiandeboot /mnt
Il suffit de l’installer :
# apt install debootstrap
Et tout simplement :
# debootstrap stable /mnt/
Bien sur, on s’assure que le point de montage soit disponible.
Ensuite, on va juste changer le mdp root de cette nouvelle Debian en chrootant :
# chroot /mnt
Puis :
chroot# passwd root
chroot# exit
Avant de lancer la création de la machine, on va désactiver une fonction qui, sinon, va nous faire un boucle pendant 30 sec.
On édite le fichier /etc/initramfs-tools/conf.d/resume pour modifier :
# RESUME=xxxxxx
RESUME=none
On termine avec :
# update-initramfs -u
On pense à démonter :
# umount /mnt
On lance la création de la machine :
virt-install --name debiandeboot
--vcpus 1
--cpu host
--ram 1024
--import
--disk vol=kvm-lvm/debiandeboot,bus=virtio
--network=none
--boot kernel=/vmlinuz,initrd=/initrd.img,kernel_args="root=/dev/vda console=ttyS0"
--graphics none
--console pty,target_type=serial
--os-variant debian10
•.import : permet de spécifier que l’OS est deja installé
•.disk : on spécifie le nom du volume et le nom de l’image
•.network : ici pas besoin de réseau, on veut juste une machine basique pour le test
•.boot : c’est la que la magie opère, on lui spécifie le noyau de l’hyperviseur. Attention dans la partie kernel_args, ne pas inverser les options, sinon, ça plante…
Une fois la machine chargée, on peut se connecter dessus, mais, c’est tout.
Le FS est en read only (bah oui, pas de fstab), le hostname n’est pas configuré, le swap n’existe pas, pas de réseau…. il manque plein de choses, mais au moins, ça boot.
L’important ici était de vous montrer la technique.
Dans la partie suivante, nous commencerons à préparer le terrain pour créer des VMs « complètes », en préparant un template pour nos futures VMs.
Dans cette sixième partie de la série sur KVM, nous allons voir la création d’un template à partir de deboostrap.
Ce template servira à la création de VM autonome, c’est à dire avec un grub, un noyau propre bref plus facilement bidouillable (c’est bien plus simple et moins risqué pour faire des modifs du noyau, etc…)
Ceci reste faisable avec la méthode précédente, en faisant du coup le travail sur des copies du noyau sur l’hyperviseur, mais ça laisse quand même un gros risque de « foirage »…
Puis la, on peut templater ce qu’on veut au final, une veille version de Debian, une sid, voir une autre distribution de Linux.
Afin de faciliter le déploiement de mes VMs, j’ai un répertoire skel contenant les fichiers qui seront chargés (et modifiés pour certains) pour chaque VM à l’aide de commandes sed.
On va donc préparer tout cela.
Ici, je reste simple et ne couvre pas certains fichiers, mais libre à vous d’ajouter ceux que vous désirez.
Pour commencer, on se positionne dans le répertoire /root :
# cd
Puis :
# mkdir vm/skel/etc -p
# cd vm/skel/etc
Le répertoire /root/vm contiendra des scripts bash dont on parlera plus tard.
On créé un répertoire :
# mkdir apt
On va copier le fichier sources.list depuis l’hyperviseur
# cp /etc/apt/sources.list apt/
On va créer un répertoire :
# mkdir default
# cd default
Et dedans, créez un fichier grub semblable à cela :
GRUB_DEFAULT=0
GRUB_TIMEOUT=1
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0"
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"
On règle pour visionner les messages de boot, pour avoir la console et au passage, on remet le nom des interfaces en ethX.
On revient dans /root/vm/skel/etc/ :
#cd ..
Créez un fichier fstab avec ceci :
UUID=rootuuid / ext4 errors=remount-ro 0 1
UUID=swapuuid none swap sw 0 0
« rootuuid » et « swapuuid » seront modifiés lors de la création de notre VM.
un fichier hostname :
debian
Ici, on modifiera « debian » en fonction de la future VM.
Un fichiers hosts :
127.0.0.1 localhost
127.0.1.1 debian
La encore, ce sera « debian » qui sera modifié
Pour le réseau, création du répertoire :
# mkdir network
# cd network
Et ici, un fichier interfaces :
auto lo
iface lo inet loopback
auto eth0.10
iface eth0.10 inet static
address 10.10.1.IP
netmask 255.255.255.0
gateway 10.10.1.1
auto eth0.20
iface eth0.20 inet static
address 10.20.1.IP
netmask 255.255.255.0
auto eth1
iface eth1 inet static
address 10.99.1.IP
netmask 255.255.255.0
Ici, c’est « IP » qui sera modifié.
Et on revient en arrière :
# cd ..
Et pour finir, un fichier resolv.conf avec votre resolveur :
nameserver 1.1.1.1
par exemple…
On revient dans /root/vm :
# cd /root/vm
Et on va y créer un dossier pour le template :
# mkdir debugo
Pour le debootstrap, une petite astuce pour aller plus vite en utilisant l’iso :
# mount -o loop /img/debian.iso /media/cdrom/
Et on lance :
# debootstrap --no-check-gpg --include=grub-pc,linux-image-amd64,locales \
--exclude=os-prober stable debugo file:/media/cdrom
Je rajoute les paquets pour grub et le noyau et j’exclue au passage os-prober qui nous ferait apparaitre l’OS de l’hyperviseur dans le Grub de la VM…
On va préparer le template en quelques étapes.
# mount -t sysfs /sys debugo/sys
# mount -t proc /proc debugo/proc
# mount --bind /dev debugo/dev
# mount -t devpts /dev/pts debugo/dev/pts
# mount --bind /tmp debugo/tmp
Puis :
cp /etc/apt/sources.list debugo/etc/apt/
Pourquoi je copie le sources.list à ce moment ?
Pour la suite, les apt dans le chroot nécessitent un sources.list, qui n’est pas présent par défaut.
Et je ne copie que celui ci car durant la création du template je peux rajouter des paquets qui modifient des fichiers que j’ai déjà configuré (par ex, postfix), la copie du squelette ne doit donc intervenir qu’à la fin.
Maintenant, chrootons :
# LANG=C chroot /mnt
Et pour être sur (au cas ou votre iso ne serait pas à jour par exemple et que vous ne l’ayez pas vu) :
chroot# apt-get update && apt-get upgrade -y
Première chose à configurer, la timezone.
Dans le chroot :
chroot# ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime
chroot# dpkg-reconfigure --frontend=noninteractive tzdata
Toujours dans le chroot :
chroot# sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
chroot# sed -i -e 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen
chroot# dpkg-reconfigure --frontend=noninteractive locales
chroot# update-locale LANG=fr_FR.UTF-8
On va installer le paquet acpid, qui va permettre l’extinction et le reboot de la machine depuis l’hyperviseur.
chroot# apt-get install acpid -y
chroot# systemctl enable acpid
Et voila, nos futures VMs auront un bouton power.
Ici, on va rajouter tous les paquets que l’on désire :
chroot# apt-get install ssh htop bash-completion wget man-db dnsutils \
bsd-mailx net-tools whois telnet tcpdump traceroute parted postfix
Liste non exhaustive…
J’évite d’utiliser tasksel pour installer les trucs standards car il a tendance à en mettre trop. Du coup, je le fais à la mimine.
On sort du chroot :
chroot# exit
Et on lance la copie de nos fichiers :
# cp skel/etc/* debugo/etc/ -r
Pour être propre :
# umount debugo/{sys,proc,dev/pts,dev,tmp}
# umount /media/cdrom/
On termine en créant notre archive :
# tar zcvf debugo.tar.gz debugo/
Et on peut supprimer le répertoire
# rm debugo/ -r
Et voila, on a un tar tout chaud pour nos VMS, et on va voir comment s’en servir pour se créer une VM en quelques secondes.