En esta segunda parte del artículo se configura la dirección IP de servicio y se comenta el uso de la interfaz de red virtual “dummy0”.
Configurando la IP de servicio
Como ya se mencionó en la primera parte, utilizando “keepalived” -que implementa el protocolo VRRP-, haremos que una dirección IP esté asignada a un servidor de forma inicial; y si este falla, que esa dirección IP sea asignada automáticamente al otro servidor.
El fichero de configuración de”keepalived” es “/etc/keepalived/keepalived.conf”. Cada servidor tendrá el suyo propio, muy similar a su par.
Para el primer servidor, ejecutaremos lo siguiente
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
superusuario@servidor-1 # cat <<EOF > /etc/keepalived/keepalived.conf # Algunas definiciones globales, como el identificador de este servidor global_defs { router_id servidor-1 } vrrp_instance servicio-100 { state MASTER interface eth0 virtual_router_id 100 priority 100 advert_int 1 # Usuario/clave para enlazar authentication { auth_type PASS auth_pass 4h[-/BhJbj$vU6>=^]hS.cYt)>8+WaA+ } # IP que vamos a flotar virtual_ipaddress { 192.0.2.100/24 brd 192.0.2.255 dev dummy0 } # Trafico VRRP unicast en lugar de multicast por la # NIC interna. unicast_peer { 192.0.2.6 } # Vigila el estado de la interfaz dummy0. Si no está disponible, # migrará la dirección IP de servicio. track_interface { dummy0 } } EOF |
Para el segundo servidor, ejecutaremos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
superusuario@servidor-2 # cat <<EOF > /etc/keepalived/keepalived.conf # Algunas definiciones globales, como el identificador de este servidor global_defs { router_id servidor-2 } vrrp_instance servicio-100 { state BACKUP interface eth0 virtual_router_id 100 priority 50 advert_int 1 # Usuario/clave para enlazar authentication { auth_type PASS auth_pass 4h[-/BhJbj$vU6>=^]hS.cYt)>8+WaA+ } # IP que vamos a flotar virtual_ipaddress { 192.0.2.100/24 brd 192.0.2.255 dev dummy0 } # Trafico VRRP unicast en lugar de multicast por la # NIC interna. unicast_peer { 192.0.2.5 } # Vigila el estado de la interfaz dummy0. Si no está disponible, # migrará la dirección IP de servicio. track_interface { eth0 dummy0 } } EOF |
Las líneas resaltadas son aquellas que difieren según el servidor.
Analicemos este fichero de forma genérica:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
global_defs { router_id servidor-X } vrrp_instance servicio-X { state MASTER interface eth0 virtual_router_id 100 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 4h[-/BhJbj$vU6>=^]hS.cYt)>8+WaA+ } virtual_ipaddress { 192.0.2.100/24 brd 192.0.2.255 dev dummy0 } unicast_peer { 192.0.2.5 } track_interface { eth0 dummy0 } } |
Las líneas 1 a 3 son un bloque de definiciones globales. En este caso solo hemos utilizado “router_id” para identificar el servidor cuando intercambie información de VRRP. Otra funcionalidad no mostrada aquí es notificar vía email cuando se produce algún cambio de estado.
Las líneas 5 a 28 definen una “instancia VRRP”. Una instancia es un grupo de servidores que se comunicaran entre ellos intercambiando información de estado siguiendo unas reglas que nosotros indiquemos.
Dentro de la instancia VRRP definimos qué estado inicial (línea 6) tiene cada servidor: MASTER, que será el que tenga asignada la dirección IP de servicio por defecto; o BACKUP, que la tendrá si el servidor MASTER no responde o notifica que alguna regla no se cumple.
Cuando un servidor en estado BACKUP no puede comunicarse con el servidor MASTER, o el servidor MASTER informa que no se cumplen las reglas de la instancia VRRP, el servidor BACKUP tomará el estado de MASTER y el servidor MASTER el estado de BACKUP, invirtiendo sus roles.
La información sera intercambiada con un cifrado simétrico a través de la interfaz de red eth0 (línea 7) para evitar que un servidor malintencionado altere el intercambio de información de estado (líneas 12 a 15).
VRRP es un protocolo que intercambia información de estado mediante paquetes de red multicast. Como solo tenemos dos servidores, establecemos una comunicación directa entre ellos –unicast– (líneas 21 a 23) y no utilizaremos el envío de paquetes multicast. Otra razón para hacer esto es la posibilidad de que el switch al que están conectados los servidores no permita el “tráfico multicast”.
En las líneas 17 a 19 indicamos que esta instancia VRRP debe asignar a la interfaz de red “dummy0” la dirección IP de servicio “192.0.2.100/24”. Es aquí donde se define que IP (o IPs) tendrá el servidor si esta en estado MASTER.
En las líneas 25 a 28 le indicamos una regla a VRRP: Vigila las interfaces de red eth0 y dummy0. Si alguna de estas interfaces de red no está disponible (estado “down”), entonces se notificará para que el nodo “BACKUP” (el que no tiene la IP de servicio en ese momento) se la asigne.
Finalmente reiniciaremos en cada servidor el servicio “keepalived”:
1 |
superusuario@servidor-X # systemctl restart keepalived |
Podemos verificar el correcto arranque de keepalived con la configuración arriba indicada mediante el comando journalctl.
Para el primer nodo veremos algo así:
1 2 3 4 5 6 |
root@servidor-1:~# journalctl -u keepalived [...] ago 30 13:09:04 servidor-1 VRRP_Instance(servicio-100) Transition to MASTER STATE ago 30 13:09:04 servidor-1 Keepalived_vrrp[562]: VRRP_Instance(servicio-100) Received lower prio advert, forcing new election ago 30 13:09:05 servidor-1 Keepalived_vrrp[562]: VRRP_Instance(servicio-100) Entering MASTER STATE [...] |
Vemos en las dos últimas líneas como se fuerza una nueva elección de maestro y como este nodo, “servidor-1”, es elegido como tal (MASTER STATE).
Tambien podemos verificar que la interfaz de red “dummy0” tiene asignada la IP 192.0.2.100 al ser el maestro:
1 2 3 4 5 |
root@servidor-1:~# ip -4 addr show dev dummy0 3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default link/ether 6a:0c:c1:40:8f:26 brd ff:ff:ff:ff:ff:ff inet 192.0.2.100/24 brd 192.0.2.255 scope global dummy0 valid_lft forever preferred_lft forever |
En el segundo nodo veremos lo siguiente:
1 2 3 4 5 6 |
root@servidor-2:~# journalctl -u keepalived [...] ago 30 13:09:05 servidor-2 Keepalived_vrrp[563]: VRRP_Instance(servicio-100) Transition to MASTER STATE ago 30 13:09:05 servidor-2 Keepalived_vrrp[563]: VRRP_Instance(servicio-100) Received higher prio advert ago 30 13:09:05 servidor-2 Keepalived_vrrp[563]: VRRP_Instance(servicio-100) Entering BACKUP STATE [...] |
En las dos últimas líneas igualmente vemos que este nodo recibe un aviso de “prioridad superior” (desde el nodo “servidor-1”) y que por tanto pasa a tener el estado de respaldo (BACKUP STATE).
En el segundo nodo no habrá ninguna dirección IP asociada a la interfaz de red “dummy0” al estar como nodo de respaldo:
1 |
root@servidor-2:~# ip -4 addr show dev dummy0 |
Verificando el funcionamiento
Con “keepalived” funcionando y los nodos definidos en maestro y esclavo, llega el momento de hacer las pruebas necesarias para verificar que, realmente, el comportamiento es el adecuado.
Utilizaremos el comando “ping” desde algún sistema en la misma subred 192.0.2.100/24 para verificar que la dirección IP de servicio está disponible. Puede hacerse desde el nodo de respaldo, aunque es recomendable utilizar un sistema externo a los nodos que están siendo puestos en marcha:
1 2 3 4 5 6 7 8 9 10 11 |
root@cliente-1:~# ping -c 5 192.0.2.100 PING 192.0.2.100 (192.0.2.100) 56(84) bytes of data. 64 bytes from 192.0.2.100: icmp_seq=1 ttl=64 time=1.79 ms 64 bytes from 192.0.2.100: icmp_seq=2 ttl=64 time=0.401 ms 64 bytes from 192.0.2.100: icmp_seq=3 ttl=64 time=0.377 ms 64 bytes from 192.0.2.100: icmp_seq=4 ttl=64 time=0.359 ms 64 bytes from 192.0.2.100: icmp_seq=5 ttl=64 time=0.451 ms --- 192.0.2.100 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4006ms rtt min/avg/max/mdev = 0.359/0.676/1.795/0.560 ms |
La primera prueba real que haremos será verificar qué ocurre cuando el nodo activo deja de estar disponible por reinicio o perdida de corriente eléctrica; y la segunda consistirá en simular un fallo en la interfaz de red.
En caso de reinicio del nodo activo
Conectados a ambos nodos, en el maestro reiniciaremos el servidor y en el secundario observaremos qué ocurre:
1 |
root@servidor-1:~# systemctl reboot |
1 2 3 4 |
root@servidor-2:~# journalctl -fu keepalived [...] ago 30 13:40:34 servidor-2 Keepalived_vrrp[570]: VRRP_Instance(servicio-100) Transition to MASTER STATE ago 30 13:40:35 servidor-2 Keepalived_vrrp[570]: VRRP_Instance(servicio-100) Entering MASTER STATE |
El nodo esclavo pasa a ser el maestro, y la dirección IP es asignada a este nodo:
1 2 3 4 |
root@servidor-2:~# ip -4 addr show dev dummy0 3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default inet 192.0.2.100/24 brd 192.0.2.255 scope global dummy0 valid_lft forever preferred_lft forever |
La dirección IP de servicio seguirá siendo accesible desde los demás sistemas de la red. La siguiente salida muestra qué percepción ha tenido un cliente durante el proceso desde que falló el primer nodo hasta que el secundario tomó el control y comenzó a responder las peticiones:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
root@cliente-1:~# ping -D 192.0.2.100 PING 192.0.2.100 (192.0.2.100) 56(84) bytes of data. [1472557717.182408] 64 bytes from 192.0.2.100: icmp_seq=1 ttl=64 time=0.341 ms [1472557718.181466] 64 bytes from 192.0.2.100: icmp_seq=2 ttl=64 time=0.419 ms ### REINICIO EJECUTADO EN ESTE PUNTO ### [1472557743.375291] 64 bytes from 192.0.2.100: icmp_seq=27 ttl=64 time=0.779 ms [1472557744.373882] 64 bytes from 192.0.2.100: icmp_seq=28 ttl=64 time=0.366 ms [1472557745.372843] 64 bytes from 192.0.2.100: icmp_seq=29 ttl=64 time=0.354 ms [1472557746.372258] 64 bytes from 192.0.2.100: icmp_seq=30 ttl=64 time=0.411 ms [1472557747.373111] 64 bytes from 192.0.2.100: icmp_seq=31 ttl=64 time=0.398 ms [1472557748.372796] 64 bytes from 192.0.2.100: icmp_seq=32 ttl=64 time=0.398 ms [1472557749.373202] 64 bytes from 192.0.2.100: icmp_seq=33 ttl=64 time=0.371 ms [1472557750.373515] 64 bytes from 192.0.2.100: icmp_seq=34 ttl=64 time=0.357 ms [1472557751.373162] 64 bytes from 192.0.2.100: icmp_seq=35 ttl=64 time=0.372 ms ^C --- 192.0.2.100 ping statistics --- 35 packets transmitted, 11 received, 68% packet loss, time 34190ms rtt min/avg/max/mdev = 0.341/0.415/0.779/0.117 ms |
Como puede observarse, la dirección IP virtual no ha estado disponible durante 25 segundos.
En caso de perdida de la interfaz de red física
Es posible simular la pérdida de una interfaz de red mediante el siguiente comando:
1 |
root@servidor-1:~# ip link set eth0 down |
Podremos comprobar que el nodo esclavo detecta dicho fallo en el maestro y asigna la dirección IP virtual a su interfaz dummy0:
1 2 3 4 |
root@servidor-2:~# journalctl -fu keepalived [...] sep 12 10:17:12 servidor-2 Keepalived_vrrp[578]: VRRP_Instance(servicio-100) Transition to MASTER STATE sep 12 10:17:13 servidor-2 Keepalived_vrrp[578]: VRRP_Instance(servicio-100) Entering MASTER STATE |
Al igual que en el caso anterior, la dirección IP virtual es reasignada:
1 2 3 4 |
root@servidor-2:~# ip -4 addr show dev dummy0 3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default inet 192.0.2.100/24 brd 192.0.2.255 scope global dummy0 valid_lft forever preferred_lft forever |
El estado actual del servicio sería como muestra la siguiente imagen:
En caso de deshabilitar la interfaz de red en el segundo nodo mediante
1 |
root@servidor-2:~# ip link set eth0 down |
Al no tener ninguna interfaz habilitada (ni en el primer nodo ni en el segundo), el servicio dejaría de ser prestado.
El uso de la interfaz virtual “dummy0”
En lugar de utilizar la interfaz de red física “eth0”, decidimos utilizar “dummy0”, una interfaz virtual.
Una ventaja que presenta el uso de la interfaz virtual es la de poder deshabilitarla sin perder conexión al equipo a la hora de su administración.
Tambien podemos deshabilitar la interfaz de red “dummy0” según convenga para tareas administrativas, como la actualización del software del servidor. Al deshabilitarla, el tráfico fluirá automáticamente al nodo esclavo mientras estas tareas son completadas sin afectar a los usuarios.
Notas finales
Por simplicidad a lo largo de estos dos artículos relacionados con la dirección IP de servicio, hemos utilizado una única interfaz de red física tanto para la gestión del servidor como para prestar el servicio.
Es recomendable utilizar múltiples interfaces de red físicas, cada una para una tarea. Idealmente la interfaz de red física “eth0” se utilizará para prestar el servicio, mientras que otra interfaz de red “eth1” será la utilizada para administrar el servidor y donde “keepalived” intercambia el estado de ambos nodos.
De igual modo, por simplicidad, sólo hemos utilizado una conexión para cada tarea. En entornos donde prime la alta disponibilidad debe utilizarse un doble enlace de red mediante “bonding” o “teaming”, utilizando tarjetas de red independientes; en un futuro publicaré sobre ello.
Hemos utilizado una interfaz de red virtual “dummy0” por flexibilidad, de forma que podamos deshabilitarla y seguir operando en el servidor para su mantenimiento. Tambien nos permite forzar a que el nodo esclavo tome el control deshabilitandola en el maestro.