Skip to content

Instantly share code, notes, and snippets.

@k4mrul
Forked from mukeshmodiindia/README.md
Created August 8, 2023 05:30
Show Gist options
  • Save k4mrul/8eb0c0a79e24327f9eb2b0e32c9e0686 to your computer and use it in GitHub Desktop.
Save k4mrul/8eb0c0a79e24327f9eb2b0e32c9e0686 to your computer and use it in GitHub Desktop.
Deploy Percona Server for MongoDB Replica set with Ansible

Deploy the MongoDB Replica set using Ansible.

Pre-requisite:

Make sure to add hosts entries in /etc/hosts in all mongod instance. Verify whether it's reachable, i.e within network. Check it with ping or telnet. ping hostname/ip telnet hostname/ip mongo_port Quick guide

Adjust the hosts details in inventory. Adjust the global variables in group_vars/all

Run the playbook --> main.yml ansible-playbook main.yml -i inventory Inventory file --> Inventory file should contain fully qualified domain. It has been tested against that. Keep a separate inventory file per environment (for example dev, test, prod).

For each standalone replicaset you should name them rsXXXX.

Example of inventory for a Replica Set:

[rs1] fully-qualified-domain1 mongodb_primary=True fully-qualified-domain2 fully-qualified-domain3

Configuration The all variables file contains all the user-modifiable parameters. Each of these come with a small description to clarify the purpose, unless it is self-explanatory. You should review and modify this file before making the deployment. Running The playbook is meant to handle a deployment from scratch, unless run with some specific tags (e.g. conf). So be extra careful if you are running it against servers that already have data.

Cleanup If you want cleanup a failed deploy, usually stopping mongod components and removing the datadir content is enough e.g. service mongod stop; rm -rf {{ mongod_path }}/* Connecting Connection string example with TLS mongo --tls --tlsCAFile /tmp/test-ca.pem --tlsCertificateKeyFile /tmp/test-client.pem --port 27017 --host -u -p

---
########################################
## General configuration
## keep it in group_vars/all
########################################
packages:
- percona-server-mongodb
#repo version to install
repo_version: psmdb-42
mongo_root_password: your_secrets
rs_port: 27017
mongod_log_path: /var/log/mongo
mongod_path: /var/lib/mongo
#mongo_extra_args: Define argument like --tls --tlsCertificateKeyFile /path/client.pem --tlsCAFile /path/caToValidateServerCertificates.pem
# use_tls: true/false
use_tls: false
# only relevant if use_tls: false
keyfile_path: /var/lib/mongo
keyFile_location: /var/lib/mongo/keyfile
# openssl rand -base64 741 if you want to generate a new one
keyfile_content: |
8pYcxvCqoe89kcp33KuTtKVf5MoHGEFjTnudrq5BosvWRoIxLowmdjrmUpVfAivh
CHjqM6w0zVBytAxH1lW+7teMYe6eDn2S/O/1YlRRiW57bWU3zjliW3VdguJar5i9
keyfile_encryption: false
encryption_key_content: |
vvMTZ3dnSbG7wc6DkPpt+rp3Cc+jF8lJsYlq6QE1yEM=
# path to the keyfile to encrypt
encryption_keyfile: /opt/mongodb.key
########################################
## General configuration
## keep it in templates/createRoot.js.j2
########################################
db.createUser({
user: "root",
pwd: "{{ mongo_root_password }}",
roles: [
{role: "root", db: "admin"}
]
})
########################################
## General configuration
## keep it in templates/init-rs.js.j2
########################################
rs.initiate(
{
_id: "{{ group_names[0] }}",
members: [
{% for h in groups[ group_names[0] ] %}
{ _id : {{ loop.index }}, host : "{{ h }}:{%if hostvars[inventory_hostname].group_names[0].startswith('rs') %}{{ rs_port }}{% else %}{{ rs_port }}{% endif %}", priority: {% if loop.first %}10{% else %}1{% endif %} } {% if not loop.last %},{% endif %}
{% endfor %}
]
}
);
# Ansible inventory file
#
# Group names control the role a server will fulfill
[rs1]
ip-172-31-93-193.ec2.internal mongodb_primary=True
ip-172-31-85-203.ec2.internal
ip-172-31-80-251.ec2.internal
---
- name: install percona rpms, Deploy PSMDB RS
hosts: all
become: yes
tasks:
- name: install percona key
rpm_key:
key: https://downloads.percona.com/downloads/RPM-GPG-KEY-percona
state: present
when: ansible_os_family == "RedHat"
- name: install percona repo
package:
name: "https://repo.percona.com/yum/percona-release-latest.noarch.rpm"
state: present
when: ansible_os_family == "RedHat"
- name: install deb files from repo
become: yes
block:
- name: download percona repo
get_url:
url: "https://repo.percona.com/apt/percona-release_latest.focal_all.deb"
dest: /home/percona
when: ansible_os_family == "Debian"
- name: install repo
apt:
deb: /home/percona/percona-release_latest.focal_all.deb
when: ansible_os_family == "Debian"
- name: Update and upgrade apt packages
apt:
update_cache: yes
when: ansible_os_family == "Debian"
- name: Enable specific version
shell: "/usr/bin/percona-release enable {{ repo_version }} && /usr/bin/percona-release enable tools"
- name: install packages
package:
name: "{{ item }}"
state: present
with_items: "{{ packages }}"
- name: copy mongod.conf to rs member
become: yes
template:
src: templates/mongod-replicaset.conf.j2
dest: /etc/mongod.conf
owner: root
group: root
mode: 0644
- name: copy init-rs.js file to initialize the replica set
template:
src: templates/init-rs.js.j2
dest: /tmp/init-rs.js
mode: 0644
when: mongodb_primary is defined and mongodb_primary
- name: bootstrap replica sets
block:
- name: create the datadir
become: yes
file:
path: "{{ mongod_path }}"
owner: mongod
mode: '0750'
state: directory
- name: set up keyfile if not using ssl
become: yes
copy:
dest: "{{ keyFile_location }}"
content: "{{ keyfile_content }}"
owner: mongod
group: root
mode: 0600
when: not use_tls | bool
- name: start mongod on rs member
become: yes
service:
name: mongod
state: restarted
- name: wait for few secs so servers finish starting
pause:
seconds: 15
- name: run the init command for rs
shell: mongo {{ mongo_extra_args | default("") }} --port {{ rs_port}} < /tmp/init-rs.js
when: mongodb_primary is defined and mongodb_primary
- name: wait a few secs so replica sets finish initializing
pause:
seconds: 15
- name: create a users for RS
block:
- name: prepare the command to create root user
template:
src: templates/createRoot.js.j2
dest: /tmp/createRoot.js
mode: 0644
when: mongodb_primary is defined and mongodb_primary
- name: run the command to create a root user
shell: mongo admin {{ mongo_extra_args | default("") }} --port {{ rs_port }} < /tmp/createRoot.js
when: mongodb_primary is defined and mongodb_primary
...
########################################
## General configuration
## keep it in templates/mongod-replicaset.conf.j2
########################################
# mongod.conf - Shard Server
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
logRotate: rename
path: {{ mongod_log_path }}/mongod.log
# Where and how to store data.
storage:
dbPath: {{ mongod_path }}
directoryPerDB: true
journal:
enabled: true
wiredTiger:
engineConfig:
directoryForIndexes: true
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
# network interfaces
net:
{%if hostvars[inventory_hostname].group_names[0].startswith('rs') %}
port: {{ rs_port }}
{% else %}
port: {{ rs_port }}
{% endif %}
bindIp: localhost,{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}
security:
authorization: enabled
{% if use_tls %}
clusterAuthMode: x509
{% else %}
keyFile: {{ keyFile_location }}
{% endif %}
operationProfiling:
slowOpThresholdMs: 200
mode: slowOp
slowOpSampleRate: 0.1
replication:
replSetName: {{ hostvars[inventory_hostname].group_names[0] }}
#sharding:
# clusterRole: shardsvr
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment