- copy
files/example-app-inventory-step-3.json
into thevars
directory - execute
run.sh
This guide assumes:
- You are using the CI-CD Starter or a version of it. It's possible to take a different approach, but we haven't documented that
- You are onboarding a Java app that builds into an uber jar (TODO - guide for web apps)
- Your app exposes a REST API on port
8080
- Your app does not require external services (e.g. a database) to be available in order to boot up and operate
- You have installed the
oc
binary that corresponds to the OpenShift cluster you are using - The necessary tools to build your app are installed in a local or remote workspace which you can access
- You have basic familiarity with OpenShift objects and how they are configured via templates
- You have basic familiarity with
Jenkinsfile
As an example, we will use a Vert.x REST API, built with maven into an uber jar, and deployed to openshift with the Java S2I image.
This guide will start you down the path of deploying applications to OpenShift using version controlled templates and ansible. With the getting starting material we've provided here, we think this is a simple, yet robust approach for both developers and operators.
But that's a decision each team needs to make for itself. So before going further, and have a conversation with your team that this is the approach you want to take. It might help to take a look at this example of what an app looks like when managed with this approach. We refer to these documents as an "Application Inventory." In practical terms, it's just a .json
file that provides a list of projects and the templates to apply to those projects, written in a way that our ansible automation can consume it. We should note here that those templates are accessed via oc process
, which allows you to retrieve the template via http(s)
(as is shown in the previous example), via the local file system, or via OpenShift when the template has been installed in a project.
If the team decides to move forward with this approach, there are few more things you need to do :
- Decide as a team how many stages of your pipeline you want. We default to 3: development (dev), test (test), and user acceptance test (uat).
- Decide as a team what you want the projects to be called. This example uses acme-dev, acme-test, and acme-uat. We suggest you follow a similar convention, though how you map your apps to the projects within a stage (e.g. dev or uat) is the subject of a different, yet to be written guide.
- Fork this repository into your own VCS. This will be a shared repository between dev and ops, so make sure you agree on it's location, naming, access rights etc.
In this section, we'll verify you app can be compiled, packaged and built into a container image to run on OpenShift.
- Clone your source code and build it. Ensure that:
- the build passes
- the build produces a target directory with a single jar, which is an uber-jar for your app. More than one jar in the target directory can cause issues with S2I. The maven fabric plugin and the vert.x maven plugin can help you achieve this objective.
- Create a new openshift project to test S2I works correctly
oc new-project build-test
- Create a S2I build in the test project
oc new-build --binary=true --name=test -i=redhat-openjdk18-openshift
- Run the S2I build, using the output your local app build in step 1. If the uber-jar is not created in a
target
folder in the root directory, update the command below accordingly.oc start-build test --from-dir=target/ --follow
- Create an application to consume the image you just built.
oc new-app test
- Expose the applications HTTP endpoint so you can verify it deployed correctly
oc expose svc test
- Navigate to your test project in the OpenShift Console. Inspect the URL for your app and ensure it produces the correct results. Check the log of the deployment and make sure it's error free.
- If everything worked correctly, delete the test project:
oc delete project build-test
Take a look a this skeleton Application Inventory. At this time, it's just a list of projects, with some information on how those projects should display themselves in the OpenShift Console. We're going to use this example to start creating your own Application Inventory.
- Create a new file:
vars/application-inventory.json
and copy the contents of the example into it - Update the contents to reflect the project names your team decided upon. This guide will not walk you through building out CI or CD tooling, but instead assumes you are using the CI-CD Starter. By default, the the CI-CD starter will create a
labs-ci-cd
project with Jenkins/Nexus/etc, so unless you changed the default project names, you should reuse thislabs-ci-cd
project. You can change this later if you so wish. - Create the projects in OpenShift by executing
run.sh
. Verify the projects are created with the OpenShift console or usingoc
. - Take a second to reflect on what you just did. Specifically, updating a piece of configuration in a version controlled repository, and then executing automation to ensure OpenShift reflects this configuration. This approach is fundamental to this guide. should begin a recurring feedback loop of updating the Application Inventory and then using the automation tooling to create the corresponding state in OpenShift.
OpenShift natively supports a Pipeline Build Strategy which allows OpenShift to manage Jenkins Pipeline builds just like a normal S2I build. This section will show you how to create the Jenkinsfile
for your app.
- Review this example Jenkinsfile. TODO - explain what's happening here.
- Copy this example Jenkinsfile into a working copy of your application's source code. By default, you should place it in the root of your source code hierarchy, which hopefully the root directory of the repository. If the root of the source code is further nested in the repository, place the
Jenkinsfile
alongside the source, but remember you'll need to set a property for this later on. - Now it's time to customize your
Jenkinsfile
for your app. TheJenkinsfile
has comments telling you how to do that. - Commit your changes back to the source repository and push them (via PR if necessary) to the upstream repository that will be build by Jenkins later on.
With the projects in place and our application ready to go, we can reuse the provided templates to provision the Jenkins Pipeline and the S2I build that will create our container image. Again, we'll leverage an example to help get us started.
- Update the
labs-ci-cd
project invars/application-inventory.json
with thetemplates
section found on lines 9-19. Don't forget to add a comma at the end of your line 8. - The
filename
property tellsoc process
where to find the template either as a local file (relative torun.sh
), or as ahttp(s)
resource. In this case, we're using anhttp(s)
resource. Open this URL and read through it. You'll notice it has twoBuildConfigs
, one for the Jenkins pipeline, and one for S2I build to create the container image. Also notice that the template uses several parameters, which you'll need to populate with values that correspond to your app. - Update the value of
PIPELINE_SOURCE_REPOSITORY_URL
with the git repository url for your app. Note that this will be used by Jenkins to clone your source code, so the VCS needs to be visible to Jenkins on the network, and if usingssh
, your Jenkins needs to be configured with thessh-key
. - Update
PIPELINE_SOURCE_REPOSITORY_REF
with the git ref for your app. If usingmaster
, you can remove this line if you wish. - If your
Jenkinsfile
is not in the root directory, updatePIPELINE_CONTEXT_DIR
with it's location. If theJenkinsfile
is in the root directory, you have the option of deleting this line. - Update
NAME
with the value you want use for the name of all of your objects. - Create the OpenShift objects by executing
run.sh
. This is a safe operation because ansible is idempotent, so it will leave your existing projects in place. Verify that the Pipeline is created and running using OpenShift console. When it gets to theBuild Image
step, verify that the S2I build is run.
The Jenkins Pipeline should pause at a step called Deploy to Dev
. At this point, you can move on to the last section
With the projects in place, the Jenkins Pipeline running, and the container image built, it is time to configure our dev
, test
& uat
projects with the template that will deploy the app. Again, let's first look at an example.
- Navigate the template, which again is a
http(s)
resource. Read through it. It should look straightforward, apart from theRoleBinding
objects. One of the objects enables the JenkinsServiceAccount
to tag the container image into theImageStream
in the namespace, which is how promotions are handled. The otherRoleBinding
provides the proper access rights for applications using the fabric8 kubernetes client. - Update your
dev
project invars/application-inventory.json
with thetemplates
section found on lines 23-31. Don't forget to add a comma at the end of your line 22. - Update
APP_NAMESPACE
to reflect the name of the project the template is deployed in - If you are using the CI-CD Starter, you do not need to update
PIPELINES_NAMESPACE
. If you are not, then update this value to the project where the application container image was built. - Update
NAME
with the value you want use for the name of all of your objects. - Repeat the above steps for the
test
&uat
projects. Then move on - Create the OpenShift objects by executing
run.sh
. This is a safe operation because the ansible automation usesoc apply
under the covers to process our template, which delegates the responsibility of idempotence to OpenShift. Verify that theDeploymentConfig
and related objects are created in thedev
,test
&uat
projects. - To promote the container image, navigate back to the Jenkins Pipeline and approve the deployments. After each deploy, verify your container image comes up properly and the log is free of errors.
- If all goes correctly, commit your changes and push them (via PR if needed) to the upstream repository
Simply update your existing Application Inventory with new apps following this guide. You may need to create new templates or modify the existing ones. That is perfectly OK and our design is intended to support you doing that. If you want to use an existing template already found in OpenShift, simple specify name
instead of filename
. The convention for these types of types established by oc process
is <project-name>//<template-name>
as seen in this example.