Multiple Deployment Methods for OpenShift

From a developer’s point of view, deploying an application to OpenShift is easy. The challenging part is finding the best way to do it. Because OpenShift is so adaptable and flexible, it offers almost a thousand and one ways to deploy an application.

The best way will be the one that best fits your criteria:

  • Your development process: What is your existing ecosystem and flow? For example, are you already using Jenkins, Nexus, etc.?
  • Your developers’ maturity regarding containers and CI/CD: Are they already accustomed to containers and agile delivery process? Do they want to manage containers, Dockerfiles, or pipeline as code?
  • Your ops or technical experts’ involvement: Do they need to customize provided base images or base templates for introducing specificities?
  • Will you need to build different service offers allowing multiple workflows adapted to multiple development teams?

Following this tutorial, you will deploy the same application using 6 different methods. Remember that these are just 6 methods that represent main ways of doing things, there are a number of variations that may be defined using some elements picked from one or another method exposed here.

The source code of the application to deploy can be found on my GitHub repository where this tutorial comes to life as a simple README that grows. For deploying the application repeatedly, you will only need an OpenShift project for isolating things out. Method #6 may also require a JBoss Developer Studio on version 10+. We propose you create this project using the identifier ocp-tasks because some methods have this id hard-coded.

Startup by creating the project using the following command:

oc new-project ocp-tasks --display-name="OpenShift Tasks" --description="Demonstrating many ways to deploy application on OpenShift"

and here we go!

Option 1: Use provided JBoss EAP 7 S2I template

This is the most obvious for people starting with OpenShift: you’ll use the default template and base image provided by OpenShift without any customization upfront. To illustrate this flow within your ocp-tasks project:

  • Go to Add to project page.
  • Pick the jboss-eap70-openshift:1.4 template
  • Adapt the name of application to tpl-tasks or whatever you choose.
  • Refer this Github repository (http://github.com/lbroudoux/openshift-tasks) or another internal one.
  • Optionally, add some extra environment variables on the BuildConfig for referring Maven component mirror (MAVEN_MIRROR_URL).
  • Hit the save button and you’ll have the application running in a few minutes.

The process executed by OpenShift can be described as follows:

  • Given the template configuration and given the URL for the source repository, OpenShift will realize the checkout of code sources.
  • It sees the application is powered by Maven and launches the Maven build so that it produces compiled Java classes and then deployable binary artifact (here called openshift-task.war).
  • That later binary artifact is then added on top of jboss-eap70 base image to produce a Docker image for our application.
  • Image is stored within OpenShift Docker registry and can then trigger a new deployment (because the template says that a new image should trigger a new deployment).

Option 2: Bring your own S2I template

This variant consists in providing your own template that will be a customization of OpenShift provided template. Providing your own template allows you to lower the number of parameters the developer will have to fill and fixing hard values. To illustrate this flow within your ocp-tasks project:

  • Register your app template in OpenShift using oc create -f https://raw.githubusercontent.com/lbroudoux/openshift-tasks/master/app-template.yaml -n ocp-tasks.
  • Go to “Add to project” page.
  • Pick the openshift-tasks template.
  • Adapt the name of application to s2i-tasks or whatever you choose.
  • Refer this Github repository (http://github.com/lbroudoux/openshift-tasks) or another internal one.
  • Hit the save button and you’ll have the application running in few minutes.

The process executed by OpenShift can be described as follows and is basically the same as with standard base template:

The main differences you may noticed when creating your application is that the form to complete before deploying is drastically simpler than the default one. Providing a custom template allows you to pre-configure or hard code some parameters to ensure that users would not be able to change values and will be choosing the right values.

Option 3: Custom S2I for binary deployment

This variant consists in providing your own template, like the previous one, but adapting the source-to-image process by making OpenShift build your application image not from source but from a binary file you will inject. This variant is using the S2I customization capabilities as described here. The customization script we used is located into a companion repository here to enforce separation of concerns, but it could be located in the same repository.

To illustrate this flow within your ocp-tasks project, we assume that previous step (Option 2) has been done and template is already registered. The whole process of this variant is fully described here showing the split of responsibilities between Jenkins and OpenShift:

The trick here is to use a Jenkins instance to host the first part of your build process (like you would normally do without OpenShift). For doing that you may of course use a Jenkins instance deployed into your OpenShift project. You can easily create one using the jenkins-persistent template.

In this Jenkins instance, create a new job item (calling it bin-tasks for example) and configure it as a regular Jenkins Maven build. In configuration, you may want to checkout this Github repository (http://github.com/lbroudoux/openshift-tasks), to realize a mvn package and finally store the generated artifacts using Jenkins built-in store. This last choice is for making things simple: In a real-world scenario, you would want to store the generated artifact into a Nexus or Artifactory repository.

This second part is related to OpenShift. Because the previous variant has been done, you are now able to:

  • Go to “Add to project” page.
  • Pick the openshift-tasks template.
  • Adapt the name of application to bin-tasks or whatever you choose.
  • Refer the companion Github repository (http://github.com/lbroudoux/openshift-tasks-bin-deploy) or another internal one.
  • Hit the save button.

Build and then deployment may start, but you will likely deploy an empty JBoss EAP because you have not supplied any deployable artifact yet. So you may cancel the automatically started build and deployment before going further.

You now have a build config in Jenkins responsible for producing the binary and a build config in OpenShift that will be responsible for collecting the binary artifact and building a container image for deployment. Having a closer look at assemble file, you’ll notice that our build in OpenShift will need further environment variables to be able to retrieve the artifact. Through the console, go to your bin-tasks build and add these variables:

  • WAR_FILE_URL will be URL to which is published your artifact by Jenkins. Something like http://jenkins-ocp-tasks.example.com/job/bin-tasks/lastSuccessfulBuild/artifact/target/openshift-tasks.war.
  • WAR_FILE_USER is a user that is allowed to get this file.
  • WAR_FILE_PASSWORD is the Jenkins API token for this user (go to User settings in Jenkins and reveal API Token).

Finally, you may want to link all things together. So that when the bin-tasks job in Jenkins ends up successfully, it may trigger the bin-tasks build configuration into OpenShift. This can be easily done via a new Jenkins job that will use the OpenShift plugin for Jenkins. Create such a new job called for example bin-tasks-deploy (if your Jenkins runs into OpenShift, you may clone de OpenShift Sample job) and configure this job for watching bin-tasks successful result and then trigerring a new OpenShift build: this is a built-in build action coming with OpenShift plug in for Jenkins.

Option 4: Build pipeline managed out of Source code

In this variant, you’ll see how OpenShift enables you to build pipeline definition and management. In this first variant about CI/CD, the pipeline is managed outside of source code, in a centralized way, possible by people who are not members of the development team. To deploy this variant, we’ll use a slightly different custom template than in step (Option 2). In the previous step, build and deployment of application were linked together via the template: A trigger was used to automatically deploy a newly created image. The template we’ll use now defines no trigger so that the build and the deployment are not tied together and can be orchestrated and deployment repeated over and over on a bunch of different environments. For simplicity, we’ll just illustrate one deployment on a sole environment but you’ll get the point.

To illustrate this flow within your ocp-tasks project, we assume that previous step (Option 3) has been done and a Jenkins instance is already present in your project. The whole process of this variant is fully described here showing the split of responsibilities between Jenkins and OpenShift:

You may notice that the steps of the pipeline here are predictable and managed in Jenkins outside of source code. Jenkins delegates some operations of the pipeline workflow to OpenShift but it’s definitely up to you to enrich this process with integration tests, compliance checks, user acceptance tests and so on. In order to deploy this example bootstrap process, follow these steps:
– Register the new app template in OpenShift using oc create -f https://raw.githubusercontent.com/lbroudoux/openshift-tasks/master/app-template-no-trigger.yaml -n ocp-tasks.

  • Go to “Add to project” page.
  • Pick the openshift-tasks-no-trigger template.
  • Adapt the name of application to jkp-tasks.
  • Refer this Github repository (http://github.com/lbroudoux/openshift-tasks) or another internal one.
  • Hit the save button (a first Build should now have been started).
  • Declare a new Pipeline build configuration using oc create -f https://raw.githubusercontent.com/lbroudoux/openshift-tasks/master/pipeline-bc.yaml -n ocp-tasks.

A new pipeline has been created and is now available through the console by going to Builds > Pipelines. It is now up to you to start this pipeline and have the application running in few minutes. An optimal way of starting such a pipeline is by using a webhook, hooks are available for single builds and also for pipelines.

Option 5: Build pipeline managed within Source code

This variant consists of dynamically discovering a Jenkins configuration that will be used to configure a build pipeline within a Jenkins instance. It demonstrates the Jenkinsfile build strategy using an external Jenkinsfile that may be used to treat pipeline as code. At the beginning of every build iteration, OpenShift will discover this file and update the corresponding pipeline definition in Jenkins. To illustrate this flow within your ocp-tasks project:
* Register your app template in OpenShift using oc create -f https://raw.githubusercontent.com/lbroudoux/openshift-tasks/master/app-template-jenkinsfile.yaml -n ocp-tasks.
* Go to “Add to project” page.
* Pick the openshift-tasks-jenkinsfile template.
* Adapt the name of application to jkf-tasks.
* Refer this Github repository (http://github.com/lbroudoux/openshift-tasks) or another internal one.
* Hit the save button.

The application is not automatically built and deployed because our template does not contain anything in the build configuration that will instantiate the pipeline for the first time. Browsing the console and going to Builds > Pipelines, you may find the discovered pipeline. It’s up to you to start this pipeline and get the application running in few minutes. An optimal way of starting such a pipeline is by using a webhook, hooks are available for single Builds and also for pipelines.

This process is described as follows:

If you have a look at the Jenkinsfile, you’ll see that each and every operation of the pipeline process is handled as code.

Option 6: Directly from IDE

This last variant will show you how to directly deploy / hot redeploy your application from your IDE. For that we will use JBoss Developer Studio that embeds the OpenShift plug in. To illustrate this flow within your ocp-tasks project, we assume that previous step (Option 2) has been done and template is already registered. You must also have a local copy of the project (cloned from http://github.com/lbroudoux/openshift-tasks for example) that is imported as a Maven project within your IDE.

First thing to do is to establish a connection to your OpenShift cluster – this can be a remote or local instance. This can be easily done through the OpenShift Explorer view in IDE as shown in screenshot below. The process of connecting is as straightforward as using the webc console. Once this is done, the view displays a tree of the resources you are allowed to access.

You will now be able to deploy your local project directly to OpenShift. For that, right click on your Project and select Configuration > Deploy to OpenShift. You’ll come to a dialog asking you to select the target OpenShift project corresponding to a source IDE project and to select the appropriate template for deploying (reuse openshift-tasks).

In the next dialog, you’ll have access to the template parameters. Name your target application ide-tasks.

Wait for a few minutes and check the deployment success on your OpenShift instance. Now we want to go further and be able to automatically redeploy code changes as we change it in the IDE editor. To do that go back to the connection view in your IDE, see the newly created ide-tasks Service and right click and choose Server Adapter…. In the next dialog, you will need to create a link between your local Eclipse project and the OpenShift service.

ide server adaptor

Once done, you should have this new server adapter connection appearing into the Servers view of your IDE.

ide server adaptor

Synchronization of sources will start and may take some time as a first run. Now, just edit the file within your IDE (for example the /src/main/webapp/index.jsp file) and it will be automatically synchronized and deployed within the war file within the JBoss EAP within the Docker container running your application in OpenShift. Just like Russian dolls! The console within the IDE helps track what changes have been synchronized and applied to the remote application:

ide-hotdeploy

Summary

In this tutorial, we have seen 6 different methods for deploying the same application. Remember that these are just 6 methods and that there are many shades of grey in these black/white methods. Moreover, these methods can be complementary to each other: It’s up to you to find and redefine the one that best suits your expertise and development process.

Based on my experience, I would apply the following criteria for picking-up a bootstrap method:

  • Option 1 is useful for deploying existing apps that do not need to change frequently (none or very few evolutions planned in the roadmap) like support tooling or instant application.
  • Option 2 can be used when you have many apps following the same deployment scheme and when you are on the way to CI/CD. However, it is not well suited for applications needing velocity and auditability (the binary artifacts are not stored and referenced).
  • Option 3 is a must-have for a serious CI/CD journey in a traceability focused environment. It is an optimized build process with all artifacts being stored for full traceability and ease of analysis, reuse, and redeployment.
  • Option 4 is usually the first step when starting CI/CD implementation: Pipeline definitions and management is delegated to a centralized team responsible for the methodology deployment.
  • Option 5 represents an evolution of (Option 4) when CI/CD process are mastered and then delegated to agile and autonomous development teams. Each team may adapt them to better suit the application needs.
  • Option 6 may be very useful when working on an application requiring specific configuration or dependencies that cannot be easily reproduced outside of an OpenShift platform.

Feel free to share, comment, and send feedback.

Categories
Jenkins, OpenShift Container Platform, OpenShift Origin
Tags
, , , , ,
  • Milan Lesichkov

    Looks like another article that tries to say too much with complicated words and expressions, technical jargon and what not. Stopped reading after the first 2 paragraphs. Is it only me or its like written in an alien language?

  • Todd Wilson

    Great article and I really appreciate the deep level of detail! We have had multiple teams using OpenShift for over a year now and I whole heartedly agree that there is no “one size fits all” for our apps.

  • Karl Nicholas

    Is there a way to trigger a re-deploy when I push an image to docker hub? I used S2I to build an image, put it up on docker hub, and did a deployment from there. How can I trigger a new deployment when I push a new image to docker hub?

    Perhaps there is a better way? I created a wildfly image with the changes to the standalone.xml I needed. Then I used S2I to build my local source into a runnable wildfly application image, which is what I pushed and deployed. I’m trying to get around having to go through a github repository.

    I’m thinking I could create an application with the customer wildfly image that I created and use the direct from IDE option to the application, but what if I want to use the command line?