Mongo standalone setup using Ansible roles

Nowadays almost every business is adopting digital technologies. Technologies are delivering our applications faster with efficiency which helps us to win. Historically, that required lots of manual effort and time-consuming to do the same things. But today, we have Ansible the powerful automation tool to drive complexity out of their environment and accelerate their work.

Ansible is an open-source tool use for multiple purposes like configuration management, application deployments, and infrastructure as code. It supports YAML language. YAML language works on key-value pair format.

MongoDB: MongoDB is the document database, it stores data in JSON-like documents. It also stores the data in key-value pair format. Example: (name: abc) here name is the key and abc is its value.

Ansible roles: Ansible roles are defined in a predefined directory structure in which we define a set of tasks to configure a host to serve a certain purpose. A role directory structure contains:- defaults, vars, handlers, templates, tasks, and meta.

Defaults and Vars: Defaults and vars both files contain variables used in the role but the key difference in both the files is precedence. For e.g., if we take a variable “package_name” in both files and in defaults we provide the value “httpd” and in vars, we provide “Nginx” then it will take the value Nginx because the precedence of vars file is more than defaults.

Handlers: Handlers are responsible to run only when a change is made on a machine. E.g. you may want to restart the service when the task made changes in the configuration file.

Templates: Templates are the files that contain all configuration parameters and also provide the privilege of providing dynamic values are given in the form of variables.

Tasks: Tasks are the main execution file in which we write what exactly we want to execute to achieve the goal. E.g. to install a web server and configure it according to the requirement.

Dependency: You must have python in your system to run ansible.


Let’s start Automating


1. First, we need to initialize an Ansible role, you can use the name of the role of your choice. I choose mongodb.

ansible-galaxy init mongodb

2. After init you will find a directory structure we discussed above. As we have discussed above that we have two variable files one defaults and the other is vars. So we will add these variables in the defaults directory. These are the variables that we will use in our role accordingly.

cd defaults/
vim main.yml

--- 
# defaults file for mongodb variables.
# Service file variables
mongo_service_user: mongod
mongo_service_group: mongod
# Config variables
mongo_log_path: /data/log/mongodb/mongod.log
mongo_dbpath: /data/db
mongo_pid_path_file: /var/run/mongodb/mongod.pid
timezone_info: /usr/share/zoneinfo
mongo_port: 27017
mongo_bind_address: 0.0.0.0

3. After adding variables in default file we willl add other required variables in vars file.

cd ../vars/
vim main.yml

# vars file for mongodb 

# Installation vars 
mongo_package: "mongodb-org-4.4.4-1.amzn2.x86_64" 
mongo_repo_version: 4.4

4. Before proceeding to task file for Installing the package we need to add some files in our templates directory. These are “Jinja (j2)” templates which accepts variables dynamically. As we can see in the below code for e.g., on path we have given variable mongo_log_path when it will copy to the destination it will put the values on the place of variables.
We need to create 3 files:
1. “mongo_repo.j2” : Repository file to install mongo package.
2. “mongo_servicefile.j2” : This is the service file of mongo package.
3. “mongo_init_config.j2 : Config file of mongo package.

vim mongo_repo.j2

[mongodb-org-{{ mongo_repo }}]     
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/{{ mongo_repo }}/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-{{ mongo_repo }}.asc 

5. Configuration file of MongoDB service (mongod.service)

cd templates/ 
vim mongo_init_config.j2

---
# mongod.conf 
systemLog: 
  destination: file 
  logAppend: true 
  path: {{ code }} 
# Where and how to store data. 
storage: 
  dbPath: {{ db_path }} 
  journal:
    enabled: true
  engine: wiredTiger
#  mmapv1:
#  wiredTiger:
# how the process runs
processManagement:
  fork: true 
  pidFilePath: {{ pid_path }}  
  timeZoneInfo: {{ time_zone }}
# network interfaces
net:
  port: {{ port }}
  bindIp: {{ bind_address }} 
#operationProfiling:
replication:
  replSetName: "rs0"
#sharding: 
## Enterprise-Only Options
#auditLog:
#snmp:
cd templates/ 
vim mongo_servicefile.j2

[Unit]
Description=MongoDB Database Server      
Documentation=https://docs.mongodb.org/manual
After=network.target
[Service]
User={{ mongo_user }}
Group={{ mongo_group }}
EnvironmentFile=/etc/default/mongod
ExecStart=/usr/bin/mongod --config /etc/mongod.conf
PIDFile=/var/run/mongodb/mongod.pid
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings
[Install]
WantedBy=multi-user.target

Now we need to create a file install_mongo.yml file. In this file, we will write the code to get the prerequisites and install mongodb.

cd ../tasks 
vim install_mongo.yml

---                               
- name: Updating cache
  yum:
    update_cache: yes

- name: Installing latest patches
  command: yum update -y
  args:
     warn: false
 
- name: Enable EPEL Repository
  yum:
    name: epel-release
    state: latest

- name: Installing PIP
  yum:
    name: python-pip
    state: present

- name: Installing MongoDB prerequisites      
  pip:
    name: pymongo
    state: present
  with_items:
    - pymongo
    - pyOpenSSL

- name: Adding MongoDB repository
  template:
    src: mongo_repo.j2
    dest: /etc/yum.repos.d/mongodb-org-4.4.repo
    mode: 0644

- name: Installing MongoDB package
  yum:
    name: "{{ mongo_package  }}"
    state: present

- name: Daemon Reload
  shell: systemctl daemon-reload

- name: Starting MongoDB service
  service:
    name: mongod
    state: started

Explanation of Install_mongo.yml file:

  • Installing latest patches on server.
  • Installing PIP to install mongodb dependencies like pymongo.
  • Pymongo is required to run the queries on mongo shell.
  • Copying the mongo repository in repos directory to install mongo package.
  • Installing mongo package with the version specified in vars section.
  • Reloading daemon to get mongodb service.
  • Starting mongodb service.
  • Starting mongodb service.


After installing the package we need to configure our mongo configuration according to our environment.

vim configure.yml

---                                               
- name: Adding MongoDB service file
  template:
    src: mongo_servicefile.j2
    dest: /usr/lib/systemd/system/mongod.service
    owner: root
    group: root
    mode: 0777
    force: yes
  notify:
    - daemon_reload

- name: Creating Log directory
  file:
    state: directory
    path: "{{ item }}"
    owner: mongod
    group: mongod
    mode: 0755
  loop:
    - /data
    - /data/log
    - /data/log/mongodb
    - /data/db
    - /var/run/mongodb/

- name: Adding MongoDB initialization config file
  template:
    src: mongo_init_config.j2
    dest: /etc/mongod.conf
    mode: 0644
    force: yes

- name: Restart mongod service
  service:
     name: mongod
     state: restarted

Explanation of configure.yml file:

  • Adding of mongodb service file with owner as root and permission.
  • Creation of directories as we mentioned in our config files.
  • Adding mongodb initial config file.

Now we will edit main.yml. Ansible calls only main.yml in tasks. In main.yml we will include two files we created above.

vim main.yml

---                               
# tasks file for mongodb
- name: Installing MongoDB
  include_tasks: install_mongo.yml

- name: Configuring MongoDB
  include_tasks: configure.yml

At the end we will add handlers to our role.

cd handlers
vim main.yml

---                         
# handlers file for mongodb
- name: daemon_reload
  systemd:
    daemon_reload: "yes"

- name: mongodb_restart
  service:
    name: mongod
    state: restarted

Finally, we have created all the required files to deploy MongoDB successfully. But we need to create one more file to run this setup. Go one directory back and create a mongo.yml. This is the file in which we will call the role and tell ansible that where to deploy that code.

cd ../..
vim mongo.yml

---
- hosts: localhost
  roles:
    - mongodb 
  become: true
  any_errors_fatal: true

Explanation of mongo.yml

  • Hosts: In hosts we will define the IP’s where we want to deploy. If we want to deploy on the same server we will write localhost.
  • Role: In roles we will define the path of the role.
  • Become Become means run this role with sudo permission.

To run the ansible role we need to run the command.

ansible-playbook mongo.yml

kudos we have successfully completed our automated setup of standalone mongodb server. Now in the next blog (in continuation), I will show how to implement authentication and replication using ansible role.

Share Blog

Comments Section