Mongodb Vol2 Replicasets


Un replicaset es un grupo de instancias de Mongo que mantienen el mismo dataset o conjunto de datos, de este modo los datos estarán replicados en diferentes servidores consiguiendo alta disponibilidad de nuestras bases de datos. En cuanto a nuestra aplicación tan solo debemos pasarle la lista de servidores al driver de conexión que utilicemos y este transparentemente se conectará al servidor correcto.

 

La topología de un replicaset(RS) de Mongo define tres figuras:

  • Primary: Servidor primario del RS, los clientes se conectan a este por defecto para ejecutar las querys, tanto lecturas como escrituras.
  • Secondary: Servidor con los datos del Primary server replicados.
  • Arbiter: Servidor sin datos, tan solo vota a la hora de elegir un nuevo Primary server.

NOTA: Las votaciones para elegir un Primary server se realizan cuando hay algún cambio de topología. Mongo no recomienda el uso de RS con Arbitros, vale la pena montar un nodo mas con el dataset replicado.

En este artículo se irá indicando en mayúsculas donde se deben ejecutar ciertos comandos, si es en el Primary en el Secondary o en Todos los servidores.

TODOS

Compilamos e instalamos MongoDb:

emerge -av dev-db/mongodb

Bindeamos el servicio a todas las ips:

vi /etc/mongodb.conf
bind_ip = 0.0.0.0

PRIMARY

Accedemos a la CLI de MongoDb:

mongo

Creamos el usuario admin:

use admin
db.createUser(
  {
    user: "admin",
    pwd: "PASSWORD",
    roles: [ "root" ]
  }
)

Creamos el usuario de admin del RS:

db.createUser(
  {
    user: "clusterAdmin",
    pwd: "PASSWORDRS",
    roles: [ "root" ]
  }
)

TODOS

Habilitamos la autenticación:

vi /etc/mongodb.conf
security:
    authorization: enabled

Reiniciamos el servicio:

/etc/init.d/mongodb restart

PRIMARY

Los nodos de un RS de Mongo se comunican de forma segura entres ellos ya sea por certificados SSL que deberán ser renovados cada X tiempo o por ficheros de keys.

Generamos los ficheros de keys:

openssl rand -base64 756 > /etc/mongodb.key
chmod 400 /etc/mongodb.key
chown mongodb:mongodb /etc/mongodb.key

Copiamos la key a todos los servers del RS y le asignamos los mismos permisos que antes.

TODOS

vi /etc/mongodb.conf
security:
    keyFile: /etc/mongodb.key
replication:
    replSetName: rs0

Reiniciamos el servicio:

/etc/init.d/mongodb restart

PRIMARY

mongo -u "clusterAdmin" -p "PASSWORDRS" --authenticationDatabase "admin"
rs.initiate(
  {
    _id : 'rs0',
    members: [
      { _id : 0, host : "kr0mtest:27017" },
      { _id : 1, host : "kr0mtest2:27017" },
      { _id : 2, host : "kr0mtest3:27017" }
    ]
  }
)
rs0:SECONDARY>

Al rato se elegirá un PRIMARY:

rs0:PRIMARY> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2020-04-17T10:38:46.841Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "syncingTo" : "",
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1587119923, 1),
            "t" : NumberLong(1)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1587119923, 1),
            "t" : NumberLong(1)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1587119923, 1),
            "t" : NumberLong(1)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1587119923, 1),
            "t" : NumberLong(1)
        }
    },
    "lastStableCheckpointTimestamp" : Timestamp(1587119903, 1),
    "members" : [
        {
            "_id" : 0,
            "name" : "kr0mtest:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 265286,
            "optime" : {
                "ts" : Timestamp(1587119923, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2020-04-17T10:38:43Z"),
            "syncingTo" : "",
            "syncSourceHost" : "",
            "syncSourceId" : -1,
            "infoMessage" : "",
            "electionTime" : Timestamp(1586854672, 1),
            "electionDate" : ISODate("2020-04-14T08:57:52Z"),
            "configVersion" : 1,
            "self" : true,
            "lastHeartbeatMessage" : ""
        },
        {
            "_id" : 1,
            "name" : "kr0mtest2:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 84614,
            "optime" : {
                "ts" : Timestamp(1587119923, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1587119923, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2020-04-17T10:38:43Z"),
            "optimeDurableDate" : ISODate("2020-04-17T10:38:43Z"),
            "lastHeartbeat" : ISODate("2020-04-17T10:38:44.999Z"),
            "lastHeartbeatRecv" : ISODate("2020-04-17T10:38:44.998Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "kr0mtest3:27017",
            "syncSourceHost" : "kr0mtest3:27017",
            "syncSourceId" : 2,
            "infoMessage" : "",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "kr0mtest3:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 265265,
            "optime" : {
                "ts" : Timestamp(1587119923, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1587119923, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2020-04-17T10:38:43Z"),
            "optimeDurableDate" : ISODate("2020-04-17T10:38:43Z"),
            "lastHeartbeat" : ISODate("2020-04-17T10:38:45.870Z"),
            "lastHeartbeatRecv" : ISODate("2020-04-17T10:38:45.888Z"),
            "pingMs" : NumberLong(1),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "kr0mtest:27017",
            "syncSourceHost" : "kr0mtest:27017",
            "syncSourceId" : 0,
            "infoMessage" : "",
            "configVersion" : 1
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1587119923, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1587119923, 1),
        "signature" : {
            "hash" : BinData(0,"xSsKDy+0YUJcBM4vpFN0VaJa+rg="),
            "keyId" : NumberLong("6815488928334741505")
        }
    }
}
Si te ha gustado el artículo puedes invitarme a un redbull aquí.
Autor: kr0m -- 18/04/2020 01:13:18