Configuración Manual de un Cluster MongoDB con Replica Set
La configuración de un cluster MongoDB utilizando Replica Sets es un proceso que requiere atención al detalle pero que, una vez comprendido, resulta bastante directo. En esta guía vamos a configurar un cluster con tres nodos: un nodo primario que aceptará todas las operaciones de escritura, y dos nodos secundarios que replicarán los datos del primario y podrán servir lecturas si así lo configuramos.
Conceptos fundamentales
Antes de empezar con la instalación, es importante entender qué es un Replica Set. MongoDB utiliza este sistema para proporcionar alta disponibilidad y redundancia de datos. Un Replica Set es un grupo de instancias de MongoDB que mantienen el mismo conjunto de datos. Uno de los nodos actúa como primario y recibe todas las operaciones de escritura, mientras que los demás nodos son secundarios que replican los datos del primario de forma asíncrona.
Cuando el nodo primario falla, los nodos secundarios inician un proceso de elección automática para elegir un nuevo primario. Este proceso garantiza que el cluster pueda seguir funcionando incluso si uno de los nodos deja de estar disponible. Para que las elecciones funcionen correctamente, necesitamos un número impar de nodos con derecho a voto, por eso lo más común es tener tres nodos o utilizar un nodo especial llamado árbitro si solo queremos dos nodos de datos.
Requisitos previos
Para seguir esta guía necesitamos tener tres máquinas, ya sean físicas o virtuales, con un sistema operativo Linux. En este caso vamos a usar Ubuntu, pero los pasos son similares en otras distribuciones. Las máquinas deben poder comunicarse entre sí a través de la red, y necesitamos tener acceso root o privilegios de sudo en cada una de ellas.
Vamos a llamar a nuestros nodos mongodb-primary con IP 192.168.1.10, mongodb-secondary-1 con IP 192.168.1.11 y mongodb-secondary-2 con IP 192.168.1.12. Es importante que estas IPs sean estáticas o que estemos seguros de que no van a cambiar.
Instalación de MongoDB en cada nodo
El primer paso es instalar MongoDB en cada una de las tres máquinas. MongoDB no viene en los repositorios por defecto de Ubuntu, así que primero necesitamos añadir el repositorio oficial de MongoDB. Comenzamos importando la clave GPG pública que MongoDB utiliza para firmar sus paquetes.
wget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | sudo apt-key add -
Una vez que tenemos la clave importada, creamos el archivo de lista de fuentes para MongoDB. Este archivo le dice a apt dónde encontrar los paquetes de MongoDB.
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
Ahora actualizamos la lista de paquetes disponibles e instalamos MongoDB. El paquete mongodb-org incluye el servidor MongoDB, las herramientas de línea de comandos y todo lo necesario para ejecutar una instancia de MongoDB.
sudo apt-get update
sudo apt-get install -y mongodb-org
Este proceso lo repetimos exactamente igual en las tres máquinas. Es importante que instalemos la misma versión de MongoDB en todos los nodos para evitar problemas de compatibilidad.
Configuración del primer nodo (Primary)
Una vez instalado MongoDB, necesitamos configurarlo para que funcione como parte de un Replica Set. El archivo de configuración principal de MongoDB se encuentra en /etc/mongod.conf y es un archivo YAML, así que la indentación es importante.
Empezamos por el nodo que queremos que sea el primario. Editamos el archivo de configuración con nuestro editor favorito.
sudo nano /etc/mongod.conf
Por defecto, MongoDB solo escucha conexiones desde localhost, pero necesitamos que escuche en todas las interfaces de red para que los otros nodos puedan conectarse. Buscamos la sección de net y cambiamos el bindIp para que acepte conexiones desde cualquier IP. También nos aseguramos de que el puerto sea el 27017, que es el puerto por defecto de MongoDB.
La sección net debería quedar así:
net:
port: 27017
bindIp: 0.0.0.0
Ahora viene la parte más importante: configurar el Replica Set. Al final del archivo añadimos una nueva sección llamada replication donde especificamos el nombre de nuestro Replica Set. Este nombre debe ser el mismo en todos los nodos del cluster.
replication:
replSetName: "rs0"
El nombre rs0 es una convención común, pero podemos usar cualquier nombre que queramos, siempre que sea el mismo en todos los nodos. Una vez hechos estos cambios, guardamos el archivo y reiniciamos el servicio de MongoDB para que los cambios tengan efecto.
sudo systemctl restart mongod
sudo systemctl enable mongod
El comando enable asegura que MongoDB se inicie automáticamente cuando la máquina arranque.
Configuración de los nodos secundarios
En los otros dos nodos, mongodb-secondary-1 y mongodb-secondary-2, hacemos exactamente lo mismo. Editamos el archivo /etc/mongod.conf y aplicamos los mismos cambios: configuramos bindIp a 0.0.0.0 y añadimos la sección de replication con el mismo replSetName.
sudo nano /etc/mongod.conf
Las secciones net y replication deben ser idénticas a las del nodo primario:
net:
port: 27017
bindIp: 0.0.0.0
replication:
replSetName: "rs0"
Después de guardar los cambios, reiniciamos MongoDB en cada uno de estos nodos.
sudo systemctl restart mongod
sudo systemctl enable mongod
En este punto tenemos tres instancias de MongoDB ejecutándose, cada una configurada para ser parte del Replica Set rs0, pero aún no están conectadas entre sí. Ese será nuestro próximo paso.
Inicialización del Replica Set
La inicialización del Replica Set solo se hace desde uno de los nodos, típicamente el que queremos que sea el primario. Nos conectamos a MongoDB usando el shell de mongo, que es la herramienta de línea de comandos para interactuar con MongoDB.
mongosh
Una vez dentro del shell de MongoDB, ejecutamos el comando para inicializar el Replica Set. La función rs.initiate() crea el Replica Set y añade el primer miembro, que será este nodo.
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "192.168.1.10:27017" }
]
})
MongoDB responderá con un objeto que indica si la operación fue exitosa. Si todo va bien, veremos un mensaje que dice "ok" : 1. Después de unos segundos, el prompt del shell cambiará de > a rs0:PRIMARY>, indicando que este nodo ha sido elegido como primario.
Ahora necesitamos añadir los otros dos nodos al Replica Set. Esto se hace con la función rs.add(), que recibe como parámetro la dirección del nodo que queremos añadir.
rs.add("192.168.1.11:27017")
rs.add("192.168.1.12:27017")
Después de añadir cada nodo, MongoDB comenzará el proceso de sincronización. Los nodos secundarios copiarán todos los datos del nodo primario, lo cual puede tomar tiempo dependiendo de cuántos datos tengamos.
Verificación del estado del cluster
Para verificar que todo está funcionando correctamente, podemos ejecutar el comando rs.status() desde el shell de MongoDB. Este comando nos dará información detallada sobre cada miembro del Replica Set.
rs.status()
La salida será un documento JSON largo que contiene información sobre cada nodo. Lo más importante es verificar que un nodo tiene el estado PRIMARY y los otros dos tienen el estado SECONDARY. También podemos ver si los nodos están sincronizados correctamente mirando el campo syncingTo en los nodos secundarios.
Si queremos ver la configuración del Replica Set de forma más concisa, podemos usar rs.conf():
rs.conf()
Este comando nos muestra la configuración actual del Replica Set, incluyendo todos los miembros y sus prioridades.
Cadena de conexión para aplicaciones
Una vez que el Replica Set está funcionando, nuestras aplicaciones necesitan conectarse usando una cadena de conexión especial que incluye todos los nodos del cluster. Esta cadena permite que la aplicación se conecte automáticamente al nodo primario y falle sobre a un secundario si el primario deja de estar disponible.
La cadena de conexión tiene este formato:
mongodb://192.168.1.10:27017,192.168.1.11:27017,192.168.1.12:27017/?replicaSet=rs0
Es importante incluir todos los nodos en la cadena de conexión y especificar el parámetro replicaSet con el nombre de nuestro Replica Set. Cuando una aplicación se conecta usando esta cadena, el driver de MongoDB descubrirá automáticamente cuál es el nodo primario y dirigirá todas las escrituras a él.
Configuración adicional de seguridad
En un entorno de producción, es fundamental habilitar la autenticación en MongoDB. Sin autenticación, cualquier persona que pueda acceder a la red puede conectarse a nuestro cluster y leer o modificar los datos.
Para habilitar la autenticación en un Replica Set, primero necesitamos crear un archivo keyfile que contenga una clave compartida entre todos los nodos. Esta clave se usa para la autenticación interna entre los miembros del Replica Set.
Creamos el archivo keyfile en el nodo primario:
openssl rand -base64 756 > /etc/mongodb-keyfile
sudo chown mongodb:mongodb /etc/mongodb-keyfile
sudo chmod 400 /etc/mongodb-keyfile
Los permisos son importantes: el archivo debe ser propiedad del usuario mongodb y solo ese usuario debe poder leerlo. Ahora copiamos este archivo a los otros dos nodos. Es crucial que el contenido del archivo sea exactamente el mismo en todos los nodos.
scp /etc/mongodb-keyfile [email protected]:/tmp/
scp /etc/mongodb-keyfile [email protected]:/tmp/
En cada uno de los nodos secundarios, movemos el archivo a su ubicación final y configuramos los permisos:
sudo mv /tmp/mongodb-keyfile /etc/mongodb-keyfile
sudo chown mongodb:mongodb /etc/mongodb-keyfile
sudo chmod 400 /etc/mongodb-keyfile
Antes de activar la autenticación, necesitamos crear un usuario administrador. Nos conectamos al nodo primario y creamos un usuario en la base de datos admin:
use admin
db.createUser({
user: "admin",
pwd: "contraseña_segura",
roles: [ { role: "root", db: "admin" } ]
})
Ahora editamos el archivo mongod.conf en cada nodo para activar la autenticación. Añadimos estas líneas:
security:
keyFile: /etc/mongodb-keyfile
authorization: enabled
Reiniciamos MongoDB en todos los nodos:
sudo systemctl restart mongod
A partir de ahora, necesitaremos autenticarnos para conectarnos a MongoDB:
mongosh -u admin -p contraseña_segura --authenticationDatabase admin
Consideraciones sobre el rendimiento
En un Replica Set, todas las escrituras van al nodo primario, y los secundarios replican esos cambios de forma asíncrona. Esto significa que puede haber un pequeño retraso entre que se escribe un dato en el primario y ese dato aparece en los secundarios. Este retraso normalmente es de milisegundos, pero puede aumentar si hay mucha carga o problemas de red.
Por defecto, las lecturas también van al nodo primario, pero podemos configurar nuestras aplicaciones para que lean de los secundarios si no necesitamos consistencia estricta. Esto se hace configurando el readPreference en la cadena de conexión o en la configuración del driver.
Si queremos distribuir la carga de lecturas entre todos los nodos, podemos usar:
mongodb://192.168.1.10:27017,192.168.1.11:27017,192.168.1.12:27017/?replicaSet=rs0&readPreference=secondaryPreferred
Con secondaryPreferred, las lecturas irán a los secundarios si están disponibles, y solo al primario si ningún secundario está disponible.
Mantenimiento y monitorización
Es importante monitorizar el estado del Replica Set regularmente. Además de rs.status(), podemos usar el comando db.serverStatus() para obtener métricas detalladas sobre el rendimiento del servidor. También deberíamos revisar los logs de MongoDB regularmente, que por defecto se encuentran en /var/log/mongodb/mongod.log.
Si necesitamos hacer mantenimiento en un nodo secundario, podemos sacarlo del Replica Set temporalmente, hacer el mantenimiento, y luego volverlo a añadir. El nodo se sincronizará automáticamente cuando vuelva a estar disponible.
Para remover temporalmente un nodo del Replica Set:
rs.remove("192.168.1.11:27017")
Y para volver a añadirlo después del mantenimiento:
rs.add("192.168.1.11:27017")
Añadir un nodo árbitro
Si solo queremos dos nodos que almacenen datos pero necesitamos un tercer nodo para las elecciones, podemos usar un árbitro. Un árbitro participa en las elecciones pero no almacena ningún dato, por lo que puede ejecutarse en una máquina con recursos muy limitados.
Instalamos MongoDB en la máquina del árbitro igual que en los otros nodos, pero cuando lo añadimos al Replica Set, usamos rs.addArb():
rs.addArb("192.168.1.13:27017")
El árbitro nunca puede convertirse en primario y no mantiene ninguna copia de los datos, simplemente vota en las elecciones para desempatar cuando hay un número par de nodos de datos.
Conclusión
Con estos pasos tenemos un cluster MongoDB completamente funcional con alta disponibilidad. Si el nodo primario falla, los secundarios elegirán automáticamente un nuevo primario y el servicio continuará funcionando sin intervención manual. Es importante probar el failover en un entorno de desarrollo para familiarizarnos con cómo funciona antes de depender de él en producción.
Recuerda siempre hacer copias de seguridad regulares usando mongodump y configurar alertas para ser notificado si algún nodo del cluster deja de estar disponible. Un Replica Set proporciona alta disponibilidad, pero no reemplaza las copias de seguridad.
Documentación generada con Inteligencia Artificial