Optimising Performance with GraalVM: Running Spring Boot Native Image on Kubernetes

Abhishek Anand
CodeX
Published in
3 min readFeb 19, 2023
Photo by Growtika

In the previous article, I explained how to migrate an existing Spring Boot application to use GraalVM native image, which can offer faster startup times and lower memory usage. In this article, we’ll take the next step and explore how to deploy the GraalVM built native executable on Kubernetes. By using Kubernetes, you can easily manage and scale your application, and take advantage of the platform’s built-in features like load balancing and auto-scaling. We’ll walk through the steps for creating a Docker image using a Dockerfile, pushing the image to a container registry, creating a Kubernetes deployment file, and exposing the application to the outside world.

Creating Dockerfile

#Use GraalVM Maven base image 
FROM vegardit/graalvm-maven:22.3.1-java17
COPY src /home/app/src
COPY pom.xml /home/app
#Build a native executable
RUN mvn -f /home/app/pom.xml -Pnative native:compile
WORKDIR /home/app/target
#Expose port on which Spring Boot app will run
EXPOSE 9092
#Switch to non root user
USER 1001
#Entrypoint command present in Kubernetes deployment

  1. FROM: This step specifies the base image to use, which is vegardit/graalvm-maven:22.3.1-java17. This means that the Docker image will be built on top of the GraalVM Maven base image.I have used this image as it contains Maven pre-installed with GraalVM.
  2. COPY: This step copies the source code of the Spring Boot application to the /home/app/src directory in the Docker image, and the pom.xml file to the /home/app directory.
  3. RUN: This step uses the mvn command to build a native executable for the Spring Boot application, by specifying the Maven project file using the -f option and the native profile using the -P option. The native:compile command tells Maven to compile the application to a native executable.
  4. WORKDIR: This step sets the working directory to /home/app/target.
  5. EXPOSE: This step exposes the port 9092 on which the Spring Boot application will run. This means that when the Docker container is run, this port will be available for other containers or for external clients to access the application.
  6. USER: This step sets the user ID to 1001, which is a non-root user. This is a best practice for security reasons, as running an application as a non-root user can reduce the risk of security vulnerabilities.
  7. ENTRYPOINT: This step is not present in this Dockerfile, but it is mentioned in the description as being present in the Kubernetes deployment. The entrypoint is the command that is executed when the Docker container is run. In this case, it would be the command to start the Spring Boot application.

Running the application on Kubernetes

Build the Docker image using the Dockerfile. You can do this by running the following command in the same directory as the Dockerfile:

docker build -t your-image-name:version .

Push the Docker image to a container registry. This can be a public registry like Docker Hub or a private registry that you have set up for your organization. Make sure to authenticate with the registry before pushing the image.

docker push your-image-name

Create a Kubernetes deployment file that specifies the Docker image to use, the number of replicas to create, and any other configuration for the deployment. Here’s an example of a deployment file:

apiVersion: apps/v1
kind: Deployment
metadata:
name: your-deployment-name
spec:
replicas: 1
selector:
matchLabels:
app: your-app-name
template:
metadata:
labels:
app: your-app-name
spec:
containers:
- name: your-container-name
image: your-image-name
command: ["./your-executable-name","-Djavax.net.ssl.trustStore=/opt/certs/truststore.jks","-Djavax.net.ssl.trustStorePassword=changeit"]
ports:
- containerPort: 9092

The Entrypoint command is provided in the command key which basically runs the executable and additionally passes arguments to load a custom trust store and supplies the password of the trust store.

You can also add your poperties on ConfigMap and application passwords on Secrets.

Apply the deployment file to your Kubernetes cluster using the kubectl apply command:

kubectl apply -f your-deployment-file.yaml

Verify that the deployment and pod have been created using the kubectl command:

kubectl get deployments
kubectl get pods

To expose the application to the outside world, create a Kubernetes Service using the kubectl expose command:

kubectl expose deployment your-deployment-name --type=LoadBalancer --port=80 --target-port=9092

If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee https://www.buymeacoffee.com/abhiandy

--

--

Abhishek Anand
CodeX
Writer for

Spring Boot Advocate | Senior Software Engineer @ Intuit | ex-VMware