Quarkus & KNative— An Attempt

Roudranil Roy
5 min readMay 30, 2022

--

For those of you who are new to Quarkus, its “A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.” Arguably Quarkus has brought the community interest back from NodeJs or Go, to Java. Read more.

In this article I’ll walk you through my journey in pursuit of pure KNative joy.

Table of Contents:

A. Setup Local environment

  1. Install GRAALVM [Official Guide].
  2. Setup IntelliJ Idea [Official Guide]

B. Code , Build & Test

[ Full Source Code ]

  1. Setup Quarkus Starter Code. Modify Group, Artifact, Version as per your needs. [Link ]
My Quarkus Starter Configruation

I chose Gradle as my build tool over maven because of two primary reasons. (1) I personally find Gradle to be easier to work with than Maven. (2) There are disproportionately high number of guides out there on Quarkus + Maven than Quarkus + Gradle.

4. Run Initial Build and check Output.

roudra$ ./gradlew clean build
Starting a Gradle Daemon (subsequent builds will be faster)
[WARN] Could not detect project version. Using 'latest'.
[INFO] Checking for existing resources in: /Users/roudra/Projects/Git/punctual-phoenix/src/main/kubernetes.
BUILD SUCCESSFUL in 21s
9 actionable tasks: 9 executed

5. Run server locally.

$ ./gradlew quarkusDev> Task :quarkusDev
Listening for transport dt_socket at address: 5005
[WARN] Could not detect project version. Using ‘latest’.
Press [h] for more options>
Tests paused
Press [r] to resume testing, [h] for more options>
Press [r] to resume testing, [o] Toggle test output, [h] for more options>
[INFO] Checking for existing resources in: /Users/roudra/Projects/Git/punctual-phoenix/src/main/kubernetes.
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2022–05–30 16:41:31,728 INFO [io.quarkus] (Quarkus Main Thread) punctual-phoenix 1.0.7 on JVM (powered by Quarkus 2.9.2.Final) started in 3.563s. Listening on: http://localhost:8080
2022–05–30 16:41:31,732 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2022–05–30 16:41:31,732 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui, vertx]

6. Navigate to http://localhost:8080

C. Deploy on Cloud — QUarkus JVM on OpenShift

I’m using Redhat Dev Sandbox. You can choose any other provider of your choice or use Minikube if you want to maintain a cluster in local.

  1. Request for Dev Sandbox. [Guide]
  2. Setup CI/CD. I’m using GitHub actions (because it’s pretty good). [Sample File]

3. Check deployment.

Deployment, Service, Route, Pod
Server Startup Logs
Running on Server.

D. Deploy on Cloud — QUarkus Native on OpenShift

Switching from JVM Mode to Native mode is pretty easy.

(a) install Native Image plugin for GRAALVM

- name: 'Setup GraalVM Environment'
uses: DeLaGuardo/setup-graalvm@5.0
with:
graalvm: '22.0.0.2'
java: 'java11'
- name: 'Install Native Image Plugin'
run: gu install native-image

(b) add arguments to build native image.

- name: 'Build Quarkus Native JAR'
run: |
./gradlew clean build -x test -Dquarkus.package.type=native -Dquarkus.native.container-build=true

this should generate “runner” file.

(c) Use docker for native to build docker.

./src/main/docker/Dockerfile.native---- docker code ----
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5
WORKDIR /work/
RUN chown 1001 /work \
&& chmod "g+rwX" /work \
&& chown 1001:root /work
COPY --chown=1001:root build/*-runner /work/application

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

Since I’m running in PROD mode with native executable, the DEV-UI & Swagger UI are not available.To Enable add the below properties and redeploy

quarkus.swagger-ui.always-include=true
Swagger UI accessible from http://host:port/q/swagger-ui/#/

E. Deploy on Cloud — KNative (Service and Eventing)

At this point, to turn the application to a KNative service instead of traditional OSE Service, I simply

(a) Add Kubernetes plugin to build.gradle.

implementation ‘io.quarkus:quarkus-kubernetes’

(b) Add the following properties to application.properties

== application.properties == #Kubernetes
quarkus.kubernetes.deployment-target=knative
quarkus.kubernetes.namespace=rr42724-dev
quarkus.kubernetes.version=1.0.10
quarkus.kubernetes.replicas=2
quarkus.kubernetes.readiness-probe.initial-delay=20s
quarkus.kubernetes.readiness-probe.period=45s

quarkus.swagger-ui.always-include=true

quarkus.container-image.group=roudra
quarkus.container-image.registry=ghcr.io
quarkus.container-image.name=punctual-phoenix-kn-native

With ./gradlew build command the following files get generated

(c) Run KubeCtl with the knative.yml as argument to generate Kubernetes Servicing.

== workflow-action.yml ==
instead of ...
- name: Create and expose app
id: deploy-and-expose
uses: redhat-actions/oc-new-app@v1
use ...
- name: Create Kubernetes Serving
id: deploy-and-expose
run: |
kubectl apply -f ./build/kubernetes/knative.yml

Github Actions File [Sample]

--

--