How to deploy MongoDB cluster on Kubernetes

Reading Time: 3 minutes

MongoDB is an open-source document-oriented no SQL database. It uses JSON and BSON to store the data. MongoDB replicaset is the cluster of MongoDB nodes divided into a primary node and one or more secondary nodes. Primary node acts as the master node and is responsible for write operations. The secondary nodes and the primary node can both be used for read operation. From hereon, we will be using replicaset to denote MongoDB replicaset and not the Kubernetes replicaset.


Prerequisites:
  • A Kubernetes Cluster (I will be using minikube single node cluster on my local system)

Deploying the MongoDB Cluster

Deploy the Headless Service for node discovery

We will need to deploy a headless service so that the mongodb nodes can communicate with each other. So we create the yaml manifest mongodb-headless.yml

apiVersion: v1
kind: Service
metadata:
  name: mongodb-headless
spec:
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
  - name: mongodb
    port: 27017
    targetPort: 27017
  selector:
    app: mongodb

Use the following command to deploy the above yaml manifest.

kubectl apply -f mongodb-headless.yml
Deploy the Config Map

We will need to deploy a Config Map with the scripts to elect a primary node when the replicaset is initialized. So we create the yaml manifest mongo-config.yml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mongo-config
data:
  script.sh: |-
    #!/bin/bash
    if [[ "$POD_NAME" = "mongodb-0" ]];
    then
    export MONGODB_REPLICA_SET_MODE="primary"
    else
    export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="27017"
    export MONGODB_REPLICA_SET_MODE="secondary"
    fi

    exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh

Use the following command to deploy the above yaml manifest.

kubectl apply -f mongo-config.yml
Persisting the Data

Since we are using minikube we will be using the minikube hostpath storage provisioner to create persistent volumes. For cloud based clusters, you can use any cloud native provisioners.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: minikube-hostpath
provisioner: k8s.io/minikube-hostpath
reclaimPolicy: Delete
Creating the StatefulSet

MongoDB is a stateful application. So we will be using statefulset to deploy the replicasets. Some key features to note are:

  • We will be using bitnami image of mongodb as it is fully configurable using environment variable
  • Containers of Bitnami images are non root containers running with user 1001.
  • We will be using security contexts to change the group of the files in the volume mounted.
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
  namespace: capstone
spec:
  serviceName: mongodb
  selector:
    matchLabels:
      app: mongodb
  replicas: 3
  template:
    metadata:
      labels:
        app: mongodb
    
    spec:
      securityContext:
        fsGroup: 1001
      containers:
        - name: mongodb
          image: bitnami/mongodb
          imagePullPolicy: IfNotPresent
          env:
            - name: MONGODB_DISABLE_SYSTEM_LOG
              value: "false"
            - name: MONGODB_SYSTEM_LOG_VERBOSITY
              value: "1"
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: MONGODB_REPLICA_SET_NAME
              value: "replicaset"
            - name: MONGODB_INITIAL_PRIMARY_HOST
              value: "mongodb-0.mongodb"
            - name: MONGODB_ADVERTISED_HOSTNAME
              value: "$(POD_NAME).mongodb"
            - name: ALLOW_EMPTY_PASSWORD
              value: "yes"
          command:
            - /scripts/script.sh
          securityContext:
            runAsUser: 1001
          volumeMounts:
            - name: config
              mountPath: /scripts
            - name: data
              mountPath: /bitnami/mongodb
              
      volumes:
        - name: config
          configMap:
            name: mongo-config
            defaultMode: 0755
            items:
              - key: script.sh
                path: script.sh
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 1Gi
        storageClassName: minikube-hostpath
         

Use the following command to deploy the above yaml manifest.

kubectl apply -f mongodb-sts.yml
Verifying the replica set deployment and accessing the replica set

If we execute the commands: kubectl get sts mongodb and kubectl get pods -l app=mongodb , we see the cluster deployed.

We can exec into any of the nodes in the replicaset and check the status. So, we will be using the following command:

kubectl exec -it mongodb-0 -- mongo

After executing the command we will get get a prompt similar to:

Then execute the following command:

rs.status()

The above command returns the replica set status. We can see the list of members in the replica set from the configuration.

We can scale the number of replicas using the command:

kubectl scale sts mongodb --replicas 5

CONCLUSION

In this blog, we have setup a three node MongoDB cluster. We also looked at how to scale the number of nodes. In this blog, we have setup a cluster which does not require user authentication. We can also set up a cluster with authentication enabled. We need to use other environment variables listed in the project’s Github Readme. I have provided the link to the Github repository incase you need to head for additional informations.

REFERENCES

Scala Future

Written by 

Dipayan Pramanik is a Software Intern at Knoldus Inc. He is passionate about coding and is always ready to take up challenges. His hobbies include music and gaming.

2 thoughts on “How to deploy MongoDB cluster on Kubernetes4 min read

Comments are closed.