From 0defd33f42d14430bed704f53c452aaac64f12fa Mon Sep 17 00:00:00 2001 From: bennojoy Date: Wed, 17 Apr 2013 21:16:45 +0530 Subject: [PATCH] mongod 1.2 update --- mongodb/README.md | 97 ++++++++++++------ mongodb/group_vars/all | 8 +- mongodb/hosts | 35 +++---- mongodb/images/check.png | Bin 0 -> 184558 bytes mongodb/images/nosql_primer.png | Bin 0 -> 185485 bytes mongodb/images/replica_set.png | Bin 0 -> 144874 bytes mongodb/images/scale.png | Bin 0 -> 437275 bytes mongodb/images/sharding.png | Bin 0 -> 243335 bytes mongodb/images/site.png | Bin 0 -> 426155 bytes mongodb/playbooks/addnode.yml | 13 --- mongodb/playbooks/addshard.yml | 9 -- mongodb/playbooks/common.yml | 10 -- mongodb/playbooks/mongoc.yml | 7 -- mongodb/playbooks/mongod.yml | 7 -- mongodb/playbooks/mongos.yml | 7 -- mongodb/playbooks/nodes.yml | 13 +++ mongodb/playbooks/test.yml | 6 -- mongodb/roles/common/tasks/main.yml | 19 ++-- mongodb/roles/common/templates/epel.repo.j2 | 26 +++++ mongodb/roles/common/templates/hosts.j2 | 2 +- mongodb/roles/common/templates/iptables.j2 | 8 +- mongodb/roles/mongoc/tasks/main.yml | 11 +- mongodb/roles/mongoc/templates/mongoc.j2 | 2 +- mongodb/roles/mongod/tasks/addshard.yml | 15 --- mongodb/roles/mongod/tasks/main.yml | 28 ++--- mongodb/roles/mongod/tasks/shards.yml | 15 +++ mongodb/roles/mongod/templates/mongod.j2 | 2 +- mongodb/roles/mongod/templates/repset_init.j2 | 2 +- mongodb/roles/mongos/tasks/main.yml | 10 +- mongodb/roles/mongos/templates/mongos.conf.j2 | 2 +- mongodb/roles/mongos/templates/mongos.j2 | 2 +- mongodb/site.yml | 22 +++- 32 files changed, 199 insertions(+), 179 deletions(-) create mode 100644 mongodb/images/check.png create mode 100644 mongodb/images/nosql_primer.png create mode 100644 mongodb/images/replica_set.png create mode 100644 mongodb/images/scale.png create mode 100644 mongodb/images/sharding.png create mode 100644 mongodb/images/site.png delete mode 100644 mongodb/playbooks/addnode.yml delete mode 100644 mongodb/playbooks/addshard.yml delete mode 100644 mongodb/playbooks/common.yml delete mode 100644 mongodb/playbooks/mongoc.yml delete mode 100644 mongodb/playbooks/mongod.yml delete mode 100644 mongodb/playbooks/mongos.yml create mode 100644 mongodb/playbooks/nodes.yml delete mode 100644 mongodb/playbooks/test.yml create mode 100644 mongodb/roles/common/templates/epel.repo.j2 delete mode 100644 mongodb/roles/mongod/tasks/addshard.yml create mode 100644 mongodb/roles/mongod/tasks/shards.yml diff --git a/mongodb/README.md b/mongodb/README.md index 9926d1e..b487f4b 100644 --- a/mongodb/README.md +++ b/mongodb/README.md @@ -1,80 +1,106 @@ -Deploying a shared production ready MongoDB cluster with Ansible +##Deploying a sharded production ready MongoDB cluster with Ansible ------------------------------------------------------------------------------ -In this example we demonstrate how we can orchestrate the deployment of a production grade MongoDB Cluster. The functionality of this example includes: +####A Primer into the MongoDB NoSQL database. -1) Deploying a N node MongoDB cluster, which has N shards and N replication nodes. +![Alt text](/images/nosql_primer.png "Primer NoSQL") -2) Scale out capability. Expand the Cluster by adding nodes to the cluster. +The above diagram shows how the MongoDB nosql differs from the traditional relational database model. In RDBMS the data of a user is stored in table and the records of users are stored in rows/columns, While in mongodb the 'table' is replaced by 'collection' and the individual 'records' are called 'documents'. +One thing also to be noticed is that the data is stored as key/value pairs in BJSON format. -3) Security, All the mongodb process are secured using the best practices. +Another thing to be noticed is that nosql has a looser consistency model, as an example the second document in the users collection has an additonal field of 'last name'. Due to this flexibility the nosql database model can give us: -###Deployment Architecture. +Better Horizontal scaling capability. -To better explain the deployment architecture let's take an example where we are deploying a 3 node MongoDB cluster ( Minimum recommended by MongoDB). +Also mongodb has inbuilt support for -The way Ansible configures the three nodes is as follows: +Data Replication & HA -1) Install the mongodb software on all nodes. +Which makes it good choice for users who have very large data to handle and less requirement for ACID. + + +#### MongoDB's Data replication . + +![Alt text](/images/replica_set.png "Replica Set") + + +Data backup is achieved in Mongodb via Replica sets. As the figure above show's a single replication set consists of a replication master (active) and several other replications slaves (passive). All the database operations like Add/Delete/Update happens on the replication master and the master replicates the data to the slave nodes. mongod is the process which is resposible for all the database activities as well as replication processes. The minimum recommended number of slave servers are 3. -2) Creates 3 replication sets, with one primary on each node and the rest two acting as secondaries. -3) Configures MongodDB configuration DB servers as listed in the inventory section[mongocservers]. Recommended number is 3, so it can be the same three servers as the datanodes. +#### MongoDB's Sharding (Horizontal Scaling) . -4) Configures a Mongos server as listed in the inventory file [mongosservers]. +![Alt text](/images/Sharding.png "Sharding") -5) Adds 3 Shards each belonging to individual replication sets. +Sharding allows to achieve a very high performing database, by partioning the data into seperate chunks and allocating diffent ranges of chunks to diffrent shard servers. The figure above shows a collection which has 90 documents which has been sharded across the three shard server, The first shard getting ranges from 1- 29 etc... . When a client wants to access a certian document it contacts the query router (mongos process), which inturn would contact the 'configuration node' (lightweight mongod process) which keeps a record of which ranges of chunks are distributed across which shards. -6) All the processes, mongod,mogos are secured using the keyfiles. +Please do note that every shard server should be backed by a replica set, so that when data is written/queried copies of the data are available. So in a three shard deployment we would require 3 replica sets and primaries of each would act as the sharding server. -Once the cluster is deployed, if we want to scale the cluster, Ansible configures it as follows: +Here's a basic steps of how sharding works. -1) Install the MongoDB application on the new node. +1) A new database is created, and collections are added. -2) Configure the replication set with primary as the new node and the secondaries as listed in the inventory file [replicationservers]. ( don't forget to add the new node also in the replicationservers section] +2) New documents get updated as an when clients update, all the new documents goes into a single shard. -3) Adds a new shard to the mongos service pointing to the new replication set. +3) when the size of collection in a shard exceeds the 'chunk_size' the collection is split and balanced across shards. -#### Pre-requisite +##Deploy MongoDB cluster via Ansible. +-------------------------------------------- -1) Update the group_vars/all file which contains site specific parmaters, especially the section which contains the mapping of the hostname's and the ports that it should use for the mongod process. Please do make sure the ansible hostname matches the same. Also dont forget to add the variable when adding a new node. +### Deploy the Cluster. -2) The default directory for storing data is /data, please do change it if requried, also make sure it has sufficient space 10G recommended. +![Alt text](/images/site.png "Site") + +The above diagram illustrates the deployment model for mongodb cluster via Ansible, This deployment models focuses on deploying a three shard servers, each having a replica set, the backup replica servers are other two shard primaries. The configuration server are co-located with the shard's. The mongos servers are best deployed on seperate servers. These are the minimum recomended configuration for a production grade mongodb deployment. +Please note that the playbooks are capable of deploying N node cluster not necesarily three. Also all the processes are secured using keyfiles. + +####Pre-Requisite's + +Edit the group_vars/all file to reflect the below variables. + +1) iface: 'eth1' # the interface to be used for all communication. +2) mongod_ports: # The hostname and tcp/ip port combination. + mongo1: 2700 + mongo2: 2701 + mongo3: 2702 + +3) The default directory for storing data is /data, please do change it if requried, also make sure it has sufficient space 10G recommended. -###The following example deploys a three node MongoDB Cluster +###Once the pre-requisite's have been done, we can procced with the site deployment. The following example deploys a three node MongoDB Cluster The inventory file looks as follows: #The site wide list of mongodb servers - [mongoservers] + [mongo_servers] mongo1 mongo2 mongo3 #The list of servers where replication should happen, including the master server. - [replicationservers] + [replication_servers] mongo1 mongo2 mongo3 #The list of mongodb configuration servers, make sure it is 1 or 3 - [mongocservers] + [mongoc_servers] mongo1 mongo2 mongo3 #The list of servers where mongos servers would run. [mongosservers] - mongos + mongos1 + mongos2 Build the site with the following command: ansible-playbook -i hosts site.yml + ###Verifying the deployed MongoDB Cluster -Once completed we can check replication set availibitly by connecting to individual primary replication set nodes, 'mongo --host --port +Once completed we can check replication set availibitly by connecting to individual primary replication set nodes, 'mongo --host 192.168.1.1 --port 2700 and issue the command to query the status of replication set, we should get a similar output. @@ -112,7 +138,7 @@ and issue the command to query the status of replication set, we should get a si } -we can check the status of the Shards as follows: connect to the mongos service 'mongos --host --port 8888' +we can check the status of the Shards as follows: connect to the mongos service 'mongos --host 192.168.1.1 --port 8888' and issue the following command to get the status of the Shards. @@ -127,7 +153,10 @@ and issue the following command to get the status of the Shards. { "_id" : "admin", "partitioned" : false, "primary" : "config" } -###We can also make sure the Sharding works by creating a database,collection and populate it with documents and check if the chunks of the collection are balanced equally across nodes. +###We can also make sure the Sharding works by creating a database,collection and populate it with documents and check if the chunks of the collection are balanced equally across nodes. The below diagram illustrates the verification step. + + +![Alt text](/images/check.png "check") The above mentioned steps can be tested with an automated playbook. @@ -158,7 +187,9 @@ Once the playbook completes, we check if the shadring has succeded by logging on -### Adding a new node to the Cluster +### Scaling the Cluster + +![Alt text](/images/scale.png "scale") To add a new node to the configured MongoDb Cluster, setup the inventory file as follows: @@ -172,6 +203,7 @@ To add a new node to the configured MongoDb Cluster, setup the inventory file as #The list of servers where replication should happen, make sure the new node is listed here. [replicationservers] mongo4 + mongo3 mongo1 mongo2 @@ -183,11 +215,12 @@ To add a new node to the configured MongoDb Cluster, setup the inventory file as #The list of servers where mongos servers would run. [mongosservers] - mongos + mongos1 + mongos2 Make sure you have the new node added in the replicationservers section and execute the following command: - ansible-playbook -i hosts playbooks/addnode.yml -e servername=mongo4 + ansible-playbook -i hosts site.yml ###Verification. diff --git a/mongodb/group_vars/all b/mongodb/group_vars/all index 9dc45f2..6fd5474 100644 --- a/mongodb/group_vars/all +++ b/mongodb/group_vars/all @@ -19,8 +19,8 @@ iface: eth1 mongo_admin_pass: 123456 mongod_ports: - bensible: 2700 - web2: 2701 - web3: 2702 - web4: 2703 + hadoop1: 2700 + hadoop2: 2701 + hadoop3: 2702 + hadoop4: 2703 diff --git a/mongodb/hosts b/mongodb/hosts index fddf4b2..821d246 100644 --- a/mongodb/hosts +++ b/mongodb/hosts @@ -1,29 +1,28 @@ #The site wide list of mongodb servers -[mongoservers] -web2 -web3 -web4 -bensible - +[mongo_servers] +hadoop1 +hadoop2 +hadoop3 +hadoop4 #The list of servers where replication should happen, by default include all servers -[replicationservers] -bensible -web2 -web3 - +[replication_servers] +hadoop1 +hadoop2 +hadoop3 +hadoop4 #The list of mongodb configuration servers, make sure it is 1 or 3 -[mongocservers] -web4 -web2 -web3 +[mongoc_servers] +hadoop1 +hadoop2 +hadoop3 #The list of servers where mongos servers would run. -[mongosservers] -web4 -web3 +[mongos_servers] +hadoop1 +hadoop2 diff --git a/mongodb/images/check.png b/mongodb/images/check.png new file mode 100644 index 0000000000000000000000000000000000000000..51867e3b9ce5431f175645ddb11d7972cd4a4637 GIT binary patch literal 184558 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