Introduction

Quarkus simplifies the deployment of applications as serverless services on OpenShift with a very classy extension called the quarkus-openshift extension. The traditional source-to-image (S2I) source workflow generates the deployable artifacts of the applications inside OpenShift. However, the quarkus-openshift extension uses the S2I binary workflow to provide a more streamlined deployment process. So, instead of building from the source, the extension uses either a JAR file or a native executable from the local file system. As a result, the build process for a Quarkus application is relatively faster than a traditional S2I method. This extension can be used when deploying the applications either from a local machine or from a build server or continuous integration (CI) system to perform repeatable builds. Since this extension uses the S2I binary workflow, this extension will push the serverless application image into the OpenShift’s internal image registry by default. 

So, suppose there is a need to leverage an external enterprise image registry like Quay, for example. In that case, this extension can still help up to the point where it can create the native image, and then the image can be pushed to an external image registry of choice. Then, the Knative kn CLI can be used to create the Knative service for the serverless application on OpenShift.

Creating serverless service using quarkus-openshift extension

To build and run a Quarkus application as a serverless application, first, the quarkus-openshift extension has to be added as a dependency to the Quarkus project’s pom.xml: 

   <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-openshift</artifactId>
  </dependency>

Then, to create a serverless service for the Quarkus application, the properties given below are to be added to the application.properties file of the Quarkus project. With these properties set, the quarkus-openshift extension would automatically create the required set of artifacts to run the Quarkus application as a serverless service on OpenShift: 

quarkus.kubernetes.deployment-target=knative
quarkus.openshift.build-strategy=docker
quarkus.kubernetes-client.trust-certs=true
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000
quarkus.container-image.group=quarkus-serverless
quarkus.native.container-build=true
quarkus.native.container-runtime=docker
quarkus.openshift.native-dockerfile=Dockerfile.native

Here is a short note on each of these properties:

  • quarkus.kubernetes.deployment-target - Setting this value to “knative” would enable the creation of deployment descriptors for serverless / Knative Serving by the quarkus-openshift extension.
  • quarkus.openshift.build-strategy - indicates the build configuration strategy that has to be used in OpenShift to build the application image. It should be set to “docker.”
  • Quarkus.kubernetes-client.trust-certs - indicates whether or not the client should trust a self-signed certificate presented by the OpenShift API server. It should be set to “true” if the OpenShift API server uses an untrusted/self-signed certificate.
  • quarkus.container-image.registry - to specify the image registry from which OpenShift Serverless should pull the container image from.
  • quarkus.container-image.group - by default, the extension assumes that the project name from which the container image should be pulled to be the same as the username of the host system from which the deployment is triggered. So, to specify the project that contains the image stream for the Quarkus serverless application, the value for this property has to be set with the correct project name that would contain the container image stream.
  • Two properties listed below are to be set to get the Quarkus application compiled to a native executable: 
  • quarkus.native.container-build - to indicate if the native container build should be triggered. It should be set to “true” to enable a native container build.
  • quarkus.native.container-runtime - to set the container runtime that should be used to build the native executable. The value for this property should be either “docker” or “podman.

One may wonder about the need to have GraalVM generate a native executable for a Quarkus application. However, the GraalVM setup is no longer required as the quarkus-openshift extension will use the Red Hat-provided base image for Mandrel to create a native executable. (Mandrel is a downstream release of GraalVM, focused on native image creation for Quarkus applications). The quarkus-openshift extension will automatically pull the relevant Mandrel image from Red Hat’s image registry (https://registry.redhat.io) and use it for the native executable creation.

  • Finally, the property quarkus.openshift.native-dockerfile helps to specify a custom Dockerfile that should be used to build the container image for the native executable created using Mandrel. Here is a sample Dockerfile that uses the Red Hat-provided “ubi-minimal” base image to build the final container image and set appropriate permissions: 
## Create the final image
FROM registry.access.redhat.com/ubi8/ubi-minimal
WORKDIR /work/
COPY target/*-runner /work/application
# set up permissions for user `1001`
RUN chmod 775 /work /work/application \
&& chown -R 1001 /work \
&& chmod -R "g+rwX" /work \
&& chown -R 1001:root /work
EXPOSE 8080
USER 1001
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

With all of these properties set, executing a Maven build (with relevant parameters, as shown below) will create a native executable for the Quarkus application and the deployment of the application as a serverless application into OpenShift:

mvn clean package -DskipTests=true -Pnative -Dquarkus.kubernetes.deploy=true

To see the quarkus-openshift extension in action, here is a demonstration that shows how this extension enables the deployment of a Sales Order maintenance application as a serverless service.

Using an external image registry

To use an external image registry (instead of OpenShift’s internal image registry) to host the serverless application container image, the Quarkus serverless application should first be built with Maven (as shown below) to create the native executable:

`mvn clean package -DskipTests=true -Pnative

Then, a container image for the generated native executable should be created using the same Dockerfile that was used earlier. For example:

podman build -t <<reg-url>>/<<repo-name>>/<<image-name>>:<<version>> -f Dockerfile.native .

The container image could then be pushed to an external registry using podman or docker:  

podman push <<reg-url>>/<<repo-name>>/<<image-name>>:<<version>>

Finally, the Knative kn CLI could be used to create the serverless service for the application on OpenShift:. 

kn service create <<app-name>> --image quay.io/<<repo-name>>/<<image-name>>:<<version>>

Here is a quick demonstration that puts these pieces together and shows how a Quarkus serverless application could be deployed from an external image registry. 


About the author