Skip to content

MongoDB Bonus: StatefulSet

In this exercise we will continue with the MongoDB deployment.


1. Scaling Mongo Deployment

The scaling of the MongoDB deployment is not reasonable, because all instances will share the same volume. For this reason we want to switch the mongoDB from Deployment to Stateful Set!

Remove the Deployment and configure your blueprint file of mongo-deploy to resemble a Stateful Set. In this first step, remove the volume reference and definition, we will add it in the next task.

name: mongo-deploy
replicas: 2
serviceName: mongo
HINT

1. Change kind to StatefulSet
2. Change spec.replicas to 2
3. Add mongo-service under spec.serviceName in the Deployment definition file
4. Take 11 - Statefulset/1-mongo-sts.yaml as a reference

When you are done, check the results. Display all Pods, Services and Endpoints.



2. Dynamic Provisioning of External Storage

Just like in Lab 3, we will make use of a Storage Class.

Configure the mongo-deploy Stateful Set to make use of the mongo-fs Storage Class. Remember to mount the Persistent Volume on the Pods!

storageClass: mongo-fs
volumes: entries-storage
mountPath: /data/db
HINT

1. The Storage Class must be filled in under the volumeClaimTemplates section:

Solution

volumeClaimTemplates:
    - metadata:
        name: entries-storage
        namespace: mongo
      spec:
        accessModes:
          - ReadWriteOnce
        storageClassName: mongo-fs
        resources:
          requests:
            storage: 100Mi


2. Add volumeMounts to the blueprint file:
Solution

volumeMounts:
  - mountPath: /data/db
    name: entries-storage


1. Take 11 - Statefulset/2-mongo-sts.yaml as a reference

Deploy the definition file and check the results.

Access the application and discuss the behavior.



BONUS 3. Create Headless Service for MongoDB Stateful Set

Let us implement one more particularity of Stateful Sets.

We know, that in a Stateful Set, all instances get their own PVC and PV to write their data. A regular Load Balancer Service would balance the requests across all instances, which means that every request could (apparently) randomly reach another instance.

If we want to reach a certain instance though, it is necessary to define, which instance to call. The Headless Service does exactly that by forwarding requests to the desired instance. This only works with a Stateful Set, as the instances are deployed in ascending order with unique and permanent names.

Read more about Headless Services in the Kubernetes Documentation.

Create a Headless Service with the name headless-svc and edit the mongo-deploy Stateful Set to use that service instead of the mongo-service ClusterIP Service.

In a production setup, we would need to make some more adjustments in order to properly sync across all instances of a database. To get a grasp of a proper setup, read into the Replicated Stateful Application section in the Kubernetes Documentation.

HINT 1

- Headless Services bear the value None for the spec.ClusterIP


HINT 2

- Further only specify the spec.port to the port you want to expose, no specification of targetPort or nodePort is needed!


HINT 3

- Set the name of the Headless Service - headless-svc - into the spec.serviceName of the Stateful Set


Solution

- Take 11 - Statefulset/3-headless-svc.yaml as a reference


Everything should still be working, except you can now request each instance directly via [unique-pod-name].[service-name].default.cluster.local, e.g. mongo-deploy-0.mongo-service.cluster.local.