Saltar a contenido

Fase 2 — Incus

Objetivo

Clúster Incus de 3 nodos con quorum, cluster groups por arquitectura y oliver en scheduler manual.

Qué aprendes

Incus como hipervisor compartido: quorum dqlite en 3 miembros, cluster groups para dirigir cargas x86 vs ARM64 (arquitectura ARM de 64 bits), y scheduler manual para proteger RAM.

Stack de esta fase

flowchart TB
  subgraph cluster [Incus_cluster_3_nodos]
    INV[invincible_x86]
    NOL[oliver_x86_quorum]
    DEB[deborah_arm64]
  end
  INV --> CGx86[x86_nodes]
  DEB --> CGarm[arm64_nodes]
  NOL --> CGx86

Profundización: Clúster Incus

Antes de empezar

  • Fase 1 — Red completada (IPs fijas en br0).
  • br0 operativo en los 3 nodos.
  • ≥ 20 GB libres en cada nodo (ver requisitos de almacenamiento).

Requisitos de almacenamiento

Default HomeLab: driver dir (directorio en el filesystem del SO, sin disco dedicado). Variables en group_vars/incus_cluster/vars.yml.

Aspecto Valor / requisito
Driver dir — sin partición ni loop dedicado
Pool por nodo local (cada miembro tiene su pool local)
Ruta del pool /var/lib/incus/storage-pools/local
Filesystem ext4 o xfs; no NFS/CIFS como backend
Espacio libre mínimo 20 GB por nodo; 50 GB+ si crearás VMs o muchas instancias
Metadatos dqlite y config del daemon comparten disco con el pool

Por nodo

Nodo Disco Implicación
invincible TECLAST 120 GB SSD Leader + UI; evitar llenar disco con imágenes CAPN
oliver Kingston 224 GB SSD Quorum; pool local obligatorio aunque no reciba instancias
deborah eMMC + NVMe 250 GB Si eMMC justo: incus_storage_path: /srv/incus/storage-pools/local en host_vars

Limitaciones de dir

  • Sin copy-on-write a nivel de pool (snapshots de instancia y export tarball sí).
  • VMs (máquinas virtuales) más lentas que con zfs/btrfs/lvm.
  • Sin thin provisioning ni compresión nativa.
  • Cada miembro mantiene su pool local; no hay storage distribuido tipo Ceph.

Profundización: Clúster Incus — Almacenamiento

Ejecutar

Paso 1 — Instalar paquete Incus en los 3 nodos

cd ansible
ansible-playbook -i inventory.ini playbook-bootstrap.yml

En cada nodo:

curl https://pkgs.zabbly.com/get/incus-stable | sudo bash -x

Paso 2 — Bootstrap, join, groups, scheduler y UI

Un solo playbook: bootstrap en invincible, join en oliver y deborah, cluster groups, scheduler manual y UI.

cd ansible
ansible-playbook -i inventory.ini playbook-incus-cluster.yml

Tags opcionales: --tags bootstrap, --tags join, --tags groups, --tags ui.

En invincible (bootstrap):

sudo incus admin init
# clustering=yes, no te unes (bootstrap), storage backend dir

En invincible, generar tokens:

incus cluster add oliver
incus cluster add deborah

En oliver y deborah: incus admin init → unirse con el token.

Cluster groups y scheduler:

incus cluster group create x86-nodes
incus cluster group create arm64-nodes
incus cluster group assign invincible x86-nodes,default
incus cluster group assign oliver x86-nodes,default
incus cluster group assign deborah arm64-nodes,default
incus cluster set oliver scheduler.instance manual

UI en invincible:

sudo apt install incus-ui-canonical
sudo incus config set core.https_address=:8443

Perfil de red (instancias en la LAN)

Paso manual obligatorio — ni el playbook de Ansible ni incus admin init lo hacen solos, en ningún camino de los dos de arriba. Sin esto, las instancias de Incus quedan en la red NAT (Network Address Translation) privada por defecto, no en tu LAN (red local).

En invincible (los perfiles son compartidos por todo el clúster, no hace falta repetirlo en oliver/deborah):

incus profile device add default eth0 nic nictype=bridged parent=br0

Verificar:

incus profile show default   # tiene que mostrar eth0 → parent br0

UI de administración

Ansible instala incus-ui-canonical y core.https_address en invincible (play ui del playbook). Acceso inicial por certificado de cliente; SSO (inicio de sesión único) (Dex) en Fase 4.

  1. Añade incus.homelab.local en /etc/hosts (bloque completo en Resumen del HomeLab).
  2. Abre https://incus.homelab.local:8443
  3. Acepta el certificado autofirmado
  4. Genera/importa un certificado de cliente

OIDC con Dex

El login SSO (GitHub vía Dex) se configura en Fase 4 — Incus UI OIDC. Por defecto los usuarios OIDC (OpenID Connect) no ven nada hasta asignarles un grupo (incus auth).

Profundización: Clúster Incus — UI · Backup y snapshots (opcional)

Backup y snapshots (opcional)

No se configuran en el bootstrap. Ver Backup y snapshots.

Opciones

Decisión Default HomeLab Alternativa
Storage backend dir (Ansible) btrfs, zfs, lvm vía incus_storage_driver en host_vars
oliver scheduler.instance manual —
Pool en deborah Ruta default en eMMC incus_storage_path en NVMe (/srv/incus/...)

Cambiar driver en clúster existente

Un clúster ya inicializado no se puede re-preseed sin migración manual. Elige el driver antes del primer playbook-incus-cluster.yml.

Análisis de trade-offs
Ansible (playbook-incus-cluster.yml)
Preseed idempotente, tokens y UI en un paso
Requiere Ansible y SSH a los 3 nodos
Manual (incus admin init)
Sin playbook; útil para depurar un nodo
Tokens de un solo uso; fácil desalinear versiones
Storage dir
Cero fricción, 20 GB libres bastan
VMs lentas; sin CoW de pool
zfs / btrfs
Snapshots y mejor I/O
Disco/loop dedicado; no cambiar tras bootstrap
Pool en eMMC (deborah)
Sin montar NVMe
Riesgo de llenar eMMC con imágenes
Pool en NVMe (/srv/incus)
Más espacio e I/O
Config extra en host_vars

Verificar

incus cluster list
# 3 miembros ONLINE
incus cluster group list
incus storage list
incus profile show default   # eth0 → parent br0
curl -kI https://incus.homelab.local:8443

Si falla

Síntoma Revisar
Join rechazado Token de un solo uso; IP estable en br0
Quorum roto Versiones Incus alineadas en los 3 nodos
Espacio insuficiente df -h; mínimo 20 GB (incus_storage_min_free_gb)
Playbook no idempotente Nodo ya clusterizado; revisar incus cluster list

Siguiente

→ Fase 3 — K3s

URLs y /etc/hosts globales: Resumen del HomeLab (tras Fase 6).