csmart.virt_infra
- Rol de Ansible: Infraestructura Virtual
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...
- https://bugzilla.redhat.com/show_bug.cgi?id=1719978
- https://bugzilla.redhat.com/show_bug.cgi?id=1756015
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:
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.
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:
- CentOS 7
- CentOS Stream 8
- Fedora 33
- Fedora 34
- Debian 10
- Ubuntu 18.04 LTS
- Ubuntu 20.04 LTS
- openSUSE 15.3 JeOS
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
Define and manage guests and networks on a KVM host with Ansible
ansible-galaxy install csmart.virt_infra