Pour créer une machine virtuelle sur la plateforme, vous devez déclarer plusieurs choses :

  • La ou les bulles dans laquelle elle est : La bulle BUSINESS ici

  • Son adresse IP : Admettons la 10.15.15.9/26 (bien sûr ce n’est pas sa vrai IPv4)

  • Son hostname/son nom DNS : Son hostname est business-backup-01 et donc son nom en DNS sera business-backup-01.business.31tls00.ef-fr.net

  • Le stockage requis par la VM par défaut c’est 20Go et j’ai laissé à 20Go

  • Son nombre de vCPU (virtual CPU), par défaut c’est 1vCPU : j’ai mis à 2vCPU

  • Sa quantité de RAM, par défaut c’est 1Go : j’ai mis 2Go

Enregistrement DNS

Avant de créer la VM, on vient modifier la zone DNS :

ssh lan-proxy-02.private.31tls00.ef-fr.net

On choisit la zone DNS :

export ZONE_NAME=business.ef-fr.net

Puis on la modifie (Puisque c’est du Bind9, on ne doit pas oublier de modifier le serial à chaque modification, cela sert d’indicateur pour savoir la dernière modification effectuée sur la zone):

vim /var/lib/bind/db.${ZONE_NAME}

L’enregistrement doit ressembler à ça :

business-backup-01 A 10.15.15.9

Puis on vient vérifier que l’on a pas fait d’erreur :

named-checkzone ${ZONE_NAME} /var/lib/bind/db.${ZONE_NAME} && systemctl reload bind9.service

Sur OSS nous utilisons plusieurs fichiers bind pour gérer les différentes zones DNS. Celles-ci suivent la logique de ce qui est mis en place sur l’infrastructure. Soit la séparation en plusieurs bulles. Donc lorsqu’on déploie une VM on doit faire attention à ça.

Création du stockage

Maintenant, pour créer la VM, il faut se connecter à la machine de stockage et passer en root :

ssh str-31tls00-1.adm-srv.31tls00.ef-fr.net
sudo su -l

Après ça, il faut déclarer certains paramètres :

export VM_NAME=business-backup-01
export VM_DISK_SIZE=20g

On alloue le stockage sur le RAID ZFS :

zfs create -V ${VM_DISK_SIZE:-20g} tank/${VM_NAME}

On copie la cloudimg (en l’occurrence une de Debian 12) sur le stockage :

dd bs=4k if=$VM_CLOUD_IMAGE of=/dev/zvol/tank/${VM_NAME}

Plus exactement, on vient ici copier toutes les partitions et données de bases contenues dans la Cloudimg. Par exemple c’est comme si on installait une ISO avec Rufus sur une clef USB.

Puis on déclare le stockage sur le réseau pour l’hyperviseur.

Dans l’ordre :

  • Détermine l’ID du volume iSCSI

  • Création d’une nouvelle cible iSCSI

  • Binding de la cible iSCSI à l’IP de l’hyperviseur

  • Création de l’unité logique (bind du volume ZFS à l’iSCSI)

  • Sauvegarde de la configuration iSCSI

export TARGET_ID=$(tgtadm --mode target --op show | grep -E '^Target [0-9]+:' | cut -d':' -f1 | awk '{print $2 + 1}'  | sort -r -V | head -n 1) && \
tgtadm --lld iscsi --op new --mode target --tid ${TARGET_ID:-1} --targetname iqn.$(date --iso | cut -d'-' -f1,2).net.ef-fr:${VM_NAME} && \
tgtadm --lld iscsi --op bind --mode target --tid ${TARGET_ID:-1} --initiator-address ${HYP_IPV4} && \
tgtadm --lld iscsi --op new --mode logicalunit --tid ${TARGET_ID:-1} --lun 1 --blocksize=4096 --backing-store /dev/zvol/tank/${VM_NAME} && \
tgt-admin --dump | tee /etc/tgt/conf.d/kvm.conf

En effet, le stockage est séparé de l’hyperviseur sur un serveur iSCSI. Pourquoi ? Car ZFS utilise beaucoup de cache, et ce cache est stocké dans la RAM (environ 120Go de RAM utilisé sur les 256Go de la machine de stockage). Cela améliore les accès disques d’utiliser du cache. Je ne peux pas vous expliquer la raison de pourquoi ils sont partis sur du ZFS et pas du LVM par exemple. Mais la principale raison peut être celle là ainsi que la rapidité de ZFS. Bien sûr celui-ci se retrouve confronté à tous les possibles problèmes du RAID. En l’occurrence ici c’est du RAID software. Il existe aussi des cartes de RAID hardware qui dans certains cas peuvent permettre de meilleure fluidité et agilité par rapport à un RAID software (par exemple la PERC H710 chez Dell)

Création de la VM

On se connecte à l’hyperviseur :

ssh hyp-31tls00-1.adm-srv.31tls00.ef-fr.net
sudo su -l

Puis on déclare les paramètres de la VM :

export VM_NAME=business-backup-01
export VM_VCPUS=1
export VM_MEMORY=2048
export VM_NETWORKS=business

On créé la configuration réseau de la VM (c’est un netplan):

vim /opt/cloud-init/network-config/${VM_NAME}.cfg
---
network:
version: 2
ethernets:
    enp1s0:
    dhcp4: false
    addresses:
        - 10.15.15.9/26
    routes:
        - to: default
        via: 10.15.15.1
    nameservers:
        addresses:
        - 10.15.15.1

On vérifie que le fichier YAML est valide :

yamllint /opt/cloud-init/network-config/${VM_NAME}.cfg

Puis on vient déclarer le volume ISCI de la VM (son disque qui est sur le réseau, dans la machine de stockage)

Dans l’ordre :

  • Création du pool de stockage iSCSI de la VM en fonction des informations renseignées sur le serveur stockage

  • Actualisation du pool

  • Définition du pool de stockage de manière permanente sous la forme d’un fichier XML

  • Démarrage automatique du pool de stockage

virsh pool-create-as --name=${VM_NAME} --type=iscsi --source-host=${STR_IPV4} --source-dev=iqn.$(date --iso | cut -d'-' -f1,2).net.ef-fr:${VM_NAME} --target="/dev/disk/by-path" && \
virsh pool-refresh ${VM_NAME} && \
virsh pool-dumpxml ${VM_NAME} | virsh pool-define /dev/stdin && \
virsh pool-autostart ${VM_NAME}

Et enfin, on créé la VM avec virt-install :

Dans l’ordre :

  • Initialisation de la commande de création de la VM

  • Ajout du nom de la VM

  • Configuration des ressources matériel

  • Ajout des disques de stockage (stockage cloud init et stockage de la VM)

  • Configuration du ou des réseaux de la VM

  • Configuration du BIOS de la VM

  • Création de la VM

export VM_CREATION_CMD="virt-install --virt-type kvm --osinfo linux2020 --nographics --noautoconsole --autostart " && \
export VM_CREATION_CMD=$VM_CREATION_CMD"--name ${VM_NAME} " && \
export VM_CREATION_CMD=$VM_CREATION_CMD"--vcpus=${VM_VCPUS:-1} --memory=${VM_MEMORY:-1024} " && \
export VM_CREATION_CMD=$VM_CREATION_CMD$(for VOLUME_ID in $(virsh -q vol-list ${VM_NAME} | awk '{print $1}'); do echo '--disk=vol='${VM_NAME}'/'${VOLUME_ID}' '; done) && \
export VM_CREATION_CMD=$VM_CREATION_CMD$(for VM_NETWORK in $(echo ${VM_NETWORKS} | sed 's/,/\n/g'); do echo '--network=network='${VM_NETWORK}' '; done) && \
export VM_CREATION_CMD=$VM_CREATION_CMD"--cloud-init user-data=/opt/cloud-init/user-data/default.yml,network-config=/opt/cloud-init/network-config/${VM_NAME}.cfg " && \
export VM_CREATION_CMD=$VM_CREATION_CMD"--sysinfo 'smbios,system.serial=ds=nocloud;local-hostname=${VM_NAME}'" && \
eval $VM_CREATION_CMD

Après avoir fait tout cela, notre VM business-backup-01 est créée !

Cela fait beaucoup de commandes à faire pour créer la VM.

Pour résumer l’ensemble des commandes, on a :

  • Déclaré l’IP de la machine dans la zone DNS

  • Copié l’image Debian sur le stockage de la VM

  • Créé et déclaré le stockage de la VM

  • Créé la configuration réseau de la VM

  • Créé la VM à partir de sa configuration réseau, stockage et cloud init

Concernant la configuration Cloud Init, étant privée je ne peux pas la montrer ici, en revanche je peux donner un exemple de celle-ci :

users:
- name: nphilipsinibaldi
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    shell: /bin/bash
    ssh_authorized_keys:
        - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAcCc6Aho3OOoa/W/rdy5D+1uHDQ8MfaxhwRTALXWLiA patch@blitz

package_update: true

packages:
    - curl
    - vim
    - git
    - htop
    - unzip

Cette configuration déclare mon utilisateur avec ma clef SSH, elle autorise l’utilisation de sudo sans mot de passe, la mise à jour des paquets ainsi qu’une liste de paquets à installer sur la machine.

Après avoir effectuée tout ça, nous allons sur Rundeck (un outil d’automatisation) pour créer les utilisateurs administrateurs sur la VM en fonction d’une base dans un LDAP, puis nous installons node exporter sur la machine. Node exporter permet de faire un export de toutes les metrics d’une VM vers un Prometheus, celui-ci est lui même relié à un Grafana pour pouvoir avoir toutes les informations d’une VM. Depuis le Prometheus nous recevons aussi les alertes avec Alertmanager concernant la vie de la VM. par exemple si la RAM est trop pleine, si l’utilisation CPU dépasse un certain seuil...