>_Criando um Cluster MongoDB no CentOS 7.2

Ambiente:

IP - 192.168.10.52:
CentOS 7.2 - Docker Engine 1.11 - MongoDB router
IP - 192.168.10.61:
CentOS 7.2 - Docker Engine 1.11 - MongoDB configdb e Shard
IP - 192.168.10.62:
CentOS 7.2 - Docker Engine 1.11 - MongoDB configdb e Shard

Acesso no SSH:
IP:PORTA (Ex: 192.168.10.61 -p 2210)
User: root
Pass: senha-aqui
Portas: 2210 configdb / 2220 shard / 2230 router

mongodb

Shards

Cada shard é uma instância do MongoDB que guarda um pedaço dos dados da coleção.

Config Servers

Cada config server é uma instância do MongoDb que guarda os metadados sobre o cluster. Os metadados mapeiam os chunks de dados para os shards.

Router

Cada router é uma instância mongos que faz o roteamento das escritas e leituras para os shards. As aplicações não conseguem acessar diretamente os shards.

O que é Sharding?

Sharding é uma técnica de divisão de dados em vários servidores. Com o sharding é possível escalar seu ambiente horizontalmente. Com ele você ganha performance na escrita/leitura dos dados. Com o sharding é possível dividir X registros entre os Y grupos de sharding.
Exemplo: Imagine um ambiente onde tempos cerca de 1000 milhão de registros, se utilizarmos a técnica do sharding, podemos dividir este 1000 milhão de registros entre 2 ou mais servidores de sharding, balanceando então a busca por esses registros.

Pergunta: O que eu ganho com isso?
Resposta: Performance e ganho de espaço em disco.

Rumbora para parte técnica do ambiente. Ui 🙁

Obs: Para simular este tutorial, você deverá possuir conhecimentos nas seguintes tecnologias:

Ansible:
O Ansible é uma ferramenta que, inicialmente pode ser categorizada como gerenciador de configuração (configuration management), e comparado a ferramentas bastante populares como o Puppet, Salt, Chef e outos. Mas também pode ser perfeitamente utilizado como ferramenta de deploy e orquestração de tarefas

Docker:
Docker é uma plataforma Open Source escrito em Go, que é uma linguagem de programação de alto desempenho desenvolvida dentro do Google, que facilita a criação e administração de ambientes isolados.

Git:
Git é um sistema de controle de versão de arquivos. Através deles podemos desenvolver projetos na qual diversas pessoas podem contribuir simultaneamente no mesmo, editando e criando novos arquivos e permitindo que os mesmos possam existir sem o risco de suas alterações serem sobrescritas.

Obs: Será necessário instalar o Ansible nos servidores. Segue o link para instalação do Ansible no CentOS 7.2:

>_Instalação rápida do Ansible no CentOS 7.2

Primeira parte do tutorial.

Preparando o ambiente.

Passo 1 – Em ambos os servidores será  ajustado o Kernel conforme abaixo:

# vim /etc/rc.local
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo never > /sys/kernel/mm/transparent_hugepage/enabled
# chmod +x /etc/rc.local

Passo 2 – Em ambos os servidores, será criado a estrutura de diretórios para os containers do MongoDB.

# mkdir -p /storage/mongo/{configdb,configdb-log,shard,shard-log,router-log}

# chmod -R 777 /storage/mongo/{configdb-log,shard-log,router-log}

# mkdir /etc/ansible

Passo 3 – instalando do git e o telnet em ambos os servidores.

# yum install git telnet -y

Passo 4 – Passo importante. Também em ambos os servidores, entre no diretório /etc/ansible e em seguida clone o playbook ansible-docker-engine.

# cd /etc/ansible/
# git clone https://github.com/vandocouto/ansible-docker-engine.git

Passo 5 – Após o clone, acesse o diretório ansible-docker-engine.

# cd ansible-docker-engine

Passo 6 – Para quem já conhece o Ansible, os próximos passos serão bem tranquilos.

No arquivos hosts, informe os IP dos servidores que serão utilizado para o cluster do MongoDB. Lembrando que para este tutorial estou utilizando 3 servidores/instâncias.

# vim hosts
[docker-engine]
192.168.10.52
192.168.10.61
192.168.10.62

Passo 7 – Após o ajuste do arquivo hosts, vamos rodar o playbook da instalação do Docker Engine e também o Build da imagem do MongoDB customizada
Obs: Execute em ambos os servidores.

Tem que funcionar……. 🙁

# ansible-playbook -i hosts site.yml

Passo 9 – Se tudo correu bem, parabéns!!!! Basta executar o comando docker images e verificar se existe uma imagem chamada centos:mongodb.

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              mongodb             519ffe6de7ca        About an hour ago   607.8 MB
centos              centos7             904d6c400333        2 weeks ago         196.7 MB

Segunda parte do tutorial.

Construíndo o Cluster de MongoDB.

Rumbora….

Configurando o Servidor 192.168.10.61.

Passo 1 – Entre no diretório /root/scripts.

# cd /root/scripts/

Passo 2 – Abra o arquivo mongodb-confidb e altere o ip conforme sua estrutura.

# vim mongodb-configdb

Altere a variável IP:
IP=”192.168.10.61″

Passo 3 – Inicie o container mongodb-configdb.

# ./mongodb-configdb

Passo 4 – Abra o arquivo mongodb-shard e altere o ip conforme sua estrutura.

# vim mongodb-shard

Altere a variável IP:
IP=”192.168.10.61″

Passo 5 – Inicie o container mongodb-shard.

# ./mongodb-shard

Passo 6 – Com o comando docker ps verifique se os containers foram iniciados.

# docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                                                        NAMES
426f1cdd36d1        centos:mongodb      "/usr/sbin/sshd -D"   11 minutes ago      Up 11 minutes       192.168.10.61:27011->27011/tcp, 192.168.10.61:2220->22/tcp   MongoDB-shard
94def987d455        centos:mongodb      "/usr/sbin/sshd -D"   11 minutes ago      Up 11 minutes       192.168.10.61:27010->27010/tcp, 192.168.10.61:2210->22/tcp   MongoDB-configdb

Passo 7 – Configurando o Servidor 192.168.10.62.

# cd /root/scripts/
# vim mongodb-configdb

Altere a variável IP:
IP=”192.168.10.62″

# vim mongodb-shard

Altere a variável IP:
IP=”192.168.10.62″

# ./mongodb-shard
# docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                                                        NAMES
2e3c38672307        centos:mongodb      "/usr/sbin/sshd -D"   6 minutes ago       Up 6 minutes        192.168.10.62:27011->27011/tcp, 192.168.10.62:2220->22/tcp   MongoDB-shard
76fdc3debca0        centos:mongodb      "/usr/sbin/sshd -D"   9 minutes ago       Up 9 minutes        192.168.10.62:27010->27010/tcp, 192.168.10.62:2210->22/tcp   MongoDB-configdb

Acessando os container através do Servidor 192.168.10.61.

# ssh root@192.168.10.61 -p2210
root@192.168.10.61's password: 
[root@426f1cdd36d1 ~]# 

Abrindo o MongoDB dentro da instância mongodb-configdb.

Passo 8 – Verificando se o container mongodb-configdb foi iniciado.

# mongo --port 27010
MongoDB shell version: 3.2.7
>

Acessando o container mongodb-shard.

# ssh root@192.168.10.61 -p2220
root@192.168.10.61's password: 
[root@426f1cdd36d1 ~]# 

Abrindo o MongoDB dentro da instância mongodb-shard.

Passo 9 – Verificando se o container mongodb-sahrd foi iniciado.

# mongo --port 27011 
> 

Acessando os container através do Servidor 192.168.10.62.

# ssh root@192.168.10.62 -p2210
root@192.168.10.62's password: 
[root@76fdc3debca0 ~]# 

Passo 10 -Verificando se o container mongodb-confidb foi iniciado.

# mongo --port 27010
> 

Abrindo o MongoDB dentro da instância mongodb-shard.

# ssh root@192.168.10.62 -p2220
root@192.168.10.62's password: 
[root@2e3c38672307 ~]# 

Passo 11 -Verificando se o container mongodb-sahrd foi iniciado.

# mongo --port 27011
> 

Terceira parte do tutorial.

Iniciando a configuração do Cluster.

Portas das instâncias de MongoDB:
27010 – mongodb-configdb – (porta ssh 2210)
27011 – mongodb-shard – (porta ssh 2220)
27017 – mongodb-router – (porta ssh 2230)

mongodb-cluster-shard

O primeiro passo para configuração do Cluster, será a configuração dos configdb (config server).
Obs: A Configuração será realizada no container mongodb-configdb que está no servidor 192.168.10.61.

# ssh root@192.168.10.61 -p2210
root@192.168.10.61's password: 
[root@94def987d455 ~]# mongo --port 27010
MongoDB shell version: 3.2.7
connecting to: 127.0.0.1:27010/test
Server has startup warnings: 
2016-06-17T16:49:39.857-0300 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2016-06-17T16:49:39.857-0300 I CONTROL  [initandlisten] 
> 

Passo 12 – Vamos verificar se existe alguma configuração com o comando rs.status.

> rs.status()
{
	"info" : "run rs.initiate(...) if not yet done for the set",
	"ok" : 0,
	"errmsg" : "no replset config has been received",
	"code" : 94
}
> 

Passo 13 – Configurando a estrutura inicial do cluster. Nesta etapa será adicionado os container mongodb-configdb.

rs.initiate( {
   _id: "configReplSet",
   configsvr: true,
   members: [
      { _id: 0, host: "192.168.10.61:27010" },
      { _id: 1, host: "192.168.10.62:27010" }
   ]
} )
{ "ok" : 1 }
configReplSet:OTHER> 
configReplSet:PRIMARY> 

Opa temos um cara como primário, isso é bom!!!
Vamos verificar o segundo container (mongodb-configdb) que está alocada no servidor 192.168.10.62.

# ssh 192.168.10.62 -p2210
# mongo --port 27010
MongoDB shell version: 3.2.7
connecting to: 127.0.0.1:27010/test
Server has startup warnings: 
2016-06-17T16:52:29.876-0300 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2016-06-17T16:52:29.876-0300 I CONTROL  [initandlisten] 
configReplSet:SECONDARY> 

Opa temos um como secundário!!!

configReplSet:SECONDARY> rs.status()
{
	"set" : "configReplSet",
	"date" : ISODate("2016-06-17T20:26:05.917Z"),
	"myState" : 2,
	"term" : NumberLong(1),
	"syncingTo" : "192.168.10.61:27010",
	"configsvr" : true,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.10.61:27010",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 131,
			"optime" : {
				"ts" : Timestamp(1466195044, 2),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2016-06-17T20:24:04Z"),
			"lastHeartbeat" : ISODate("2016-06-17T20:26:05.863Z"),
			"lastHeartbeatRecv" : ISODate("2016-06-17T20:26:04.170Z"),
			"pingMs" : NumberLong(0),
			"electionTime" : Timestamp(1466195044, 1),
			"electionDate" : ISODate("2016-06-17T20:24:04Z"),
			"configVersion" : 1
		},
		{
			"_id" : 1,
			"name" : "192.168.10.62:27010",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2016,
			"optime" : {
				"ts" : Timestamp(1466195044, 2),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2016-06-17T20:24:04Z"),
			"syncingTo" : "192.168.10.61:27010",
			"configVersion" : 1,
			"self" : true
		}
	],
	"ok" : 1
}

Funcionou….. 😉
Ai você deve estar se perguntando:
Tá, subir é fácil, quero ver simular um desastre….

Eu respondo:
Vamos lá, já que estamos com a mão na massa, vou simular um desastre então…

Vamos encerrar o container mongodb-configdb que está rodando no servidor 192.168.10.61 que por sinal é o container que está como Primary…. (Se é loko cachoeira!)

Passo 14 – No servidor 192.168.10.61 vou encerrar o container com o comando abaixo:
Obs: Para encerrar o container, bastá saber o ID dele com o comando docker ps.

# docker rm -f 94def987d455

Feito.
Agora vamos verificar o estado do container que está alocado no servidor 192.168.10.62.
Obs: Ainda esta como Secondary.

configReplSet:SECONDARY> rs.status()
{
	"set" : "configReplSet",
	"date" : ISODate("2016-06-17T20:31:57.863Z"),
	"myState" : 2,
	"term" : NumberLong(1),
	"configsvr" : true,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.10.61:27010",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : {
				"ts" : Timestamp(0, 0),
				"t" : NumberLong(-1)
			},
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2016-06-17T20:31:57.751Z"),
			"lastHeartbeatRecv" : ISODate("2016-06-17T20:31:42.480Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "Connection refused",
			"configVersion" : -1
		},
		{
			"_id" : 1,
			"name" : "192.168.10.62:27010",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2368,
			"optime" : {
				"ts" : Timestamp(1466195044, 2),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2016-06-17T20:24:04Z"),
			"infoMessage" : "could not find member to sync from",
			"configVersion" : 1,
			"self" : true
		}
	],
	"ok" : 1
}

Passo 15 – Com o usuário admin do MongoDB, faremos alguns ajustes para tornar o container como Primary.

configReplSet:SECONDARY>use admin
configReplSet:SECONDARY> cfg = rs.conf()
configReplSet:SECONDARY>cfg.members = [cfg.members[1]]
configReplSet:SECONDARY>rs.reconfig(cfg, {force : true})

OHHHHHH!
Opa… O container mongodb-configdb que está alocado servidor 192.168.10.62 tornou-se como Primary.

configReplSet:PRIMARY> rs.status()
{
	"set" : "configReplSet",
	"date" : ISODate("2016-06-17T20:35:31.748Z"),
	"myState" : 1,
	"term" : NumberLong(2),
	"configsvr" : true,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.10.62:27010",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 2582,
			"optime" : {
				"ts" : Timestamp(1466195621, 2),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2016-06-17T20:33:41Z"),
			"infoMessage" : "could not find member to sync from",
			"electionTime" : Timestamp(1466195621, 1),
			"electionDate" : ISODate("2016-06-17T20:33:41Z"),
			"configVersion" : 100949,
			"self" : true
		}
	],
	"ok" : 1
}

show, mas …Como faço para voltar a outra instância de MongoDB que estava rodando no servidor 192.168.10.61?

Fácil, vamos lá:

Passo 16 – No servidor 192.168.10.61 irei subir novamente o container mongodb-configdb.

# cd /root/scripts/
# ./mongodb-configdb
# ssh root@192.168.10.61 -p2210
# mongo --port 27010
>

Passo 17 – No servidor 192.168.10.62 ire acessar o container mongodb-confidb, e em seguida adicionar o container (mongodb-configdb) que está no servidor 192.168.10.61 novamente no cluster.

configReplSet:PRIMARY> rs.add("192.168.10.61:27010")
configReplSet:PRIMARY> rs.status()
{
	"set" : "configReplSet",
	"date" : ISODate("2016-06-17T20:38:58.354Z"),
	"myState" : 1,
	"term" : NumberLong(2),
	"configsvr" : true,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"members" : [
		{
			"_id" : 1,
			"name" : "192.168.10.62:27010",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 2789,
			"optime" : {
				"ts" : Timestamp(1466195904, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2016-06-17T20:38:24Z"),
			"electionTime" : Timestamp(1466195621, 1),
			"electionDate" : ISODate("2016-06-17T20:33:41Z"),
			"configVersion" : 100950,
			"self" : true
		},
		{
			"_id" : 2,
			"name" : "192.168.10.61:27010",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 27,
			"optime" : {
				"ts" : Timestamp(1466195904, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2016-06-17T20:38:24Z"),
			"lastHeartbeat" : ISODate("2016-06-17T20:38:56.497Z"),
			"lastHeartbeatRecv" : ISODate("2016-06-17T20:38:56.484Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "192.168.10.62:27010",
			"configVersion" : 100950
		}
	],
	"ok" : 1
}
configReplSet:PRIMARY> 

Caramba, e não que funcionou mesmo…rs

Quarta parte do tutorial.

Subindo o container mongo-router.

Passo 16 – No servidor 192.168.10.52, acesse o diretório /root/scripts/

# cd /root/scripts/

Passo 17 – Em seguida altere o IP conforme sua estrutura.

# vim mongodb-router

Altere a variável IP:
IP=”192.168.10.52″

Passo 18 – Após a alteração inicie o container ./mongodb-router.

# ./mongodb-router

Passo 19 – Com o comando docker ps verifique se o container foi iniciado.

# docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                                                        NAMES
19923e1a0dde        centos:mongodb      "/usr/sbin/sshd -D"   29 seconds ago      Up 23 seconds       192.168.10.52:27017->27017/tcp, 192.168.10.52:2230->22/tcp   MongoDB-router

Passo 20 – Acessando o container mongodb-router.

# ssh root@192.168.10.52 -p2230
root@192.168.10.52's password: 
[root@19923e1a0dde ~]# 

Passo 21 – Acessando o MongoDB do container mongodb-router.

# mongo --port 27017
mongos> 

Passo 22 – Registrando os Shards no Router.

mongos> sh.addShard("192.168.10.61:27011")
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("192.168.10.62:27011")
{ "shardAdded" : "shard0001", "ok" : 1 }

Passo 23 – Aplicando o balanceamento entre os shards.

mongos> sh.getBalancerState()
true

Passo 24 – Criando uma database chamada tutoriaisgnulinux.

mongos> use tutoriaisgnulinux
switched to db tutoriaisgnulinux

Passo 25 – Habilitando o sharding na database tutoriaisgnulinux.

mongos> sh.enableSharding("tutoriaisgnulinux")
{ "ok" : 1 }

Passo 26 – Criando o coletetor e especificando qual coleção dessa database será shardeada com o sh.shardCollection. No meu caso será a tabela post que possui o campo id.

mongos> db.query.ensureIndex( { post : "hashed" } )
{
	"raw" : {
		"192.168.10.62:27011" : {
			"createdCollectionAutomatically" : true,
			"numIndexesBefore" : 1,
			"numIndexesAfter" : 2,
			"ok" : 1
		}
	},
	"ok" : 1
}
mongos> sh.shardCollection("tutoriaisgnulinux.post", { "id": "hashed" } )
{ "collectionsharded" : "tutoriaisgnulinux.post", "ok" : 1 }

Enviando os dados para o Router.

Passo 27 – Fazendo uma pequena inserção na tabela post.

mongos> for (var i = 1; i <= 10000; i++){ db.post.insert( { id : i } )}
WriteResult({ "nInserted" : 1 })

Lembrando que devemos aplicar inserções somente pelo mnongodb-router. Somente ele saberá balancear os dados entre os shards.

Passo 28 – Verificando como ficou o balanceamento entre o shards.

mongos> db.post.getShardDistribution()

Shard shard0000 at 192.168.10.61:27011
 data : 165KiB docs : 4993 chunks : 2
 estimated data per chunk : 82KiB
 estimated docs per chunk : 2496

Shard shard0001 at 192.168.10.62:27011
 data : 166KiB docs : 5007 chunks : 2
 estimated data per chunk : 83KiB
 estimated docs per chunk : 2503

Totals
 data : 332KiB docs : 10000 chunks : 4
 Shard shard0000 contains 49.93% data, 49.93% docs in cluster, avg obj size on shard : 34B
 Shard shard0001 contains 50.07% data, 50.07% docs in cluster, avg obj size on shard : 34B

Dica.
O tamanho padrão do chunk de cada shard é 64MB, logo a coleção precisar ser maior que 64MB para que ocorra a divisão dos seus dados pela shard key.

Passo 29 – Verificando como ficou a estrutura de todos os chunks presente na estrutura do cluster.

mongos> db.printShardingStatus()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"minCompatibleVersion" : 5,
	"currentVersion" : 6,
	"clusterId" : ObjectId("576461d53dc900a4698704d0")
}
  shards:
	{  "_id" : "shard0000",  "host" : "192.168.10.61:27011" }
	{  "_id" : "shard0001",  "host" : "192.168.10.62:27011" }
  active mongoses:
	"3.2.7" : 1
  balancer:
	Currently enabled:  yes
	Currently running:  no
	Failed balancer rounds in last 5 attempts:  0
	Migration Results for the last 24 hours: 
		No recent migrations
  databases:
	{  "_id" : "tutoriaisgnulinux",  "primary" : "shard0001",  "partitioned" : true }
		tutoriaisgnulinux.post
			shard key: { "id" : "hashed" }
			unique: false
			balancing: true
			chunks:
				shard0000	2
				shard0001	2
			{ "id" : { "$minKey" : 1 } } -->> { "id" : NumberLong("-4611686018427387902") } on : shard0000 Timestamp(2, 2) 
			{ "id" : NumberLong("-4611686018427387902") } -->> { "id" : NumberLong(0) } on : shard0000 Timestamp(2, 3) 
			{ "id" : NumberLong(0) } -->> { "id" : NumberLong("4611686018427387902") } on : shard0001 Timestamp(2, 4) 
			{ "id" : NumberLong("4611686018427387902") } -->> { "id" : { "$maxKey" : 1 } } on : shard0001 Timestamp(2, 5) 

Feito.
Existem muitas outras formas para criar um cluster com o MongoDB, porém bem mais complexas. Vale a pena perder um bom tempo e estudar este poderoso banco de dados NoSQL.

Fontes:
http://nomadev.com.br/be-mean-mongodb-como-usar-sharding/
http://www.mongodbspain.com/
https://renanandraderj.wordpress.com/2014/09/15/sharding-com-mongodb/

>_Criando um Cluster MongoDB no CentOS 7.2
Tagged on:

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

%d blogueiros gostam disto: