De vegades necessitem crear un cluster amb més seguretat que un contenidor o màquina virtual, ja que en cas que ens guanyin accés a la màquina física, si muntem un entorn amb docker en alta disponibilitat, ens el poden tombar igualment, es per això que en aquests casos podem optar per un cluster hardware. Exemple d’això poden ser muntar un cluster de firewall o de routing.
En aquests casos, necessitem, com a mínim, dos màquines físiques el més semblants possibles, ja que el servei haurà de treballar indistintament en una o en l’altre.
De totes maneres, i al igual que en qualsevol altre cluster, es molt recomanable fer el cluster amb 3 nodes. Això es degut a que, en cas que hi hagi una desconnexió de qualsevol dels nodes del cluster, el tercer cluster serveix per tenir quorum. També necessitarem, en cas que el node amb el servei quedi bloquejat poder reiniciar-lo des de un altre node, per això primer definirem conceptes:
Els requisits per muntar un cluster de hardware son:
Els requisits desitajs per muntar un cluster de hardware, son, els requisits més:
Aquest requisits es poden portar fins a la obsessió, i dependrà en gran mesura del grau de disponibilitat i criticitat que necessiti el sistema (es diferent muntar un servei en cluster per aprendre cóm funciona, que un servei en cluster per controlar el tràfic aeri de un aeroport internacional. En aquests casos es pot arribar a posar màquines amb CPU's i memòria replicada, es a dir que si una màquina te 64 Gb de RAM i 4 CPUs, nomes farem servir 32Gb i 2 CPUS les operacions dintre de la màquina estaràn replicades, i en cas de fallada de una CPU o de un mòdul de memòria la màquina seguira funcionant. Ja us he dit que es pot portar fins a l'extrem)
Per muntar el nostre entorn farem servir 5 màquines:
En aquestes màquines hi afegirem 3 xarxes:
Xarxa | Rang | Màscara |
---|---|---|
Heartbeat | 192.168.100.8 | /29 |
Servei | 172.16.84.0 | /24 |
Administració | 192.168.1.0 | /24 |
L'esquema final que ens quedarà serà el següent:
On accedirem al servei des de la màquina Service Access i gestionarem els nodes des de la màquina Admin access
A efectes de la pràctica farem servir la última versió LTS de Debian pels nodes i la última versió LTS de Ubuntu Desktop per la màquina de gestió i de servei.
Muntarem la infraestructura a partir de les dades de la següent taula
Host/Server | IP Administració | IP Servei | IP Heartbeat |
---|---|---|---|
Node1 | 192.168.1.11/24 | 172.16.84.11/24 | 192.168.100.11/29 |
Node2 | 192.168.1.12/24 | 172.16.84.12/24 | 192.168.100.12/29 |
Node3 | 192.168.1.13/24 | 172.16.84.13/24 | 192.168.100.13/29 |
ClusterAdm | 192.168.1.20/24 | ||
ClusterSvc | 172.16.84.20/24 |
La instal·lació dels nodes es una instal·lació normal, sense entorn gràfic i amb el servei ssh. En la pràctica ho farem amb un gestor de màquines virtual
Un cop la instalació sigui completa, reiniciarem la màquina i comprovarem que funciona correctament, aprofitant per canviar la IP autoasignada per una IP fixe (Un servidor no ha de estar mai configurat per DHCP), modificant el fitxer /etc/network/interfaces, aprofitant per afegir les dues noves xarxes:
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface allow-hotplug ens160 iface ens160 inet dhcp
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface # allow-hotplug ens160 # iface ens160 inet dhcp #Xarxa de Servei auto ens160 iface ens160 inet static address 172.16.84.11 netmask 255.255.255.0 gateway 172.16.84.2 dns-nameservers 172.16.84.2 1.1.1.1 8.8.8.8 # Xarxa d'administració auto ens161 iface ens161 inet static address 192.168.1.11 nemask 255.255.255.0 # Xarxa de Heartbeat auto ens256 iface ens256 inet static address 192.168.100.11 netmask 255.255.255.248
Un cop fet aquests canvis, reiniciem la màquina i comprovem que s'apliquen els canvis:
root@node1:~# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:da:2f:f7 brd ff:ff:ff:ff:ff:ff altname enp2s0 inet 172.16.84.139/24 brd 172.16.84.255 scope global dynamic ens160 valid_lft 1603sec preferred_lft 1603sec inet6 fe80::20c:29ff:feda:2ff7/64 scope link valid_lft forever preferred_lft forever 3: ens161: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 00:0c:29:da:2f:0b brd ff:ff:ff:ff:ff:ff altname enp3s0 4: ens256: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 00:0c:29:da:2f:01 brd ff:ff:ff:ff:ff:ff altname enp26s0
root@node1:~# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:da:2f:f7 brd ff:ff:ff:ff:ff:ff altname enp2s0 inet 172.16.84.11/24 brd 172.16.84.255 scope global ens160 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feda:2ff7/64 scope link valid_lft forever preferred_lft forever 3: ens161: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:da:2f:0b brd ff:ff:ff:ff:ff:ff altname enp3s0 inet 192.168.1.11/24 brd 192.168.1.255 scope global ens161 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feda:2f0b/64 scope link valid_lft forever preferred_lft forever 4: ens256: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 00:0c:29:da:2f:01 brd ff:ff:ff:ff:ff:ff altname enp26s0 inet 192.168.100.11/29 brd 192.168.100.15 scope global ens256 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feda:2f01/64 scope link valid_lft forever preferred_lft forever
En aquest punt podem parar la màquina i clonar-la 2 vegades per fer els altres 2 nodes i fem les seguents modificacions:
ping node1 ping 192.168.1.11 ping 172.16.18.11
ip route ping www.google.com
Si els pings ha estat tots correctes, ja podem deixar les màquines corrent en segon pla, perquè ara muntarem les màquines d'accés. La resta de la configuració i proves les farem des d'aquestes.
A l'hora de crear aquesta màquina tindrem en conte:
També podem aprofitar una màquina que tinguem instal·lada i connectar-la a la xarxa privada d'administració. El que es important es que aquesta màquina vegi per ssh als 3 nodes per la xarxa d'administració.
També hem de tenir present que, quan estigui instal·lada, aquesta màquina no estarà connectada al exterior.
La instal·lació es força directe i no requereix de res en especial. Un cop ja tenim la màquina instal·lada podem instal·lar el ClusterSSH
#apt install clusterssh -y
I canviar la configuració del adaptador de xarxa:
# This is the network config written by 'subiquity' network: ethernets: ens160: dhcp4: true version: 2
# This is the network config written by 'subiquity' network: renderer: networkd ethernets: ens160: addresses: - 192.168.1.20/24 nameservers: addresses: [4.2.2.2, 1.1.1.1] version: 2
Comprovem que podem connectar amb el ClusterSSH als servidors:
ping 192.168.1.11 cssh root@192.168.1.11 root@192.168.1.12 root@192.168.1.13
En arrencar el programa ens trobarem amb una imatge similar a la següent:
On veiem «3 sesions ssh als 3 nodes» i una caixeta petita que posa CSSH[3]:
Tot el que escribim en aquests calaixet s'escriurà a la resta de finestres. Per tant, per assegurar que les màquines son identiques, la configuració, la farem des de aquesta finestreta i la farem servir com un replicador de terminals.
Amb la màquina de servei farem el mateix que hem fet amb els nodes, pero aquesta vegada a partir de la màquina d'administració, aplicant els següents canvis:
Provarem de fer ping als nodes per la xarxa de servei:
ping 172.16.84.11 ping 172.16.84.12 ping 172.16.84.13
I si funciona, podem deixar la infraestructura per muntada i acabada.
Ara passarem a la instal·lació del software
A partir de la consola de ClusterSSH executarem concurrentment en els 3 nodes les següents comandes:
# Actualitzem el sistema a ultimes versions apt update && apt upgrade # Instal·lem el servei de cluster apt install pacemaker crmsh # Instal·lem un servei per afegir-lo al cluster apt install nginx # Tot i que el desabilitem de l'arrencada de la màquina systemctl disable nginx # I deshabilitem el servei de cluster mentre no el tenim configurat systemctl disable pacemaker
Ara, i abans de posar en marxa el cluster hem de fer unes modificacions als arxius de configuració del cluster:
crypto_cipher: none crypto_hash: none
crypto_cipher: aes256 crypto_hash: sha1
I, en el apartat nodelist, hem d'afegir informació pels 3 nodes, tenint en conte que la informació ha de ser la mateixa pels 3 nodes, i posant la informació de la xarxa de heartbeat.
nodelist { # Change/uncomment/add node sections to match cluster configuration node { # Hostname of the node name: node1 # Cluster membership node identifier nodeid: 1 # Address of first link ring0_addr: 127.0.0.1 # When knet transport is used it's possible to define up to 8 links #ring1_addr: 192.168.1.1 } # ... }
nodelist { # Change/uncomment/add node sections to match cluster configuration node { # Hostname of the node name: node1 # Cluster membership node identifier nodeid: 1 # Address of first link ring0_addr: 192.168.100.11 # When knet transport is used it's possible to define up to 8 links #ring1_addr: 192.168.1.1 } node { # Hostname of the node name: node2 # Cluster membership node identifier nodeid: 2 # Address of first link ring0_addr: 192.168.100.12 # When knet transport is used it's possible to define up to 8 links #ring1_addr: 192.168.1.1 } node { # Hostname of the node name: node3 # Cluster membership node identifier nodeid: 3 # Address of first link ring0_addr: 192.168.100.13 # When knet transport is used it's possible to define up to 8 links #ring1_addr: 192.168.1.1 } }
També podem canviar el nom del cluster i posar-li el que volguem:
cluster_name: NomDelCluster
Per tal de assegurar que els cluster comparteixen clau segura s'ha de generar aquesta clau i propagar-la a tots els nodes del cluster, per fe aixo, ho farem des del Node1 Exclusivament, es a dir, que obrirem una sessió ssh capa el node1 per fer aquesta operativa i executarem:
corosync-keygen
, i propagarem la clau generada als altres dos nodes: (Recordeu que, per habilitar la còpia via ssh s'ha d'habilitar la opció PermitRootLogin yes del fitxer /etc/ssh/sshd_config)
scp /etc/corosync/authkey root@node2:/etc/corosync/authkey scp /etc/corosync/authkey root@node3:/etc/corosync/authkey
Un cop copiada la clau, podem engegar el cluster
systemctl start corosync systemctl start pacemaker
I comprovar que els serveis estan engegats
# crm status Status of pacemakerd: 'Pacemaker is running' (last updated 2023-07-01 21:23:43 +02:00) Cluster Summary: * Stack: corosync * Current DC: node2 (version 2.1.5-a3f44794f94) - partition with quorum * Last updated: Sat Jul 1 21:23:43 2023 * Last change: Sat Jul 1 21:15:39 2023 by hacluster via crmd on node2 * 3 nodes configured * 0 resource instances configured Node List: * Online: [ node1 node2 node3 ] Full List of Resources: * No resources
Ara ja tenim el cluster creat. Només falta afegir serveis al cluster
Els serveis del cluster, també anomenats recursos, son els recursos que s'aniràn migrant de node a node mentre estigui el cluster disponible.
Per afegir els recursos, ho farem des de una màquina i fent servir l'entorn que corosync ens posa a disposició per editar-los. Aquest es la shell crm (Cluster Resource Manager)
crm
Amb aquesta shell podem fer servir el tabulador per saber les opcions que tenim disponibles i per finalitzar les paraules que volem pasar-li, podem fer servir la comanda help per mostrar ajuda sobre les comandes.
N'afegirem els següents recursos:
Obrim crm configure:
crm configure
I executem les seguents comandes per habilitar el agents de tanca més endavant (stonith-enable) i habilitar que el cluster continui funcionant amb un sol node (no-quorum-policy)
≤code bash> crm(live/node1)configure#
property stonith-enabled=no property no-quorum-policy=ignore
</code>
Ara, afegim els recursos per l'nginx (Aquest nginx l'hem instal·lat en el pas de generació de nodes, previament):
Recorda, que si les teves IP's son diferents, les has de modificar, i has de definir l'adaptador que correspongui (Hauria de ser el mateix a tots els nodes!!!)
crm(live/node1)configure# primitive IP-nginx ocf:heartbeat:IPaddr2 params ip="172.16.84.10" nic="ens160" cidr_netmask="24" meta migration-threshold=2 op monitor interval=20 timeout=60 on-fail=restart crm(live/node1)configure# primitive Nginx-rsc ocf:heartbeat:nginx meta migration-threshold=2 option monitor interval=20 timeout=60 on-fail=restart crm(live/node1)configure# colocation lb-loc inf: IP-nginx Nginx-rsc crm(live/node1)configure# order lb-ord inf: IP-nginx Nginx-rsc crm(live/node1)configure# commit
Amb això, hem creat 2 recursos (IP-nginx i Nginx-rsc) i hem definit que:
Si en qualsevol moment ens equivoquem a l'hora de generar els recursos, (ens apareix qualsevol error per pantalla):
crm(live/node1)configure# up resource stop "nom_del_recurs" configure delete "nom_del_recurs" commit
La tanca es posa, perque, en cas que hi hagi un node malfuncionant per qualsevol motiu, es pugui aïllar del cluster
Per evitar tocar la base de dades del cluster, i liar-la parda, primer generarem una CIB de proves (Shadow cib)
crm(live/node1)# cib new fencing INFO: cib.new: fencing shadow CIB created crm(fencing/node1)#
Per veure quins agents de stonith tenim, podem executar des de la linia de comandes de qualsevol node:
stonith_admin -I
Hi ha molts. Els executables son a /usr/sbin i al man de cada un d'ells surten les opcions que s'hi poden fer servir.
Nosaltres farem servir fence_virsh, asumint que els nostres nodes son accesssibles via ssh, i hem habilitat l'access com a root. Si no fos així hauriem de configurar sudo per permetre que un usuari pogues executar les accions del cluster.
crm(fencing/node1)# configure crm(fencing/node1)configure# property stonith-enabled=yes crm(fencing/node1)configure# primitive fence_node01 stonith:fence_virsh params ipaddr=172.16.84.11 port=node1 action=off login=root passwd=Hola123 op monitor interval=60s crm(fencing/node1)configure# primitive fence_node02 stonith:fence_virsh params ipaddr=172.16.84.12 port=node2 action=off login=root passwd=Hola123 op monitor interval=60s crm(fencing/node1)configure# primitive fence_node03 stonith:fence_virsh params ipaddr=172.16.84.13 port=node3 action=off login=root passwd=Hola123 op monitor interval=60s crm(fencing/node1)configure# location l_fence_node01 fence_node01 -inf: node1 crm(fencing/node1)configure# location l_fence_node02 fence_node02 -inf: node2 crm(fencing/node1)configure# location l_fence_node03 fence_node03 -inf: node3 commit
Amb això ja tindriem generats els agents de tanca. Podem simular el funcionament amb la nova cib:
crm(fencing/node1)configure# cib cibstatus simulate Current cluster status: * Node List: * Online: [ node1 node2 node3 ] * Full List of Resources: * IP-nginx (ocf:heartbeat:IPaddr2): Started node2 * Nginx-rsc (ocf:heartbeat:nginx): Started node2 * fence_node01 (stonith:fence_virsh): Stopped * fence_node02 (stonith:fence_virsh): Stopped * fence_node03 (stonith:fence_virsh): Stopped Transition Summary: * Start fence_node01 ( node3 ) * Start fence_node02 ( node1 ) * Start fence_node03 ( node1 ) Executing Cluster Transition: * Resource action: fence_node01 monitor on node3 * Resource action: fence_node01 monitor on node2 * Resource action: fence_node01 monitor on node1 * Resource action: fence_node02 monitor on node3 * Resource action: fence_node02 monitor on node2 * Resource action: fence_node02 monitor on node1 * Resource action: fence_node03 monitor on node3 * Resource action: fence_node03 monitor on node2 * Resource action: fence_node03 monitor on node1 * Resource action: fence_node01 start on node3 * Resource action: fence_node02 start on node1 * Resource action: fence_node03 start on node1 * Resource action: fence_node01 monitor=60000 on node3 * Resource action: fence_node02 monitor=60000 on node1 * Resource action: fence_node03 monitor=60000 on node1 Revised Cluster Status: * Node List: * Online: [ node1 node2 node3 ] * Full List of Resources: * IP-nginx (ocf:heartbeat:IPaddr2): Started node2 * Nginx-rsc (ocf:heartbeat:nginx): Started node2 * fence_node01 (stonith:fence_virsh): Started node3 * fence_node02 (stonith:fence_virsh): Started node1 * fence_node03 (stonith:fence_virsh): Started node1
I, si tot sembla correcte, podem pasar els canvis a producció:
crm(fencing/node1)configure# cib commit INFO: configure.cib.commit: committed 'fencing' shadow CIB to the cluster crm(fencing/node1)configure# cib use crm(live/node1)configure#
Per fer un check de l'status podem fer-ho amb **crm status*
que ens haurà de donar un resultat semblant al següent:
crm_mon Cluster Summary: * Stack: corosync * Current DC: node2 (version 2.1.5-a3f44794f94) - partition with quorum * Last updated: Mon Jul 3 08:41:48 2023 * Last change: Mon Jul 3 08:40:06 2023 by root via cibadmin on node1 * 3 nodes configured * 5 resource instances configured Node List: * Online: [ node1 node2 node3 ] Active Resources: * IP-nginx (ocf:heartbeat:IPaddr2): Started node2 * Nginx-rsc (ocf:heartbeat:nginx): Started node2 * fence_node01 (stonith:fence_virsh): Started node3 * fence_node02 (stonith:fence_virsh): Started node1 * fence_node03 (stonith:fence_virsh): Started node1
Amb això ja tindrem el nostre Nginx en cluster corrent en 3 nodes, i podem jugar tancant i encenent nodes i comprovar com l'Nginx continua funcionant independentment del node on corri.
https://github.com/dprokscha/cputty
https://inlab.fib.upc.edu/es/blog/pacemaker-alta-disponibilidad-para-linux