Nube de varios nodos con alta disponibilidad (strongctl)
Con más de un controller en el inventario, strongctl arma el plano de control en alta disponibilidad. No hace falta ninguna opción adicional: la variable ha (en group_vars/all.yml) se vuelve verdadera por sí sola.
Ejemplo: 3 controllers, 2 computes
strongctl init --vip 10.0.0.10 \
--controller ctl1=10.0.0.11 --controller ctl2=10.0.0.12 --controller ctl3=10.0.0.13 \
--compute cmp1=10.0.0.21 --network cmp1=10.0.0.21 \
--compute cmp2=10.0.0.22 --storage cmp2=10.0.0.22
strongctl bootstrap && strongctl deploy && strongctl verify
strongctl se ejecuta en uno de los controllers y accede a los nodos por SSH como root (la clave de root del controller en authorized_keys). --vip es una IP libre en la red de gestión: es la dirección pública de las APIs (controller_address).
Qué se ejecuta en cada controller
| Componente | Cómo queda en alta disponibilidad |
|---|---|
| VIP de las APIs | Keepalived (VRRP unicast). La VIP queda en el controller de mayor prioridad con HAProxy activo y cambia de nodo en pocos segundos si HAProxy o el nodo fallan. |
| HAProxy | En los 3 controllers, escuchando en la VIP (ip_nonlocal_bind). Termina el TLS y reparte las APIs entre los 3. |
| APIs (uWSGI) | En los 3 controllers, escuchando en la dirección de gestión de cada uno. |
| MariaDB | Clúster Galera en los 3 controllers. Los servicios usan VIP:3306, donde HAProxy envía todo a un solo nodo (los demás quedan en reserva) para evitar conflictos de escritura. |
| RabbitMQ | Clúster en los 3 controllers (cookie común, pause_minority). Los servicios reciben los 3 nodos en transport_url y usan colas quorum (rabbit_quorum_queue). |
| memcached | En los 3 controllers. Los servicios reciben la lista de los 3. |
| OVN NB/SB | Clúster RAFT en los 3 controllers. ovn-northd se ejecuta en todos: uno activo y los demás en espera. Neutron y los chassis reciben la lista de los 3. |
| Keystone | En los 3 controllers, con las mismas claves fernet y credential (copiadas del primero). |
| Horizon | En los 3 controllers, con la misma SECRET_KEY (la sesión vale en cualquiera). |
| Glance | En los 3 controllers, pero HAProxy envía todo al primero y deja los demás en reserva, porque el almacenamiento file es local. Con almacenamiento compartido (NFS, Ceph), use glance_shared_store: true en globals.yml para habilitar los tres. |
| Metadata y noVNC | Escuchan en todos los controllers y responden en la VIP dondequiera que esté. |
Las tareas de base de datos (db sync, celdas de Nova, metadefs de Glance, bootstrap de Keystone) se ejecutan una sola vez, en el primer controller.
Comprobación
strongctl verify también comprueba, en cada controller:
- el tamaño del clúster Galera y si el nodo está
Synced; - los nodos de RabbitMQ;
- los servidores RAFT de NB y SB;
- que la VIP esté en exactamente un controller.
Recuperación
- Un controller cae y vuelve: MariaDB vuelve a Galera (IST/SST), RabbitMQ vuelve al clúster y OVN vuelve a RAFT por sí solos. Compruébelo con
strongctl verify. - Cayeron los tres controllers: Galera no arranca solo. En el nodo con
safe_to_bootstrap: 1en/var/lib/mysql/grastate.dat(el último en detenerse), ejecutegalera_new_cluster; en los demás,systemctl start mariadb. - Cambio de configuración de MariaDB: el deploy reinicia los controllers 2 y 3 de uno en uno. El primero necesita un reinicio manual (
systemctl restart mariadb), también de uno en uno.
Prueba de laboratorio
tests/lxd/run-multinode.sh monta la nube anterior en 5 contenedores LXD y:
- despliega y comprueba la idempotencia;
- crea una VM en cada nodo de cómputo y prueba la IP flotante;
- apaga el dueño de la VIP y comprueba que la nube sigue funcionando (token, listas, una VM nueva);
- vuelve a encender el controller y comprueba que regresa al clúster;
- ejecuta Tempest smoke.
El resultado queda en out/multinode/.