Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 19fv2

Quarkus – Supersonic Subatomic Java, trying out Quarkus guide “Quarkus – Kubernetes extension”  (reinvestigated, part 1)

In my previous article, I shared with you the steps I took, to set up a demo environment, so I could get started with Quarkus.
[https://technology.amis.nl/software-development/java/quarkus-supersonic-subatomic-java-get-started-reinvestigated/]

After the “ Get Started” part, I now focused on one of the mentioned “Next Steps”, “Deploying Quarkus Applications on Kubernetes”, with the following content:

This guide covers how to deploy a native application on Kubernetes.
Want to learn more? Check out the guides to continue your journey.
[https://quarkus.io/get-started/]

In this article, you can read more about the Quarkus code guide I tried out again (after some years), related to the following topic:
• The ability to automatically generate Kubernetes resources by Quarkus

You can also read about all the steps I took to further set up my demo environment and meet the requirements for the Quarkus guide “Quarkus – Kubernetes extension”, such as, In my case, installing OpenJDK JDK 24 and Apache Maven 3.9.9. For the Kubernetes cluster, I installed K3s (a lightweight certified Kubernetes distribution) and a Kubernetes Dashboard.

Quarkus guide “Quarkus – Kubernetes extension”

From the Quarkus “Get Started”, part “What’s next?”, I clicked on the link “Deploying Quarkus Applications on Kubernetes”.
[https://quarkus.io/get-started/]

Quarkus offers the ability to automatically generate Kubernetes resources based on sane defaults and user-supplied configuration using dekorate. It currently supports generating resources for vanilla Kubernetes, OpenShift and Knative. Furthermore, Quarkus can deploy the application to a target Kubernetes cluster by applying the generated manifests to the target cluster’s API Server. Finally, when either one of container image extensions is present (see the container image guide for more details), Quarkus has the ability to create a container image and push it to a registry before deploying the application to the target platform.
[https://quarkus.io/guides/deploying-to-kubernetes]

Looking at the prerequisites, first I had to prepare my demo environment.

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 20

What I still needed was:

  • Apache Maven 3.9.9
  • Access to a Kubernetes cluster

As you could read in my previous article about Quarkus, JBang was already installed, nevertheless I also opted for installing a JDK. I choose to download and install the latest open-source JDK. Oracle’s free, GPL-licensed, production-ready OpenJDK JDK 24 binaries for Linux, macOS, and Windows, which are available at jdk.java.net/24;

As I did before, for the Kubernetes cluster I used K3s (a lightweight certified Kubernetes distribution)
[https://k3s.io/]

As I mentioned in my previous article, some years ago, I wrote a series of articles about Quarkus.
Then I also had a look at the Quarkus Kubernetes Extension, and I described how a set up a demo environment. Of course I had a look it also.

Feel free, to read:

First, I execute a number of the installation steps manually, but later on I will try to further automate the set up of my demo environment as much as possible, using Vagrant and shell scripts.

In my existing demo environment, created when I wrote my previous article, I changed the content of the Vagrantfile to:
[in bold, I highlighted the changes]

Vagrant.configure("2") do |config|
  config.vm.box = "generic/ubuntu2204"
  
  config.vm.define "ubuntu_quarkus_k3s" do |ubuntu_quarkus_k3s|
  
    config.vm.synced_folder "C:\\My\\AMIS\\MySharedFolder", "/mnt/mysharedfolder", automount: true
    
    config.vm.network "forwarded_port",
      guest: 8001,
      host:  8001,
      auto_correct: true
      
   config.vm.network "forwarded_port",
      guest: 8080,
      host:  8080,
      auto_correct: true
      
   config.vm.network "forwarded_port",
      guest: 8090,
      host:  8090,
      auto_correct: true
      
   config.vm.network "forwarded_port",
      guest: 8443,
      host:  8443,
      auto_correct: true
      
    config.vm.provider "virtualbox" do |vb|
        vb.name = "Ubuntu Quarkus"
        vb.memory = "8192"
        vb.cpus = "1"
        
      args = []
      config.vm.provision "quarkus shell script", type: "shell",
          path: "scripts/quarkus.sh",
          args: args
          
    end
    
  end

end

Installing a JDK

In order to install a JDK, I visited the website: https://openjdk.org/

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 21

Download and install the latest open-source JDK. Oracle’s free, GPL-licensed, production-ready OpenJDK JDK 24 binaries for Linux, macOS, and Windows are available at jdk.java.net/24; Oracle’s commercially-licensed JDK 24 binaries, based on the same code, are here.

From there I clicked on the link “jdk.java.net/24”.

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 22

From this page I copied the url: https://download.java.net/java/GA/jdk24.0.1/24a58e0e276943138bf3e963e6291ac2/9/GPL/openjdk-24.0.1_linux-x64_bin.tar.gz

I also had a look at the “Installation” page.

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 23

To download the tar.gz file, I used the following command on the Linux Command Prompt:

cd /tmp
wget https://download.java.net/java/GA/jdk24.0.1/24a58e0e276943138bf3e963e6291ac2/9/GPL/openjdk-24.0.1_linux-x64_bin.tar.gz

With the following output:

--2025-05-14 17:14:48--  https://download.java.net/java/GA/jdk24.0.1/24a58e0e276943138bf3e963e6291ac2/9/GPL/openjdk-24.0.1_linux-x64_bin.tar.gz
Resolving download.java.net (download.java.net)... 23.220.112.104
Connecting to download.java.net (download.java.net)|23.220.112.104|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 212255549 (202M) [application/x-gzip]
Saving to: ‘openjdk-24.0.1_linux-x64_bin.tar.gz’

openjdk-24.0.1_linux-x64_bin. 100%[=================================================>] 202.42M   904KB/s    in 3m 33s

2025-05-14 17:18:21 (972 KB/s) - ‘openjdk-24.0.1_linux-x64_bin.tar.gz’ saved [212255549/212255549]

To unzip the archive in the /opt directory, I used the following command on the Linux Command Prompt:

sudo tar xzvf openjdk-24.0.1_linux-x64_bin.tar.gz -C /opt

With the following output:

jdk-24.0.1/bin/jar
jdk-24.0.1/bin/jarsigner
jdk-24.0.1/bin/java
jdk-24.0.1/bin/javac
jdk-24.0.1/bin/javadoc
jdk-24.0.1/bin/javap
jdk-24.0.1/bin/jcmd
jdk-24.0.1/bin/jconsole
jdk-24.0.1/bin/jdb
jdk-24.0.1/bin/jdeprscan
jdk-24.0.1/bin/jdeps
jdk-24.0.1/bin/jfr
jdk-24.0.1/bin/jhsdb
jdk-24.0.1/bin/jimage
jdk-24.0.1/bin/jinfo
jdk-24.0.1/bin/jlink
jdk-24.0.1/bin/jmap
jdk-24.0.1/bin/jmod
jdk-24.0.1/bin/jnativescan
jdk-24.0.1/bin/jpackage
jdk-24.0.1/bin/jps
jdk-24.0.1/bin/jrunscript
jdk-24.0.1/bin/jshell
jdk-24.0.1/bin/jstack
jdk-24.0.1/bin/jstat
jdk-24.0.1/bin/jstatd
jdk-24.0.1/bin/jwebserver
jdk-24.0.1/bin/keytool
jdk-24.0.1/bin/rmiregistry
jdk-24.0.1/bin/serialver
...
jdk-24.0.1/release

Next, I used the following command on the Linux Command Prompt:

cd /opt
ls -latr

With the following output:

ls -latr
total 16
drwxr-xr-x 19 root root 4096 Jan 11  2024 ..
drwxr-xr-x  6 root root 4096 May 14 15:29 apache-maven-3.9.9
drwxr-xr-x  4 root root 4096 May 14 17:13 .
drwxr-xr-x  9 root root 4096 May 14 17:18 jdk-24.0.1

In order to prepend the OpenJDK directory to the JAVA_HOME environment variable, I used the following commands on the Linux Command Prompt:

JAVA_HOME=/opt/jdk-24.0.1
export JAVA_HOME 
echo $JAVA_HOME

With the following output:

/opt/jdk-24.0.1

In order to prepend the OpenJDK bin directory to the PATH environment variable, I used the following commands on the Linux Command Prompt:

export PATH=/opt/jdk-24.0.1/bin:$PATH
echo $PATH

With the following output:

/opt/jdk-24.0.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

In order to check the OpenJDK version, I used the following commands on the Linux Command Prompt:

java --version

With the following output:

openjdk 24.0.1 2025-04-15
OpenJDK Runtime Environment (build 24.0.1+9-30)
OpenJDK 64-Bit Server VM (build 24.0.1+9-30, mixed mode, sharing)

Installing Maven

In order to install Maven, I visited the website: https://maven.apache.org/

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 24

From there I clicked on the link “Downloads”.

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 25

To download the tar.gz file, I used the following command on the Linux Command Prompt:

cd /tmp
wget https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz

With the following output:

--2025-05-14 11:56:36--  https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
Resolving dlcdn.apache.org (dlcdn.apache.org)... 151.101.2.132, 2a04:4e42::644
Connecting to dlcdn.apache.org (dlcdn.apache.org)|151.101.2.132|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 9102945 (8.7M) [application/x-gzip]
Saving to: ‘apache-maven-3.9.9-bin.tar.gz’

apache-maven-3.9.9-bin.tar.gz 100%[=================================================>]   8.68M  1.96MB/s    in 5.2s

2025-05-14 11:56:41 (1.66 MB/s) - ‘apache-maven-3.9.9-bin.tar.gz’ saved [9102945/9102945]

On the “Welcome to Apache Maven” page, I clicked on the link “Installation”.
[https://maven.apache.org/install.html]

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 26

To unzip the archive in the /opt directory, I used the following command on the Linux Command Prompt:

sudo tar xzvf apache-maven-3.9.9-bin.tar.gz -C /opt

With the following output:

apache-maven-3.9.9/README.txt
apache-maven-3.9.9/LICENSE
apache-maven-3.9.9/NOTICE
apache-maven-3.9.9/lib/
apache-maven-3.9.9/lib/aopalliance.license
apache-maven-3.9.9/lib/commons-cli.license
apache-maven-3.9.9/lib/commons-codec.license
apache-maven-3.9.9/lib/failureaccess.license
apache-maven-3.9.9/lib/guava.license
apache-maven-3.9.9/lib/guice.license
apache-maven-3.9.9/lib/httpclient.license
apache-maven-3.9.9/lib/httpcore.license
apache-maven-3.9.9/lib/jansi.license
apache-maven-3.9.9/lib/javax.annotation-api.license
apache-maven-3.9.9/lib/javax.inject.license
apache-maven-3.9.9/lib/jcl-over-slf4j.license
apache-maven-3.9.9/lib/org.eclipse.sisu.inject.license
apache-maven-3.9.9/lib/org.eclipse.sisu.plexus.license
apache-maven-3.9.9/lib/plexus-cipher.license
apache-maven-3.9.9/lib/plexus-component-annotations.license
apache-maven-3.9.9/lib/plexus-interpolation.license
apache-maven-3.9.9/lib/plexus-sec-dispatcher.license
apache-maven-3.9.9/lib/plexus-utils.license
apache-maven-3.9.9/lib/plexus-xml.license
apache-maven-3.9.9/lib/slf4j-api.license
apache-maven-3.9.9/boot/
apache-maven-3.9.9/boot/plexus-classworlds.license
apache-maven-3.9.9/lib/jansi-native/
apache-maven-3.9.9/lib/jansi-native/Windows/
apache-maven-3.9.9/lib/jansi-native/Windows/arm64/
apache-maven-3.9.9/lib/jansi-native/Windows/x86/
apache-maven-3.9.9/lib/jansi-native/Windows/x86_64/
apache-maven-3.9.9/lib/jansi-native/Windows/arm64/libjansi.so
apache-maven-3.9.9/lib/jansi-native/Windows/x86/jansi.dll
apache-maven-3.9.9/lib/jansi-native/Windows/x86_64/jansi.dll
apache-maven-3.9.9/bin/m2.conf
apache-maven-3.9.9/bin/mvn.cmd
apache-maven-3.9.9/bin/mvnDebug.cmd
apache-maven-3.9.9/bin/mvn
apache-maven-3.9.9/bin/mvnDebug
apache-maven-3.9.9/bin/mvnyjp
apache-maven-3.9.9/conf/
apache-maven-3.9.9/conf/logging/
apache-maven-3.9.9/conf/logging/simplelogger.properties
apache-maven-3.9.9/conf/settings.xml
apache-maven-3.9.9/conf/toolchains.xml
apache-maven-3.9.9/lib/ext/
apache-maven-3.9.9/lib/ext/hazelcast/
apache-maven-3.9.9/lib/ext/redisson/
apache-maven-3.9.9/lib/jansi-native/
apache-maven-3.9.9/lib/ext/README.txt
apache-maven-3.9.9/lib/ext/hazelcast/README.txt
apache-maven-3.9.9/lib/ext/redisson/README.txt
apache-maven-3.9.9/lib/jansi-native/README.txt
apache-maven-3.9.9/boot/plexus-classworlds-2.8.0.jar
apache-maven-3.9.9/lib/jcl-over-slf4j-1.7.36.jar
apache-maven-3.9.9/lib/maven-settings-3.9.9.jar
apache-maven-3.9.9/lib/maven-embedder-3.9.9.jar
apache-maven-3.9.9/lib/aopalliance-1.0.jar
apache-maven-3.9.9/lib/maven-resolver-provider-3.9.9.jar
apache-maven-3.9.9/lib/slf4j-api-1.7.36.jar
apache-maven-3.9.9/lib/wagon-provider-api-3.5.3.jar
apache-maven-3.9.9/lib/maven-resolver-api-1.9.22.jar
apache-maven-3.9.9/lib/commons-cli-1.8.0.jar
apache-maven-3.9.9/lib/javax.annotation-api-1.3.2.jar
apache-maven-3.9.9/lib/maven-repository-metadata-3.9.9.jar
apache-maven-3.9.9/lib/httpcore-4.4.16.jar
apache-maven-3.9.9/lib/maven-resolver-util-1.9.22.jar
apache-maven-3.9.9/lib/wagon-http-3.5.3.jar
apache-maven-3.9.9/lib/org.eclipse.sisu.inject-0.9.0.M3.jar
apache-maven-3.9.9/lib/maven-core-3.9.9.jar
apache-maven-3.9.9/lib/maven-builder-support-3.9.9.jar
apache-maven-3.9.9/lib/maven-resolver-impl-1.9.22.jar
apache-maven-3.9.9/lib/maven-resolver-transport-wagon-1.9.22.jar
apache-maven-3.9.9/lib/maven-artifact-3.9.9.jar
apache-maven-3.9.9/lib/plexus-cipher-2.0.jar
apache-maven-3.9.9/lib/maven-settings-builder-3.9.9.jar
apache-maven-3.9.9/lib/failureaccess-1.0.2.jar
apache-maven-3.9.9/lib/plexus-sec-dispatcher-2.0.jar
apache-maven-3.9.9/lib/maven-shared-utils-3.4.2.jar
apache-maven-3.9.9/lib/guava-33.2.1-jre.jar
apache-maven-3.9.9/lib/wagon-file-3.5.3.jar
apache-maven-3.9.9/lib/maven-model-builder-3.9.9.jar
apache-maven-3.9.9/lib/maven-slf4j-provider-3.9.9.jar
apache-maven-3.9.9/lib/plexus-interpolation-1.27.jar
apache-maven-3.9.9/lib/maven-resolver-transport-http-1.9.22.jar
apache-maven-3.9.9/lib/maven-model-3.9.9.jar
apache-maven-3.9.9/lib/plexus-xml-3.0.1.jar
apache-maven-3.9.9/lib/maven-resolver-spi-1.9.22.jar
apache-maven-3.9.9/lib/maven-compat-3.9.9.jar
apache-maven-3.9.9/lib/guice-5.1.0.jar
apache-maven-3.9.9/lib/commons-codec-1.17.1.jar
apache-maven-3.9.9/lib/javax.inject-1.jar
apache-maven-3.9.9/lib/org.eclipse.sisu.plexus-0.9.0.M3.jar
apache-maven-3.9.9/lib/jansi-2.4.1.jar
apache-maven-3.9.9/lib/maven-resolver-named-locks-1.9.22.jar
apache-maven-3.9.9/lib/maven-plugin-api-3.9.9.jar
apache-maven-3.9.9/lib/wagon-http-shared-3.5.3.jar
apache-maven-3.9.9/lib/httpclient-4.5.14.jar
apache-maven-3.9.9/lib/maven-resolver-transport-file-1.9.22.jar
apache-maven-3.9.9/lib/plexus-component-annotations-2.1.0.jar
apache-maven-3.9.9/lib/maven-resolver-connector-basic-1.9.22.jar
apache-maven-3.9.9/lib/plexus-utils-3.5.1.jar

Next, I used the following command on the Linux Command Prompt:

cd /opt
ls -latr

With the following output:

ls -latr
total 12
drwxr-xr-x 19 root root 4096 Jan 11  2024 ..
drwxr-xr-x  3 root root 4096 May 14 12:06 .
drwxr-xr-x  6 root root 4096 May 14 12:06 apache-maven-3.9.9

In order to prepend the Maven bin directory to the PATH environment variable, I used the following commands on the Linux Command Prompt:

export PATH=/opt/apache-maven-3.9.9/bin:$PATH
echo $PATH

With the following output:

/opt/apache-maven-3.9.9/bin:/home/vagrant/.jbang/bin:/home/vagrant/.jbang/currentjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

In order to check the Maven version, I used the following commands on the Linux Command Prompt:

mvn -v

With the following output:

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by org.fusesource.jansi.internal.JansiLoader in an unnamed module (file:/opt/apache-maven-3.9.9/lib/jansi-2.4.1.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)
Maven home: /opt/apache-maven-3.9.9
Java version: 24.0.1, vendor: Oracle Corporation, runtime: /opt/jdk-24.0.1
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-91-generic", arch: "amd64", family: "unix"

To further automate all these manual steps mentioned above, in the env/scripts directory on my Windows laptop, I created the file quarkus-kubernetes-extension.sh with the following content:

#!/bin/bash
echo "**** Begin installing Quarkus Kubernetes extension"

echo "****** Begin installing OpenJDK"

#Download the tar.gz file
date "+%Y-%m-%d %H:%M:%S"
cd /tmp
wget https://download.java.net/java/GA/jdk24.0.1/24a58e0e276943138bf3e963e6291ac2/9/GPL/openjdk-24.0.1_linux-x64_bin.tar.gz
date "+%Y-%m-%d %H:%M:%S"

#Unzip the archive in the /opt directory
sudo tar xzvf openjdk-24.0.1_linux-x64_bin.tar.gz -C /opt

echo "****** Output from: ls -latr /opt"
ls -latr /opt

#Add the directory of the created openjdk-24.0.1_linux-x64_bin.tar.gz to the JAVA_HOME environment variable
JAVA_HOME=/opt/jdk-24.0.1
export JAVA_HOME

echo "****** JAVA_HOME:"
echo $JAVA_HOME

#Add the bin directory of the created openjdk-24.0.1_linux-x64_bin.tar.gz to the PATH environment variable
export PATH=/opt/jdk-24.0.1/bin:$PATH

echo "****** PATH:"
echo $PATH

echo "****** Output from: java --version"
java --version

echo "****** End installing OpenJDK"

echo "****** Begin installing Maven"

#Download the tar.gz file
date "+%Y-%m-%d %H:%M:%S"
cd /tmp
wget https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
date "+%Y-%m-%d %H:%M:%S"

#Unzip the archive in the /opt directory
sudo tar xzvf apache-maven-3.9.9-bin.tar.gz -C /opt

#Add the bin directory of the created directory apache-maven-3.9.9 to the PATH environment variable
export PATH=/opt/apache-maven-3.9.9/bin:$PATH
echo "****** PATH:"
echo $PATH

#Check the Maven version
echo "****** Output from: mvn -v"
mvn -v

#Permanently setting environment variables for all users
cd /tmp
sudo printf "export JAVA_HOME=/opt/jdk-24.0.1\nexport PATH=/opt/jdk-24.0.1/bin:$PATH\nexport PATH=/opt/apache-maven-3.9.9/bin:$PATH\n" > myenvvars.sh
sudo cp /tmp/myenvvars.sh /etc/profile.d/myenvvars.sh
rm myenvvars.sh

echo "****** Output from: cat /etc/profile.d/myenvvars.sh"
cat /etc/profile.d/myenvvars.sh

echo "****** End installing Maven"

echo "**** End installing Quarkus Kubernetes extension"

Next, in my Vagrantfile, I added a Vagrant Shell provisioner to upload and execute my external script within the guest machine:

      args = []
      config.vm.provision "quarkus-kubernetes-extension shell script", type: "shell",
          path: "scripts/quarkus-kubernetes-extension.sh",
          args: args

For the demo environment to start, from the directory named env on my Windows laptop, I opened a Windows Command Prompt (cmd) and typed: vagrant up. Once the VM was running, for executing later manual steps, I used vagrant ssh to connect into the running VM. But each time I made the connection, I had to set the JAVA_HOME and PATH again. So as you can see in the script above, I also added a part for permanently setting environment variables for all users (as I remembered I had done and described some years ago, in a previous article).
[https://technology.amis.nl/software-development/java/using-vagrant-and-shell-scripts-to-further-automate-setting-up-my-quarkus-demo-environment-from-scratch-and-trying-out-a-quarkus-code-guide/]

Access to a Kubernetes cluster

As I mentioned in my previous article, some years ago, I wrote a series of articles about Quarkus.

As I did before, for the Kubernetes cluster, I used K3s (a lightweight certified Kubernetes distribution)
[https://k3s.io/]

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 27
[https://k3s.io/]

In the menu I clicked on “Docs” and navigated to “Quick-Start Guide”.

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 28
[https://docs.k3s.io/quick-start]

According to this guide, in order to install K3s, this is the step to take:

curl -sfL https://get.k3s.io | sh -

After running this installation:

  • The K3s service will be configured to automatically restart after node reboots or if the process crashes or is killed
  • Additional utilities will be installed, including kubectl, crictl, ctr, k3s-killall.sh, and k3s-uninstall.sh
  • A kubeconfig file will be written to /etc/rancher/k3s/k3s.yaml and the kubectl installed by K3s will automatically use it

A single-node server installation is a fully-functional Kubernetes cluster, including all the datastore, control-plane, kubelet, and container runtime components necessary to host workload pods.
[https://docs.k3s.io/quick-start]

This was fine for my situation.

Then I had a look at the requirements.
[https://docs.k3s.io/installation/requirements]

The important bit for me, mentioned there, for a single-node server installation, were the minimum hardware requirements:

  • CPU: 2 cores
  • RAM: 2 GB

Later on I made sure that my Vagrantfile was changed according to these requirements. Below you can see the part in that file were this is done:
[in bold, I highlighted the changes]

    config.vm.provider "virtualbox" do |vb|
        vb.name = "Ubuntu Quarkus K3s"
        vb.memory = "8192"
        vb.cpus = "2"

With regard to installing K3s on Ubuntu and additional setup requirements:

It is recommended to turn off ufw (uncomplicated firewall):

ufw disable

[https://docs.k3s.io/installation/requirements?os=debian]

Again, this was fine for my situation.

Installing K3s

For installing K3s, I used the following command on the Linux Command Prompt:

curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" sh -

With the following output:

[INFO]  Finding release for channel stable
[INFO]  Using v1.32.4+k3s1 as release
[INFO]  Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.32.4+k3s1/sha256sum-amd64.txt
[INFO]  Downloading binary https://github.com/k3s-io/k3s/releases/download/v1.32.4+k3s1/k3s
[INFO]  Verifying binary download
[INFO]  Installing k3s to /usr/local/bin/k3s
[INFO]  Skipping installation of SELinux RPM
[INFO]  Creating /usr/local/bin/kubectl symlink to k3s
[INFO]  Creating /usr/local/bin/crictl symlink to k3s
[INFO]  Creating /usr/local/bin/ctr symlink to k3s
[INFO]  Creating killall script /usr/local/bin/k3s-killall.sh
[INFO]  Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO]  env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO]  systemd: Creating service file /etc/systemd/system/k3s.service
[INFO]  systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO]  systemd: Starting k3s

You can read more about using environment variable K3S_KUBECONFIG_MODE in a previous article.
[https://technology.amis.nl/continuous-delivery/containers/rapidly-spinning-up-a-vm-with-ubuntu-and-k3s-with-the-kubernetes-dashboard-on-my-windows-laptop-using-vagrant-and-oracle-virtualbox/]

So once K3s was installed, I used the following command on the Linux Command Prompt:

kubectl get nodes

With the following output:

NAME                     STATUS   ROLES                  AGE     VERSION
ubuntu2204.localdomain   Ready    control-plane,master   3m41s   v1.32.4+k3s1

In order to confirm that the cluster is available, I used the following command on the Linux Command Prompt:

kubectl get pods --all-namespaces

With the following output:

NAMESPACE     NAME                                      READY   STATUS      RESTARTS   AGE
kube-system   coredns-697968c856-knmgp                  1/1     Running     0          4m4s
kube-system   helm-install-traefik-crd-xjz44            0/1     Completed   0          4m5s
kube-system   helm-install-traefik-jt8sd                0/1     Completed   2          4m5s
kube-system   local-path-provisioner-774c6665dc-nzrkd   1/1     Running     0          4m4s
kube-system   metrics-server-6f4c6675d5-crprt           1/1     Running     0          4m4s
kube-system   svclb-traefik-8631df09-kvm8j              2/2     Running     0          3m27s
kube-system   traefik-c98fdf6fb-dzwpz                   1/1     Running     0          3m27s

Then, I used the following command:

ls -latr /etc/rancher/k3s/
total 12
-rw-r--r-- 1 root root 2961 May 17 05:04 k3s.yaml
drwxr-xr-x 4 root root 4096 May 17 05:04 ..
drwxr-xr-x 2 root root 4096 May 17 05:04 .

Here we can see the changed permissions for file k3s.yaml.

Then, I used the following command:

cat /etc/rancher/k3s/k3s.yaml

With the following output (certificate data is shortened):

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0t…LS0K
    server: https://127.0.0.1:6443
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    client-certificate-data: LS0t…LS0K
    client-key-data: LS0t..LQo=

To further automate all these manual steps mentioned above, in the env/scripts directory on my Windows laptop, I created the file k3s.sh with the following content:

#!/bin/bash
echo "**** Begin installing k3s"

#Disable firewall
sudo ufw disable

#Install
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" sh -

# Wait 2 minutes
echo "****** Waiting 2 minutes ..."
sleep 120

#List nodes en pods
echo "****** List nodes"
kubectl get nodes

echo "****** List pods"
kubectl get pods --all-namespaces

echo "**** End installing k3s"

Installing a Kubernetes Dasboard

I also wanted a Kubernetes Dasboard. I had a look at:

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/

But I opted to use some scripts, that I also used in the past, for setting up a Kubernetes Dashboard in my demo environment (with the help of Helm). The scripts installed Helm and a Kubernetes dashboard.
[https://technology.amis.nl/continuous-delivery/containers/rapidly-spinning-up-a-vm-with-ubuntu-and-k3s-with-the-kubernetes-dashboard-on-my-windows-laptop-using-vagrant-and-oracle-virtualbox/]

The following yaml files were used (present in my shared folder) to create a Service Account, ClusterRoleBinding and Secret within Kubernetes.

Content of file serviceaccount-k3s.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

Content of file clusterrolebinding-k3s.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

Content of file secret-k3s.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
  annotations:
    kubernetes.io/service-account.name: "admin-user"
type: kubernetes.io/service-account-token  

Remark about the Secret:
I used a long-lived Bearer Token for the ServiceAccount, saved in a Secret.
[https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md#getting-a-long-lived-bearer-token-for-serviceaccount]

In the env/scripts directory on my Windows laptop, I created the file helm.sh with the following content:

#!/bin/bash
echo "**** Begin installing Helm"

#Install socat
sudo apt-get install socat

#Install Helm
sudo snap install helm --classic

# Wait 2 minutes
echo "**** Waiting 2 minutes ..."
sleep 120

#Show version
echo "****** Output from: helm version"
helm version

#List pods
echo "****** List pods with namespace kube-system"
kubectl get pods --namespace kube-system

#Make Kubernetes cluster reachable with helm 3.0
kubectl config view --raw >~/.kube/config

echo "**** End installing Helm"

Remark about using helm with k3s:
I added to the script:

kubectl config view --raw >~/.kube/config

In order to avoid:

ubuntu_quarkus_k3s: ****** Install Helm chart k3s-chart
    ubuntu_quarkus_k3s: Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get "http://localhost:8080/version": dial tcp 127.0.0.1:8080: connect: connection refused
    ubuntu_quarkus_k3s: ****** Waiting 30 seconds ...

[https://github.com/helm/helm/issues/12682]
[https://github.com/k3s-io/k3s/issues/1126]

In the env/scripts directory on my Windows laptop, I created the file dashboard.sh with the following content:

#!/bin/bash

echo "**** Begin preparing Kubernetes Dashboard"

echo "****** Install Kubernetes Dashboard"
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

#Create Helm chart
echo "****** Create Helm chart"
cd /mnt/mysharedfolder
cd helmcharts
rm -rf /mnt/mysharedfolder/helmcharts/k3s-chart/*
helm create k3s-chart

rm -rf /mnt/mysharedfolder/helmcharts/k3s-chart/templates/*
cp /mnt/mysharedfolder/yaml/*k3s.yaml /mnt/mysharedfolder/helmcharts/k3s-chart/templates

# Install Helm chart
cd /mnt/mysharedfolder
cd helmcharts
echo "****** Install Helm chart k3s-chart"
helm install k3s-release ./k3s-chart

# Wait 30 seconds
echo "****** Waiting 30 seconds ..."
sleep 30

#List helm releases
echo "****** List helm releases"
helm list -d

#List secrets
echo "****** List secrets with namespace kubernetes-dashboard"
kubectl get secrets --namespace kubernetes-dashboard

echo "****** Describe secret with namespace kubernetes-dashboard"
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

kubectl proxy --address='0.0.0.0' </dev/null &>/dev/null &

echo "**** End preparing Kubernetes Dashboard"

Next, in my Vagrantfile, I added two more Vagrant Shell provisioners to upload and execute my external scripts within the guest machine:

      args = []
      config.vm.provision "helm shell script", type: "shell",
          path: "scripts/helm.sh",
          args: args
          
      args = []
      config.vm.provision "dashboard shell script", type: "shell",
          path: "scripts/dashboard.sh",
          args: args

In order to confirm that the dashboard is available, I used the following command on the Linux Command Prompt:

kubectl get pods --all-namespaces

With the following output:

NAMESPACE              NAME                                         READY   STATUS      RESTARTS   AGE
kube-system            coredns-697968c856-knmgp                     1/1     Running     0          9m41s
kube-system            helm-install-traefik-crd-xjz44               0/1     Completed   0          9m42s
kube-system            helm-install-traefik-jt8sd                   0/1     Completed   2          9m42s
kube-system            local-path-provisioner-774c6665dc-nzrkd      1/1     Running     0          9m41s
kube-system            metrics-server-6f4c6675d5-crprt              1/1     Running     0          9m41s
kube-system            svclb-traefik-8631df09-kvm8j                 2/2     Running     0          9m4s
kube-system            traefik-c98fdf6fb-dzwpz                      1/1     Running     0          9m4s
kubernetes-dashboard   dashboard-metrics-scraper-749c668b7f-r7vrn   1/1     Running     0          52s
kubernetes-dashboard   kubernetes-dashboard-76b75d676c-gl9pf        1/1     Running     0          53s

After this, in the Web Browser on my Windows laptop, I started the Kubernetes Dashboard, via:

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 29

I used the token, that was visible in the output of my script, via:

kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

The Kubernetes Dashboard was opened with the default namespace selected. Below, you can see an overview of the Namespaces:

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 30

With all the requirements now met, I could proceed with the Kubernetes Extension code guide.
[https://quarkus.io/guides/deploying-to-kubernetes]

In order to create a new project that contains both the Kubernetes and Jib extensions, I used the following commands on the Linux Command Prompt:

cd /mnt/mysharedfolder
mvn io.quarkus.platform:quarkus-maven-plugin:3.22.3:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=kubernetes-quickstart \
    -Dextensions='rest,kubernetes,jib'
cd kubernetes-quickstart

With the following output:

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by org.fusesource.jansi.internal.JansiLoader in an unnamed module (file:/opt/apache-maven-3.9.9/lib/jansi-2.4.1.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper (file:/opt/apache-maven-3.9.9/lib/guava-33.2.1-jre.jar)
WARNING: Please consider reporting this to the maintainers of class com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
[INFO] Scanning for projects...
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/platform/quarkus-maven-plugin/3.22.3/quarkus-maven-plugin-3.22.3.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/platform/quarkus-maven-plugin/3.22.3/quarkus-maven-plugin-3.22.3.pom (10 kB at 9.8 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/platform/quarkus-bom/3.22.3/quarkus-bom-3.22.3.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/platform/quarkus-bom/3.22.3/quarkus-bom-3.22.3.pom (389 kB at 819 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/platform/quarkus-maven-plugin/3.22.3/quarkus-maven-plugin-3.22.3.jar
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/platform/quarkus-maven-plugin/3.22.3/quarkus-maven-plugin-3.22.3.jar (458 kB at 959 kB/s)
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- quarkus:3.22.3:create (default-cli) @ standalone-pom ---
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-bootstrap-core/3.22.3/quarkus-bootstrap-core-3.22.3.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-bootstrap-core/3.22.3/quarkus-bootstrap-core-3.22.3.pom (4.3 kB at 148 kB/s)
..
Downloaded from central: https://repo.maven.apache.org/maven2/org/freemarker/freemarker/2.3.34/freemarker-2.3.34.jar (1.9 MB at 71 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.18.3/jackson-databind-2.18.3.jar (1.7 MB at 62 kB/s)
[INFO] Looking for the newly published extensions in registry.quarkus.io
[INFO] -----------
[INFO] selected extensions:
- io.quarkus:quarkus-rest
- io.quarkus:quarkus-kubernetes
- io.quarkus:quarkus-container-image-jib

[INFO]
applying codestarts...
[INFO] 📚 java
🔨 maven
📦 quarkus
📝 config-properties
🔧 tooling-dockerfiles
🔧 tooling-maven-wrapper
🚀 rest-codestart
[INFO]
-----------
[SUCCESS] ✅  quarkus project has been successfully generated in:
--> /mnt/mysharedfolder/kubernetes-quickstart
-----------
[INFO]
[INFO] ========================================================================================
[INFO] Your new application has been created in /mnt/mysharedfolder/kubernetes-quickstart
[INFO] Navigate into this directory and launch your application with mvn quarkus:dev
[INFO] Your application will be accessible on http://localhost:8080
[INFO] ========================================================================================
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:01 min
[INFO] Finished at: 2025-05-17T14:37:48Z
[INFO] ------------------------------------------------------------------------

This added the following dependencies to the build file (pom.xml):

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes</artifactId>
</dependency>
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-container-image-jib</artifactId>
</dependency>

By adding these dependencies, we enable the generation of Kubernetes manifests each time we perform a build while also enabling the build of a container image using Jib. 
[https://quarkus.io/guides/deploying-to-kubernetes]

Generation of Kubernetes manifests

Next, following the instructions in the guide, I used the following commands on the Linux Command Prompt:

./mvnw install

With the following output:

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by org.fusesource.jansi.internal.JansiLoader in an unnamed module (file:/home/vagrant/.m2/wrapper/dists/apache-maven-3.9.9-bin/33b4b2b4/apache-maven-3.9.9/lib/jansi-2.4.1.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper (file:/home/vagrant/.m2/wrapper/dists/apache-maven-3.9.9-bin/33b4b2b4/apache-maven-3.9.9/lib/guava-33.2.1-jre.jar)
WARNING: Please consider reporting this to the maintainers of class com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< org.acme:kubernetes-quickstart >-------------------
[INFO] Building kubernetes-quickstart 1.0.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ kubernetes-quickstart ---
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO]
[INFO] --- quarkus:3.22.3:generate-code (default) @ kubernetes-quickstart ---
Downloading from central: https://repo.maven.apache.org/maven2/io/fabric8/kubernetes-model-apiextensions/7.1.0/kubernetes-model-apiextensions-7.1.0.jar
...
Downloaded from central: https://repo.maven.apache.org/maven2/io/fabric8/kubernetes-model-core/7.1.0/kubernetes-model-core-7.1.0.jar (3.2 MB at 303 kB/s)
[INFO]
[INFO] --- compiler:3.14.0:compile (default-compile) @ kubernetes-quickstart ---
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-shared-incremental/1.1/maven-shared-incremental-1.1.pom
...
Downloaded from central: https://repo.maven.apache.org/maven2/com/thoughtworks/qdox/qdox/2.2.0/qdox-2.2.0.jar (353 kB at 348 kB/s)
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 1 source file with javac [debug parameters release 21] to target/classes
[INFO]
[INFO] --- quarkus:3.22.3:generate-code-tests (default) @ kubernetes-quickstart ---
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ kubernetes-quickstart ---
[INFO] skip non existing resourceDirectory /mnt/mysharedfolder/kubernetes-quickstart/src/test/resources
[INFO]
[INFO] --- compiler:3.14.0:testCompile (default-testCompile) @ kubernetes-quickstart ---
[INFO] Recompiling the module because of changed dependency.
[INFO] Compiling 2 source files with javac [debug parameters release 21] to target/test-classes
[INFO]
[INFO] --- surefire:3.5.2:test (default-test) @ kubernetes-quickstart ---
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/surefire/surefire-api/3.5.2/surefire-api-3.5.2.pom
...
Downloaded from central: https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-engine/1.9.3/junit-platform-engine-1.9.3.jar (189 kB at 441 kB/s)
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by org.jboss.threads.JBossExecutors (file:/home/vagrant/.m2/repository/org/jboss/threads/jboss-threads/3.8.0.Final/jboss-threads-3.8.0.Final.jar)
WARNING: Please consider reporting this to the maintainers of class org.jboss.threads.JBossExecutors
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
[INFO] Running org.acme.GreetingResourceTest
2025-05-17 14:59:16,622 INFO  [io.quarkus] (main) kubernetes-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.22.3) started in 5.563s. Listening on: http://localhost:8081
2025-05-17 14:59:16,627 INFO  [io.quarkus] (main) Profile test activated.
2025-05-17 14:59:16,628 INFO  [io.quarkus] (main) Installed features: [cdi, compose, kubernetes, rest, smallrye-context-propagation, vertx]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.654 s -- in org.acme.GreetingResourceTest
2025-05-17 14:59:18,830 INFO  [io.quarkus] (main) kubernetes-quickstart stopped in 0.067s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- jar:3.4.1:jar (default-jar) @ kubernetes-quickstart ---
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/file-management/3.1.0/file-management-3.1.0.pom
...
Downloaded from central: https://repo.maven.apache.org/maven2/com/github/luben/zstd-jni/1.5.5-11/zstd-jni-1.5.5-11.jar (6.8 MB at 912 kB/s)
[INFO] Building jar: /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- quarkus:3.22.3:build (default) @ kubernetes-quickstart ---
[INFO] [io.quarkus.kubernetes.deployment.PropertyUtil] Kubernetes manifests are generated with 'The container port http' having default value '8080'. The app and manifests will get out of sync if the property 'quarkus.http.port' is changed at runtime.
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 5351ms
[INFO]
[INFO] --- failsafe:3.5.2:integration-test (default) @ kubernetes-quickstart ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- quarkus:3.22.3:native-image-agent (default) @ kubernetes-quickstart ---
[INFO] Missing native-image-agent-base-config directory with native image agent configuration to transform
[INFO]
[INFO] --- failsafe:3.5.2:verify (default) @ kubernetes-quickstart ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- install:3.1.2:install (default-install) @ kubernetes-quickstart ---
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/resolver/maven-resolver-util/1.9.18/maven-resolver-util-1.9.18.pom
...
Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-xml/3.0.0/plexus-xml-3.0.0.jar (93 kB at 278 kB/s)
[INFO] Installing /mnt/mysharedfolder/kubernetes-quickstart/pom.xml to /home/vagrant/.m2/repository/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/kubernetes-quickstart-1.0.0-SNAPSHOT.pom
[INFO] Installing /mnt/mysharedfolder/kubernetes-quickstart/target/kubernetes-quickstart-1.0.0-SNAPSHOT.jar to /home/vagrant/.m2/repository/org/acme/kubernetes-quickstart/1.0.0-SNAPSHOT/kubernetes-quickstart-1.0.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  53.149 s
[INFO] Finished at: 2025-05-17T14:59:34Z
[INFO] ------------------------------------------------------------------------

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 31

You will notice amongst the other files that are created, two files named kubernetes.json and kubernetes.yml in the target/kubernetes/ directory.

If you look at either file you will see that it contains both a Kubernetes Deployment and a Service.
[https://quarkus.io/guides/deploying-to-kubernetes]

Below, you can see the content of the target/kubernetes.yml Kubernetes manifest, provided by the Quarkus project install:

---
apiVersion: v1
kind: Service
metadata:
  annotations:
    app.quarkus.io/quarkus-version: 3.22.3
    app.quarkus.io/build-timestamp: 2025-05-17 - 14:59:30 +0000
  labels:
    app.kubernetes.io/name: kubernetes-quickstart
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: kubernetes-quickstart
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 8080
  selector:
    app.kubernetes.io/name: kubernetes-quickstart
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/quarkus-version: 3.22.3
    app.quarkus.io/build-timestamp: 2025-05-17 - 14:59:30 +0000
  labels:
    app.kubernetes.io/name: kubernetes-quickstart
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: kubernetes-quickstart
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: kubernetes-quickstart
      app.kubernetes.io/version: 1.0.0-SNAPSHOT
  template:
    metadata:
      annotations:
        app.quarkus.io/quarkus-version: 3.22.3
        app.quarkus.io/build-timestamp: 2025-05-17 - 14:59:30 +0000
      labels:
        app.kubernetes.io/managed-by: quarkus
        app.kubernetes.io/name: kubernetes-quickstart
        app.kubernetes.io/version: 1.0.0-SNAPSHOT
    spec:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: docker.io/vagrant/kubernetes-quickstart:1.0.0-SNAPSHOT
          imagePullPolicy: Always
          name: kubernetes-quickstart
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP

The generated manifest can be applied to the cluster from the project root using kubectl:

kubectl apply -f target/kubernetes/kubernetes.yml

Remark about the Deployment container image part:
An important thing to note about the Deployment (or StatefulSet) is that it uses yourDockerUsername/kubernetes-quickstart:1.0.0-SNAPSHOT as the container image of the Pod. The name of the image is controlled by the Jib extension and can be customized using the usual application.properties.
[https://quarkus.io/guides/deploying-to-kubernetes]

As you can see, at the moment the Jib extension build a container image with the following name:

docker.io/vagrant/kubernetes-quickstart:1.0.0-SNAPSHOT

Jib extension

The extension quarkus-container-image-jib is powered by Jib for performing container image builds. The major benefit of using Jib with Quarkus is that all the dependencies (everything found under target/lib) are cached in a different layer than the actual application making rebuilds really fast and small (when it comes to pushing). Another important benefit of using this extension is that it provides the ability to create a container image without having to have any dedicated client side tooling (like Docker) or running daemon processes (like the Docker daemon) when all that is needed is the ability to push to a container image registry.
[https://quarkus.io/guides/container-image#jib]

Jib

Quarkus - Supersonic Subatomic Java, trying out Quarkus guide “Quarkus - Kubernetes extension”  (reinvestigated, part 1) lameriks 2025 05 32

Jib builds optimized Docker and OCI images for your Java applications without a Docker daemon – and without deep mastery of Docker best-practices. It is available as plugins for Maven and Gradle and as a Java library.
[https://github.com/GoogleContainerTools/jib/blob/master/README.md#what-is-jib]

Goals of Jib:

  • Fast – Deploy your changes fast. Jib separates your application into multiple layers, splitting dependencies from classes. Now you don’t have to wait for Docker to rebuild your entire Java application – just deploy the layers that changed.
  • Reproducible – Rebuilding your container image with the same contents always generates the same image. Never trigger an unnecessary update again.
  • Daemonless – Reduce your CLI dependencies. Build your Docker image from within Maven or Gradle and push to any registry of your choice. No more writing Dockerfiles and calling docker build/push.

[https://github.com/GoogleContainerTools/jib/blob/master/README.md#goals]

Before I was going to use kubectl, in order to apply the generated manifest to the cluster, I wanted at least, one more thing to do.

In my previous articles, I wrote some years ago, about the Quarkus Kubernetes Extension, I used the default public Docker image registry. This time, I wanted to try out using a local private registry.

But more about that “journey”, you can read in my next article.

I conclude this article. I shared with you the steps I took, trying out the Quarkus guide “Quarkus – Kubernetes extension” (again 😊) and also the steps to further set up my demo environment (in order to meet the requirements for that extension). In my case, installing OpenJDK JDK 24, Apache Maven 3.9.9 and for the Kubernetes cluster, I installed K3s (a lightweight certified Kubernetes distribution) and a Kubernetes Dashboard.

Feel free, among my other articles on this subject, to read:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.