Implement an OpenShift deployment strategy using Templates
Imagine you have a GitHub repository with the source code of an application you wrote and you want to build and deploy it to an OpenShift cluster.
OpenShift gives you several options to do it, the easiest way being Source-to-Image, you just throw in your GitHub repository URL and OpenShift will do the magic for you: it will understand the code language, it will select the appropriate base image it has in its internal registry, based on your code language, and will merge your code into that base image, creating and deploying your code to the cluster.
Great, isn’t it? But what if you want something less opinionated and little more control over the process? A great flexibility can come from OpenShift Templates. Ok, but what exactly is a Template? Let us Red Hat speak for themselves; from Red Hat OpenShift documentation (https://docs.openshift.com/container-platform/4.6/openshift_images/using-templates.html) :
A template describes a set of objects that can be parameterized and processed to produce a list of objects for creation by OpenShift Container Platform. A template can be processed to create anything you have permission to create within a project, for example services, build configurations, and DeploymentConfigs. A template may also define a set of labels to apply to every object defined in the template.
Easier than what you thought a Template is just a straightforward way to describe all the objects you need to actually deploy an application to OpenShift (typically DeploymentConfig, Service, Route and maybe BuildConfig) and have full control of their configuration.
Just for the sake of knowledge other deployment strategies can be:
- Jenkins pipeline: yes you can use the good old Jenkins to implement your CI/CD process on OpenShift; I wrote an article on this, have a look at the link https://robertopozzi.medium.com/using-jenkins-pipelines-to-implement-ci-cd-on-red-hat-openshift-f0cac479e66e) to understand better;
- OpenShift pipeline (based on Tekton): this is a native Kubernetes implementation of build and deploy Tasks and Pipelines; I plan to publish a specific article on it soon, so watch out.
How to create an OpenShift Template to build and deploy an application
So, now let us jump into using an actual Template. The scenario I am going to describe is quite easy:
- Source code for the application is in a private GitHub repository;
- An OpenShift cluster is up and running somewhere, ready to run the application;
- A Template is defined to access source code in the private GitHub repository, build application from source, deploy and expose it as a Route to be accessible.
The template I am going to use as an example can be downloaded from the link Windfire Restaurants Backend Template and it defines all the following objects:
- ImageStream that references the container image in OpenShift Internal Registry;
- BuildConfig of type Git that, in my case, uses nodejs:12 base image to build from source code;
- DeploymentConfig that defines how the application is deployed to OpenShift cluster;
- Service of type ClusterIP that exposes required ports and allows to interact with the running pods from within the OpenShift cluster;
- Route that exposes the Service outside the OpenShift cluster.
Let us start from the end, the parameters section, where you can define everything that can be parameterized (we will see how you can inject variables in the deployment process later).
Do you see that OPENSHIFT_GITHUB_SECRET parameter ? What is it needed for?
Remember my GitHub repository is private, so OpenShift build process (defined by a BuildConfig object) needs credentials to access GitHub, clone the repository and access the source code to build the application.
So let us step back and start by creating the Secret where we will store GitHub credentials that allow OpenShift to access private repositories; it is as simple as this:
# Remember to first authenticate to OpenShift with oc login
oc create secret generic <GIVE_IT_THE_NAME_YOU_WANT> \
--from-literal=username=<YOUR_GITHUB_USERNAME> \
--from-literal=password=<YOUR_GITHUB_PERSONAL_ACCESS_TOKEN> \
--type=kubernetes.io/basic-auth
Since we want to build the application from source code, the first OpenShift object that we need is a BuildConfig, here is an example, taken from my template, that you can replicate and easily adapt to your case:
Let us analyze the anatomy of this BuildConfig:
- uri: this is obviously the GitHub repository where application code resides (in my case https://github.com/robipozzi/windfire-restaurants-node);
- ref: this is the branch from which the code will be taken;
- contextDir: this is needed only in case the actual source code for the application is not in the root directory of the repository (in my case I had to use it since my code is in the app folder of GitHub repository);
- strategy: in my case is sourceStrategy since I build from source code directly and nodejs:12 is just the Node.js base image that OpenShift provides (you will need to change it according to your application).
And finally, yes that sourceSecret is exactly the name of the Secret that holds the GitHub credentials we have created before.
Once you have created the GitHub Secret and adapted the definitions for DeploymentConfig, Service and Route to your case, you are ready to go and deploy the application by feeding OpenShift with the Template we created, something like this:
## Set OpenShift project where your application will be deployed
## Remember <YOUR_OPENSHIFT_PROJECT> project must pre-exist
oc project <YOUR_OPENSHIFT_PROJECT>## Get the Base Domain of your OpenShift cluster
export BASE_DOMAIN=$(oc get DNS cluster -o jsonpath=’{.spec.baseDomain}’)## Deploy application using the Template
oc new-app -f <PATH_TO_TEMPLATE_FILE>
-p OPENSHIFT_PROJECT=<YOUR_OPENSHIFT_PROJECT> \
-p OPENSHIFT_CLUSTER_DOMAIN=$BASE_DOMAIN \
-p OPENSHIFT_GITHUB_SECRET=<YOUR_GITHUB_SECRET_NAME>
The “oc-new-app” command ingests the Template, dynamically sets some parameters (i.e.: OPENSHIFT_PROJECT, OPENSHIFT_CLUSTER_DOMAIN and OPENSHIFT_GITHUB_SECRET) with appropriate values you can externally control, creates all the objects in the template and deploys the application to the cluster, as easy as that.
Update application with triggers and GitHub Webhooks
Once you have deployed the application, it is possible to use GitHub Webhooks to trigger automatic application deployment updates whenever a change is pushed to the GitHub repository.
Remember the Template has created a BuildConfig object in your cluster; ensure a GitHub trigger is enabled on it by issuing the following command:
## Set a GitHub trigger to BuildConfig
oc set triggers bc/windfire-restaurants-backend --from-github
This will allow the BuildConfig to be triggered by a webhook that is configured on GitHub.
To do so, firstly you need to get the secret that is automatically generated when the “from-github” trigger is set on the BuildConfig, with the following command:
oc edit bc/windfire-restaurants-backend
You should find something like the following, write down the secret because you will need it in a second.
Then find the GitHub Webhook URL with the following command:
oc describe bc/windfire-restaurants-backend
You should find something similar to the following, write down the URL, replace with the actual secret you found before and write it down, you will need it when you are going to configure Webhooks in GitHub.
Now we have everything we need to set a Webhook trigger in GitHub.
Go to the GitHub repository an do the following:
- click on Settings;
- click on Webhooks;
- click Add Webhook button and configure it appropriately: set Payload URL to the Webhook URL you noted down before, just like the following:
Pretty easy, isn’t it?
And now you can just try to push some changes to your GitHub repository and you will see the magic happening: the GitHub webhook will trigger a new Build in your OpenShift cluster, which will update the application.
What to read next
This is the first of a series of articles exploring the options you have to build and deploy applications to OpenShift, you can go on reading the next articles in the series at the following links: