Digital Developer Conference: Cloud Security 2021 -- Build the skills to secure your cloud and data Register free

Seamlessly upgrade a JanusGraph operator

This tutorial shows you how to develop and deploy a Level II operator on the OpenShift Container Platform. This is the continuation of the Level I operator tutorial series where it has the functionality to upgrade the version of your operand — in this case, the operand is JanusGraph.

When you have completed this tutorial, you will understand how to:

  • Build and push the latest version of the JanusGraph image
  • Upgrade the version of the operand (JanusGraph application)

Prerequisites

To complete this tutorial, we assume that you:

  • have some experience developing operators
  • have some knowledge of Kubernetes Operators concepts
  • have created the Level I operator

Estimated time

It should take you about 30 minutes to complete this tutorial.

What is Operators Level II capability?

Operators Level II capability is what’s referred to as a seamless upgrade. The operator should support a seamless upgrade of the operator and the operand. An upgrade to the operator means that the custom resource (CR) instances are in a new desired state and would upgrade the operand. The upgrade can also mean upgrading the application that the operator manages along with other internals such as schema migrations. It’s important to clearly state what is and isn’t upgraded in the process.

To upgrade the current version of the operand (JanusGraph) to the desired version using go, you need to:

  • Check for the current version of the container image.
  • Compare the current version of the CR instance with the container image.
  • If the current version is not the same and is lower than the one in the CR, then you should update the container image. If the current version is higher than the one in the CR, ignore the version upgrade.

Steps

  1. Implement the version upgrade in the operator controller
  2. Deploy the operator
  3. Update the CR version and apply
  4. Test the version upgrade

1. Implement the version upgrade in the operator controller

The operator should be capable of upgrading the current version to a higher one. To do this, the following cases should be implemented in the operator’s controller:

  1. Get the desired version from the CR.
  2. Get the current version from the container specification.
  3. Check to see if the container image needs to be upgraded.
  4. Upgrade the container image if the current version is less than the desired version.

Let’s look at the code implementation (note the comments to see what the code is doing):

  // version upgrade/downgrade
  //1. Get the desired version from the CR
    desiredVersion := janusgraph.Spec.Version    
    crImage := fmt.Sprintf("%s:%s", JANUS_IMAGE, desiredVersion)
  //2. Get the current version from the container specification
  manifestImage := *&found.Spec.Template.Spec.Containers[0].Image
    versionSplit := strings.Split(manifestImage, ":")
    currentVersion := versionSplit[1]
    log.Info("Current version is", ":", currentVersion)
  //3. Check to see if the container image needs to be upgraded
    // only version with  x.x.x format will work
    // ex: 1.1.1 or 1.1 or 2
    vA, err := semver.NewVersion(desiredVersion)
    if err != nil {
        fmt.Println(err.Error())
    }
    log.Info("Desired Version ", ":", vA.String())
    vB, err := semver.NewVersion(currentVersion)
    if err != nil {
        fmt.Println(err.Error())
    }
  //4. Upgrade the container image if the current version is less than the desired version
    if vB.LessThan(*vA) {
        log.Info("Upgrading to new version", ":", vA.String())
        found.Spec.Template.Spec.Containers[0].Image = crImage
        err = r.Update(ctx, found)
        if err != nil {
            log.Error(err, "Failed to update version")
            return ctrl.Result{}, err
        }
        // Spec updated - return and requeue
        return ctrl.Result{Requeue: true}, nil
    } else {
        log.Info("Not Upgrading : ", "Already at latest version", currentVersion)
    }

2. Deploy the operator

After the code has been changed, you can deploy the operator to your cluster using the steps described in the previous tutorial, “Develop and deploy a Level I JanusGraph operator using Apache Cassandra.”

3. Update the CR version and apply

To upgrade the version, the CR instance should contain the version that you are upgrading to. Modify the version attribute in the spec:

apiVersion: graph.example.com/v1alpha1
kind: Janusgraph
metadata:
  name: janusgraph-sample
spec:
  # Add fields here
  size: 3
  version: 1.0.1

After you’ve updated it to the desired version, you can apply the CR to your cluster:

oc apply -f config/samples/graph_v1alpha1_janusgraph.yaml

4. Test the version upgrade

There are multiple ways to test if the version of the operand has changed:

  • Test your application to make sure the feature changes have been applied.
  • Check your pods to see if the container image has the latest version. You can do that describing the pods and check Containers.janusgraph.Image to make sure it has the right image and version:
oc describe <pod name>
Containers:
  janusgraph:
    Container ID:   cri-o://f6d4584e850308d988f13cfdf76ab89b4da77687763c64e6640b50b0bcc8ae4b
    Image:          sanjeevghimire/janusgraph:1.0.1
    Image ID:       docker.io/sanjeevghimire/janusgraph@sha256:609ed2aa1c802f4ea377855f0add33e024572c0ddfa728dcded24f0f1164eaa8
    Port:           8182/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 09 Jun 2021 12:04:17 -0700

Conclusion

You have now successfully implemented Level II operator for JanusGraph — well done!

The next tutorial in this series shows you how to certify a JanusGraph image.