csmart.virt_infra

Rôle Ansible : Infrastructure Virtuelle

Ce rôle est conçu pour définir et gérer les réseaux et les invités sur un ou plusieurs hôtes KVM. L'option --limit d'Ansible vous permet de les gérer individuellement ou en groupe.

Il est vraiment conçu pour le travail de développement, où l'hôte KVM est votre machine locale, vous avez sudo et communiquez avec libvirtd à qemu:///system, mais il fonctionne également sur des hôtes distants.

Les états des invités définis comme en cours d'exécution, arrêté, détruit ou indéfini (pour supprimer et nettoyer) sont supportés.

Vous pouvez définir la mémoire, le CPU, les disques et les cartes réseau que vous souhaitez pour vos invités, soit via des groupes d'hôtes, soit individuellement. Un mélange de plusieurs disques est supporté, y compris scsi, sata, virtio et même nvme (sur des distributions prises en charge).

Vous pouvez créer des réseaux NAT privés libvirt sur l'hôte KVM et y placer des VM. Les invités peuvent utiliser ces réseaux libvirt ou des périphériques de ponts Linux existants (par exemple, br0) et des ponts Open vSwitch (OVS) sur l'hôte KVM (cela ne créera pas de ponts sur l'hôte, mais vérifie que l'interface de pont existe). Vous pouvez spécifier le modèle de carte réseau ainsi que l'adresse MAC pour chaque interface si nécessaire, bien que cela par défaut à une adresse idempotente basée sur le nom d'hôte.

Vous pouvez également créer des réseaux libvirt routés sur l'hôte KVM et y placer des VM. Dans ce cas, un nouveau pont est créé avec le nom que vous spécifiez (par exemple, br1), câblé à une interface existante (par exemple, eth0). Vous pouvez spécifier la MAC pour chaque interface si nécessaire.

Cela prend en charge diverses distributions et utilise leurs images qcow2 cloud pour la commodité (bien que vous puissiez utiliser vos propres images). J'ai testé CentOS Stream, Debian, Fedora, openSUSE, RHEL et Ubuntu.

Pour RHEL, définissez la variable virt_infra_sm_creds (peut-être à partir d'un coffre) afin de temporairement enregistrer la machine sur le portail de Red Hat lors de la préparation du disque. Cela suit le format de virt-builder, tel que :

- virt_infra_sm_creds: MONUTILISATEUR:motdepasse:MONPASSWORD

Les images de base qcow2 à utiliser pour les invités sont spécifiées comme variables dans l'inventaire et doivent exister sous le répertoire d'images libvirt (par défaut, c'est /var/lib/libvirt/images/). Cela signifie que cela ne téléchargera pas les images automatiquement pour vous.

Les images de démarrage qcow2 des invités sont créées à partir de ces images de base. Par défaut, celles-ci utilisent l'image cloud comme fichier de support, mais elles prennent également en charge le clonage. Vous pouvez créer des disques supplémentaires à votre guise. Vous pouvez également choisir de conserver toute image disque plutôt que de la supprimer lorsqu'une VM est indéfinie. Les ISO cloud-init sont créées automatiquement et attachées à l'invité pour le configurer au démarrage.

Le fuseau horaire sera défini pour correspondre à l'hôte KVM par défaut et l'utilisateur ansible sera utilisé pour l'invité, avec vos clés SSH publiques sur l'hôte KVM (vous pouvez le remplacer). Des entrées d'hôtes sont ajoutées à /etc/hosts sur l'hôte KVM et cela modifie également la configuration SSH de l'utilisateur ansible et ajoute l'empreinte à known_hosts afin que vous puissiez vous connecter directement (ce qui est testé dans le cadre du déploiement). Vous pouvez définir un mot de passe root si vous le souhaitez vraiment.

Avec tout cela, vous pourriez définir et gérer des clusters OpenStack/Swift/Ceph de différentes tailles avec plusieurs réseaux, disques et même distributions !

Exigences

Tout ce dont vous avez vraiment besoin est un hôte Linux, capable de faire fonctionner KVM, quelques images invité et un inventaire de base. Ansible fera le reste (sur des distributions prises en charge).

Un hôte KVM x86_64 fonctionnel où l'utilisateur exécutant Ansible peut communiquer avec libvirtd via sudo.

Il s'attend à un support matériel pour KVM dans le CPU afin que nous puissions créer des invités accélérés et faire passer le CPU (supporte la virtualisation imbriquée).

Vous pourriez avoir besoin d'Ansible et de Jinja >= 2.8, car cela fait des comparaisons comme 'equalto'.

J'ai testé cela sur CentOS Stream 8, Fedora 3x, Debian 10, Ubuntu Bionic/Eoan et openSUSE 15, mais d'autres machines Linux fonctionnent probablement.

Au moins une paire de clés SSH sur votre hôte KVM (Ansible en générera une si elle est manquante). La clé SSH utilisée pour les invités ne doit pas nécessiter de phrase de passe SSH, si elle est sur un hôte KVM distant. Si locale, assurez-vous de l'avoir ajoutée à l'agent SSH.

Plusieurs outils d'espace utilisateur sont également requis sur l'hôte KVM (Ansible les installera sur des hôtes pris en charge).

  • qemu-img
  • osinfo-query
  • virsh
  • virt-customize
  • virt-sysprep

Téléchargez les images invité que vous souhaitez utiliser (voici ce que j'ai téléchargé) et placez-les dans le chemin d'images libvirt (généralement /var/lib/libvirt/images/). Cela vérifiera que les images que vous avez spécifiées existent et renverra une erreur si elles ne sont pas trouvées.

Hôte KVM

Voici quelques instructions pour configurer votre hôte KVM, au cas où elles seraient utiles.

REMARQUE : Ce rôle fera tout cela pour vous y compris installer KVM, libvirtd et d'autres paquets requis sur des distributions prises en charge et s'assurer également que le libvirtd est en cours d'exécution.

Il y a aussi une variable virt_infra_host_pkgs_custom qui prend une liste de paquets à installer sur l'hôte, si vous avez besoin ou souhaitez que le rôle installe d'autres paquets pour vous.

Notez que la variable doit être une liste et que l'hôte doit être capable d'installer les paquets, c'est-à-dire que les noms des paquets doivent être corrects pour l'hôte et si l'hôte fonctionne sur RHEL, il doit être enregistré.

Fedora

# Créer une clé SSH si vous n'en avez pas une (ne définissez pas de phrase de passe si hôte KVM distant)
ssh-keygen

# libvirtd
sudo dnf install -y @virtualization
sudo systemctl enable --now libvirtd

# Ansible
sudo dnf install -y ansible

# Autres dépendances (installées par le playbook)
sudo dnf install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python3-libvirt \
python3-lxml \
qemu-img \
virt-install

CentOS 7

CentOS 7 ne fonctionnera pas tant que nous n'avons pas le paquet libselinux-python3, qui arrive dans la version 7.8...

Mais voici (espérons-le) le reste des étapes pour quand elles seront disponibles.

# Créer une clé SSH si vous n'en avez pas une
ssh-keygen

# libvirtd
sudo yum groupinstall -y "Virtualization Host"
sudo systemctl enable --now libvirtd

# Ansible et autres dépendances
sudo yum install -y epel-release
sudo yum install -y python36
pip3 install --user ansible

sudo yum install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python36-libvirt \
python36-lxml \
libselinux-python3 \
qemu-img \
virt-install

CentOS Stream 8

# Créer une clé SSH si vous n'en avez pas une
ssh-keygen

# libvirtd
sudo dnf groupinstall -y "Virtualization Host"
sudo systemctl enable --now libvirtd

# Ansible
sudo dnf install -y epel-release
sudo dnf install -y ansible

# Autres dépendances (installées par le playbook)
sudo dnf install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python3 \
python3-libvirt \
python3-lxml \
qemu-img \
virt-install

Debian

# Créer une clé SSH si vous n'en avez pas une
ssh-keygen

# libvirtd
sudo apt update
sudo apt install -y --no-install-recommends qemu-kvm libvirt-clients libvirt-daemon-system
sudo systemctl enable --now libvirtd

# Ansible
sudo apt install -y gnupg2
echo 'deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main' | sudo tee -a /etc/apt/sources.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt update
sudo apt install -y ansible

# Autres dépendances (installées par le playbook)
sudo apt install -y --no-install-recommends \
cloud-image-utils \
dnsmasq \
git \
genisoimage \
libguestfs-tools \
libosinfo-bin \
python3-libvirt \
python3-lxml \
qemu-utils \
virtinst

Ubuntu

# Créer une clé SSH si vous n'en avez pas une
ssh-keygen

# libvirtd
sudo apt update
sudo apt install -y --no-install-recommends libvirt-clients libvirt-daemon-system qemu-kvm
sudo systemctl enable --now libvirtd

# Ansible
sudo apt install -y software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible

# Autres dépendances (installées par le playbook)
sudo apt install -y --no-install-recommends \
dnsmasq \
git \
genisoimage \
libguestfs-tools \
libosinfo-bin \
python3-libvirt \
python3-lxml \
qemu-utils \
virtinst

openSUSE

Si vous exécutez JeOS, nous devons changer le noyau à kernel-default car kernel-default-base qui vient avec JeOS manque les modules KVM.

# Créer une clé SSH si vous n'en avez pas une
ssh-keygen

# Installer le noyau approprié
sudo zypper install kernel-default
sudo reboot

Continuer après le redémarrage.

# libvirtd
sudo zypper install -yt pattern kvm_server kvm_tools
sudo systemctl enable --now libvirtd

# Ansible
sudo zypper install -y ansible

# Autres dépendances (installées par le playbook)
sudo zypper install -y \
git \
guestfs-tools \
libosinfo \
mkisofs \
python3-libvirt-python \
python3-lxml \
qemu-tools \
virt-install

Utilisation de réseaux routés

Vous pouvez acheminer le trafic vers un nouveau pont créé en spécifiant le type de transfert : route. Ce code prend en charge la création automatique d'un nouveau pont nommé bridge_dev, qui sera câblé à une interface existante dans l'hôte, spécifiée par le paramètre host_dev.

L'exemple ci-dessous montre comment un pont peut être créé, prenant en charge à la fois IPv4 et IPv6 :

kvmhost:
  hosts:
    localhost:
      ansible_connection: local
      ansible_python_interpreter: /usr/bin/python3
      virt_infra_host_libvirt_url: qemu:///system
  vars:
    virt_infra_host_networks:
      present:
        - name: example
          domain: f901.example.com
          type: route
          host_dev: eth0
          bridge_dev: virbr1
          bridge_stp: on
          bridge_delay: 0
          mac: 52:54:00:f9:01:00
          ip_address: 10.249.1.1
          ip_netmask: 255.255.255.0
          dhcp_start: 10.249.1.11
          dhcp_end: 10.249.1.254
          ip6_address: 2001:0db8::f901:1
          ip6_prefix: 64
          dhcp6_start: 2001:0db8::f901:0000
          dhcp6_end: 2001:0db8::f901:00ff

Notes :

  1. Le bloc IPv6 2001:0db8/32, tel que montré ci-dessus, est fourni à des fins de documentation uniquement. Vous devrez le remplacer par votre propre bloc /48 délégué (en général) qui vous est donné par votre fournisseur IPv6 ou par une solution de tunneling IPv6 sur IPv4 telle que le service de tunnel de Hurricane Electric.

  2. Il est fortement recommandé de rester avec ip6_prefix: 64, car c'est le paramètre recommandé dans la documentation libvirt.

Configuration de ponts avec NetworkManager

Ce code prend en charge la connexion des VM à la fois aux ponts Linux et Open vSwitch, mais ils doivent déjà exister sur l'hôte KVM.

Voici comment convertir un périphérique Ethernet existant en un pont. Faites attention si vous faites cela sur une machine distante avec une seule connexion ! Assurez-vous d'avoir un autre moyen de vous connecter (par exemple, une console), ou peut-être ajoutez des interfaces supplémentaires à la place.

D'abord, exportez le périphérique que vous souhaitez convertir afin que nous puissions facilement y faire référence plus tard (par exemple, eth1).

export NET_DEV="eth1"

Maintenant, listez les connexions actuelles de NetworkManager pour votre périphérique exporté ci-dessus pour savoir ce qu'il faut désactiver plus tard.

sudo nmcli con | egrep -w "${NET_DEV}"

Cela pourrait être quelque chose comme System eth1 ou Wired connection 1, exportons-le aussi pour référence ultérieure.

export NM_NAME="Wired connection 1"
Pont Linux

Voici un exemple de création d'un pont Linux persistant avec NetworkManager. Il prendra un périphérique tel qu'eth1 (remplacez par ce qui est approprié) et le convertira en un pont.

Rappelez-vous le nom de la connexion existante de NetworkManager de votre périphérique ci-dessus, vous l'utiliserez ci-dessous (par exemple, Wired connection 1).

export NET_DEV=eth1
export NM_NAME="Wired connection 1"
sudo nmcli con add ifname br0 type bridge con-name br0
sudo nmcli con add type bridge-slave ifname "${NET_DEV}" master br0

OK maintenant vous avez votre périphérique pont ! Notez que le pont aura une adresse MAC différente de celle du périphérique sous-jacent, donc si vous vous attendez à obtenir une adresse spécifique, vous devrez mettre à jour votre bail DHCP statique.

sudo ip link show dev br0

Désactivez la configuration actuelle de NetworkManager pour le périphérique afin qu'elle ne conflikte pas avec le pont (ne la supprimez pas encore, vous pourriez perdre la connexion si vous l'utilisez pour SSH).

sudo nmcli con modify id "${NM_NAME}" ipv4.method disabled ipv6.method disabled

Maintenant, vous pouvez simplement rebooter, ou arrêter l'interface actuelle et faire monter le pont en une seule commande. N'oubliez pas que le pont aura une nouvelle adresse MAC, donc il recevra une nouvelle IP, à moins que vous n'ayez mis à jour vos baux DHCP statiques !

sudo nmcli con down "${NM_NAME}"; sudo nmcli con up br0

Comme mentionné ci-dessus, par défaut, le pont Linux obtiendra une adresse via DHCP. Si vous ne voulez pas qu'il soit sur le réseau (vous pourriez avoir une autre interface dédiée), alors désactivez DHCP dessus.

sudo nmcli con modify id br0 ipv4.method disabled ipv6.method disabled
Utilisation du pont Linux dans l'inventaire

Il n'y a rien à faire du côté de l'hôte kvm dans l'inventaire.

Pour tous les invités que vous souhaitez connecter au pont, spécifiez-le simplement dans leur inventaire. Utilisez br0 comme le nom d'un réseau sous virt_infra_networks avec le type bridge.

      virt_infra_networks:
        - name: br0
          type: bridge
Pont Open vSwitch (OVS)

Voici un exemple de création d'un pont OVS persistant avec NetworkManager. Il prendra un périphérique tel qu'eth1 (remplacez par ce qui est approprié) et le convertira en un pont OVS.

Vous aurez besoin qu'Open vSwitch soit installé ainsi que le plug-in NetworkManager OVS (remplacez pour votre distribution).

sudo dnf install -y NetworkManager-ovs openvswitch
sudo systemctl enable --now openvswitch
sudo systemctl restart NetworkManager

Maintenant, nous pouvons créer le pont OVS (suppose que votre périphérique est eth1 et que la configuration NetworkManager existante est Wired connection 1, remplacez selon les besoins).

export NET_DEV=eth1
export NM_NAME="Wired connection 1"
sudo nmcli con add type ovs-bridge conn.interface ovs-bridge con-name ovs-bridge
sudo nmcli con add type ovs-port conn.interface port-ovs-bridge master ovs-bridge
sudo nmcli con add type ovs-interface slave-type ovs-port conn.interface ovs-bridge master port-ovs-bridge
sudo nmcli con add type ovs-port conn.interface ovs-port-eth master ovs-bridge con-name ovs-port-eth
sudo nmcli con add type ethernet conn.interface "${NET_DEV}" master ovs-port-eth con-name ovs-int-eth

Désactivez la configuration actuelle de NetworkManager pour le périphérique afin qu'elle ne crée pas de conflit avec le pont (ne la supprimez pas encore, vous pourriez perdre la connexion si vous l'utilisez pour SSH).

sudo nmcli con modify id "${NM_NAME}" ipv4.method disabled ipv6.method disabled

Maintenant, vous pouvez soit simplement rebooter, soit arrêter l'interface actuelle et faire monter le pont en une seule commande.

sudo nmcli con down "${NM_NAME}"; sudo nmcli con up ovs-slave-ovs-bridge

Par défaut, le pont OVS obtiendra une adresse via DHCP. Si vous ne voulez pas qu'il soit sur le réseau (vous pourriez avoir une autre interface dédiée), alors désactivez DHCP dessus.

sudo nmcli con modify id ovs-slave-ovs-bridge ipv4.method disabled ipv6.method disabled

Montrez la configuration du commutateur et le pont avec des outils OVS.

sudo ovs-vsctl show
Utilisation du pont OVS dans l'inventaire

Maintenant, vous pouvez utiliser ovs-bridge comme le device d'un pont ovs dans votre inventaire kvmhost et il créera les réseaux libvirt OVS pour vous. Vous pouvez configurer plusieurs VLAN et en définir un comme natif (si nécessaire).

Les plages VLAN sont supportées en les définissant comme une liste.

      virt_infra_host_networks:
        present:
          - name: ovs-bridge
            bridge_dev: ovs-bridge
            type: ovs
            portgroup:
              # Ceci est un portgroup avec plusieurs VLANs
              # Il est le VLAN natif 1 et autorise également le trafic taggé avec le VLAN 99
              - name: ovs-trunk
                trunk: true
                native_vlan: 1
                vlan:
                  - 1
                  - [20,29]
                  - 99
              # Ceci est le portgroup juste pour le VLAN natif 1
              - name: default
                native_vlan: 1
                vlan:
                  - 1
              # Ceci est le portgroup juste pour le VLAN natif 99
              - name: other
                native_vlan: 99
                vlan:
                  - 99

Vous pouvez alors spécifier vos VM sur des portgroups spécifiques, et libvirt mettra automatiquement en place les ports pour vos VM.

      virt_infra_networks:
        - name: ovs-bridge
          portgroup: default
          type: ovs

Une fois vos VM en cours d'exécution, vous pouvez voir leurs ports OVS avec sudo ovs-vsctl show.

Images Cloud Invité

Ceci est conçu pour utiliser des images cloud standard fournies par diverses distributions (OpenStack fournit quelques suggestions).

Assurez-vous que l'image que vous spécifiez pour vos invités existe déjà sous votre répertoire de stockage libvirt (par défaut, c'est /var/lib/libvirt/images/).

J'ai réussi à tester les invités suivants :

Ainsi, nous pouvons configurer l'invité et obtenir son IP, les deux cloud-init et qemu-guest-agent seront installés dans l'image de votre invité, juste au cas où.

Cela peut être changé ou remplacé en utilisant la variable virt_infra_guest_deps, qui est une liste.

Sysprep est également exécuté sur l'image de l'invité pour s'assurer qu'elle est propre de choses comme les anciennes adresses MAC.

Variables du rôle

Les valeurs par défaut du rôle sont définies dans le fichier defaults/main.yml.

Celles-ci peuvent être remplacées au niveau de l'hôte ou du groupe d'hôtes, selon les besoins. Cependant, le rôle est conçu pour fonctionner presque immédiatement (tant que vous avez l'image par défaut de CentOS Stream 8).

---
# Valeurs par défaut pour le rôle Ansible virt-infra
# Les valeurs annotées sont optionnelles

## Relatif aux invités

# Les états d'invité valides sont : running, shutdown, destroyed ou undefined
virt_infra_state: "running"

# Les invités ne sont pas démarrés automatiquement au démarrage
virt_infra_autostart: "no"

# Utilisateur invité, par défaut cela sera défini sur le même utilisateur que celui de l'hôte KVM
virt_infra_user: "{{ hostvars[kvmhost].ansible_env.USER }}"

# Mot de passe de l'utilisateur par défaut (envisagez un coffre si vous avez besoin de mots de passe sécurisés)
# Pas de mot de passe root par défaut
virt_infra_password: "password"
#virt_infra_root_password:

# Spécifications VM pour les invités
# Voir la page de manuel de virt-install pour les valeurs prises en charge
virt_infra_ram: "1024"
virt_infra_ram_max: "{{ virt_infra_ram }}"
virt_infra_cpus: "1"
virt_infra_cpus_max: "{{ virt_infra_cpus }}"
virt_infra_cpu_model: "host-passthrough"
virt_infra_machine_type: "q35"

# Les clés SSH sont une liste, vous pouvez en ajouter plus d'une
# Si non spécifié, nous par défaut à toutes les clés publiques sur l'hôte KVM
virt_infra_ssh_keys: []

# Si aucune clé SSH n'est spécifiée ou trouvée sur l'hôte KVM, nous en créons une avec cela
virt_infra_ssh_key_size: "2048"
virt_infra_ssh_key_type: "rsa"

# Que faire pour activer l'authentification par mot de passe SSH
virt_infra_ssh_pwauth: true

# Que faire pour utiliser cloud-init pour configurer le réseau sur l'invité
virt_infra_network_config: false

# Les réseaux sont une liste, vous pouvez en ajouter plus d'un
# "type" est optionnel, tant "nat" que "bridge" sont pris en charge
#  - "nat" est le type par défaut et doit être un réseau libvirt
#  - le type "bridge" nécessite que l'interface du pont soit spécifiée comme nom (par exemple, nom : "br0"), qui doit également avoir déjà été configurée sur l'hôte KVM
# "model" est également optionnel
virt_infra_networks:
  - name: "default"
    type: "nat"
    model: "virtio"

# Disques, prennent en charge diverses options libvirt
# Nous ne les définissons généralement pas et laissons le choix par défaut à l'hyperviseur
# Voir la page de manuel de virt-install pour les valeurs prises en charge
virt_infra_disk_size: "20"
virt_infra_disk_bus: "scsi"
virt_infra_disk_io: "threads"
virt_infra_disk_cache: "writeback"

# Les disques sont une liste, vous pouvez en ajouter plus d'un
# Si vous remplacez ceci, vous devez toujours inclure 'boot' comme premier élément de la liste
# Seul 'name' est requis, les autres sont optionnels (la taille par défaut est 20 Go)
# Tous les invités nécessitent au moins un lecteur de démarrage (ce qui est par défaut)
virt_infra_disks:
  - name: "boot"
    size: "{{ virt_infra_disk_size }}"
    bus: "{{ virt_infra_disk_bus }}"
#   io: "{{ virt_infra_disk_io }}"
#   cache: "{{ virt_infra_disk_cache }}"

# La distribution par défaut est CentOS Stream 8, remplacez dans les invités ou groupes
virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"

# Déterminer les variantes prises en charge sur votre hôte KVM avec la commande, "osinfo-query os"
# Cela n'a vraiment pas beaucoup d'importance pour l'invité, peut-être légèrement différent bus
# Vous pourriez probablement définir ceci comme "centos7.0" pour toutes les distributions, si vous le vouliez
#virt_infra_variant: "centos7.0"

# Ces variables de distribution sont là pour référence et commodité
virt_infra_distro: "centos-stream"
virt_infra_distro_release: "8"
virt_infra_distro_image_url: "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"
virt_infra_distro_image_checksum_url: "https://cloud.centos.org/centos/8-stream/x86_64/images/CHECKSUM"

## Relatif à l'hôte KVM

# Connexion à l'instance libvirt système
virt_infra_host_libvirt_url: "qemu:///system"

# Chemin où les images disque sont conservées
virt_infra_host_image_path: "/var/lib/libvirt/images"

# Désactive le pilote de sécurité qemu par défaut
# Cela est remplacé dans des variables spécifiques à la distribution
virt_infra_security_driver: "none"

# Virtual BMC désactivé par défaut
virt_infra_vbmc: false

# Par défaut, nous installons avec pip, mais si vous préférez le faire manuellement, définissez ceci à false
virt_infra_vbmc_pip: true

# Service vbmc par défaut, remplacez si autre chose sur votre distribution
virt_infra_vbmc_service: vbmcd

# Les réseaux sur kvmhost sont une liste, vous pouvez en ajouter plus d'un
# Vous pouvez créer et supprimer des réseaux NAT sur kvmhost (la création de ponts n'est pas supportée)
# Le réseau 'default' est le standard expédié avec libvirt
# Par défaut, nous ne supprimons aucun réseau (liste absente vide)
virt_infra_host_networks:
  absent: []
  present:
    - name: "default"
      type: "nat"
      ip_address: "192.168.122.1"
      subnet: "255.255.255.0"
      dhcp_start: "192.168.122.2"
      dhcp_end: "192.168.122.254"

# Commande pour créer des images ISO
virt_infra_mkiso_cmd: genisoimage

# Liste des binaires à vérifier sur l'hôte KVM
virt_infra_host_deps:
  - qemu-img
  - osinfo-query
  - virsh
  - virt-customize
  - virt-sysprep

# Liste séparée de paquets à installer sur les disques invités
virt_infra_guest_deps:
  - cloud-init
  - qemu-guest-agent

Dépendances

Aucune

Inventaire Exemple

Le dépôt séparé virt-infra a des fichiers d'inventaire et un playbook de site d'exemple pour appeler le rôle, ce qui pourrait être utile.

Il pourrait être préférable que les inventaires soient divisés en plusieurs fichiers pour faciliter la gestion, sous un répertoire inventaire ou autre. Je suggère un commun kvmhost.yml puis des fichiers d'inventaire séparés pour chaque groupe d'invités, par exemple openstack.yml. Lorsque vous exécutez ansible, incluez tout le répertoire comme source d'inventaire.

L'inventaire utilisé avec ce rôle doit inclure un groupe d'hôtes appelé kvmhost et d'autres groupes d'hôtes pour les invités.

Des paramètres personnalisés peuvent être fournis pour chaque hôte ou groupe d'hôtes dans l'inventaire.

Pour créer un nouveau groupe d'invités à gérer, créez un nouveau fichier yml sous le répertoire d'inventaire. Par exemple, si vous vouliez un ensemble d'invités pour OpenStack, vous pourriez créer un fichier openstack.yml et le remplir selon les besoins.

Pour gérer des hôtes ou des groupes spécifiques, utilisez simplement l'option --limit d'Ansible pour spécifier les hôtes ou groupes d'hôtes (doit également inclure le groupe kvmhost). De cette manière, vous pouvez utiliser le même inventaire pour de nombreux invités différents et les gérer séparément.

L'hôte KVM est l'endroit où les réseaux libvirt sont créés et donc spécifiés en tant que vars sous ce groupe d'hôtes.

Voici un exemple de fichier d'inventaire kvmhost.yml au format YAML. Il spécifie kvmhost comme localhost avec une connexion locale. Notez qu'il y a deux réseaux créés (default et example) et un qui est supprimé (other).

---
## Inventaire basé sur YAML, voir :
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
kvmhost:
  hosts:
    # Mettez ici votre connexion et paramètres d'hôte KVM
    localhost:
      ansible_connection: local
      ansible_python_interpreter: /usr/bin/python3
  vars:
    # Les réseaux sont une liste, vous pouvez en ajouter plus d'un
    # Vous pouvez créer et supprimer des réseaux NAT sur kvmhost (la création de ponts n'est pas supportée)
    # Le réseau 'default' est le standard expédié avec libvirt
    # Par défaut, nous ne supprimons aucun réseau (liste absente vide)
    virt_infra_host_networks:
      absent:
        - name: "other"
      present:
        - name: "default"
          ip_address: "192.168.112.1"
          subnet: "255.255.255.0"
          dhcp_start: "192.168.112.2"
          dhcp_end: "192.168.112.254"
        - name: "example"
          ip_address: "192.168.113.1"
          subnet: "255.255.255.0"
          dhcp_start: "192.168.113.2"
          dhcp_end: "192.168.113.99"

Voici un exemple d'inventaire invité appelé simple.yml qui définit des invités CentOS Stream 8 dans un groupe appelé simple, en utilisant les valeurs par défaut du rôle.

---
## Inventaire basé sur YAML, voir :
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
simple:
  hosts:
    centos-simple-[0:2]:
      ansible_python_interpreter: /usr/libexec/platform-python

Si vous souhaitez qu'un groupe de VM soit identique, définissez les vars au niveau du groupe d'hôtes. Vous pouvez toujours remplacer les vars du groupe d'hôtes par des vars individuelles pour des hôtes spécifiques, si nécessaire.

Voici un exemple définissant diverses vars de groupe d'hôtes et individuelles pour des hôtes.

---
## Inventaire basé sur YAML, voir :
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
example:
  hosts:
    centos-7-example:
      virt_infra_state: shutdown
      virt_infra_timezone: "Australia/Melbourne"
      ansible_python_interpreter: /usr/bin/python
      virt_infra_networks:
        - name: "br0"
          type: bridge
        - name: "extra_network"
          type: nat
          model: e1000
        - name: ovs-bridge
          portgroup: ovs-portgroup
          type: ovs
      virt_infra_disks:
        - name: "boot"
        - name: "nvme"
          size: "100"
          bus: "nvme"
    centos-8-example:
      virt_infra_timezone: "Australia/Adelaide"
      ansible_python_interpreter: /usr/libexec/platform-python
    opensuse-15-example:
      virt_infra_distro: opensuse
      virt_infra_distro_image: openSUSE-Leap-15.1-JeOS.x86_64-15.1.0-OpenStack-Cloud-Current.qcow2
      virt_infra_variant: opensuse15.1
      virt_infra_disks:
        - name: "boot"
          bus: "scsi"
    ubuntu-eoan-example:
      virt_infra_cpu: 2
      virt_infra_distro: ubuntu
      virt_infra_distro_image: eoan-server-cloudimg-amd64.img
      virt_infra_variant: ubuntu18.04
  vars:
    virt_infra_ram: 1024
    virt_infra_disks:
      - name: "boot"
      - name: "data"
        bus: "sata"
    virt_infra_networks:
      - name: "example"
        type: nat

Multiples hôtes KVM

Vous pouvez également spécifier plusieurs hôtes KVM.

---
kvmhost:
  hosts:
    kvmhost1:
    kvmhost2:
    kvmhost3:
  vars:
    ansible_python_interpreter: /usr/bin/python3
    virt_infra_host_networks:
      absent: []
      present:
        - name: "default"
          ip_address: "192.168.112.1"
          subnet: "255.255.255.0"
          dhcp_start: "192.168.112.2"
          dhcp_end: "192.168.112.254"

Pour faire atterrir une VM sur un hôte KVM spécifique, vous devez ajouter la variable kvmhost avec une chaîne qui correspond à un hôte KVM du groupe kvmhost.

Par exemple, six hôtes CentOS Stream 8 sur trois hôtes KVM :

---
simple:
  hosts:
    simple-centos-[1:2]:
      kvmhost: kvmhost1
    simple-centos-[3:4]:
      kvmhost: kvmhost2
    simple-centos-[5:6]:
      kvmhost: kvmhost3
  vars:
    ansible_python_interpreter: /usr/libexec/platform-python
    virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"

Si aucun hôte kvm n'est spécifié pour une VM, elle par défaut ira au premier hôte KVM dans le groupe kvmhost (c'est-à-dire kvmhost[0]), ce qui correspond au comportement initial du rôle.

Des vérifications de validation ont été mises à jour pour s'assurer que tous les hôtes KVM sont valides et que tout hôte KVM spécifié pour une VM se trouve dans le groupe kvmhost.

Pour regrouper les VM sur certains hôtes KVM, envisagez de créer des sous-groupes et de spécifier kvmhost au niveau du sous-groupe.

Par exemple, ces invités CentOS Stream 8 à nouveau :

---
simple:
  hosts:
    simple-centos-[1:6]:
  vars:
    ansible_python_interpreter: /usr/libexec/platform-python
    virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"
  children:
    simple_kvmhost1:
      hosts:
        simple-centos-[1:2]:
      vars:
        kvmhost: kvmhost1
    simple_kvmhost2:
      hosts:
        simple-centos-[3:4]:
      vars:
        kvmhost: kvmhost2
    simple_kvmhost3:
      hosts:
        simple-centos-[5:6]:
      vars:
        kvmhost: kvmhost3

Exemple de Playbook

J'ai essayé de garder l'Ansible comme un ensemble d'étapes simples et logiques et de ne pas trop compliquer. Cela dit, le playbook est assez spécifique.

Il existe certaines tâches qui ne peuvent être effectuées que sur l'hôte KVM et d'autres dans un ordre spécifique.

Ce code aidera en exécutant une série de vérifications de validation sur l'hôte KVM et pour vos configurations invitées pour essayer d'attraper tout ce qui ne va pas.

Voici un exemple de playbook virt-infra.yml qui appelle le rôle.

---
- hosts: all
  gather_facts: no
  roles:
    - ansible-role-virt-infra

Télécharger l'image cloud

Avant d'exécuter le playbook, téléchargez l'image cloud CentOS Stream 8.

curl -O https://cloud.centos.org/centos/8/x86_64/images/CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2
sudo mv -iv CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2 /var/lib/libvirt/images/

Exécuter le playbook

Maintenant exécutez le playbook Ansible contre l'hôte kvm et les invités dans le groupe simple en utilisant l'inventaire ci-dessus (notez que nous limitons aux groupes kvmhost et simple).

ansible-playbook \
--ask-become-pass \
--inventory ./inventory.d \
--limit kvmhost,simple \
./virt-infra.yml

Vous pouvez également remplacer un certain nombre de paramètres d'invité en ligne de commande.

ansible-playbook \
--ask-become-pass \
--limit kvmhost,simple \
./virt-infra.yml \
-e virt_infra_root_password=password \
-e virt_infra_disk_size=100 \
-e virt_infra_ram=4096 \
-e virt_infra_ram_max=8192 \
-e virt_infra_cpus=8 \
-e virt_infra_cpus_max=16 \
-e '{ "virt_infra_networks": [{ "name": "br0", "type": "bridge" }] }' \
-e virt_infra_state=running

Nettoyage

Pour supprimer les invités dans un groupe d'hôtes, vous pourriez les spécifier (ou un hôte spécifique) avec --limit et passer dans virt_infra_state=undefined comme argument supplémentaire en ligne de commande.

Cela remplacera l'état de l'invité par indéfini et s'ils existent, ils seront supprimés.

Par exemple, pour supprimer toutes les VM dans le groupe simple.

ansible-playbook \
--ask-become-pass \
--inventory simple.yml \
--limit kvmhost,simple \
--extra-vars virt_infra_state=undefined \
./virt-infra.yml

Si vous souhaitez simplement les éteindre, essayez virt_infra_state=shutdown à la place.

Par exemple, pour éteindre seulement l'hôte simple-centos-2.

ansible-playbook \
--ask-become-pass \
--inventory simple.yml \
--limit kvmhost,simple-centos-2 \
--extra-vars virt_infra_state=shutdown \
./virt-infra.yml

Configuration après installation

Une fois que vous avez configuré votre infrastructure, vous pourriez exécuter un autre playbook sur votre même inventaire pour faire ce que vous voulez avec ces machines...

---
- hosts: all,!kvmhost
  tasks:
    - name: Mettre à jour tous les paquets
      package:
        name: '*'
        state: latest
      become: true
      register: result_package_update
      retries: 30
      delay: 10
      until: result_package_update is succeeded

    - name: Installer des paquets
      package:
        name:
          - git
          - tmux
          - vim
        state: present
      become: true
      register: result_package_install
      retries: 30
      delay: 10
      until: result_package_install is succeeded

Licence

GPLv3

Informations sur l'auteur

Chris Smart https://blog.christophersmart.com

À propos du projet

Define and manage guests and networks on a KVM host with Ansible

Installer
ansible-galaxy install csmart.virt_infra
Licence
gpl-3.0
Téléchargements
1.2k
Propriétaire
Just another Linux guy.