On trouve des images de Fedora ou de Centos à télécharger, portant la mention de "cloud image".
Contrairement à une image iso, cette image contient un système déja installé, et évite d'avoir à passer par toutes les étapes de l'installation avant de pouvoir l'utiliser.
Les avantages sont la rapidité de déploiement: déployer une machine est presque aussi rapide que de copier un image disque.
L'inconvénient est qu'une telle image n'est pas utilisable telle quelle. Il faudra la personnaliser lors de son premier déploiement avec cloud-init afin de créer les utilisateurs et leurs clés ssh, par exemple.
Les commandes de cet article ont étés testées sur Fedora 33, mais devraient fonctionner sur les versions récentes de Fedora, de Red Hat Enterprise Linux ou de CentOS.
Installation de libvirt
Commençons par installer libvirt, afin de pouvoir lancer des VM
Vérifier que le processeur supporte la virtualisation
Commençons par vérifier que les instructions du processeur sont présentes afin d'avoir de bonnes performances:
host# cat /proc/cpuinfo | egrep "vmx|svm"
Si aucune ligne n'apparait en lançant cette commande, soit votre processeur est très ancien, soit vous devez activer les instructions "vt" dans le bios de votre machine.
Installation de libvirt et quelques outils
Lancer la commande suivante pour installer les packages requis
host# sudo dnf -y install libvirt virt-install qemu-kvm cloud-utils bridge-utils wget
Les paquets installés sont :
libvirt, qemu-kvm: ce sont les paquets requis pour lancer des VM
virt-install : un outil pour créer des VM à partir d'options fournies en ligne de commande
cloud-utils : un outil permettant de manipuler des fichiers cloud-init
bridge-utils : un outil pour manipuer les interfaces bridges. On ne l'utilise pas dans cet article, mais ça peut être utile pour vérifier le fonctionnement du réseau
wget : permet de télécherger facilement des fichiers depuis une URL
Lancer et démarrer le démon libvirt
Lancer Libvirt et l'activer au démarrage du système:
host# sudo systemctl enable libvirtd --now
On peut vérifier que les modules kvm et kvm_intel (ou kvm_amd) sont chargés
host# lsmod | grep kvm
kvm_intel 319488 0
kvm 823296 1 kvm_intel
irqbypass 16384 1 kvm
Si seul le module kvm est chargé, les instructions de virtualisation intégrées au processeur ne seront pas utilisées, et les performances des VM ne seront pas optimales
Récupération et redimensionnement de l'image centos stream 8
Récupérer l'image de CentOS depuis https://cloud.centos.org/centos/8-stream/x86_64/images/ :
host# wget https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20200113.0.x86_64.qcow2
Copier l'image dans /var/lib/libvirt/images
host# cp CentOS-Stream-GenericCloud-8-20200113.0.x86_64.qcow2 /var/lib/libvirt/images/server.qcow2
Ce répertoire est le répertoire par défaut où sont stockées les images des VMs. Il est possible de les stocker ailleurs, mais il faut changer les contextes selinux pour que tout fonctionne bien. Donc, par facilité, on utilise le répertoire par défaut
Redimensionner l'image, par exemple à 30Go:
host# qemu-img resize /var/lib/libvirt/images/server.qcow2 30G
Image resized.
Cloud-init
Cloud-init est un fichier yaml qui décrit les modifiations à appliquer à la machine lors de son premier démarrage.
Dans cet exemple, on va faire le minimum pour avoir une machine sur laquelle on peut se connecter et utiliser sudo pour devenir root.
Créer un fichier. Son nom et sa location n'est pas importante dans cette étape:
vi cloud-user
#cloud-config
users:
- name: nicolas
groups: [ wheel ]
sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
shell: /bin/bash
ssh-authorized-keys:
- ssh-rsa AAAA[...]ErC+Ak7bUUdvjVGsAlDeNPFsck= root@tiger.local
Dans ce fichier, nous définissons un utilisateur, dont le nom est "nicolas", qui est dans le groupe wheel, qui a un shell bash, et qui peut se connecter avec la clé privée qui correspond à la clé publique renseignée.
La ligne sudo permet d'utiliser la commande sudo sans mot de passe. Sur CentOS ou RHEL, les membres du groupe wheel peuvent utiliser sudo, mais doivent taper leur mot de passe. Et je ne voulais pas créer un mot de passe pour cet utilisateur.
Cette ligne a pour effet de créer dans la VM un fichier /etc/sudoers.d/90-cloud-init-users contenant :
# User rules for nicolas
nicolas ALL=(ALL) NOPASSWD:ALL
Créer une image iso contenant ce fichier de paramétrage pour cloud-init :
host# cloud-localds /var/lib/libvirt/images/server-user.iso cloud-user
Création de la VM et premier lancement
Entrer la commande suivante pour créer une VM qui s'appelle "serveur", avec 2Go de RAM, et les disques que nous avons créés précédemment :
host# virt-install --name server \
--memory 2048 \
--disk /var/lib/libvirt/images/server.qcow2,device=disk,bus=virtio \
--disk /var/lib/libvirt/images/server-user.iso,device=cdrom \
--os-type linux --os-variant centos8 \
--virt-type kvm --graphics none \
--network network=default,model=virtio \
--import
L'installation débute
Running text console command: virsh --connect qemu:///system console server
Connected to domain server
Escape character is ^] (Ctrl + ])
[ 0.000000] Linux version 4.18.0-147.3.1.el8_1.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 8.3.1 20190507 (Red Hat 8.3.1-4) (GCC)) #1 SMP Fri Jan 3 23:55:26 UTC 2020
[ 0.000000] Command line: BOOT_IMAGE=(hd0,msdos1)/boot/vmlinuz-4.18.0-147.3.1.el8_1.x86_64 root=UUID=6fcd25ee-bbf3-4fc5-b449-c6a23ac51c07 ro console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto
[..]
[ OK ] Started Update UTMP about System Runlevel Changes.
CentOS Linux 8 (Core)
Kernel 4.18.0-147.3.1.el8_1.x86_64 on an x86_64
Activate the web console with: systemctl enable --now cockpit.socket
localhost login:
L'invite de login s'affiche, mais comme nous ne possédons pas de mot de passe, ni pour root, ni pour utilisateur standard, il faut se connecter avec ssh à la machine.
Appuyer sur [CRTL]+[$] pour quitter la console de la VM, et revenir sur l'hôte
Domain creation completed.
host#
Connexion à la VM
Libvirt affecte une adresse aux machines crées sur le bridge virbr0 que nous avons utilisé. Entrez la commande suivante pour obtenir l'adresse de la VM:
host# virsh net-dhcp-leases default
Expiry Time MAC address Protocol IP address Hostname Client ID or DUID
-----------------------------------------------------------------------------------------------------------
2020-12-26 17:06:38 52:54:00:fa:9e:b7 ipv4 192.168.122.71/24 - 01:52:54:00:fa:9e:b7
Dans mon exemple, l'adresse de la VM est 192.168.122.71.
# ssh nicolas@192.168.122.71
The authenticity of host '192.168.122.71 (192.168.122.71)' can't be established.
ECDSA key fingerprint is SHA256:HWeKa0vLmqHpfoFm+95AIxmmO8oH+Pjqy2H4YwmSLpo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.122.71' (ECDSA) to the list of known hosts.
Activate the web console with: systemctl enable --now cockpit.socket
[nicolas@localhost ~]$ sudo su
[root@localhost nicolas]#
On peut se connecter à la VM, et devenir root.
NSS et utilisation des noms de VM à la place de leur adresse IP
Jusqu'à présent, il faut chercher l'IP de la machine. On ne peut pas utiliser son nom directement :
host# ping server
ping: server: Name or service not known
Le paquet libvirt-nss permet d'utiliser les infos provenant de libvirt au sein de nns afin d'effectuer la résolution de noms. La commande suivante permet de l'installer:
host# dnf install libvirt-nss
Ajouter "libvirt libvirt_guest" dans la ligne "host:" du fichier /etc/nsswitch.conf afin d'ajouter libvirt dans les sources de résolutions de noms d'hôtes:
hosts: files libvirt libvirt_guest resolve [!UNAVAIL=return] myhostname dns
Il est maintenant possible d'utiliser le nom de la VM dans des commandes :
# ping server
PING server (192.168.122.151) 56(84) bytes of data.
64 bytes from 192.168.122.151 (192.168.122.151): icmp_seq=1 ttl=64 time=0.224 ms
64 bytes from 192.168.122.151 (192.168.122.151): icmp_seq=2 ttl=64 time=0.171 ms
^C
--- server ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.171/0.197/0.224/0.026 ms
There are comments.