In the previous scenarios, you deployed the Coolstore monolith using an OpenShift Template into the {{USER_ID}}-coolstore-dev Project. The template created the necessary objects (BuildConfig, DeploymentConfig, ImageStreams, Services, and Routes) and gave you as a Developer a playground in which to run the app, make changes and debug.
In this step, we are now going to setup a separate production environment and explore some best practices and techniques for developers and DevOps teams for getting code from the developer (that’s YOU!) to production with less downtime and greater consistency.
The existing {{USER_ID}}-coolstore-dev project is used as a developer environment for building new versions of the app after code changes and deploying them to the development environment.
In a real project on OpenShift, dev, test and production environments would typically use different OpenShift projects and perhaps even different OpenShift clusters.
For simplicity in this scenario we will only use a dev and prod environment, and no test/QA environment.
Back in the {{ CONSOLE_URL }}/topology/ns/{{ USER_ID }}-coolstore-dev[Topology View^], click on the project drop-down and select Create Project.
Fill in the fields, and click Create
:
-
Name: {{USER_ID}}-coolstore-prod
-
Display Name: {{USER_ID}} Coolstore Monolith - Production
-
Description: leave this field empty
Warning
|
YOU |
This will create a new OpenShift project called {{USER_ID}}-coolstore-prod from which our production application will run.
In this case we’ll use the production template to create the objects.
Click the Start building your application in the Topology view:
In the search box, type in pipeline
and choose Coolstore Monolith using pipelines and then click Instantiate Template.
Fill in the following fields:
-
Namespace:
{{ USER_ID }}-coolstore-prod
(this should already be selected) -
User ID:
{{ USER_ID }}
Keep the other values as-is and scroll down and click Create.
Go to the {{ CONSOLE_URL }}/topology/ns/{{ USER_ID }}-coolstore-prod[Topology View^] to see the elements that were deployed.
The Topology view in the Developer perspective of the web console provides a visual representation of all the applications within a project, their build status, and the components and services associated with them.
Label the components so that they get proper icons by running this command in the VS Code Terminal:
oc project {{USER_ID}}-coolstore-prod && \
oc label dc/coolstore-prod-postgresql app.openshift.io/runtime=postgresql --overwrite && \
oc label dc/coolstore-prod app.openshift.io/runtime=jboss --overwrite && \
oc label dc/coolstore-prod-postgresql app.kubernetes.io/part-of=coolstore-prod --overwrite && \
oc label dc/coolstore-prod app.kubernetes.io/part-of=coolstore-prod --overwrite && \
oc annotate dc/coolstore-prod app.openshift.io/connects-to=coolstore-prod-postgresql --overwrite && \
oc annotate dc/coolstore-prod app.openshift.io/vcs-uri=https://github.com/RedHat-Middleware-Workshops/cloud-native-workshop-v2m2-labs.git --overwrite && \
oc annotate dc/coolstore-prod app.openshift.io/vcs-ref=ocp-4.10 --overwrite
You can see the postgres database running (with a dark blue circle), and the coolstore monolith, which has not yet been deployed or started. In previous labs we deployed manually from a binary build of our app in our developer project. In this lab we will use a CI/CD pipeline to build and deploy automatically go our production environment.
We will use a Jenkins Helm Chart in our project and use a Jenkins Pipeline build strategy, one of the most popular continuous integration and continuous delivery tool.
Right-Click on the Topology view. Then, click on Helm Charts in the Add to Project popup menu:
Type in jenkins
in the search box, and click on Jenkins Helm chart:
Leave all fields and click Install:
Back on the {{ CONSOLE_URL }}/topology/ns/{{ USER_ID }}-coolstore-prod[Topology View^] you can see the production database, and an application called Jenkins which OpenShift uses to manage CI/CD pipeline deployments.
There is no running production app just yet. The only running app is back in the dev environment, where you used a binary build to run the app previously.
In the next step, we’ll promote the app from the dev environment to the production environment using an OpenShift pipeline build. Let’s get going!
So far you have built and deployed the app manually to OpenShift in the dev environment. Although it’s convenient for local development, it’s an error-prone way of delivering software when extended to test and production environments.
Continuous Delivery (CD) refers to a set of practices with the intention of automating various aspects of delivery software. One of these practices is called delivery pipeline which is an automated process to define the steps a change in code or configuration has to go through in order to reach upper environments and eventually to production.
OpenShift simplifies building CI/CD Pipelines by integrating the popular Jenkins pipelines into the platform and enables defining truly complex workflows directly from within OpenShift. OpenShift 4 also introduces Tekton Pipelines, an evolution of CI/CD for Kubernetes, which you might be exploring in a later module if it’s on the agenda for today.
The first step for any deployment pipeline is to store all code and configurations in a source code repository. In this workshop, the source code and configurations are stored in a GitHub repository we’ve been using.
OpenShift has built-in support for Jenkins CI/CD pipelines by allowing developers to define a Jenkins pipeline for execution by a Jenkins automation engine.
The build can get started, monitored, and managed by OpenShift in the same way as any other build types e.g. S2I. Pipeline workflows are defined in a Jenkinsfile
, either embedded directly in the build configuration, or supplied in Git repository and referenced by the build configuration. They are written using the Groovy scripting language.
As part of the production environment template you used in the last step, a Pipeline build object was created. Ordinarily the pipeline would contain steps to build the project in the dev environment, store the resulting image in the local repository, run the image and execute tests against it, then wait for human approval to promote the resulting image to other environments like test or production.
Note
|
You may notice a Pipelines menu item on the left menu of the OpenShift Console. This menu item is for exploring Tekton Pipelines, which is a newer pipeline technology based on the Tekton project. There are other modules as part of this workshop that explore Tekton. For now we’ll concentrate on Jenkins. |
Our pipeline is somewhat simplified for the purposes of this Workshop. Inspect the contents of the pipeline by navigating to the {{ CONSOLE_URL }}/k8s/ns/{{USER_ID}}-coolstore-prod/buildconfigs[Build Config page^] and click on monolith-pipeline
:
Then, you will see the details of Jenkinsfile on the right side:
You can also inspect this via the following command via VS Code Terminal window:
oc describe bc/monolith-pipeline -n {{USER_ID}}-coolstore-prod
The pipeline syntax allows creating complex deployment scenarios with the possibility of defining checkpoints for manual interaction and approval processes using the large set of steps and plugins that Jenkins provides in order to adapt the pipeline to the processes used in your team.
To simplify the pipeline in this workshop, we simulate the build and tests and skip any need for human input. Once the pipeline completes, it deploys the app from the dev environment to our production environment using the above tag()
method within the openshift
object, which simply re-tags the image you already created using a tag which will trigger deployment in the production environment.
Let’s invoke the build pipeline.
On the {{ CONSOLE_URL }}/k8s/ns/{{USER_ID}}-coolstore-prod/buildconfigs/monolith-pipeline[Pipeline Details Page^], select Actions > Start Build:
This will start the pipeline. It will take a minute or two to start the pipeline! Future runs will not take as much time as the Jenkins infrastructure will already be warmed up. You can watch the progress of the pipeline:
Once the pipeline completes, return to the {{ CONSOLE_URL }}/topology/ns/{{ USER_ID }}-coolstore-prod[Topology View^] and notice that the application is now deployed and running!
It may take a few moments for the container to deploy fully.
Congratulations! You have successfully setup a development and production environment for your project and can use this workflow for future projects as well.
In the next step, we’ll add a human interaction element to the pipeline, so that you as a project lead can be in charge of approving changes.
In previous steps, you used an OpenShift Pipeline to automate the process of building and deploying changes from the dev environment to production. In this step, we’ll add a final checkpoint to the pipeline which will require you as the project lead to approve the final push to production.
Ordinarily your pipeline definition would be checked into a source code management system like Git, and to change the pipeline you’d edit the Jenkinsfile in the source base. For this workshop we’ll just edit it directly to add the necessary changes. You can edit it with the oc command but we’ll use the Web Console.
Back on the {{ CONSOLE_URL }}/k8s/ns/{{USER_ID}}-coolstore-prod/buildconfigs/monolith-pipeline[Pipeline Details Page^] click on the YAML tab. Add a new stage to the pipeline, just before the Deploy to PROD stage:
Note
|
You will need to copy and paste the below code into the right place of BuildConfig as shown in the below image. |
stage ('Approve Go Live') {
steps {
timeout(time:30, unit:'MINUTES') {
input message:'Go Live in Production (switch to new version)?'
}
}
}
Your final pipeline should look like:
Click Save.
With the approval step in place, let’s simulate a new change from a developer who wants to change the color of the header in the coolstore to a blue background color.
First, in VS Code, in the cloud-native-workshop-v2m2-labs
project, open monolith/src/main/webapp/app/css/coolstore.css
, which contains the CSS stylesheet for the
CoolStore app.
Add the following CSS to turn the header bar background to Blue (Copy to add it at the bottom):
.navbar-header {
background: blue
}
Now we need to update the catalog endpoint in the monolith application. Run the following commands in a Terminal to update the baseUrl to the proper value with your username:
Warning
|
You do not need to run these if you already completed the Optimizing Existing Applications lab and have created |
JSPATH="$PROJECT_SOURCE/monolith/src/main/webapp/app/services/catalog.js"
CATALOGHOST=$(oc get route -n {{ USER_ID}}-catalog catalog-springboot -o jsonpath={% raw %}"{.spec.host}"{% endraw %})
sed -i 's/REPLACEURL/'$CATALOGHOST'/' "$JSPATH"
Next, re-build the app once more via VS Code Terminal:
mvn clean package -Popenshift -DskipTests -f $PROJECT_SOURCE/monolith
And re-deploy it to the dev environment using a binary build just as we did before via VS Code Terminal:
oc start-build -n {{USER_ID}}-coolstore-dev coolstore --from-file=$PROJECT_SOURCE/monolith/deployments/ROOT.war --follow
Wait for it to complete the deployment via VS Code Terminal:
oc -n {{USER_ID}}-coolstore-dev rollout status -w dc/coolstore
And verify that the blue header is visible in the dev application by navigating to the http://www-{{USER_ID}}-coolstore-dev.{{ ROUTE_SUBDOMAIN}}[Coolstore Dev Web frontend^]. It should look like the following:
Warning
|
If it doesn’t, you may need to do a hard browser refresh. Try holding the shift key while clicking the browser refresh button, or opening a separate "Private Browser" session to access the UI. |
Confirm the http://www-{{USER_ID}}-coolstore-prod.{{ ROUTE_SUBDOMAIN}}[Coolstore Prod Web frontend^] is still using the original black header:
We’re happy with this change in dev, so let’s promote the new change to prod, using the new approval step!
Invoke the pipeline once more by navigating to the {{ CONSOLE_URL }}/k8s/ns/{{USER_ID}}-coolstore-prod/buildconfigs/monolith-pipeline[Pipeline Details Page^], select Actions > Start Build.
The same pipeline progress will be shown, however before deploying to prod, you will see a prompt in the pipeline:
Click on the link for Input Required. This will open a new tab and direct you to Jenkins itself, where you can login with the same credentials as OpenShift:
-
Username:
{{USER_ID}}
-
Password:
{{OPENSHIFT_USER_PASSWORD}}
Accept the browser certificate warning and the Jenkins/OpenShift permissions, and then you’ll find yourself at the approval prompt:
Click on Console Output on left menu then click on Proceed
.
Click Proceed, which will approve the change to be pushed to production. You could also have clicked Abort which would stop the pipeline immediately in case the change was unwanted or unapproved.
Once you click Proceed, you will see the log file from Jenkins showing the final progress and deployment.
On the {{ CONSOLE_URL }}/topology/ns/{{ USER_ID }}-coolstore-prod[Production Topology View^], wait for the production deployment to complete (and you get all blue circles!).
Once it completes, verify that the http://www-{{USER_ID}}-coolstore-prod.{{ ROUTE_SUBDOMAIN}}[Coolstore Prod Web frontend^] has the new change (blue header):
Warning
|
It may take a few seconds for the new app to be available, since we’ve not configured a proper health check and are not using Rolling Updates when deploying new apps. Real production environments would use this to ensure no downtime. If you don’t see a blue header, or you get Application Not Available errors, wait a few moments and reload. If you are still getting a black header, try holding the shift key while clicking the browser refresh button to force a hard refresh. |
Congratulations! You have added a human approval step for all future developer changes. You now have two projects that can be visualized as:
In this lab, you learned how to use the OpenShift Container Platform as a developer to build, and deploy applications. You also learned how OpenShift makes your life easier as a developer, architect, and DevOps engineer.
You can use these techniques in future projects to modernize your existing applications and add a lot of functionality without major re-writes.
The monolithic application we’ve been using so far works great, but is starting to show its age. Even small changes to one part of the app require many teams to be involved in the push to production.