15.4 Managing stateful applications with Kubernetes Operators

In this chapter, you saw that managing a stateful application can involve more than what Kubernetes provides with the StatefulSet object. In the case of MongoDB, you need to reconfigure the MongoDB replica set every time you scale the StatefulSet. If you don’t, the replica set may lose quorum and stop working. Also, if a cluster node fails, manual intervention is required to move the Pods to the remaining nodes.

Managing stateful applications is difficult. StatefulSets do a good job of automating some basic tasks, but much of the work still has to be done manually. If you want to deploy a fully automated stateful application, you need more than what StatefulSets can provide. This is where Kubernetes operators come into play. I’m not referring to the people running Kubernetes clusters, but the software that does it for them.

A Kubernetes operator is an application-specific controller that automates the deployment and management of an application running on Kubernetes. An operator is typically developed by the same organization that builds the application, as they know best how to manage it. Kubernetes doesn’t ship with operators. Instead, you must install them separately.

Each operator extends the Kubernetes API with its own set of custom object types that you use to deploy and configure the application. You create an instance of this custom object type using the Kubernetes API and leave it to the operator to create the Deployments or StatefulSets that create the Pods in which the application runs, as shown in the following figure.

In this section, you’ll learn how to use the MongoDB Community Operator to deploy MongoDB. Since I don’t know how the operator will change after the book is published, I won’t go into too much detail, but I’ll list all the steps that were necessary to install the Operator and deploy MongoDB at the time I wrote the book so you can get a feel for what’s required even if you don’t try it yourself.

If you do want to try this yourself, please follow the documentation in the GitHub repository of the MongoDB community operator at https://github.com/mongodb/mongodb-kubernetes-operator.

15.4.1 Deploying the MongoDB community operator

An operator is itself an application that you typically deploy in the same Kubernetes cluster as the application that the operator is to manage. At the time of writing, the MongoDB operator documentation instructs you to first clone the GitHub repository as follows:

$ git clone https://github.com/mongodb/mongodb-kubernetes-operator.git

Then you go to the mongodb-kubernetes-operator directory, where you find the source code of the operator and some Kubernetes object manifests. You can ignore the source code. You’re only interested in the manifest files.

You can decide if you want to deploy the operator and MongoDB in the same namespace, or if you want to deploy the operator so that each user in the cluster can deploy their own MongoDB instance(s). For simplicity, I’ll use a single namespace.

Extending the API with the MongoDBCommunity object kind

First, you create a CustomResourceDefinition object that extends your cluster’s Kubernetes API with an additional object type. To do this, you apply the object manifest as follows:

$ kubectl apply -f config/crd/bases/mongodbcommunity.mongodb.com_mongodbcommunity.yaml
customresourcedefinition/mongodbcommunity.mongodbcommunity.mongodb.com created

Using your cluster’s API, you can now create objects of kind MongoDBCommunity. You’ll create this object later.

NOTE

Unfortunately, the object kind is MongoDBCommunity, which makes it hard to understand that this object represents a MongoDB deployment and not a community. The reason it’s called MongoDBCommunity is because you’re using the community version of the operator. If you use the Enterprise version, the naming is more appropriate. There the object kind is MongoDB, which clearly indicates that the object represents a MongoDB deployment.

Creating supporting objects

Next, you create various other security-related objects by applying their manifests. Here you need to specify the namespace in which these objects should be created. Let’s use the namespace mongodb. Apply the manifests as follows:

$ kubectl apply -k config/rbac/ -n mongodb
serviceaccount/mongodb-database created
serviceaccount/mongodb-kubernetes-operator created
role.rbac.authorization.k8s.io/mongodb-database created
role.rbac.authorization.k8s.io/mongodb-kubernetes-operator created
rolebinding.rbac.authorization.k8s.io/mongodb-database created
rolebinding.rbac.authorization.k8s.io/mongodb-kubernetes-operator created

NOTE

You’ll learn more about these object types and CustomResourceDefinitions in the remaining chapters of this book.

Installing the operator

The last step is to install the operator by creating a Deployment as follows:

$ kubectl create -f config/manager/manager.yaml -n mongodb
deployment.apps/mongodb-kubernetes-operator created

Verify that the operator Pod exists and is running by listing the Pods in the mongodb namespace:

$ kubectl get pods -n mongodb
NAME                                           READY   STATUS    RESTARTS   AGE
mongodb-kubernetes-operator-648bf8cc59-wzvhx   1/1     Running   0          9s

That wasn’t so hard, was it? The operator is running now, but you haven’t deployed MongoDB yet. The operator is just the tool you use to do that.

15.4.2 Deploying MongoDB via the operator

To deploy a MongoDB replica set, you create an instance of the MongoDBCommunity object type instead of creating StatefulSets and the other objects.

Creating an instance of the MongoDBCommunity object type

First edit the file config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml to replace the string <your-password-here> with the password of your choice.

The file contains manifests for a MongoDBCommunity and a Secret object. The following listing shows the manifest of the former.

Listing 15.9 The MongoDBCommunity custom object manifest
apiVersion: mongodbcommunity.mongodb.com/v1
kind: MongoDBCommunity
metadata:
  name: example-mongodb
spec:
  members: 3
  type: ReplicaSet
  version: "4.2.6"
  security:
    authentication:
      modes: ["SCRAM"]
  users:
    - name: my-user
      db: admin
      passwordSecretRef:
        name: my-user-password
      roles:
        - name: clusterAdmin
          db: admin
        - name: userAdminAnyDatabase
          db: admin
      scramCredentialsSecretName: my-scram
  additionalMongodConfig:
    storage.wiredTiger.engineConfig.journalCompressor: zlib

As you can see, this custom object has the same structure as the Kubernetes API core objects. The apiVersion and kind fields specify the object type, the name field in the metadata section specifies the object name, and the spec section specifies the configuration for the MongoDB deployment, including type and version, the desired number of replica set members, and the security-related configuration.

NOTE

If the custom resource definition is well done, as in this case, you can use the kubectl explain command to learn more about the fields supported in this object type.

To deploy MongoDB, you apply this manifest file with kubectl apply as follows:

$ kubectl apply -f config/samples/mongodb.com_v1_mongodbcommunity_cr.yaml
mongodbcommunity.mongodbcommunity.mongodb.com/example-mongodb created
secret/my-user-password created

Inspecting the MongoDBCommunity object

You can then see the object you created with the kubectl get command as follows:

$ kubectl get mongodbcommunity
NAME              PHASE     VERSION
example-mongodb   Running   4.2.6

Just like the other Kubernetes controllers, the object you created is now processed in the reconciliation loop running in the operator. Based on the MongoDBCommunity object, the operator creates several objects: a StatefulSet, two Services, and some Secrets. If you check the ownerReferences field in these objects, you’ll see that they’re all owned by the example-mongodb MongoDBCommunity object. If you make direct changes to these objects, such as scaling the StatefulSet, the operator will immediately undo your changes.

After the operator creates the Kubernetes core objects, the core controllers do their part. For example, the StatefulSet controller creates the Pods. Use kubectl get to list them as follows:

$ kubectl get pods -l app=example-mongodb-svc
NAME                READY   STATUS    RESTARTS   AGE
example-mongodb-0   2/2     Running   0          3m
example-mongodb-1   2/2     Running   0          2m
example-mongodb-2   2/2     Running   0          1m

The MongoDB operator not only creates the StatefulSet, but also makes sure that the MongoDB replica set is initiated automatically. You can use it right away. No additional manual configuration is required.

Managing the MongoDB deployment

You control the MongoDB deployment through the MongoDBCommunity object. The operator updates the configuration every time you update this object. For example, if you want to resize the MongoDB replica set, you change the value of the members field in the example-mongodb object. The operator then scales the underlying StatefulSet and reconfigures the MongoDB replica set. This makes scaling MongoDB trivial.

NOTE

At the time of writing, you can’t use the kubectl scale command to scale the MongoDBCommunity object, but I’m sure the MongoDB operator developers will fix this soon.

15.4.3 Cleaning up

To uninstall MongoDB, delete the MongoDBCommunity object as follows:

$ kubectl delete mongodbcommunity example-mongodb
mongodbcommunity.mongodbcommunity.mongodb.com "example-mongodb" deleted

As you might expect, this orphans the underlying StatefulSet, Services, and other objects. The garbage collector then deletes them. To remove the operator, you can delete the entire mongodb Namespace as follows:

$ kubectl delete ns mongodb
namespace "mongodb" deleted

As a last step, you also need to delete the CustomResourceDefinition to remove the custom object type from the API as follows:

$ kubectl delete crd mongodbcommunity.mongodbcommunity.mongodb.com
customresourcedefinition "mongodbcommunity.mongodbcommunity.mongodb.com" deleted
Copyrights © Wang Wei all right reserved

results matching ""

    No results matching ""