Blue/Green Deployments in OpenShift With Eclipse JKube
Tutorial to implement a Blue/Green deployment to deploy your Java application into OpenShift using Eclipse JKube Maven Plug-In.
Join the DZone community and get the full member experience.
Join For FreeBlue/Green Deployment is a well-known application release model that gradually transfers user traffic from a previous version of an application or microservice to a nearly identical new release—both of which are running in production.
The old version of the application or microservice is identified with a color (e.g: Blue) while the new version is identified with the other color (e.g: Green). This model allows management of the production traffic from one color (old version) to the other (new version); the old version can stand by in case of a rollback or it can be pulled from production and updated to become the template upon which the next update is made.
This model requires a Continuous Deployment model or pipeline to orchestrate the promotion between each color and manage the downtimes or rolling process. CD pipelines could be implemented using the capabilities provided by Eclipse JKube.
Eclipse JKube is a collection of plugins that are used for building container images using Docker, JIB or S2I build strategies. In addition, Eclipse JKube generates and deploys Kubernetes/OpenShift manifests (YAML configuration files) at compile time too.
This article describes an approach to integrate a Blue/Green deployment with Eclipse JKube. This approach is based on Maven Profiles and filtering resources. Of course, this is only an integration sample and it is open to having other approaches. For this example, I would like to dig into the Eclipse JKube Profiles as another approach. However, feel free to add your ideas, comments, or suggestions.
Identifying Blue/Green Version
Every time we want to deploy a new version, we must identify the right color to be used to deploy it. This process should be done in the CD pipeline before deploying our next application version.
For example, we could use a variable called app.bg.version
in the pom.xml
file. A Maven Profile could help us to declare each version. This variable will be used to filter some resources at deployment time.
Sample Maven profile for Blue Deployment:
<profile>
<id>blue</id>
<properties>
<app.bg.version>blue</app.bg.version>
</properties>
</profile>
Sample Maven profile for Green Deployment:
xxxxxxxxxx
<profile>
<id>green</id>
<properties>
<app.bg.version>green</app.bg.version>
</properties>
</profile>
This value could also be used to define the version of the image built. A sample of that could be using the jkube.generator.name
property in the pom.xml
file as:
xxxxxxxxxx
<jkube.generator.name>${project.artifactId}-${app.bg.version}:${project.version}</jkube.generator.name>
Defining Blue/Green Objects
Each Blue and Green version should use its own resources at deployment time to avoid replacing or redeploying the other deployment. To do that we would use Eclipse JKube resource fragments to declare specific definitions of some Kubernetes or OpenShift objects.
In our case, we will declare a custom deployment object by creating a deployment.yml
file in the jkube
folder. This custom deployment will override some properties to use the active version at deployment time.
A sample of this file could be similar to:
xxxxxxxxxx
metadata
name $ project.artifactId -$ app.bg.version
labels
group $ project.groupId
project $ project.artifactId
version $ project.version -$ app.bg.version
provider jkube
spec
template
spec
containers
env
name APP_BG_VERSION
value $ app.bg.version
To access the version deployed, a service is needed to map it. This service should be aligned with the right version. A service.yml
file in the jkube
folder similar to the next one could be similar to:
xxxxxxxxxx
metadata
name $ project.artifactId -$ app.bg.version
labels
group $ project.groupId
project $ project.artifactId
version $ project.version -$ app.bg.version
provider jkube
expose"true"
spec
selector
deploymentconfig $ project.artifactId -$ app.bg.version
Deploying the Blue Version
Now, we could easily deploy the Blue version by using the Maven Profile. For example, using the OpenShift Maven Plugin the command will be similar to:
xxxxxxxxxx
❯ mvn clean package oc:resource oc:build oc:apply -Pblue
Deploying the Green Version
Likewise, we can easily deploy the Green version using the Maven Profile. For example, using the OpenShift Maven Plugin the command will be similar to:
xxxxxxxxxx
❯ mvn clean package oc:resource oc:build oc:apply -Pgreen
Blue/Green Resources Deployed
This process generates the following objects:
- Image Streams for each version:
❯ oc get is
NAME IMAGE REPOSITORY TAGS UPDATED
kafka-clients-quarkus-sample-blue default-route-openshift-image-registry.apps-crc.testing/amq-streams-demo/kafka-clients-quarkus-sample-blue 1.0.0-SNAPSHOT,1.2.0-SNAPSHOT 38 hours ago
kafka-clients-quarkus-sample-green default-route-openshift-image-registry.apps-crc.testing/amq-streams-demo/kafka-clients-quarkus-sample-green 1.1.0-SNAPSHOT,1.3.0-SNAPSHOT 38 hours ago
- Build Config for each version:
xxxxxxxxxx
❯ oc get bc
NAME TYPE FROM LATEST
kafka-clients-quarkus-sample-blue-s2i Source Binary 4
kafka-clients-quarkus-sample-green-s2i Source Binary 2
- Deployments for each version:
xxxxxxxxxx
❯ oc get dc
NAME REVISION DESIRED CURRENT TRIGGERED BY
kafka-clients-quarkus-sample-blue 7 1 1 config,image(kafka-clients-quarkus-sample-blue:1.0.0-SNAPSHOT)
kafka-clients-quarkus-sample-green 5 1 1 config,image(kafka-clients-quarkus-sample-green:1.1.0-SNAPSHOT)
- Services for each version:
xxxxxxxxxx
❯ oc get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kafka-clients-quarkus-sample-blue ClusterIP 172.25.180.88 <none> 8181/TCP 38h
kafka-clients-quarkus-sample-green ClusterIP 172.25.87.170 <none> 8181/TCP 38h
Thanks to all of these objects, we can manage both versions at the same time, and in combination with a CD pipeline and other resources, can manage the traffic to activate the right version (Blue or Green) to the final users.
For example, we could have an OpenShift route to balance the application between each version. That route could be similar to:
xxxxxxxxxx
kind Route
apiVersion route.openshift.io/v1
metadata
name kafka-clients-quarkus-sample-lb
labels
app kafka-clients-quarkus-sample
spec
to
kind Service
name kafka-clients-quarkus-sample-blue
weight100
Rolling From Blue to Green
To roll from Blue to Green version, simply path the load balancer route (in the case of OpenShift) like so:
xxxxxxxxxx
❯ oc patch route kafka-clients-quarkus-sample-lb --type=merge -p '{"spec": {"to": {"name": "kafka-clients-quarkus-sample-green"}}}'
Rolling From Green to Blue
To roll from Green to Blue version, simply path the load balancer route (in the case of OpenShift) like so:
xxxxxxxxxx
❯ oc patch route kafka-clients-quarkus-sample-lb --type=merge -p '{"spec": {"to": {"name": "kafka-clients-quarkus-sample-blue"}}}'
Show Me the Code
If you want to test and verify this approach, I developed a sample case in one of my favorite GitHub repo. This repo includes amazing frameworks as Quarkus, Schemas Avro, and Apache Kafka in a small Event-Driven Architecture.
Enjoy it!
Published at DZone with permission of Roman Martin Gil. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments