Liatrio Blog   >
DevOps Tools

OpenShift Pipeline Builds for Microservices

Microservices are much faster at starting and stopping than virtual machines, much easier to deploy and scale, and much more portable. They also isolate and modularize components of complex monoliths.

Back in April 2017, Datadog reported that the number of their customers who use Docker had risen 40% since 2016. Datadog also reported that about 40% of those using Docker use some kind of orchestration tool such as Docker Swarm or Kubernetes.

With all the benefits that containers and microservices offer, these numbers should come as no surprise. Microservices are much faster at starting and stopping than virtual machines, much easier to deploy and scale, and much more portable. They also isolate and modularize components of complex monoliths.

DevOps and microservices are a match made in heaven. Both DevOps and microservices aim at maintaining agile, easily manageable software. This increasing popularity and the obvious common alignment between microservices and DevOps led us to learn about OpenShift pipeline builds for microservices.

What Is OpenShift?

OpenShift is a platform from Redhat built on top of the container orchestration tool Kubernetes. OpenShift comes with a bunch of extra features on top of Kubernetes. These features ease the flow of development and encourage good CI/CD practices by tightly integrating with the CI tool Jenkins and allowing you to set up triggers for when to roll out a new deployment.

Using OpenShift’s source-to-image tool and buildConfigs, we can build and update images with nothing more than the application source, and then we can use image change triggers to automatically rollout a new deployment with the new image. If we wanted, we could also set up triggers for source code changes, so when a change is pushed to the source repository it will trigger a build using the buildConfig.

Even though we can automate both the build and deployment using triggers in OpenShift, we may want more intermediate steps in our workflow for testing and promoting across environments. Which is where Jenkins comes in.

Jenkins has plugins that interface with the OpenShift API and allow us to manage resources in our cluster. Beyond that, OpenShift has their own Jenkins image with the plugins properly configured to connect to the cluster upon startup, so no extra work is needed to begin working with these plugins.

Starting up Jenkins is as simple as executing one command using the oc binary tool.

oc new-app jenkins-ephemeral

We could also go into the OpenShift web console and deploy Jenkins from the catalog.

This will create all the resources needed to have Jenkins fully up and running inside the OpenShift cluster, such as the deployment, the service, and the route. It uses OpenShift’s Jenkins image, which automatically has OpenShift’s authentication realm hooked up, the OpenShift pipeline plugin and OpenShift client plugin, and other important plugins such as the pipeline plugin and Kubernetes plugin.

Openshift Pipeline Builds

What would a Jenkins pipeline look like inside OpenShift? The big difference between an OpenShift pipeline build compared with previous pipelines is the use of the pipeline DSL that the OpenShift pipeline plugin provides.

pipeline { agent none triggers { cron('30 16 * * *') } stages { stage('Start build') { agent any steps { openshiftBuild(bldCfg: '<name_of_buildConfig>', showBuildLogs: 'true') } } stage('Verify Build') { agent any steps { openshiftVerifyBuild(bldCfg: '<name_of_buildConfig>') } } stage('Testing') { agent any steps { /* Steps for testing... */ } } stage('Promote Image') { agent any steps { openshiftTag(srcStream: '<image_from_buildConfig>', srcTag: '<tag_from_buildConfig>', destStream: '<image_from_buildConfig>', destTag: 'prod') } } }}

The first stage starts a build for a new image. The bldCfg key references the name of a buildConfig that exists within the cluster. This will build a new image and push the image to an image repository either on Dockerhub or in an imagestream within the cluster.

The second stage verifies that the build completed successfully. This inspects the state of the latest build and makes sure that it completed within a reasonable amount of time. Success or failure of builds before the latest one don’t matter.

The promotion stage simply takes the image that was just built and retags it. In this case, with the destination tag being ‘prod’. So any deployments that have triggers set up to look for an image change for the image <image_from_buildConfig>:prod will automatically rollout the new deployment.

Once a developer pushes a code change, Jenkins will be triggered to start a build using source-to-image for a new image. This new image will be output to OpenShift’s built-in image registry. This image change will trigger a deployment for the respective environment. (For this example, we’ll call it dev.)

While OpenShift outputs the new image and deploys it to the dev environment, Jenkins continues through the rest of the OpenShift pipeline build stages. It verifies the latest build completed with success, performs testing, and then promotes the image. By updating the <image_from_buildConfig>:prod tag, the image change trigger will be set off and the prod environment will rollout the new image.

Expanding on OpenShift Pipeline Builds

We may want to add features to OpenShift pipeline builds to make them more ready for production. Suppose we have different projects set up inside our cluster to separate environments. If resources are spread out across multiple project spaces, we could pass in extra arguments to manage resources outside of the Jenkins microservice namespace. We could also pass in a commit hash if we wanted a specific version of the source.

steps { openshiftBuild(bldCfg: '<name_of_buildConfig>', showBuildLogs: 'true', commitID: <commit_hash> namespace: <name_of_project_BuildCfg_is_in>)}

We could also add steps for an approval before the new image gets deployed. Since promotions are handled just by tagging images, we can just add an input step after our tests and before the tagging stage:

stage('Testing') { agent any steps { /* Steps for testing... */ input 'Deploy image to prod environment?' }}

After the promotion, we could add extra stages for verifying the deployment worked properly and for scaling the deployment:

stage('Verify Deployment') { agent any steps { openshiftVerifyDeployment ( depCfg: <name_of_deploymentConfig>, verifyReplicaCount: 'true', namespace: 'prod', verbose: 'true' ) }}stage('Scale Deployment') { agent any steps { openshiftScale ( depCfg: <name_of_deploymentConfig>, replicaCount: <num_of_pods> /* number of pods to loadbalance over */ verifyReplicaCount: 'true', namespace: 'prod', verbose: 'true' ) }}

Even more pipeline DSL comes from the OpenShift Pipeline plugin that isn’t shown here. Jenkins has good documentation to show what you can do with this plugin.

OpenShift Pipeline Builds – Final Thoughts

Microservices and DevOps were meant to achieve the same thing: faster deployments with less worry about environments. OpenShift is a great platform for coupling these two concepts and providing the resources necessary to take full advantage of both. For anyone interested in experiencing the magic that OpenShift pipeline builds have to offer, consider spinning up a single node cluster on your local machine using Minishift.