This is an example project that demonstrates how to deploy simple Jakarta EE application to a Kubernetes cluster in a way that is familiar to Java developers. The application is based on an application from the "First Cup of Jakarta EE" tutorial.
The application consists of a frontend "firstcup-war" service and a separate "dukes-age" REST microservice. The firstcup-war frontend provides a simple Web-based frontend and calls the dukes-age microservice to retrieve information about the age of Duke, the Java mascot.
When run locally, the firstcup-war service contacts the dukes-age service at a URL that points to localhost. This can be changed by supplying a system property or an environment variable. When deployed to Kubernetes, the dukes-age service is assigned a DNS name and the firstcup-war is configured using an environment variable to contact the dukes-age service using that DNS name.
Both services are built as a Docker image based on the official Payara Micro Docker image. The JIB maven plugin copies the exploded WAR directory to the Docker image and then instructs Payara Micro to deploy the application from that directory.
The Docker images are then deployed to a Docker repository from which the Kubernetes cluster can pull them. It might be the public Docker Hub or a private repository. The default configuration of the build assumes that the Kubernetes cluster runs locally using MicroK8s and that there's a private local repository provided by MicroK8s.
The JKube Kubernetes Maven plugin is used to prepare the Kubernetes deployment files and also to apply them to a running Kubernetes cluster using the kubectl CLI tool.
For the firsctup-war frontend, a Kubernetes service of type LoadBalancer is created so that it can be accessed from outside of the Kubernetes cluster. The default deployment generated by the maven plugin is modified in pom.xml
to set the image pull policy to Always (while in development phase) and in src/main/jkube/deployment.yml
template file to set the environment variable DUKES_AGE_URL
to point to the URL of the dukes-age service using its DNS name.
For the dukes-age service, a Kubernetes service is created so that the dukes-age service is assigned a fixed DNS name used by the firstcup-war service to access it. We chose the type LoadBalancer only to allow scaling of the dukes-age service to multiple replicas if needed.
Clone this repository and build the example using:
mvn package
In the directory dukes-age
, run:
mvn payara-micro:start
It should start the service at http://localhost:8080/. Test using http://localhost:8080/webapi/dukesAge.
In the directory firstcup-war
, run:
mvn payara-micro:start
It should start the service at http://localhost:8081/. Open the URL in a browser.
Before going further, this example project assumes that:
- you already have a Kubernetes cluster to which you can deploy this example application
- the
kubectl
command is installed and configured to access an existing Kubernetes cluster (it was tested with MicroK8s) - you already have a Docker registry to which you can deploy Docker images. The path to the registry is by default set to localhost:32000, this can be changed by a maven property
docker.registry
. If you have a local MicroK8s cluster, you can just enable the registry add-on withmicrok8s enable registry
. If you want to use the public Docker Hub registry, set the property todocker.io
with the-D
maven command line option or in the parent pom.xml.
Then you can build and deploy the application to the Kubernetes cluster using the following maven command:
mvn install
You can then access the firstcup-war frontend either using the URL generated by your cloud provider on port 8080 or forward the port 8080 to your local machine using the following kubectl command:
kubectl port-forward service/firstcup-war 8082:8080
Then you can access it using http://localhost:8082
If you want to play with the build configuration, you can perform the deployment steps individually. First build the project using mvn package
and then invoke individual deployment steps as follows:
In order to build and deploy Docker images to a local MicroK8s Docker repository at http://localhost:32000, run the following in the project root:
mvn jib:build
If you want to deploy to a different Docker repository, specify its address with the docker.registry
property like this:
mvn -Ddocker.registry=docker.io jib:build
mvn k8s:resource
The resources are generated in the directory target/classes/META-INF/jkube
for each service. Their content is configured in the Kubernetes plugin configuration in pom.xml
and using the template files in src/main/jkube
for each service.
mvn k8s:apply
This uses the kubectl
command to apply the K8s resources previously generated by the k8s:resource goal.