csmart.virt_infra

Rol de Ansible: Infraestructura Virtual

Este rol está diseñado para definir y gestionar redes e invitados en uno o más hosts KVM. La opción --limit de Ansible te permite administrarlos de forma individual o en grupo.

Está realmente pensado para trabajar en desarrollo, donde el host KVM es tu máquina local, tienes sudo y te conectas a libvirtd en qemu:///system, sin embargo, también funciona en hosts remotos.

Están soportados los estados de los invitados como ejecutando, apagado, destruido o indefinido (para eliminar y limpiar).

Puedes configurar la memoria, CPU, discos y tarjetas de red que quieras para tus invitados, ya sea a través de grupos de hosts o de forma individual. Se soporta una mezcla de múltiples discos, incluyendo scsi, sata, virtio e incluso nvme (en distribuciones compatibles).

Puedes crear redes NAT privadas de libvirt en el host KVM y luego poner VMs en cualquiera de ellas. Los invitados pueden usar esas redes libvirt o dispositivos de puente Linux existentes (por ejemplo, br0) y de puente Open vSwitch (OVS) en el host KVM (esto no creará puentes en el host, pero verificará que la interfaz de puente exista). Puedes especificar el modelo de tarjeta de red así como la MAC para cada interfaz si lo necesitas, sin embargo, por defecto, se usará una dirección idempotente basada en el nombre del host.

También puedes crear redes libvirt enrutadas en el host KVM y luego poner VMs en cualquiera de ellas. En este caso, se crea un nuevo puente con el nombre que especifiques (por ejemplo, br1), conectado a una interfaz existente (por ejemplo, eth0). Puedes especificar la MAC para cada interfaz si lo necesitas.

Esto soporta varias distribuciones y utiliza las imágenes qcow2 cloud images por conveniencia (aunque puedes usar tus propias imágenes). He probado con CentOS Stream, Debian, Fedora, openSUSE, RHEL y Ubuntu.

Para RHEL, configura la variable virt_infra_sm_creds (quizás de un vault) para registrar temporalmente la máquina en el portal de Red Hat al preparar el disco. Esto sigue el formato de virt-builder, como:

- virt_infra_sm_creds: MYUSER:password:MYPASSWORD

Las imágenes base de qcow2 a usar para los invitados se especifican como variables en el inventario y deben existir en el directorio de imágenes de libvirt (el valor predeterminado es /var/lib/libvirt/images/). Es decir, esto no descargará las imágenes automáticamente.

Las imágenes de arranque qcow2 de los invitados se crean a partir de esas imágenes base. Por defecto, estas utilizan la imagen de cloud como archivo base, sin embargo, también soporta clonación. Puedes crear discos adicionales como desees. También puedes optar por mantener cualquier imagen de disco en lugar de eliminarla cuando una VM no esté definida. Las ISOs de cloud-init se crean automáticamente y se adjuntan al invitado para configurarlo en el arranque.

La zona horaria se configurará para coincidir con el host KVM por defecto y se usará el usuario de ansible para el invitado, junto con tus claves SSH públicas en el host KVM (puedes sobrescribir esto). Las entradas de host se agregan a /etc/hosts en el host KVM y también modifica la configuración SSH del usuario de ansible y agrega la huella digital a known_hosts para que puedas conectarte por SSH directamente (lo cual se prueba como parte de la implementación). Puedes establecer una contraseña de root si realmente lo deseas.

Con todo esto, podrías definir y gestionar clusters de OpenStack/Swift/Ceph de diferentes tamaños con múltiples redes, discos e incluso distribuciones.

Requisitos

Todo lo que realmente se necesita es un host Linux, capaz de ejecutar KVM, algunas imágenes de invitados y un inventario básico. Ansible hará el resto (en distribuciones compatibles).

Un host KVM x86_64 en funcionamiento donde el usuario que ejecuta Ansible pueda comunicarse con libvirtd a través de sudo.

Se espera soporte de hardware para KVM en el CPU para que podamos crear invitados acelerados y pasar la CPU (soporta virtualización anidada).

Es posible que necesites Ansible y Jinja >= 2.8 porque realiza cosas como comparaciones 'usado igual a'.

He probado esto en CentOS Stream 8, Fedora 3x, Debian 10, Ubuntu Bionic/Eoan y hosts openSUSE 15, pero probablemente otras máquinas Linux funcionen.

Al menos un par de claves SSH en tu host KVM (Ansible generará una si falta). La clave SSH utilizada para los invitados no debería requerir una frase de contraseña de SSH, si está en un host KVM remoto. Si es local, entonces asegúrate de haberla agregado al agente SSH.

Se requieren también varias herramientas de espacio de usuario en el host KVM (Ansible las instalará en hosts compatibles).

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

Descarga las imágenes de invitados que deseas usar (esto es lo que descargué) y ponlas en la ruta de imágenes de libvirt (generalmente /var/lib/libvirt/images/). Esto verificará que las imágenes que especificaste existan y mostrará un error si no se encuentran.

Host KVM

Aquí hay algunas instrucciones para configurar tu host KVM, en caso de que sean útiles.

NOTA: Este rol hará todo esto por ti, incluyendo instalar KVM, libvirtd y otros paquetes requeridos en distribuciones compatibles y también asegurará que libvirtd esté en funcionamiento.

También hay una variable virt_infra_host_pkgs_custom que toma una lista de paquetes a instalar en el host, en caso de que necesites o quieras que el rol instale algunos paquetes adicionales para ti.

Ten en cuenta que la variable debe ser una lista y que el host debe ser capaz de instalar los paquetes, es decir, los nombres de los paquetes deben ser correctos para el host y si el host está ejecutando RHEL, debe estar registrado.

Fedora

# Crea la clave SSH si no tienes una (no establezcas una frase de contraseña si es un host KVM remoto)
ssh-keygen

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

# Ansible
sudo dnf install -y ansible

# Otras dependencias (instaladas por el playbook)
sudo dnf install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python3-libvirt \
python3-lxml \
qemu-img \
virt-install

CentOS 7

CentOS 7 no funcionará hasta que tengamos el paquete libselinux-python3, que llegará en 7.8...

Pero aquí están (esperemos) los demás pasos para cuando estén disponibles.

# Crea la clave SSH si no tienes una
ssh-keygen

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

# Ansible y otras dependencias
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

# Crea la clave SSH si no tienes una
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

# Otras dependencias (instaladas por el playbook)
sudo dnf install -y \
git \
genisoimage \
libguestfs-tools-c \
libosinfo \
python3 \
python3-libvirt \
python3-lxml \
qemu-img \
virt-install

Debian

# Crea la clave SSH si no tienes una
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

# Otras dependencias (instaladas por el 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

# Crea la clave SSH si no tienes una
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

# Otras dependencias (instaladas por el playbook)
sudo apt install -y --no-install-recommends \
dnsmasq \
git \
genisoimage \
libguestfs-tools \
libosinfo-bin \
python3-libvirt \
python3-lxml \
qemu-utils \
virtinst

openSUSE

Si estás usando JeOS, necesitamos cambiar el kernel a kernel-default ya que kernel-default-base que viene con JeOS no tiene los módulos de KVM.

# Crea la clave SSH si no tienes una
ssh-keygen

# Instala el kernel adecuado
sudo zypper install kernel-default
sudo reboot

Continúa después del reinicio.

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

# Ansible
sudo zypper install -y ansible

# Otras dependencias (instaladas por el playbook)
sudo zypper install -y \
git \
guestfs-tools \
libosinfo \
mkisofs \
python3-libvirt-python \
python3-lxml \
qemu-tools \
virt-install

Usando redes enrutadas

Puedes enrutar tráfico hacia un puente recién creado especificando el tipo de forward: route. Este código soporta la creación automática de un nuevo puente llamado bridge_dev que estará conectado a una interfaz existente en el host, especificada por el parámetro host_dev.

El siguiente ejemplo muestra cómo se puede crear un puente, soportando tanto IPv4 como 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

Notas:

  1. El bloque IPv6 2001:0db8/32 como se muestra arriba se proporciona solo para fines documentales. Deberás sustituirlo por tu propio bloque /48 delegado (en general) dado a ti por tu proveedor IPv6 o por una solución de túnel IPv6 sobre IPv4 como el servicio de corredor de túneles de Hurricane Electric.

  2. Se recomienda encarecidamente que te mantengas con ip6_prefix: 64, ya que es la configuración recomendada en la documentación de libvirt.

Configurando puentes con NetworkManager

Este código permite conectar VMs tanto a puentes Linux como a puentes Open vSwitch, pero deben existir previamente en el host KVM.

Aquí se muestra cómo convertir un dispositivo ethernet existente en un puente. ¡Ten cuidado si lo haces en una máquina remota con una sola conexión! Asegúrate de tener otra forma de iniciar sesión (por ejemplo, consola), o quizás agregar interfaces adicionales en su lugar.

Primero, exporta el dispositivo que deseas convertir para que podamos hacer referencia a él fácilmente más tarde (por ejemplo, eth1).

export NET_DEV="eth1"

Ahora lista las conexiones actuales de NetworkManager para tu dispositivo exportado arriba para saber qué deshabilitar más tarde.

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

Esto podría ser algo como System eth1 o Wired connection 1, vamos a exportarlo también para referencia futura.

export NM_NAME="Wired connection 1"
Puente Linux

Aquí hay un ejemplo de cómo crear un puente Linux persistente con NetworkManager. Tomará un dispositivo como eth1 (sustituye según sea necesario) y lo convertirá en un puente.

Recuerda el nombre de conexión existente de NetworkManager para tu dispositivo de arriba, lo usarás más adelante (por ejemplo, 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

¡Bien, ahora tienes tu dispositivo puente! Ten en cuenta que el puente tendrá una dirección MAC diferente al dispositivo subyacente, así que si esperabas que obtuviera una dirección específica, necesitarás actualizar tu reserva DHCP estática.

sudo ip link show dev br0

Desactiva la configuración actual de NetworkManager para el dispositivo para que no conflicte con el puente (no lo elimines todavía, podrías perder la conexión si lo estás usando para SSH).

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

Ahora puedes simplemente reiniciar, o detener la interfaz actual y subir el puente en un solo comando. Recuerda que el puente tendrá una nueva dirección MAC por lo que obtendrá una nueva IP, a menos que hayas actualizado tus arrendamientos estáticos DHCP.

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

Como se mencionó anteriormente, por defecto el puente Linux obtendrá una dirección a través de DHCP. Si no deseas que esté en la red (puedes tener otra interfaz dedicada), entonces desactiva DHCP en él.

sudo nmcli con modify id br0 ipv4.method disabled ipv6.method disabled
Usando puente Linux en inventario

No hay nada que hacer en el lado de kvmhost del inventario.

Para cualquier invitado que desees conectar al puente, simplemente especifícalo en su inventario. Usa br0 como el name de una red bajo virt_infra_networks con tipo bridge.

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

Aquí hay un ejemplo de crear un puente OVS persistente con NetworkManager. Tomará un dispositivo como eth1 (sustituye según sea necesario) y lo convertirá en un puente ovs.

Necesitarás tener Open vSwitch instalado así como el plugin de NetworkManager de OVS (sustituye por tu distribución).

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

Ahora podemos crear el puente OVS (suponiendo que tu dispositivo es eth1 y la configuración de NetworkManager existente es Wired connection 1, sustituye según sea necesario).

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

Desactiva la configuración actual de NetworkManager para el dispositivo para que no conflicte con el puente (no lo elimines todavía, podrías perder la conexión si lo estás usando para SSH).

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

Ahora puedes simplemente reiniciar, o detener la interfaz actual y poner en marcha el puente en un solo comando.

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

Por defecto, el puente OVS obtendrá una dirección a través de DHCP. Si no deseas que esté en la red (puedes tener otra interfaz dedicada), entonces desactiva DHCP en él.

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

Muestra la configuración del switch y del puente con las herramientas de OVS.

sudo ovs-vsctl show
Usando ovs-bridge en inventario

Ahora puedes usar ovs-bridge como el device de un puente ovs en tu inventario kvmhost, la entrada virt_infra_host_networks lo creará para ti. Puedes configurar múltiples VLANs y establecer una como nativa (si es necesario).

Las rangos de VLAN son admitidos definiéndolo como una lista.

      virt_infra_host_networks:
        present:
          - name: ovs-bridge
            bridge_dev: ovs-bridge
            type: ovs
            portgroup:
              # Este es un grupo de puertos con múltiples VLANs
              # Es la VLAN nativa 1 y también permite tráfico etiquetado con VLAN 99
              - name: ovs-trunk
                trunk: true
                native_vlan: 1
                vlan:
                  - 1
                  - [20,29]
                  - 99
              # Este es un grupo de puertos solo para la VLAN nativa 1
              - name: default
                native_vlan: 1
                vlan:
                  - 1
              # Este es un grupo de puertos solo para la VLAN nativa 99
              - name: other
                native_vlan: 99
                vlan:
                  - 99

Luego puedes especificar que tus VMs estén en grupos de puertos específicos y libvirt automáticamente configurará los puertos para tus VMs.

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

Una vez que tus VMs estén en ejecución, puedes ver sus puertos OVS con sudo ovs-vsctl show.

Imágenes de Cloud para el Invitado

Esto está diseñado para usar imágenes de cloud estándar proporcionadas por varias distribuciones (OpenStack proporciona algunas sugerencias).

Asegúrate de que la imagen que estás especificando para tus invitados ya exista en tu directorio de almacenamiento de libvirt (por defecto esto es /var/lib/libvirt/images/).

He probado con éxito los siguientes invitados:

Para que podamos configurar el invitado y obtener su IP, tanto cloud-init como qemu-guest-agent se instalarán en la imagen del invitado, por si acaso.

Esto se puede cambiar o sobrescribir usando la variable virt_infra_guest_deps, que es una lista.

Sysprep también se ejecuta en la imagen del invitado para asegurarse de que está limpia de cosas como antiguas direcciones MAC.

Variables de Rol

Los valores predeterminados del rol se establecen en el archivo defaults/main.yml.

Estos se pueden sobrescribir a nivel de host o grupo de hosts, según sea necesario. Sin embargo, el rol está diseñado para funcionar prácticamente sin problemas (siempre que tengas la imagen predeterminada de CentOS Stream 8).

---
# Valores predeterminados para el rol de infra-virt de Ansible
# Los valores comentados son opcionales

## Relacionado con el invitado

# Los estados válidos de los invitados son: running, shutdown, destroyed o undefined
virt_infra_state: "running"

# Los invitados no se inician automáticamente al arranque
virt_infra_autostart: "no"

# Usuario del invitado, por defecto se configurará al mismo usuario que el del host KVM
virt_infra_user: "{{ hostvars[kvmhost].ansible_env.USER }}"

# Contraseña del usuario predeterminado (considera un vault si necesitas contraseñas seguras)
# Sin contraseña de root por defecto
virt_infra_password: "password"
#virt_infra_root_password:

# Especificaciones de VM para los invitados
# Consulta la manpage de virt-install para valores soportados
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"

# Las claves SSH son una lista, puedes agregar más de una
# Si no se especifica, por defecto se usan todas las claves públicas en el host KVM
virt_infra_ssh_keys: []

# Si no se especifican o encuentran claves SSH en el host KVM, creamos una con este
virt_infra_ssh_key_size: "2048"
virt_infra_ssh_key_type: "rsa"

# Si habilitar la autenticación por contraseña SSH
virt_infra_ssh_pwauth: true

# Si usar cloud-init para configurar la red en el invitado
virt_infra_network_config: false

# Las redes son una lista, puedes agregar más de una
# "type" es opcional, se soportan "nat" y "bridge"
#  - "nat" es el tipo predeterminado y debe ser una red de libvirt
#  - el tipo "bridge" requiere la interfaz puente como el nombre (por ejemplo, name: "br0") que 
#    también debe estar ya configurada en el host KVM
# "model" también es opcional
virt_infra_networks:
  - name: "default"
    type: "nat"
    model: "virtio"

# Discos, soporte para varias opciones de libvirt
# Generalmente no los configuramos, sino que los dejamos al valor predeterminado del hipervisor
# Consulta la manpage de virt-install para valores soportados
virt_infra_disk_size: "20"
virt_infra_disk_bus: "scsi"
virt_infra_disk_io: "threads"
virt_infra_disk_cache: "writeback"

# Los discos son una lista, puedes agregar más de uno
# Si sobrescribes esto, debes incluir 'boot' como primer dispositivo en la lista
# Solo 'name' es requerido, los demás son opcionales (el tamaño predeterminado es 20GB)
# Todos los invitados requieren al menos una unidad de arranque (que es el valor predeterminado)
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 distribución predeterminada es CentOS Stream 8, sobreescribe en los invitados o grupos
virt_infra_distro_image: "CentOS-Stream-GenericCloud-8-20210603.0.x86_64.qcow2"

# Determina las variantes soportadas en tu host KVM con el comando "osinfo-query os"
# Esto no hace mucha diferencia para el invitado, puede que la bus levemente distinta
# Probablemente podrías configurar esto como "centos7.0" para todas las distribuciones, si quisieras
#virt_infra_variant: "centos7.0"

# Estas variables de distribución están aquí como referencia y conveniencia
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"

## Relacionado con el host KVM

# Conectar a la instancia de libvirt del sistema
virt_infra_host_libvirt_url: "qemu:///system"

# Ruta donde se mantienen las imágenes de disco
virt_infra_host_image_path: "/var/lib/libvirt/images"

# Deshabilitar el controlador de seguridad de qemu por defecto
# Esto se sobrescribe en las variables específicas de distribución
virt_infra_security_driver: "none"

# El BMC virtual está deshabilitado por defecto
virt_infra_vbmc: false

# Por defecto instalamos con pip, pero si prefieres hacerlo manualmente, establece esto en false
virt_infra_vbmc_pip: true

# Servicio vbmc predeterminado, sobreescribe si es diferente en tu distribución
virt_infra_vbmc_service: vbmcd

# Las redes en kvmhost son una lista, puedes agregar más de una
# Puedes crear y eliminar redes NAT en kvmhost (no se soporta la creación de puentes)
# La red 'default' es la estándar que se envía con libvirt
# Por defecto no eliminamos ninguna red (lista vacía ausente)
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"

# Comando para crear imágenes ISO
virt_infra_mkiso_cmd: genisoimage

# Lista de binarios a verificar en el Host KVM
virt_infra_host_deps:
  - qemu-img
  - osinfo-query
  - virsh
  - virt-customize
  - virt-sysprep

# Lista separada por comas de paquetes para instalar en los discos de invitados
virt_infra_guest_deps:
  - cloud-init
  - qemu-guest-agent

Dependencias

Ninguna

Inventario de Ejemplo

El repositorio separado virt-infra tiene archivos de inventario de ejemplo y un playbook de sitio para llamar al rol, lo que podría ser útil.

Podría ser mejor si los inventarios se dividen en varios archivos para facilitar la gestión, bajo un directorio inventory o similar. Sugiero un común kvmhost.yml luego archivos de inventario separados para cada grupo de invitados, por ejemplo, openstack.yml. Al ejecutar ansible, incluyes todo el directorio como la fuente del inventario.

El inventario utilizado con este rol debe incluir un grupo de hosts llamado kvmhost y otros grupos de hosts para los invitados.

Configuraciones personalizadas pueden ser proporcionadas para cada host o grupo de hosts en el inventario.

Para crear un nuevo grupo de invitados a gestionar, crea un nuevo archivo yml bajo el directorio de inventario. Por ejemplo, si quisieras un conjunto de invitados para OpenStack, podrías crear un archivo openstack.yml y llenarlo según sea necesario.

Para gestionar hosts o grupos específicos, simplemente usa la opción --limit de Ansible para especificar los hosts o grupos de hosts (también debe incluir el grupo kvmhost). De esta forma puedes usar un solo inventario para muchos invitados diferentes y gestionar todos por separado.

El host KVM es donde se crean las redes de libvirt y, por lo tanto, se especifica como vars bajo ese grupo de hosts.

Aquí hay un ejemplo de archivo de inventario kvmhost.yml en formato YAML. Está especificando kvmhost como localhost con una conexión local. Ten en cuenta que se están creando dos redes (default y example) y una que se elimina (other).

---
## Inventario basado en YAML, consulta:
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
kvmhost:
  hosts:
    # Pon aquí tu conexión y configuraciones del host KVM
    localhost:
      ansible_connection: local
      ansible_python_interpreter: /usr/bin/python3
  vars:
    # Las redes son una lista, puedes agregar más de una
    # Puedes crear y eliminar redes NAT en kvmhost (no se soporta la creación de puentes)
    # La red 'default' es la estándar que se envía con libvirt
    # Por defecto no eliminamos ninguna red (lista vacía ausente)
    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"

Aquí hay un ejemplo de inventario de invitados llamado simple.yml que define huéspedes de CentOS Stream 8 en un grupo llamado simple, usando los valores predeterminados del rol.

---
## Inventario basado en YAML, consulta:
## https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html
#
simple:
  hosts:
    centos-simple-[0:2]:
      ansible_python_interpreter: /usr/libexec/platform-python

Si deseas que un grupo de VMs sean todas iguales, establece las vars a nivel de grupo de hosts. Aún puedes sobrescribir las vars del grupo de hosts con vars individuales para hosts específicos, si es necesario.

Aquí hay un ejemplo configurando varias vars del grupo de hosts e individuales.

---
## Inventario basado en YAML, consulta:
## 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

Múltiples Hosts KVM

También puedes especificar múltiples hosts 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"

Para que una VM se coloque en un host KVM específico, debes agregar la variable kvmhost con una cadena que coincida con un host KVM del grupo kvmhost.

Por ejemplo, seis hosts de CentOS Stream 8 repartidos en tres hosts 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 no se especifica ningún kvmhost para una VM, se colocará de forma predeterminada en el primer host KVM en el grupo kvmhost (es decir, kvmhost[0]), que coincide con el comportamiento original del rol.

Se han actualizado las verificaciones de validación para asegurarse de que todos los hosts KVM sean válidos y que cualquier host KVM especificado para una VM esté en el grupo kvmhost.

Para agrupar VMs en ciertos hosts KVM, considera crear grupos secundarios y especificar kvmhost a nivel de grupo secundario.

Por ejemplo, esos invitados de CentOS Stream 8 nuevamente:

---
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

Playbook de Ejemplo

He intentado mantener el Ansible como un conjunto simple y lógico de pasos y no hacerlo demasiado complicado. Dicho esto, el playbook es bastante específico.

Hay algunas tareas que solo se pueden ejecutar en el host KVM y otras en un orden específico.

Este código ayudará ejecutando un montón de verificaciones de validación en el host KVM y en tus configuraciones de invitados para intentar atrapar cualquier cosa que no esté bien.

Aquí hay un ejemplo de playbook virt-infra.yml que llama al rol.

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

Obtener la imagen de cloud

Antes de ejecutar el playbook, descarga la imagen de cloud de 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/

Ejecutar el playbook

Ahora ejecuta el playbook de Ansible contra el kvmhost y los invitados en el grupo simple usando el inventario anterior (ten en cuenta que limitamos a ambos grupos kvmhost y simple).

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

También puedes sobrescribir varias configuraciones de invitados desde la línea de comando.

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

Limpieza

Para eliminar los invitados en un grupo de hosts, podrías especificarlos (o un host en específico) con --limit y pasar virt_infra_state=undefined como un argumento adicional en la línea de comando.

Esto anulará el estado del invitado a indefinido y si existen, serán eliminados.

Por ejemplo, para eliminar todas las VMs en el grupo simple.

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

Si solo deseas apagarlas, prueba virt_infra_state=shutdown en su lugar.

Por ejemplo, para apagar solo el host 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

Configuración posterior a la instalación

Una vez que hayas configurado tu infraestructura, podrías ejecutar otro playbook contra tu mismo inventario para hacer lo que desees con esas máquinas...

---
- hosts: all,!kvmhost
  tasks:
    - name: Actualizar todos los paquetes
      package:
        name: '*'
        state: latest
      become: true
      register: result_package_update
      retries: 30
      delay: 10
      until: result_package_update is succeeded

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

Licencia

GPLv3

Información del Autor

Chris Smart https://blog.christophersmart.com

Acerca del proyecto

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

Instalar
ansible-galaxy install csmart.virt_infra
Licencia
gpl-3.0
Descargas
1.2k
Propietario
Just another Linux guy.