Table of contents
Nowadays almost every business is adopting digital technologies. Technologies are delivering our applications faster with efficiency which helps us to win. Historically, doing the same things required lots of manual effort and was time-consuming. 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 used for multiple purposes like configuration management, application deployments, and infrastructure as code. It supports the 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. E.g., if we take a variable "package_name" in both files and defaults we provide the value "httpd" and in vars, we provide "Nginx" then it will take the value Nginx because the precedence of the vars file is more than "defaults".
Handlers: Handlers are responsible for running 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 containing all configuration parameters and provide the privilege of providing dynamic values 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
- First, we need to initialize an Ansible role, you can use the name of the role of your choice. I chose MongoDB.
ansible-galaxy init mongodb
- After init, you will find the 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
- After adding variables in the default file we will add other required variables in the 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
Before proceeding to the task file for Installing the package we need to add some files in our templates directory. These are "Jinja (j2)" templates which accept variables dynamically. As we can see in the below code e.g., on the path we have given the variable mongo_log_path when it is copied to the destination it will put the values in the place of variables. We need to create 3 files:
"mongo_repo.j2": Repository file to install the mongoDB package.
"mongo_servicefile.j2": This is the service file of the mongoDB package.
"mongo_init_config.j2": Config file of the mongoDB package.
cd templates/
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
- The configuration file of MongoDB service (mongod.service)
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:
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 the latest patches on the server.
Installing PIP to install Mongodb dependencies like pymongo.
Pymongo is required to run the queries on the Mongo shell.
Copying the Mongo repository in the repos directory to install the Mongo package.
Installing Mongo package with the version specified in the vars section.
Reloading daemon to get 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 the 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 IPs 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 the standalone MongoDB server. Now in the next blog (in continuation), I will show how to implement authentication and replication using ansible role.