Deploy a Java Application on Kubernetes with Helm
This guide walks you through the process of running an example Java application on a Kubernetes cluster. It uses the Jhipster sample application, based on the Bitnami Tomcat container. The first step is to create a Docker image and use it as a starting point for creating a custom Helm chart to automate the application deployment in a Kubernetes cluster. Once the application is deployed and working, it also explores how to modify the source code for publishing a new application release and how to perform rolling updates in Kubernetes using the Helm CLI.
Assumptions and prerequisites
This guide will show you how to deploy an example Java application in a Kubernetes cluster running on Minikube. The example application is a typical web banking application.
This guide makes the following assumptions:
- You have basic knowledge of how to build Docker images.
- You have basic knowledge of Helm charts and how to create them.
- You have a Docker environment running.
- You have an account in a container registry (this tutorial assumes that you are using Docker Hub).
- You have Minikube installed in your local computer.
- You have a Kubernetes cluster running.
- You have the kubectl command line (kubectl CLI) installed.
- You have Helm and Tiller installed.
To create your own application in Java and deploy it on Kubernetes using Helm, you will typically follow these steps:
- Step 1: Obtain the application source code
- Step 2: Build the Docker image
- Step 3: Publish the Docker image
- Step 4: Create the Helm Chart
- Step 5: Deploy the example application in Kubernetes
- Step 6: Update the source code
Step 1: Obtain the application source code
To begin the process, ensure that you have access to the application source code. If the application code is stored in a Git repository, clone the repository, as shown below for the sample application:
$ git clone https://github.com/bitnami/tutorials $ cd tutorials/java-k8s
This will clone the entire tutorials repository and set the working directory to tutorials/java-k8s.
IMPORTANT: The following steps must be executed within the tutorials/java-k8s/app-code directory.
We will use the Jhipster sample application as an example for this guide. To run this application using Tomcat, we need to export the application project to a .war file using Maven, as explained in the following steps:
NOTE: It’s also possible to use the application’s own container, running the .war file directly without using Tomcat. Please follow these instructions on the Jhipster GitHub page to create it. However, any other Java application can be deployed on top of Apache Tomcat following the same approach.
NOTE: If you already have a .war file that you want to deploy, skip to the second step.
In the current directory tutorials/java-k8s, clone the repository:
$ git clone https://github.com/jhipster/jhipster-sample-app build-app
Replace the default application-prod.yml file with a custom version from the java-k8s/app-code/utils directory in order to make the application work with MariaDB.
$ cp app-code/utils/application-prod.yml build-app/src/main/resources/config/
To create our sample application .war file, build and run a container with the necessary dependencies.
Copy the Dockerfile from the java-k8s/app-code/utils directory to the build-app directory. The Dockerfile contains instructions to build a container with all the dependencies needed to create the .war file.
$ cp app-code/utils/Dockerfile build-app/
Build the image:
$ docker build build-app -t jhipster
Mount the build-app directory containing the application project and run the container to create the .war file.
$ docker run -v $(pwd)/build-app:/bitnami jhipster
Once you have successfully exported the .war file, copy it to the app-code directory:
$ cp build-app/target/*.war app-code/jhipster.war
Step 2: Build the Docker image
With the .war file in place we are ready to build our application’s container.
- Go to the java-k8s/app-code directory:
This directory already contains the docker-compose.yml file needed for this example.
In the docker-compose.yml file, you can see how the services are defined for Tomcat and MariaDB as well as the environment variables used for the database creation.
This example deploys the application faster than the database, and so the MariaDB service also includes a health check that checks if the database has been created before starting Tomcat. It’s interesting to see the difference between this health check and the health check performed by Helm (shown later in this tutorial).
jhipster-mariadb: image: bitnami/mariadb:latest environment: - MARIADB_USER=jhipster - MARIADB_PASSWORD=jhipster - MARIADB_DATABASE=jhipsterSampleApplication - ALLOW_EMPTY_PASSWORD=yes healthcheck: test: "/opt/bitnami/mariadb/bin/mysql -u jhipster -pjhipster -e 'SHOW DATABASES;'" interval: 5s retries: 20
IMPORTANT: The following steps must be executed within the tutorials/java-app/app-code directory.
Build the images and start the containers:
$ docker-compose up
Executing this command will first create the MariaDB and Tomcat images and then start the containers.
Check if the application is running on localhost:8080/jhipster. The default administrator credentials are:
- Username: admin
- Password: admin
Step 3: Publish the Docker image
Now that your Docker image is built and contains your application code, you can upload it into a public registry. This tutorial uses Docker Hub, but you can select one of your own choice such as:
To upload the image to Docker Hub, follow the steps below:
Log into Docker Hub:
$ docker login
Push the image to your Docker Hub account. Replace the USERNAME placeholder with your Docker ID:
$ docker push USERNAME/java-app:0.1.0
You should now see the new image in your Docker Hub repositories dashboard.
Step 4: Create the Helm chart
To create a brand new chart, you just need to run the helm create command. This creates a scaffold with sample files that you can modify to build your custom chart. For this tutorial, we’ll provide you with a ready-made Helm chart. If you examine the repository you just downloaded, there is a directory named helm-chart that already contains the files you need. Check out the chart’s file structure:
kubernetes |-- Chart.yaml |-- charts |-- templates | |-- NOTES.txt | |-- _helpers.tpl | |-- deployment.yaml | |-- ingress.yaml | `-- service.yaml `-- values.yaml
Here’s a brief explanation of the most important components of a Helm chart:
Chart.yaml: This file includes the metadata of the Helm chart like the version or the description.
requirements.yaml: This file specifies the requirements for deploying this chart - in this case, the MariaDB container.
values.yaml: This file declares the variables to be passed to the templates. It is important to replace the USERNAME with your Docker ID and also to check if the container name and version exist.
image: repository: USERNAME/java-app tag: 0.1.0
This file also defines the ports of the container images:
service: name: tomcat type: NodePort externalPort: 8080 internalPort: 8080
Go into the templates/ folder and check the files there:
NOTES.txt: This file specifies the output to be printed after installation.
deployment.yaml: This is the manifest file for creating the Kubernetes deployment. In this example, it includes two containers: one for the Java application and one for MariaDB.
The MariaDB container might take longer to start up than the Jhipster sample application. When this happens, the application will fail to run. The solution is to use a livenessProbe to check if the application URL is running, so the “node agent” or kubelet will restart the pod in case it is not.
livenessProbe: httpGet: path: /jhipster port: http initialDelaySeconds: 120 timeoutSeconds: 5
service.yaml: This is the manifest file for creating a service endpoint for both containers.
For a more in-depth look at chart creation, we recommend reading our Helm chart tutorial.
Step 5: Deploy the example application in Kubernetes
NOTE: Before performing the following steps, make sure you have a Kubernetes cluster running with Helm and Tiller installed. For detailed instructions, refer to our starter tutorial.
At this point, you have built a Docker image, published it in a container registry and created your custom Helm chart. It’s now time to deploy the example Java application within a Kubernetes cluster. To deploy the example application using the current Helm chart, follow these steps:
Make sure that you can connect to your Kubernetes cluster by executing the command below:
$ kubectl cluster-info
Deploy the Helm chart by executing the following:
$ helm install --set mariadb.mariadbUser=jhipster,mariadb.mariadbPassword=jhipster,mariadb.mariadbDatabase=jhipsterSampleApplication --name jhipster .
NOTE: In this example, the chart name is specified by adding the
--nameoption. If you don’t add it, one will be assigned automatically. Because of the way the application is configured, it is necessary to name the chart jhipster.
Using --set makes it possible to configure the database options in the MariaDB container like the database name, password and user credentials. The above command will create two pods within the cluster, one for the MariaDB service and the other for the application itself.
Once the chart has been installed, you will see a lot of useful information about the deployment. The application won’t be available until database configuration is complete. Follow these instructions to check the database status:
Run the kubectl get pods command to get a list of running pods:
$ kubectl get pods
When the MariaDB container takes longer to start than the application container, the livenessProbe will restart the latter as mentioned in Step 4.
Check the logs of the application pod. APP-POD-NAME is a placeholder; remember to replace it with the right value.
$ kubectl logs -f APP-POD-NAME
Now you can access the application. To obtain the application URL, run the commands shown in the “Notes” section below.
If you’re using Minikube, you can also check the application service to get the application’s URL. You have two ways to do this:
Option 1: List the services by executing the minikube service list command. You’ll notice two service names:
$ minikube service list
Option 2: Check the application service using the minikube service SERVICE command (SERVICE is a placeholder. Remember to replace it with the name of the service you want to check):
$ minikube service SERVICE --url
Enter the resulting URL in your default browser to access the application. Congratulations! Your APP application has been successfully deployed on Kubernetes.
Step 6: Update the source code and the Helm chart
As a developer, you’ll understand that your application may need new features or bug fixes in the future. To release a new Docker image, you only have to perform a few basic steps: change your application source code, rebuild and republish the image in your selected container registry. Once the new image release has been pushed to the registry, you need to update the Helm chart.
In this example we will change the Tomcat version. In the previous Docker image, we used the latest available version of the Bitnami Tomcat image. In the updated image, we will use a specific version, v8.0. Follow these instructions to complete the application update process:
In the Dockerfile, change the Tomcat version number to 8.0. Save the file.
In the docker-compose.yml file, change the version number to 0.1.1 and rebuild the image by running the docker-compose up command.
$ docker-compose up
NOTE: Before performing the next step, make sure that you are logged in to Docker Hub. Run the docker login command to access your account (if applicable).
Publish the new image following the same steps as in Step 3 but using the new version number. Remember to replace the USERNAME placeholder with your Docker ID:
$ docker push USERNAME/java-app:0.1.1
Change to the kubernetes directory, where you have the Helm chart files. Edit the values.yaml file to replace the current image tag with the new one:
Run the helm upgrade command followed by the name of the chart. After that, you will see the information about the new deployment:
$ helm upgrade jhipster .
See what revisions have been made to the chart by executing the helm history command:
$ helm history jhipster .
Enter the application URL and port, without appending /jhipster at the end in your default browser. You should see Tomcat v8.0.
Follow these steps every time you want to update your Docker image and Helm chart.
IMPORTANT: For performing a rollback of your application chart, refer to our tutorial for deploying, scaling and upgrading an application on Kubernetes with Helm. Remember to replace my-todo-app with the name of your Helm chart in the example provided in the above-mentioned tutorial.
To learn more about the topics discussed in this guide, use the links below: