How To Deploy and Use Quarkus in Kubernetes Cluster

Posted on 94 views

Welcome to this exhilarating tutorial on how to deploy and use Quarkus in Kubernetes. Kubernetes is one of the open-source tools currently preferred when automating system deployments. It makes it easy to scale and manage containerized applications.

Kubernetes works by distributing workloads across the cluster and automating the container networking needs. Also, storage and persistent volumes are allocated, by doing so the desired state of container applications is continuously maintained.

Quarkus offers provides an easy way to automatically generate the Kubernetes resources based on some defaults and the user-provided configuration. This Kubernetes-native Java framework also provides an extension used to build and push container images to a registry before the application is deployed to the target. Another feature about Quarkus is that it enabled one to use the Kubernetes ConfigMap as a configuration source without mounting them on the pod.

The cool features associated with Quarkus are:

  • Community and Standards: It provides a cohesive and fun-to-use full-stack framework by leveraging a growing list of over fifty best-of-breed libraries that you love and use
  • Container First: It offers amazingly fast boot time, incredibly low RSS memory (not just heap size!) offering near-instant scale-up and high density memory utilization in container orchestration platforms like Kubernetes
  • Unifies imperative and reactive: It allows developers to combine both the familiar imperative code and the reactive style when developing applications.
  • Kube-Native: The combination of Quarkus and Kubernetes provides an ideal environment for creating scalable, fast, and lightweight applications. It highly increases the developer productivity with tooling, pre-built integrations, application services e.t.c

By following this guide to the end, you will learn how to:

  • Use Quarkus Dekorate extension to automatically generate Kubernetes manifests based on the source code and configuration
  • Build and push images to Docker registry with Jib extension
  • Deploy an application on Kubernetes without any manually created YAML in one click
  • Use Quarkus Kubernetes Config to inject configuration properties from ConfigMap

Let’s dive in!

Setup Pre-requisites

For this guide, you will require:

  • Quarkus CLI
  • Apache Maven 3.8.1+ (Optional)
  • Access to a Kubernetes cluster

A Kubernetes cluster can be deployed with the aid of the guides below:

Once the cluster is running, install kubectl

curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin

Ensure that you can access the cluster.

# For k0s
export KUBECONFIG=/var/lib/k0s/pki/admin.conf

1. Install Quarkus CLI

The Quarkus CLI can be installed on Linux, macOS, and Windows (using WSL or bash compatible shell-like Cygwin or MinGW) by running the below commands:

curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/
curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force [email protected]

You can install it on Windows systems using the Powershell:

iex "&  $(iwr https://ps.jbang.dev)  trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/"
iex "&  $(iwr https://ps.jbang.dev)  app install --fresh --force [email protected]"

Once installed, restart your shell.

The Quarkus CLI can also be installed using SDKMAN as below:

sdk install quarkus

2. Create a Project

Use the Quarkus command-line interface (CLI) to create a new project. The below command adds resteasy-reactiveJib, and kubernetes dependencies.

quarkus create app quarkus-example --extension=resteasy-reactive,kubernetes,jib 
cd quarkus-example

Sample Output:

Deploy-and-Use-Quarkus-in-Kubernetes-696x355

After this, you will have several files generated, among these files is the pom.xml file bearing dependencies to the build file:

.........

    io.quarkus
    quarkus-resteasy-reactive


    io.quarkus
    quarkus-kubernetes


    io.quarkus
    quarkus-container-image-jib

......

The good thing with Quarkus is that it generates Deployment/StatefulSet resources that it use your registry_username/test-quarkus-app:tag as the container image of the Pod. The image here is controlled by the Jib extension and can be customized using the application.properties as shown:

Open the file for editing:

vim src/main/resources/application.properties

Add the following lines replacing where required.

quarkus.container-image.group=registry_username
quarkus.container-image.name=tutorial-app
quarkus.container-image.tag=latest
quarkus.container-image.username=registry_username
quarkus.container-image.password=Your_registry -Password

If no registry has not been specified, the default, docker.io registry will be used. A detailed demonstration on specifying a registry has been captured elsewhere in this guide.

3. Build and Deploy your Application

Jib is used to build optimized images for Java applications without a Docker daemon and no need for the mastery of deep docker practices. Dekorate is a Java library that makes it simple to generate and decorate Kubernetes manifests. It generates manifests based on the annotations, source code, and configuration variables.

Now build and deploy your application using Quarkus CLI:

quarkus build -Dquarkus.container-image.push=true

Sample Output:

Deploy-and-Use-Quarkus-in-Kubernetes-1-768x478

After the build process, you will have two files named kubernetes.json and kubernetes.yml under the target/kubernetes/ directory.

# ls target/kubernetes
kubernetes.json  kubernetes.yml

Both files contain both the Kubernetes Deployment and Service. For example, the kubernetes.yml file looks like this:

# cat target/kubernetes/kubernetes.yml
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-07-09 - 10:55:08 +0000
  labels:
    app.kubernetes.io/name: tutorial-app
    app.kubernetes.io/version: latest
  name: tutorial-app
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app.kubernetes.io/name: tutorial-app
    app.kubernetes.io/version: latest
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-07-09 - 10:55:08 +0000
  labels:
    app.kubernetes.io/version: latest
    app.kubernetes.io/name: tutorial-app
  name: tutorial-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/version: latest
      app.kubernetes.io/name: tutorial-app
  template:
    metadata:
      annotations:
        app.quarkus.io/build-timestamp: 2022-07-09 - 10:55:08 +0000
      labels:
        app.kubernetes.io/version: latest
        app.kubernetes.io/name: tutorial-app
    spec:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: registry_username/tutorial-app:latest
          imagePullPolicy: Always
          name: tutorial-app
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP

You will also have the image pushed to your registry. DockerHub for this example:

Deploy-and-Use-Quarkus-in-Kubernetes-2-768x276

It is possible to generate a StatefulSet resource instead of the default Deployment resource via the application.properties;

quarkus.kubernetes.deployment-kind=StatefulSet

Now deploy the application to your Kubernetes cluster using any of the two manifests. For example:

kubectl apply -f target/kubernetes/kubernetes.yml

Verify if the deployment is up:

# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
tutorial-app   1/1     1            1           13s

# kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
tutorial-app-bc774dc8d-k494g   1/1     Running   0          19s

Check if the service is running:

# kubectl get svc
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes     ClusterIP      10.96.0.1               443/TCP        31m
tutorial-app   LoadBalancer   10.102.87.114        80:30400/TCP   4m53s

Access the deployment using the provided port 30400. This can be done using a web browser with the URL http://IP_Address:30400/hello

Deploy-and-Use-Quarkus-in-Kubernetes-3

Or from the terminal as shown:

$ curl 192.168.205.4:30400/hello
Hello from RESTEasy Reactive

This is the output of the file at src/main/java/org/acme/GreetingResource.java

4. Tuning the generated resources using application.properties

Quarkus allows one to tune the generated manifest using the application.properties file. Through this file, several configurations can be made. These include:

A. Namespace

Quarkus allows one to run the application in a chosen namespace. It omits the namespace in the generated manifest rather than enforcing it in the default namespace.

Therefore, you can run the application in the desired namespace say test using the command:

kubectl apply -f target/kubernetes/kubernetes.yml -n=test

Aside from specifying the namespace when running the Kubernetes command, you can still capture the namespace in the application.properties as shown:

quarkus.kubernetes.namespace=mynamespace

Replace mynamespace with the desired namespace for the application.

B. Defining a Docker registry

There are several other registries that can be defined. If left undefined, docker.io is used. If you want ot use another registry such as quay.io, then you need to specify it:

quarkus.container-image.registry=my.docker-registry.net

my.docker-registry.net is the registry you want to use.

C. Environment variables

There are several ways of defining variables on Kubernetes. These includes:

  • key/value pairs
  • import all values from a Secret or ConfigMap
  • interpolate a single value identified by a given field in a Secret or ConfigMap
  • interpolate a value from a field within the same resource

Environment variables from key/value pairs

To add environment variables from key/value pairs, use the below syntax:

quarkus.kubernetes.env.vars.my-env-var=foobar

This adds MY_ENV_VAR=foobar as an environment variable. my-env-var is converted to uppercase and the dashes are replaced with underscores to result in MY_ENV_VAR.

Environment variables from Secret

To add key/value pairs of Secret as environment variables, add the lines below to application.properties:

quarkus.kubernetes.env.secrets=my-secret,my-other-secret

This will result in the following in the container environment:

envFrom:
  - secretRef:
      name: my-secret
      optional: false
  - secretRef:
      name: my-other-secret
      optional: false

You can set the variable by extracting a value defined by keyName form the my-secret:

quarkus.kubernetes.env.mapping.foo.from-secret=my-secret
quarkus.kubernetes.env.mapping.foo.with-key=keyName

Resulting into:

- env:
  - name: FOO
    valueFrom:
      secretKeyRef:
        key: keyName
        name: my-secret
        optional: false

Environment variables from ConfigMap

Quarkus can be used to add key/value pairs from ConfigMap as environment variables. To achieve this, you need to add the lines below separating the ConfigMap to be used as a source by a comma. For example:

quarkus.kubernetes.env.configmaps=my-config-map,another-config-map

This will result into:

envFrom:
  - configMapRef:
      name: my-config-map
      optional: false
  - configMapRef:
      name: another-config-map
      optional: false

It is also possible to extract keyName field from the my-config-map by using:

quarkus.kubernetes.env.mapping.foo.from-configmap=my-configmap
quarkus.kubernetes.env.mapping.foo.with-key=keyName

This will generate a manifest with the below lines:

- env:
  - name: FOO
    valueFrom:
      configMapRefKey:
        key: keyName
        name: my-configmap
        optional: false

That is it!

Closing Thoughts

That summarizes this guide on how to deploy and use Quarkus in Kubernetes. I am sure that you are now in a position to generate the Kubernetes resources based on some defaults and the user-provided configuration using Quarkus. I hope this was valuable.

coffee

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.