A Sample OpenShift Pipeline for a Spring Boot Application
This example demonstrates how to implement a full end-to-end Jenkins Pipeline for a Java application in OpenShift Container Platform. This sample demonstrates the following capabilities:
- Deploying an integrated Jenkins server inside of OpenShift
- Running both custom and oob Jenkins slaves as pods in OpenShift
- "One Click" instantiation of a Jenkins Pipeline using OpenShift's Jenkins Pipeline Strategy feature
- Building a Jenkins pipeline with library functions from our pipeline-library
- Automated rollout using the openshift-appler project.
This quickstart can be deployed quickly using Ansible. Here are the steps.
- Clone this repo
ansible-galaxy install -r requirements.yml --roles-path=galaxy
- Log into an OpenShift cluster, then run the following command.
$ ansible-playbook -i ./.applier/ galaxy/openshift-applier/playbooks/openshift-cluster-seed.yml
At this point you should have 4 projects created (
basic-spring-boot-prod) with a pipeline in the
-build project, and our Spring Rest demo app deployed to the dev/stage/prod projects.
The following breaks down the architecture of the pipeline deployed, as well as walks through the manual deployment steps
The components of this pipeline are divided into two templates.
The first template,
applier/templates/build.yml is what we are calling the "Build" template. It contains:
- An ImageStream for the s2i build config to push to
The build template contains a default source code repo for a java application compatible with this pipelines architecture (https://github.com/redhat-cop/spring-rest).
The second template,
applier/templates/deployment.yml is the "Deploy" template. It contains:
- A tomcat8 DeploymentConfig
- A Service definition
- A Route
The idea behind the split between the templates is that I can deploy the build template only once (to my build project) and that the pipeline will promote my image through all of the various stages of my application's lifecycle. The deployment template gets deployed once to each of the stages of the application lifecycle (once per OpenShift project).
This project includes a sample
Jenkinsfile pipeline script that could be included with a Java project in order to implement a basic CI/CD pipeline for that project, under the following assumptions:
- The project is built with Maven
- The OpenShift projects that represent the Application's lifecycle stages are of the naming format:
This pipeline defaults to use our Spring Boot Demo App.
Bill of Materials
- One or Two OpenShift Container Platform Clusters
- OpenShift 3.5+ is required
- Red Hat OpenJDK 1.8 image is required
- Access to GitHub
Manual Deployment Instructions
1. Create Lifecycle Stages
For the purposes of this demo, we are going to create three stages for our application to be promoted through.
In the spirit of Infrastructure as Code we have a YAML file that defines the
ProjectRequests for us. This is as an alternative to running
oc new-project, but will yeild the same result.
$ oc create -f applier/projects/projects.yml projectrequest "basic-spring-boot-build" created projectrequest "basic-spring-boot-dev" created projectrequest "basic-spring-boot-stage" created projectrequest "basic-spring-boot-prod" created
2. Stand up Jenkins master in dev
For this step, the OpenShift default template set provides exactly what we need to get jenkins up and running.
$ oc process openshift//jenkins-ephemeral | oc apply -f- -n basic-spring-boot-build route "jenkins" created deploymentconfig "jenkins" created serviceaccount "jenkins" created rolebinding "jenkins_edit" created service "jenkins-jnlp" created service "jenkins" created
4. Instantiate Pipeline
A deploy template is provided at
applier/templates/deployment.yml that defines all of the resources required to run our Tomcat application. It includes:
RoleBindingto allow Jenkins to deploy in each namespace.
This template should be instantiated once in each of the namespaces that our app will be deployed to. For this purpose, we have created a param file to be fed to
oc process to customize the template for each environment.
Deploy the deployment template to all three projects.
$ oc process -f applier/templates/deployment.yml --param-file=applier/params/deployment-dev | oc apply -f- service "spring-rest" created route "spring-rest" created imagestream "spring-rest" created deploymentconfig "spring-rest" created rolebinding "jenkins_edit" configured $ oc process -f applier/templates/deployment.yml --param-file=applier/params/deployment-stage | oc apply -f- service "spring-rest" created route "spring-rest" created imagestream "spring-rest" created deploymentconfig "spring-rest" created rolebinding "jenkins_edit" created $ oc process -f applier/templates/deployment.yml --param-file=applier/params/deployment-prod | oc apply -f- service "spring-rest" created route "spring-rest" created imagestream "spring-rest" created deploymentconfig "spring-rest" created rolebinding "jenkins_edit" created
A build template is provided at
applier/templates/build.yml that defines all the resources required to build our java app. It includes:
BuildConfigthat defines a
JenkinsPipelineStrategybuild, which will be used to define out pipeline.
BuildConfigthat defines a
Binaryinput. This will build our image.
Deploy the pipeline template in build only.
$ oc process -f applier/templates/build.yml --param-file applier/params/build-dev | oc apply -f- buildconfig "spring-rest-pipeline" created buildconfig "spring-rest" created
At this point you should be able to go to the Web Console and follow the pipeline by clicking in your
basic-spring-boot-build project, and going to Builds -> Pipelines. At several points you will be prompted for input on the pipeline. You can interact with it by clicking on the input required link, which takes you to Jenkins, where you can click the Proceed button. By the time you get through the end of the pipeline you should be able to visit the Route for your app deployed to the
myapp-prod project to confirm that your image has been promoted through all stages.
Cleaning up this example is as simple as deleting the projects we created at the beginning.
oc delete project basic-spring-boot-build basic-spring-boot-dev basic-spring-boot-prod basic-spring-boot-stage