Release of WildFly Operator 0.4.1
The WildFly Operator helps deploy and manage WildFly applications on Kubernetes and OpenShift.
With the recently released 0.4.1 version, the WildFly Operator is now able to provide seamless upgrades of your application on OpenShift.
Note
|
This feature is specific to OpenShift as it relies on resources such as ImageStreams that are not provided by vanilla Kubernetes.
|
The WildFly operator was using the applicationImage
field to identify and deploy your application on the container platform.
This field accepts different types:
-
the name of the image: quay.io/jmesnil/wildfly-demo-app:step-1
-
a tag: quay.io/jmesnil/wildfly-demo-app:step-1
-
a digest: quay.io/wildfly-quickstarts/wildfly-operator-quickstart@sha256:0af38bc38be93116b6a1d86a9c78bd14cd527121970899d719baf78e5dc7bfd2
In all these cases, the container platform would pull the image when the application is deployed and uses it for the whole application lifecycle.
If you wanted to deploy a new image, you had to edit the applicationImage
manually and specify the checksum of the new image to deploy.
Now, with the 0.4.1 release, the WildFly Operator also accepts an ImageStreamTag
for its applicationImage
field, for example wildfly-demo-app:latest
.
This imagestream tag must belong to an ImageStream
in the same namespace than the application. With that simple setting, any changes to the imagestream tag will trigger a new deployment of the application without having to modify any resources.
Note
|
This article does not provide an extensive explanation on how Images are managed by OpenShift with ImageStreams and ImageStreamTags. Please refer to the OpenShift documentation for a complete description. |
Create a Demo application
To illustrate this feature, I wrote a very simple MicroProfile application that return a JSONified version of "Hello, World!": https://github.com/jmesnil/wildfly-operator-demo-app
@Path("/")
@ApplicationScoped
public class AppEndpoint {
@Inject
@ConfigProperty(name = "greetings", defaultValue = "Hello")
String greetings;
@GET
@Produces({ "application/json" })
public String getText() {
String text = "{\"text\":\"" + greetings + ", World!\"}";
return text;
}
}
As the application has access to the full MicroProfile APIs (including MicroProfile Config), it is possible to configure the greetings returned by the application by setting the greetings
config property (which defaults to "Hello"
).
It can be configured using an environment variable named GREETINGS
.
I have built a Docker image of this application and pushed it to quay.io/jmesnil/wildfly-demo-app:step-1
.
You can run it directly from Docker:
$ docker run -p 8080:8080 -e GREETINGS=Bonjour quay.io/jmesnil/wildfly-demo-app:step-1
...
$ curl http://localhost:8080
{"text":"Bonjour, World!"}
Note
|
I created this Docker image from the
|
To show how we can seamlessly upgrade to a new version of this application, I created a second image of the application corresponding to the step-2
tag where the text is now returned in uppercase:
public String getText() {
String text = "{\"text\":\"" + (greetings + ", World!").toUpperCase() + "\"}";
return text;
}
This second image is pushed to quay.io/jmesnil/wildfly-demo-app:step-2
and can also be run directly from Docker:
$ docker run -p 8080:8080 -e GREETINGS=Ahoj quay.io/jmesnil/wildfly-demo-app:step-2
...
$ curl http://localhost:8080
{"text":"AHOJ, WORLD!"}
Install the WildFly Operator on OpenShift
We will first install the WildFly Operator on OpenShift in a new project named wildfly-demo
First, we create the new project (and the corresponding namespace):
$ oc new-project wildfly-demo
Then we install a CatalogSource
to get access to the WildFly Operator that is in the operatorhub.io catalog:
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: operatorhub-io
spec:
displayName: Operators from operatorhub.io
image: quay.io/operatorhubio/catalog:latest
sourceType: grpc
We install it by running:
$ oc apply -f operatorhub-io-catalogsource.yaml
catalogsource.operators.coreos.com/operatorhub-io created
Then we create a subscription for the current version (0.4.1) of the WildFly Operator:
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: wildfly
labels:
operators.coreos.com/wildfly.wildfly-demo: ''
spec:
channel: alpha
installPlanApproval: Automatic
name: wildfly
source: operatorhub-io
sourceNamespace: wildfly-demo
startingCSV: wildfly-operator.v0.4.1
Again, we install it on OpenShift by running:
$ oc apply -f wildfly.yaml
subscription.operators.coreos.com/wildfly created
We will then wait until the WildFly Operator is installed by monitoring its installation:
$ oc get csv -w
NAME DISPLAY VERSION REPLACES PHASE
wildfly-operator.v0.4.1 WildFly 0.4.1
wildfly-operator.v0.4.1 WildFly 0.4.1 Pending
...
wildfly-operator.v0.4.1 WildFly 0.4.1 InstallReady
...
wildfly-operator.v0.4.1 WildFly 0.4.1 Installing
...
wildfly-operator.v0.4.1 WildFly 0.4.1 Succeeded
Note
|
For the purpose of this example, the WildFly Operator is only be installed in the current |
Create an ImageStream
Before we can deploy our application on OpenShift using the WildFly Operator, we will first create
an ImageStream
named wildfly-demo-app
that will contain a stream of all our application images
$ oc import-image wildfly-demo-app:step-1 \
--from quay.io/jmesnil/wildfly-demo-app:step-1 \
--confirm
We have added the wildfly-demo-app:step-1
imagestream tag to this imagestream by importing the Docker image from quay.io/jmesnil/wildfly-demo-app:step-1
.
Then we tag it with the latest
tag that will be referenced from our deployments.
$ oc tag wildfly-demo-app:step-1 wildfly-demo-app:latest
At this point, we have an ImageStreamTag
wildfly-demo-app:latest
that we can use to deploy our application and upgrade it later seamlessly.
We have finally the image inside OpenShift and are ready to deploy our application.
Deploy the Application
To deploy the application, we create a WildFlyServer
resource with the applicationImage
set to wildfly-demo-app:latest
.
This will let OpenShift pull the image from the latest
imagestream tag in the wildfly-demo-app
imagestream.
apiVersion: wildfly.org/v1alpha1
kind: WildFlyServer
metadata:
name: wildfly-app
spec:
applicationImage: 'wildfly-demo-app:latest'
env:
- name: GREETINGS
value: Guten Tag
replicas: 2
$ oc apply -f wildfly-app.yaml
wildflyserver.wildfly.org/wildfly-app created
The WildFly Operator will then configure and deploy the application on OpenShift.
It will also automatically create a Route
to access it outside of the cluster.
The application is thoroughly described by the oc describe
command:
Name: wildfly-app
Namespace: wildfly-demo
Kind: WildFlyServer
Metadata:
...
Spec:
Application Image: wildfly-demo-app:latest
Env:
Name: GREETINGS
Value: Guten Tag
Replicas: 2
Status:
Hosts:
wildfly-app-route-wildfly-demo.apps.jmesnil-80cs.eapqe.psi.redhat.com
Pods:
Name: wildfly-app-0
Pod IP: 10.128.2.199
State: ACTIVE
Name: wildfly-app-1
Pod IP: 10.128.2.200
State: ACTIVE
Replicas: 2
Scalingdown Pods: 0
Events: <none>
The only information we need is the hosts
field that contains the public URL of our application.
If we access it, we can get our text message:
$ curl http://$(oc get wfly/wildlfy-app -o jsonpath="{.status.hosts[0]}")
{"text":"Guten Tag, World!"}
Seamless Upgrade to a New Version of the Application Image
We now want to deploy the second version of our application without disrupting our services. We can take advantage of seamless upgrades to do it.
First, we will import the quay.io/jmesnil/wildfly-demo-app:step-2
image in the wildfly-demo-app
imagestream with the step-2
tag:
$ oc import-image wildfly-demo-app:step-2 \
--from quay.io/jmesnil/wildfly-demo-app:step-2 \
--confirm
At this point, nothing has changed, the image is available in OpenShift but the WildFly Operator will not use it as it only references the wildfly-demo-app:latest
imagestream tag.
Let’s now change this latest
tag to point to the wildfly-demo-app:step-2
tag.
$ oc tag wildfly-demo-app:step-2 wildfly-demo-app:latest
Tag wildfly-demo-app:latest set to wildfly-demo-app@sha256:a9970ab8cebad210d7248e090ea88d6af87e8f910c7a087a3aac03c951cd764e.
Once this is done, OpenShift will observe that the latest
tag has changed (it corresponds to a new image) and will notify the WildFly Operator to trigger a new deployment
of the application.
If you continue to access the public route of the application, you will see that it will eventually return the upper case version of the text:
$ curl http://$(oc get wfly/wildlfy-demo-app -o jsonpath="{.status.hosts[0]}")
{"text":"GUTEN TAG, WORLD!"}
It can take some time as OpenShift will terminate and redeploy all the Pods that runs the application.
Image Build Pipeline
This short demo illustrates that it is now possible to seamlessly upgrade an application maintained by the WildFly Operator by using an imagestream tag to refer to the application image.
To illustrate this, we did a step-by-step demo to understand how and when the upgrade is triggered. However, in normal use, most of these steps are automated and the upgrade becomes really seamless (and do not require user intervention).
There is a lot more that can be achieved by taking full advantage of the OpenShift ecosystem to build and deploy images.
I have built the application image using S2I outside of OpenShift but it is possible to use BuildConfig
resources to build the image inside OpenShift and automatically tag them with the latest
imagestream tag.
Using BuildConfig
to build the images has two main benefits:
-
You can specify hooks to trigger building new images when the code from a remote Git repository is updated.
-
You can also trigger building new images when WildFly S2I images are upgraded. In that case, seamless upgrades apply not only to the application image but also to the WildFly S2I images that are used to build the application image.
In a more realistic example, we could have a staging cluster with a BuildConfig
that would trigger new application images when the code is updated (or when a new Git tag is pushed to a remote repository) or when new WildFly S2I images are released.
This would automatically trigger a test pipeline to test and verify the new application image.
Once this new application image has been validated (automatically or manually), we can then push this new application image in our production cluster and tag it with latest
to trigger an upgrade of the application in production.
Summary
When it is running on OpenShift, the WildFly Operator can leverage its ecosystem around Images to provide seamless upgrades of applications to trigger new deployments when anything in the build pipeline (application code or WildFly images) changes. This simplifies application maintenance and reduces security risks by automating the upgrades and making sure that the application is always built on top of the latest application code and WildFly images.