This tutorial explores how you can deploy Quarkus applications in containers and, more specifically, on OpenShift Paas Cloud platforms There are different approaches to deploy Quarkus applications on OpenShift. In this tutorial we will discuss them in detail.
Start by checking out this example, which is an example of JAX-RS application which uses Hibernate ORM API to persist data on a PostgreSQL database:
https://github.com/fmarchioni/mastertheboss/tree/master/quarkus/hibernate-advanced
If you have a look at the directory folder of the example, you will see that it contains the standard structure of all Quarkus applications, which includes a folder src/main/docker with two Dockerfile, one for building JVM based Container images and another one for building native Container images:
src
├── main
│ ├── docker
│ │ ├── Dockerfile.jvm
│ │ ├── Dockerfile.native
│ ├── java
│ │ └── com
│ │ └── packt
│ │ └── quarkus
│ │ └── chapter5
│ │ ├── CustomerEndpoint.java
│ │ ├── CustomerException.java
│ │ ├── Customer.java
│ │ ├── CustomerRepository.java
│ │ ├── OrderEndpoint.java
│ │ ├── OrderRepository.java
│ │ └── Orders.java
│ └── resources
│ ├── application.properties
│ ├── import.sql
│ └── META-INF
To have a quick run of this example on OpenShift, we recommend using Red Hat Code Ready Containers, which are introduced in this tutorial: Getting started with Code Ready Containers
Setting up OpenShift
Before you start CRC, it is required to increase the amount of memory assigned to the CRC process to 16GB, otherwise you won't be able to run the S2I builder process which is quite memory and CPU intensive:
$ crc config set memory 16384
Now start CRC with:
$ crc start
When your OpenShift cluster is ready, check that you are able to connect, using the credentials which have been printed on the Console:
$ oc login -u kubeadmin -p kKdPx-pjmWe-b3kuu-jeZm3 https://api.crc.testing:6443
You should be now logged into the default project. Let's create a new project for our application:
$ oc new-project quarkus
The first application we need to add to our project, is PostgreSQL database. We will create it using the 'oc' command line as follows, which allows setting the username/password/database attributes in one line:
$ oc new-app -e POSTGRESQL_USER=quarkus -e POSTGRESQL_PASSWORD=quarkus -e POSTGRESQL_DATABASE=quarkusdb postgresql
The postgresql image will be pulled from the default repository and in a minute or so you should be able to check:
oc get pods
NAME READY STATUS
postgresql-1-xdlwt 1/1 Running
Ok so now we need to plug into the Quarkus application. We can do it in several ways:
- Creating a Binary build of your application and uploading content in it from the local folder
- Using JKube Maven plugin to generate the Docker image, Kubernetes manifest and deploy to OpenShift.
Let's check them in detail.
Deploying Quarkus applications from your local folder as Binary Build
When using this approach, you will build your application locally, then create a Build Configuration and upload the content from your local folder. This approach is ideal if you have an overloaded Cloud environment but you have plenty of CPU/RAM on your Host machine. On the other hand, you will need to have installed all the required stuff to build a native Quarkus application, that is:
- GRAAL_VM 19.2.0 to build native executables with the "native-image" tool
- Maven 3.6.3
Start by building the native image for your application:
mvn package -Pnative -Dnative-image.docker-build=true -DskipTests=true
When done, create a new Binary Build named "quarkus-hibernate"
oc new-build --binary --name=quarkus-hibernate -l app=quarkus-hibernate
Next, set the dockerfilePath attribute into the Build Configuration
oc patch bc/quarkus-hibernate -p '{"spec":{"strategy":{"dockerStrategy":{"dockerfilePath":"src/main/docker/Dockerfile.native"}}}}'
Then, start the build, uploading content from the local folder:
oc start-build quarkus-hibernate --from-dir=. --follow
As soon as the build has completed, create a new OpenShift Application, using as Input the "quarkus-hibernate" Image Stream:
oc new-app --image-stream=quarkus-hibernate:latest
Expose the Service through a Route:
oc expose svc/quarkus-hibernate
Now verify that your hibernate-demo Pod is up and running:
oc get pods
NAME READY STATUS
hibernate-demo-1-rftfm 1/1 Running
postgresql-1-xdlwt 1/1 Running
Check which is the application route:
oc get routes
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
hibernate-demo hibernate-demo-quarkus.apps-crc.testing hibernate-demo 8080-tcp None
You can reach that route from the browser and verify that the application is running:
Let's see now how to use the JKube Maven plugin to deploy our application on OpenShift.
Deploying Quarkus on OpenShift using JKube Maven plugin
JKube Maven plugin is the successor of the dedprecated fabric8 Maven plugin and can be used for building container images using Docker, JIB or S2I build strategies. Eclipse JKube generates and deploys Kubernetes/OpenShift manifests at compile time too.
Using this plugin is straightforward: we recommend adding a profile for deploying applications to openshift:
<profile>
<id>openshift</id>
<properties>
<jkube.generator.quarkus.nativeImage>
true
</jkube.generator.quarkus.nativeImage>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>openshift-maven-plugin</artifactId>
<version>${jkube.version}</version>
<executions>
<execution>
<goals>
<goal>resource</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<enricher>
<config>
<jkube-service>
<type>NodePort</type>
</jkube-service>
</config>
</enricher>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
This profile includes the openshift-maven-plugin, which can be enriched adding extra services such as NodePort for remote access of the service.
To deploy the native application on OpenShift, make sure you have built the native image:
mvn package -Pnative -Dnative-image.docker-build=true -DskipTests=true
Now you can build the Docker image, generate the Kubernetes Manifests and apply then to Cluster as follows:
mvn oc:build oc:resource oc:apply
You will see from your Console logs that the application has been deployed:
[INFO] oc: OpenShift platform detected
[INFO] oc: Using project: quarkus
[INFO] oc: Creating a Service from openshift.yml namespace quarkus name hibernate-advanced
[INFO] oc: Created Service: target/jkube/applyJson/quarkus/service-hibernate-advanced.json
[INFO] oc: Creating a DeploymentConfig from openshift.yml namespace quarkus name hibernate-advanced
[INFO] oc: Created DeploymentConfig: target/jkube/applyJson/quarkus/deploymentconfig-hibernate-advanced.json
[INFO] oc: Creating Route quarkus:hibernate-advanced host: null
[INFO] oc: HINT: Use the command `oc get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Check tat Pods are available:
$ oc get pods
NAME READY STATUS RESTARTS AGE
hibernate-advanced-1-9bwjt 1/1 Running 0 15m
hibernate-advanced-1-deploy 0/1 Completed 0 15m
hibernate-advanced-s2i-1-build 0/1 Completed 0 16m
postgresql-1-4hs7z 1/1 Running 3 22m
postgresql-1-deploy 0/1 Completed 0 22m
From the Pod log you can verify that the native application is up and running:
oc logs hibernate-advanced-1-9bwjt
QUARKUS_OPTS environment variable was not set, using default values of -Xmx24M -Xms16M -Xmn24M
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-01-03 09:27:56,101 INFO [io.agr.pool] (main) Datasource '<default>': Initial size smaller than min. Connections will be created when necessary
. . . . .
Hibernate:
INSERT INTO customer (id, name, surname) VALUES ( nextval('customerId_seq'), 'John','Doe')
Hibernate:
INSERT INTO customer (id, name, surname) VALUES ( nextval('customerId_seq'), 'Fred','Smith')
2021-01-03 09:27:56,180 INFO [io.quarkus] (main) hibernate-advanced 1.0-SNAPSHOT native (powered by Quarkus 1.10.5.Final) started in 0.097s. Listening on: http://0.0.0.0:8080
2021-01-03 09:27:56,181 INFO [io.quarkus] (main) Profile prod activated.
2021-01-03 09:27:56,181 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-postgresql, mutiny, narayana-jta, resteasy, resteasy-jsonb, smallrye-context-propagation]
And finally, gather the Route so that you can access the application:
oc get routes
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
hibernate-demo hibernate-demo-quarkus.apps-crc.testing hibernate-demo 8080 None