A logo showing the text blog.marcnuri.com
Español
Home»Java»Quarkus 2 + Kubernetes Maven Plugin + GraalVM integration

Recent Posts

  • Fabric8 Kubernetes Client 7.2 is now available!
  • Connecting to an MCP Server from JavaScript using AI SDK
  • Connecting to an MCP Server from JavaScript using LangChain.js
  • The Future of Developer Tools: Adapting to Machine-Based Developers
  • Connecting to a Model Context Protocol (MCP) Server from Java using LangChain4j

Categories

  • Artificial Intelligence
  • Front-end
  • Go
  • Industry and business
  • Java
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Tools

Archives

  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • August 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • February 2020
  • January 2020
  • December 2019
  • October 2019
  • September 2019
  • July 2019
  • March 2019
  • November 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • December 2017
  • July 2017
  • January 2017
  • December 2015
  • November 2015
  • December 2014
  • March 2014
  • February 2011
  • November 2008
  • June 2008
  • May 2008
  • April 2008
  • January 2008
  • November 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007

Quarkus 2 + Kubernetes Maven Plugin + GraalVM integration

2021-07-06 in Java tagged Docker / Eclipse / GraalVM / Java / Eclipse JKube / Kubernetes / Maven / Native / Quarkus by Marc Nuri | Last updated: 2022-02-03
Versión en Español

Introduction

In this tutorial, we'll see how to develop and integrate a very simple Quarkus 2 application with Kubernetes Maven Plugin (Eclipse JKube) to publish a native GraalVM image into Docker Hub and deploy it on Kubernetes.

This is a remake of my original article Quarkus + Fabric8 Maven Plugin + GraalVM integration, since the Fabric8 Maven Plugin is now deprecated.

In the first part, I describe how to build a very simple Quarkus application. Next, I describe how to build a Quarkus native executable with GraalVM. Finally, I show how to integrate the project with Kubernetes Maven Plugin and how to publish the application container images into Docker Hub and deploy them to Kubernetes.

Quarkus 2 example application

In this section, I'll describe how to build a simple application that will return a random quote each time you perform a request to the /quotes/random endpoint.

Project bootstrapping

Since you probably already have Maven installed in your system, the easiest way to bootstrap the project is by running the following command:

mvn io.quarkus:quarkus-maven-plugin:2.1.1.Final:create \
    -DprojectGroupId=com.marcnuri.demo \
    -DprojectArtifactId=kubernetes-maven-plugin-quarkus \
    -DclassName="com.marcnuri.demo.kmp.quote.QuoteResource" \
    -Dextensions='quarkus-resteasy-jackson'

If the command completes successfully, you will be able to see a new directory kubernetes-maven-plugin-quarkus with an initial maven project with maven wrapper support.

However, if you don't have Maven installed, or if on the other hand, you prefer an interactive graphical user interface, you can navigate to code.quarkus.io to customize and download a bootstrapped project with your specific requirements.

Quarkus project bootstrap (code.quarkus.io)
Quarkus project bootstrap (code.quarkus.io)

Project resources

As I already explained, the application will serve a random quote each time a user performs a request to an endpoint. The application will load these quotes from a JSON file located in the project resources folder. For this purpose, you'll add the file quotes.json to the src/main/resources/quotes/ directory.

Random quote endpoint

Once we've got the resources set up, we can start with the code implementation. The first step is to create a Quote POJO that will be used to map the quotes defined in the JSON file when it's deserialized.

1public class Quote implements Serializable {
2  /** ... **/
3  private String content;
4  private String author;
5  /** ... **/
6}

Next, we'll create a QuoteService class to provide the service that reads the quotes from the resources directory and selects a random quote.

1@Singleton
2public class QuoteService {
3
4  private static final Logger log = LoggerFactory.getLogger(QuoteService.class);
5
6  private static final String QUOTES_RESOURCE= "/quotes/quotes.json";
7
8  private final List<Quote> quotes;
9
10  public QuoteService() {
11    quotes = new ArrayList<>();
12  }
13
14  @PostConstruct
15  protected final void initialize() {
16    final var objectMapper = new ObjectMapper();
17    try (final InputStream quotesStream = QuoteService.class.getResourceAsStream(QUOTES_RESOURCE)) {
18      quotes.addAll(objectMapper.readValue(quotesStream,
19        objectMapper.getTypeFactory().constructCollectionType(List.class, Quote.class)));
20    } catch (IOException e) {
21      log.error("Error loading quotes", e);
22    }
23  }
24
25
26  Quote getRandomQuote() {
27    return quotes.get(ThreadLocalRandom.current().nextInt(quotes.size()));
28  }
29
30}

The initialize method uses Jackson to read and deserialize the quotes.json file into a member ArrayList variable that will be used later on to fetch a random quote.

The getRandomQuote method returns a random Quote entry from the ArrayList for each invocation.

To complete the application, we need to modify the bootstrapped REST endpoint to use the service we implemented. For this purpose, we'll modify the QuoteResource class.

1@Path("/quotes")
2public class QuoteResource {
3
4  private static final String HEADER_QUOTE_AUTHOR = "Quote-Author";
5
6  private QuoteService quoteService;
7
8  @GET
9  @Path("/random")
10  @Produces(MediaType.TEXT_PLAIN)
11  public Response getRandomQuote() {
12    final var randomQuote = quoteService.getRandomQuote();
13    return Response
14      .ok(randomQuote.getContent(), MediaType.TEXT_PLAIN_TYPE)
15      .header(HEADER_QUOTE_AUTHOR, randomQuote.getAuthor())
16      .build();
17  }
18
19  @Inject
20  public void setQuoteService(QuoteService quoteService) {
21    this.quoteService = quoteService;
22  }
23}

The method getRandomQuote uses an instance of the previously described QuoteService class to get a random quote and return its content in the HTTP response body. In addition, the author of the quote is also added as a Response header.

Once we complete all the steps, we can start the application in development mode using the following command:

./mvnw clean compile quarkus:dev
[INFO] --- quarkus-maven-plugin:2.1.1.Final:dev (default-cli) @ kubernetes-maven-plugin-quarkus ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\00-MN\projects\marcnuri-demo\kubernetes-maven-plugin-quarkus\src\test\resources
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to D:\00-MN\projects\marcnuri-demo\kubernetes-maven-plugin-quarkus\target\test-classes
Listening for transport dt_socket at address: 5005
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-07-04 07:49:33,690 INFO  [io.quarkus] (Quarkus Main Thread) kubernetes-maven-plugin-quarkus 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.1.1.Final) started in 3.774s. Listening on: http://localhost:8080
2021-07-04 07:49:33,693 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2021-07-04 07:49:33,693 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy, resteasy-jackson, smallrye-context-propagation]

--
Tests paused, press [r] to resume, [h] for more options>

The endpoint will now be accessible at http://localhost:8080/quotes/random.

Screenshot of the result of executing curl localhost:8080/quotes/random -v
Screenshot of the result of executing curl localhost:8080/quotes/random -v

Building a native executable with GraalVM

Now is the time to make our application supersonic, for this purpose we are going to use GraalVM to create a native binary of the application.

We are now going to adapt the application to make it fully compatible with GraalVM.

Include resources

By default, GraalVM won’t include any of the resources available on the classpath during image creation using native-image. Resources that must be available at runtime must be specifically included during image creation.

To configure GraalVM to account for our quotes.json resource file, we need to modify the project's application.properties file and include the following line:

1quarkus.native.additional-build-args=-H:IncludeResources=.*\.json$

With this line, we indicate Quarkus to add the -H:IncludeResources command-line flag to the native-image command. In this specific case, we want to add any file that ends with the .json extension.

Native image reflection

Jackson JSON deserialization uses reflection to create instances of the target classes when performing reads. Graal native image build requires to know ahead of time which kind of elements are reflectiveley accessed by the program.

Quarkus eases this task by providing a @RegisterForReflection annotation that automates this task. For our example application, we’ll need to annotate the Quote class.

Building the native application

Now that we've completed adapting the application to be fully GraalVM compatible, we can perform the build in native mode. If Graal VM with native-image support is available in our system, we can simply run the following command:

./mvnw clean package -Pnative
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] D:\00-MN\bin\graalvm-ce-java11-21.1.0\bin\native-image.cmd
  -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dsun.nio.ch.maxUpdateArraySize=100
  -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory
  -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=3
  -J-Duser.language=en -J-Duser.country=US -J-Dfile.encoding=UTF-8 -H:IncludeResources=.*.json\$
  --initialize-at-build-time=
  -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy\$BySpaceAndTime -H:+JNI
  -H:+AllowFoldMethods -jar kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner.jar -H:FallbackThreshold=0
  -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http -H:-UseServiceLoaderFeature
  -H:+StackTrace kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]    classlist:   2,473.21 ms,  0.96 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]        (cap):   3,921.54 ms,  0.96 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]        setup:   6,147.99 ms,  0.96 GB
08:52:27,268 INFO  [org.jbo.threads] JBoss Threads version 3.4.0.Final
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]     (clinit):     664.62 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]   (typeflow):  16,865.10 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]    (objects):  20,902.79 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]   (features):     945.86 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]     analysis:  40,710.23 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]     universe:   1,702.71 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]      (parse):   4,527.99 ms,  4.67 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]     (inline):   8,267.27 ms,  5.83 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]    (compile):  24,709.00 ms,  5.69 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]      compile:  39,765.47 ms,  5.69 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]        image:   4,563.42 ms,  5.69 GB
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]        write:   2,281.61 ms,  5.69 GB
# Printing build artifacts to: kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner.build_artifacts.txt
[kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner:2772]      [total]:  98,272.86 ms,  5.69 GB
[WARNING] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] objcopy executable not found in PATH. Debug symbols will not be separated from executable.
[WARNING] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] That will result in a larger native image with debug symbols embedded in it.
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 106997ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:04 min
[INFO] Finished at: 2021-07-04T08:53:44+02:00
[INFO] -----------------------------------------------------------------------

If the command is executed successfully, a new kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner will be available in the target directory.

We can now run the application natively by executing the following command:

./target/kubernetes-maven-plugin-quarkus-1.0.0-SNAPSHOT-runner

Same as when we ran the application in JVM mode, the endpoint is now available at http://localhost:8080/quotes/random.

If GraalVM is not available in your system, but Docker is, the same command can be run inside a Docker container to build a Linux native binary:

./mvnw clean package -Pnative -Dquarkus.native.container-build=true

Kubernetes Maven Plugin (Eclipse JKube) integration

This is the final step in this tutorial. In this section, I'm going to show you how to integrate the project with Kubernetes Maven Plugin (Eclipse JKube).

The process is as simple as adding Eclipse JKube's Kubernetes Maven Plugin to our project's pom.xml

1<properties>
2    <!-- ... -->
3    <jkube.version>1.18.1</jkube.version>
4  </properties>
5  <!-- ... -->
6  <build>
7    <!-- ... -->
8    <plugins>
9      <!-- ... -->
10      <plugin>
11        <groupId>org.eclipse.jkube</groupId>
12        <artifactId>kubernetes-maven-plugin</artifactId>
13        <version>${jkube.version}</version>
14      </plugin>
15    </plugins>
16  </build>

The configuration is as straightforward as adding a <plugin> entry with groupId, artifactId & version to indicate that we want to use the Kubernetes Maven Plugin. In many cases, this may just be enough, as the plugin has a Zero-Config mode that takes care of defining most of the settings for us by analyzing the project's configuration inferring the recommended values.

Build Container (Docker) Image (k8s:build)

First, we need to remove the boiler-plate Dockerfiles that Quarkus provides for us in the src/main/docker directory. Kubernetes Maven Plugin infers all of this configuration from the project, so there's no need to maintain these files and we can safely remove them.

Eclipse JKube's Zero-Config mode uses Generators and Enrichers which provide opinionated defaults. For this project, the only common setting we need to take care of is the one related to the authorization for the Docker Hub registry. In this case, we are configuring JKube to read the push credentials from the DOCKER_HUB_USER and DOCKER_HUB_PASSWORD environment variables.

For this purpose, you need to add the following to the plugin's configuration:

1<plugin>
2  <groupId>org.eclipse.jkube</groupId>
3  <artifactId>kubernetes-maven-plugin</artifactId>
4  <version>${jkube.version}</version>
5  <configuration>
6    <authConfig>
7      <push>
8        <username>${env.DOCKER_HUB_USER}</username>
9        <password>${env.DOCKER_HUB_PASSWORD}</password>
10      </push>
11    </authConfig>
12  </configuration>
13</plugin>

Since we developed the project with support both for Quarkus JVM and Native modes, we are going to generate 2 different container (Docker) images depending on the Maven profile we select.

Docker image running application with JVM

In Quarkus 2, fast-jar is the default packaging for the JVM mode. This means, that unless stated otherwise (e.g. Maven Profile), the mvn package command will output the necessary files for this mode. Since I'm going to publish these images to Docker Hub, I will name this image marcnuri/kubernetes-maven-plugin-quarkus:jvm.

This will create an image for the marcnuri repository with the name kubernetes-maven-plugin-quarkus and jvm tag.

In order to tweak JKube's Quarkus generator opinionated default for the image name, we need to set the jkube.generator.name property. We can achieve this by adding the following entry to the pom.xml global properties section:

1<properties>
2    <!-- ... -->
3    <jkube.version>1.18.1</jkube.version>
4    <jkube.generator.name>marcnuri/kubernetes-maven-plugin-quarkus:jvm</jkube.generator.name>
5  </properties>

We can now run the following command to build the Docker image:

./mvnw clean package k8s:build
[INFO] --- kubernetes-maven-plugin:1.18.1:build (default-cli) @ kubernetes-maven-plugin-quarkus ---
[INFO] k8s: Running in Kubernetes mode
[INFO] k8s: Building Docker image in Kubernetes mode
[INFO] k8s: Running generator quarkus
[INFO] k8s: quarkus: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.9 as base / builder
[INFO] k8s: [marcnuri/kubernetes-maven-plugin-quarkus:jvm] "quarkus": Created docker-build.tar in 7 seconds 
[INFO] k8s: [marcnuri/kubernetes-maven-plugin-quarkus:jvm] "quarkus": Built image sha256:4947d
[INFO] k8s: [marcnuri/kubernetes-maven-plugin-quarkus:jvm] "quarkus": Tag with latest
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  16.113 s
[INFO] Finished at: 2021-07-04T16:22:27+02:00
[INFO] ------------------------------------------------------------------------

Docker image running application in native mode

The procedure for the native mode is very similar to the one we did earlier for JVM. In this case, I want to create an image with the following name: marcnuri/kubernetes-maven-plugin-quarkus:native.

Since the project already contains a Maven profile for native, achieving this is as simple as overriding the jkube.generator.name property for the native profile.

1<profiles>
2  <profile>
3    <id>native</id>
4    <!-- ... -->
5    <properties>
6      <quarkus.package.type>native</quarkus.package.type>
7      <jkube.generator.name>marcnuri/kubernetes-maven-plugin-quarkus:native</jkube.generator.name>
8    </properties>
9  </profile>
10</profiles>

We can now run the following command to build the native Docker image:

./mvnw clean package k8s:build -Pnative
[INFO] --- kubernetes-maven-plugin:1.18.1:build (default-cli) @ kubernetes-maven-plugin-quarkus ---
[INFO] k8s: Running in Kubernetes mode
[INFO] k8s: Building Docker image in Kubernetes mode
[INFO] k8s: Running generator quarkus
[INFO] k8s: quarkus: Using Docker image registry.access.redhat.com/ubi8/ubi-minimal:8.1 as base / builder
[INFO] k8s: Pulling from ubi8/ubi-minimal
[INFO] k8s: Digest: sha256:df6f9e5d689e4a0b295ff12abc6e2ae2932a1f3e479ae1124ab76cf40c3a8cdd
[INFO] k8s: Status: Downloaded newer image for registry.access.redhat.com/ubi8/ubi-minimal:8.1
[INFO] k8s: Pulled registry.access.redhat.com/ubi8/ubi-minimal:8.1 in 3 seconds 
[INFO] k8s: [marcnuri/kubernetes-maven-plugin-quarkus:native] "quarkus": Created docker-build.tar in 498 milliseconds
[INFO] k8s: [marcnuri/kubernetes-maven-plugin-quarkus:native] "quarkus": Built image sha256:5a1d5
[INFO] k8s: [marcnuri/kubernetes-maven-plugin-quarkus:native] "quarkus": Tag with latest
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  25.851 s
[INFO] Finished at: 2021-07-04T15:10:31Z
[INFO] ------------------------------------------------------------------------

Push image to Docker Hub (k8s:push)

Regardless of the packaging mode we choose (JVM or native), pushing the image into Docker Hub's registry is as easy as running the following command (provided that we have the required environment variables available):

./mvnw k8s:push
# or if a native image was built
./mvnw k8s:push -Pnative

Of course, this makes sense from a CI pipeline perspective. If you are running the command from your own secure local system, you can override the credentials this way:

./mvnw k8s:push -Djkube.docker.push.username=$username -Djkube.docker.push.password=$password
# or if a native image was built
./mvnw k8s:push -Pnative -Djkube.docker.push.username=$username -Djkube.docker.push.password=$password

In my case, I'm running this from a GitHub Actions Workflow:

A screenshot of GitHub Actions Workflow - mvn kubernetes:push
A screenshot of GitHub Actions Workflow - mvn kubernetes:push

Deploying the application to Kubernetes (k8s:apply)

Now that I've published my images to Docker Hub, I can safely deploy our application to Kubernetes.

The main advantage of JKube is that you don't need to deal with YAML and configuration files yourself. The plugin takes care of generating everything for you, so you only need to run the following command:

./mvnw k8s:resource k8s:apply
# or if a native image was built
./mvnw k8s:resource k8s:apply -Pnative
[INFO] --- kubernetes-maven-plugin:1.18.1:apply (default-cli) @ kubernetes-maven-plugin-quarkus ---
[INFO] k8s: Using Kubernetes at https://192.168.99.120:8443/ in namespace default with manifest D:\00-MN\projects\marcnuri-demo\kubernetes-maven-plugin-quarkus\target\classes\META-INF\jkube\kubernetes.yml 
[INFO] k8s: Creating a Service from kubernetes.yml namespace default name kubernetes-maven-plugin-quarkus
[INFO] k8s: Created Service: target\jkube\applyJson\default\service-kubernetes-maven-plugin-quarkus-4.json
[INFO] k8s: Creating a Deployment from kubernetes.yml namespace default name kubernetes-maven-plugin-quarkus
[INFO] k8s: Created Deployment: target\jkube\applyJson\default\deployment-kubernetes-maven-plugin-quarkus-4.json
[INFO] k8s: HINT: Use the command `kubectl get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  8.678 s
[INFO] Finished at: 2021-07-06T06:13:35+02:00
[INFO] ------------------------------------------------------------------------

This is a very simple project, so I didn't create an Ingress to expose the service which means that now the application remains inaccessible. I'll cover the process of creating an Ingress in an additional post. However, if you are running the application in minikube and want to access your application, with JKube is as easy as running:

./mvnw k8s:resource k8s:apply -Djkube.enricher.jkube-service.type=NodePort
# or if a native image was built
./mvnw k8s:resource k8s:apply -Djkube.enricher.jkube-service.type=NodePort -Pnative
minikube service kubernetes-maven-plugin-quarkus

If everything goes well, a browser window will be opened and you'll be able to see a page like the following:

A screenshot of a browser showing the application running on Kubernetes
A screenshot of a browser showing the application running on Kubernetes

Conclusion

In this post, I've shown you how to develop and integrate a very simple Quarkus 2 application with GraalVM native image support and the Kubernetes Maven Plugin. In the first section, I demonstrated how to bootstrap the application and create a very simple REST endpoint that will return a random quote for each request. Next, I showed you how to configure the application to be fully compatible with GraalVM to be able to generate a native binary. Finally, I showed you how to configure Kubernetes Maven Plugin to be able to build container images and push them into Docker Hub's registry. In addition, I showed you how simple it is to deploy your application to Kubernetes using Eclipse JKube.

The full source code for this post can be found at GitHub.

Quarkus 2 + GraalVM + Kubernetes Maven Plugin
Quarkus 2 + GraalVM + Kubernetes Maven Plugin
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Post navigation
Gradle: Adding the Gradle Wrapper from DockerTrigger Kubernetes CronJob manually from Java using YAKC
© 2007 - 2025 Marc Nuri