From c5ffa7e43288e9a131b75865f72d0815812a8804 Mon Sep 17 00:00:00 2001 From: bennojoy Date: Sat, 20 Apr 2013 10:14:40 +0530 Subject: [PATCH] MongoDB Update --- mongodb/README.md | 298 ++++++++++++++++++ mongodb/group_vars/all | 25 ++ mongodb/hosts | 29 ++ 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/nodes.yml | 13 + mongodb/playbooks/testsharding.yml | 17 + mongodb/roles/common/files/10gen.repo.j2 | 6 + mongodb/roles/common/files/RPM-GPG-KEY-EPEL-6 | 29 ++ mongodb/roles/common/files/epel.repo.j2 | 26 ++ mongodb/roles/common/handlers/main.yml | 5 + mongodb/roles/common/tasks/main.yml | 35 ++ mongodb/roles/common/templates/hosts.j2 | 4 + mongodb/roles/common/templates/iptables.j2 | 27 ++ mongodb/roles/mongoc/files/secret | 3 + mongodb/roles/mongoc/tasks/main.yml | 26 ++ mongodb/roles/mongoc/templates/adduser.j2 | 1 + mongodb/roles/mongoc/templates/mongoc.conf.j2 | 17 + mongodb/roles/mongoc/templates/mongoc.j2 | 94 ++++++ mongodb/roles/mongod/files/secret | 3 + mongodb/roles/mongod/tasks/main.yml | 37 +++ mongodb/roles/mongod/tasks/shards.yml | 15 + mongodb/roles/mongod/templates/mongod.conf.j2 | 25 ++ mongodb/roles/mongod/templates/mongod.j2 | 94 ++++++ mongodb/roles/mongod/templates/repset_init.j2 | 7 + mongodb/roles/mongod/templates/shard_init.j2 | 2 + mongodb/roles/mongos/files/secret | 3 + mongodb/roles/mongos/tasks/main.yml | 23 ++ .../roles/mongos/templates/enablesharding.j2 | 3 + mongodb/roles/mongos/templates/mongos.conf.j2 | 23 ++ mongodb/roles/mongos/templates/mongos.j2 | 95 ++++++ .../roles/mongos/templates/testsharding.j2 | 12 + mongodb/site.yml | 22 ++ 37 files changed, 1019 insertions(+) create mode 100644 mongodb/README.md create mode 100644 mongodb/group_vars/all create mode 100644 mongodb/hosts 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 create mode 100644 mongodb/playbooks/nodes.yml create mode 100644 mongodb/playbooks/testsharding.yml create mode 100644 mongodb/roles/common/files/10gen.repo.j2 create mode 100644 mongodb/roles/common/files/RPM-GPG-KEY-EPEL-6 create mode 100644 mongodb/roles/common/files/epel.repo.j2 create mode 100644 mongodb/roles/common/handlers/main.yml create mode 100644 mongodb/roles/common/tasks/main.yml create mode 100644 mongodb/roles/common/templates/hosts.j2 create mode 100644 mongodb/roles/common/templates/iptables.j2 create mode 100644 mongodb/roles/mongoc/files/secret create mode 100644 mongodb/roles/mongoc/tasks/main.yml create mode 100644 mongodb/roles/mongoc/templates/adduser.j2 create mode 100644 mongodb/roles/mongoc/templates/mongoc.conf.j2 create mode 100644 mongodb/roles/mongoc/templates/mongoc.j2 create mode 100644 mongodb/roles/mongod/files/secret create mode 100644 mongodb/roles/mongod/tasks/main.yml create mode 100644 mongodb/roles/mongod/tasks/shards.yml create mode 100644 mongodb/roles/mongod/templates/mongod.conf.j2 create mode 100644 mongodb/roles/mongod/templates/mongod.j2 create mode 100644 mongodb/roles/mongod/templates/repset_init.j2 create mode 100644 mongodb/roles/mongod/templates/shard_init.j2 create mode 100644 mongodb/roles/mongos/files/secret create mode 100644 mongodb/roles/mongos/tasks/main.yml create mode 100644 mongodb/roles/mongos/templates/enablesharding.j2 create mode 100644 mongodb/roles/mongos/templates/mongos.conf.j2 create mode 100644 mongodb/roles/mongos/templates/mongos.j2 create mode 100644 mongodb/roles/mongos/templates/testsharding.j2 create mode 100644 mongodb/site.yml diff --git a/mongodb/README.md b/mongodb/README.md new file mode 100644 index 0000000..170f380 --- /dev/null +++ b/mongodb/README.md @@ -0,0 +1,298 @@ +##Deploying a sharded production ready MongoDB cluster with Ansible +------------------------------------------------------------------------------ + +- Requires Ansible 1.2 +- Expects CentOS/RHEL 6 hosts + +###A Primer into the MongoDB NoSQL database. +--------------------------------------------- + +![Alt text](/images/nosql_primer.png "Primer NoSQL") + +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. + +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: + +Better Horizontal scaling capability. + +Also mongodb has inbuilt support for + +Data Replication & HA + +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. + + +### MongoDB's Sharding (Horizontal Scaling) . +------------------------------------------------ + +![Alt text](/images/sharding.png "Sharding") + +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. + +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. + +Here's a basic steps of how sharding works. + +1) A new database is created, and collections are added. + +2) New documents get updated as an when clients update, all the new documents +goes into a single shard. + +3) when the size of collection in a shard exceeds the 'chunk_size' the +collection is split and balanced across shards. + + +###Deploy MongoDB cluster via Ansible. +-------------------------------------------- + +### Deploy the Cluster. +---------------------------- + +![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) Set a unique mongod_port variable in the inventory file for each MongoDB +server. + +3) The default directory for storing data is /data, please do change it if +requried, also make sure it has sufficient space 10G recommended. + +###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 + [mongo_servers] + mongo1 mongod_port=2700 + mongo2 mongod_port=2701 + mongo3 mongod_port=2702 + + #The list of servers where replication should happen, including the master server. + [replication_servers] + mongo1 + mongo2 + mongo3 + + #The list of mongodb configuration servers, make sure it is 1 or 3 + [mongoc_servers] + mongo1 + mongo2 + mongo3 + + #The list of servers where mongos servers would run. + [mongosservers] + 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 192.168.1.1 --port 2700' +and issue the command to query the status of replication set, we should get a +similar output. + + + web2:PRIMARY> rs.status() + { + "set" : "web2", + "date" : ISODate("2013-03-19T10:26:35Z"), + "myState" : 1, + "members" : [ + { + "_id" : 0, + "name" : "web2:2013", + "health" : 1, + "state" : 1, + "stateStr" : "PRIMARY", + "uptime" : 102, + "optime" : Timestamp(1363688755000, 1), + "optimeDate" : ISODate("2013-03-19T10:25:55Z"), + "self" : true + }, + { + "_id" : 1, + "name" : "web3:2013", + "health" : 1, + "state" : 2, + "stateStr" : "SECONDARY", + "uptime" : 40, + "optime" : Timestamp(1363688755000, 1), + "optimeDate" : ISODate("2013-03-19T10:25:55Z"), + "lastHeartbeat" : ISODate("2013-03-19T10:26:33Z"), + "pingMs" : 1 + } + ], + "ok" : 1 + } + + +we can check the status of the Shards as follows: connect to the mongos service +'mongo localhost:8888/admin -u admin -p 123456' and issue the following command to get +the status of the Shards. + + + + mongos> sh.status() + --- Sharding Status --- + sharding version: { "_id" : 1, "version" : 3 } + shards: + { "_id" : "web2", "host" : "web2/web2:2013,web3:2013" } + { "_id" : "web3", "host" : "web3/web2:2014,web3:2014" } + databases: + { "_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. The below diagram illustrates the verification step. +------------------------------------------------------------------------------------------------------------------------------------------------------------- + +![Alt text](/images/check.png "check") + +The above mentioned steps can be tested with an automated playbook. + +Issue the following command to run the test. In variable passed make sure the +servername is one of any mongos server. + + ansible-playbook -i hosts playbooks/testsharding.yml -e servername=mongos + + +Once the playbook completes, we check if the shadring has succeded by logging +on to any mongos server and issuing the following command. The output display +the number of chunks spread across the shards. + + mongos> sh.status() + --- Sharding Status --- + sharding version: { "_id" : 1, "version" : 3 } + shards: + { "_id" : "bensible", "host" : "bensible/bensible:20103,web2:20103,web3:20103" } + { "_id" : "web2", "host" : "web2/bensible:20105,web2:20105,web3:20105" } + { "_id" : "web3", "host" : "web3/bensible:20102,web2:20102,web3:20102" } + databases: + { "_id" : "admin", "partitioned" : false, "primary" : "config" } + { "_id" : "test", "partitioned" : true, "primary" : "web3" } + + test.test_collection chunks: + + bensible 7 + web2 6 + web3 7 + + + + +### 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: + + #The site wide list of mongodb servers + [mongoservers] + mongo1 mongod_port=2700 + mongo2 mongod_port=2701 + mongo3 mongod_port=2702 + mongo4 mongod_port=2703 + + #The list of servers where replication should happen, make sure the new node is listed here. + [replicationservers] + mongo4 + mongo3 + mongo1 + mongo2 + + #The list of mongodb configuration servers, make sure it is 1 or 3 + [mongocservers] + mongo1 + mongo2 + mongo3 + + #The list of servers where mongos servers would run. + [mongosservers] + mongos1 + mongos2 + +Make sure you have the new node added in the replicationservers section and +execute the following command: + + ansible-playbook -i hosts site.yml + +###Verification. +----------------------------- + +The verification of the newly added node can be as easy checking the sharding +status and see the chunks being rebalanced to the newly added node. + + $/usr/bin/mongo localhost:8888/admin -u admin -p 123456 + mongos> sh.status() + --- Sharding Status --- + sharding version: { "_id" : 1, "version" : 3 } + shards: + { "_id" : "bensible", "host" : "bensible/bensible:20103,web2:20103,web3:20103" } + { "_id" : "web2", "host" : "web2/bensible:20105,web2:20105,web3:20105" } + { "_id" : "web3", "host" : "web3/bensible:20102,web2:20102,web3:20102" } + { "_id" : "web4", "host" : "web4/bensible:20101,web3:20101,web4:20101" } + databases: + { "_id" : "admin", "partitioned" : false, "primary" : "config" } + { "_id" : "test", "partitioned" : true, "primary" : "bensible" } + + test.test_collection chunks: + + web4 3 + web3 6 + web2 6 + bensible 5 + + diff --git a/mongodb/group_vars/all b/mongodb/group_vars/all new file mode 100644 index 0000000..4ea2a01 --- /dev/null +++ b/mongodb/group_vars/all @@ -0,0 +1,25 @@ +# The global variable file mongodb installation + +# The chunksize for shards in MB +mongos_chunk_size: 1 + +# The port in which mongos server should listen on +mongos_port: 8888 + +# The port for mongo config server +mongoc_port: 7777 + +# The directory prefix where the database files would be stored +mongodb_datadir_prefix: /data/ + +# The interface where the mongodb process should listen on. +# Defaults to the first interface. Change this to: +# +# iface: eth1 +# +# ...to override. +# +iface: '{{ ansible_default_ipv4.interface }}' + +# The password for admin user +mongo_admin_pass: 123456 diff --git a/mongodb/hosts b/mongodb/hosts new file mode 100644 index 0000000..7e90ce0 --- /dev/null +++ b/mongodb/hosts @@ -0,0 +1,29 @@ +#The site wide list of mongodb servers + +# the mongo servers need a mongod_port variable set, and they must not conflict. +[mongo_servers] +hadoop1 mongod_port=2700 +hadoop2 mongod_port=2701 +hadoop3 mongod_port=2702 +hadoop4 mongod_port=2703 + +#The list of servers where replication should happen, by default include all servers +[replication_servers] +hadoop1 +hadoop2 +hadoop3 +hadoop4 + +#The list of mongodb configuration servers, make sure it is 1 or 3 +[mongoc_servers] +hadoop1 +hadoop2 +hadoop3 + + +#The list of servers where mongos servers would run. +[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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