Create your own
Lesson illustration

Helm Chart for Spring Boot Microservices

Hello! Welcome to the next practical step in our journey to mastering microservice deployments.

In our last lesson, we established the "why" and "what" of Helm. You learned that Helm is a package manager that saves us from the complexity of managing raw Kubernetes YAML files, and we dissected the basic structure of a Helm chart, including Chart.yaml, values.yaml, and the templates directory.

Today, we move from theory to practice. Our goal is to create a basic Helm chart to package and deploy a Spring Boot microservice on Kubernetes. This is a hands-on session where you'll build a reusable, versioned deployment package. For your interview preparation, this skill is non-negotiable. It demonstrates that you can not only write microservices but also manage their lifecycle in a modern, automated way—a key expectation for mid-senior roles.

Let's start building.

1. Prerequisites and Scaffolding Your Chart

Before we begin, ensure you have the following tools ready from our previous modules:

  • A running local Kubernetes cluster (like Minikube or Docker Desktop's Kubernetes).
  • The kubectl CLI, configured to connect to your cluster.
  • The helm CLI (version 3+).
  • A Docker image of a Spring Boot application you've built, pushed to a registry (like Docker Hub). If you don't have one handy, we can use a public example.

The first step in creating a chart is to generate its basic structure using the helm create command. This saves you from creating all the standard files and directories manually.

Run the following command in your terminal:

helm create my-spring-boot-app

This command creates a new directory named my-spring-boot-app with all the boilerplate files we discussed in the last lesson.

To understand the purpose of each generated file and the overall process we're about to follow, the following reading provides an excellent roadmap.

Deploy Spring Boot Applications with Helm | by Jan Weyrich

The article 'Deploy Spring Boot Applications with Helm' by Jan Weyrich outlines the exact steps we'll be taking. It's a great reference for the entire process, from creating the scaffold to packaging the chart.

Please read the introduction to the section 'What are the steps to create a Helm chart for a Spring Boot application?' and subsection 1, 'Create the chart scaffold'. This will reinforce the purpose of the command we just ran and set the stage for the next steps.

2. Customizing the Chart for Your Spring Boot App

The default chart is a generic starting point for a web application. Now, we need to tailor it specifically for our Spring Boot microservice. This involves editing Chart.yaml, values.yaml, and the templates.

Step 2.1: Editing Metadata in Chart.yaml

Open my-spring-boot-app/Chart.yaml. This file contains metadata about your chart. It's good practice to update the description and appVersion.

  • version: The version of the chart itself. You'd increment this if you change the chart's templates or default values.
  • appVersion: The version of the application the chart deploys. This typically corresponds to your Docker image tag (e.g., "1.0.0").

Here's an example:

apiVersion: v2
name: my-spring-boot-app
description: A Helm chart for deploying my Spring Boot microservice
type: application
version: 0.1.0
appVersion: "1.0.0" 

Step 2.2: Configuring values.yaml

This is the most important step for customization. The values.yaml file acts as the "API" for your chart, allowing you to configure the deployment without touching the underlying Kubernetes manifests. Let's adjust the default values for a typical Spring Boot application.

Open my-spring-boot-app/values.yaml and make the following changes:

  1. Image Repository and Tag:
    Update image.repository to point to the Docker image of your Spring Boot application. The image.tag can be left empty if you want it to default to the appVersion in Chart.yaml, which is a common and useful pattern.

    image:
      repository: your-dockerhub-username/your-spring-boot-app # <-- CHANGE THIS
      pullPolicy: IfNotPresent
      # Overrides the image tag whose default is the chart's appVersion.
      tag: "" 
    
  2. Service Port:
    By default, Helm charts often assume a web server runs on port 80. Your Spring Boot application, however, runs on port 8080. If this isn't corrected, the Kubernetes Service will not be able to forward traffic to your application pod.

    service:
      type: ClusterIP
      port: 8080 # The port the service exposes
    

    We also need to ensure the targetPort in the service.yaml template correctly points to our application's container port. The default template usually handles this by referencing a named port in the deployment.yaml.

  3. Container Port and Health Probes:
    In the deployment.yaml template, we need to tell Kubernetes that our container listens on port 8080. The default templates usually have a placeholder for this. We also need to configure the liveness and readiness probes to use Spring Boot Actuator's health endpoints, which is a production best practice.

    Instead of modifying the templates directly, the default chart allows you to configure this from values.yaml. Look for sections related to service, ingress, and probes. The default values.yaml might not expose all necessary probe settings, so we'll check the deployment.yaml template.

Open my-spring-boot-app/templates/deployment.yaml. Find the ports and livenessProbe/readinessProbe sections within the container definition. They might look like this:

# templates/deployment.yaml
          ports:
            - name: http
              containerPort: {{ .Values.service.port }} # This uses the value from values.yaml
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http

The default path / is not ideal. For a Spring Boot application with Actuator, we should use /actuator/health/liveness and /actuator/health/readiness. Let's add this configuration to our values.yaml and update the template.

First, add a probes section to your values.yaml:

# values.yaml

# Add this new section
probes:
  liveness:
    path: /actuator/health/liveness
  readiness:
    path: /actuator/health/readiness

# ... existing values ...

Now, update templates/deployment.yaml to use these new values:

# templates/deployment.yaml
          livenessProbe:
            httpGet:
              path: {{ .Values.probes.liveness.path }}
              port: http
          readinessProbe:
            httpGet:
              path: {{ .Values.probes.readiness.path }}
              port: http

This change makes your chart much more robust and suitable for a real Spring Boot application.

3. Validating and Deploying Your Chart

With our chart customized, it's time to learn the commands to validate, inspect, and deploy it. These commands are your day-to-day toolkit for working with Helm.

Using Helm and Kubernetes | Baeldung on Ops

The Baeldung article 'Using Helm and Kubernetes' provides a clear, command-by-command guide to managing a chart's lifecycle. We will walk through these essential commands together.

Please read section 8, 'Managing Charts' (subsections 8.1 to 8.7, but focus on lint, template, install, ls, and uninstall). This will introduce you to the core Helm CLI commands we'll use to deploy and manage our application.

Let's apply what you just read. Navigate to the root directory of your chart (my-spring-boot-app).

  • Lint the Chart (helm lint):
    This command checks for syntax errors and adherence to best practices. It's the first thing you should run after making changes.

    helm lint .
    # Expected output:
    # ==> Linting .
    # [INFO] Chart.yaml: icon is recommended
    # 1 chart(s) linted, 0 chart(s) failed
    
  • Render the Template (helm template):
    This is an incredibly useful command for debugging. It generates the final Kubernetes YAML by rendering your templates with the values from values.yaml, but it only prints the output to your console—it doesn't deploy anything. This lets you inspect the final manifest before applying it to your cluster.

    helm template my-app-release .
    

    Inspect the output. Do you see port: 8080 in the Service? Is the image name correct in the Deployment? Are the probe paths set to the actuator endpoints?

  • Install the Chart (helm install):
    This is the command that deploys your application. It creates a release, which is a running instance of your chart.

    helm install my-app-release .
    

    Helm will print out the status of the deployment and any notes included in the chart.

  • Check the Status (helm ls and kubectl):
    You can see all your active releases with helm ls.

    helm ls
    

    And you can use kubectl to verify that your Spring Boot application's pod is running.

    kubectl get pods
    # You should see a pod with a name like 'my-app-release-my-spring-boot-app-...'
    
  • Uninstall the Release (helm uninstall):
    To tear down the entire application stack, simply uninstall the release. This removes all Kubernetes resources created by the chart.

    helm uninstall my-app-release
    
Test your understanding!

You need to add a configurable resource limit for memory to your Spring Boot application. The default should be 512Mi. How would you modify values.yaml and templates/deployment.yaml to achieve this?

Show answer
  1. Modify values.yaml:
    The default values.yaml already has a resources section. You would ensure it's configured as needed, or add it if it's missing.

    # values.yaml
    resources:
      # We usually recommend not to specify default resources and to leave this as a conscious
      # choice for the user. This also increases chances charts run on environments with little
      # resources, such as Minikube. If you do want to specify resources, uncomment the following
      # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
      limits:
        # cpu: 100m
        memory: 512Mi # Set the desired value
      requests:
        cpu: 100m
        memory: 256Mi
    
  2. Modify templates/deployment.yaml:
    The default deployment.yaml is already set up to use these values. The resources block in the container spec typically looks like this:

    # templates/deployment.yaml
              resources:
                {{- toYaml .Values.resources | nindent 12 }}
    

    The toYaml function converts the resources object from values.yaml into YAML format, and nindent 12 ensures it's correctly indented. This is a very common and efficient pattern in Helm charts. You wouldn't need to change the template at all if it's already using this pattern.

4. Externalizing Configuration with ConfigMaps

A truly production-ready chart shouldn't have configuration baked into the Docker image. Spring Boot's "externalized configuration" feature is a perfect match for Kubernetes ConfigMaps. Let's extend our chart to manage application properties.

We'll create a ConfigMap from values in our values.yaml and mount them as environment variables in our pod. Spring Boot will automatically pick them up.

Deploy Spring Boot Applications with Helm | by Jan Weyrich

Let's revisit the Jan Weyrich article. It has an excellent, practical walkthrough on integrating a ConfigMap into a Helm chart for a Spring Boot application. This is a key pattern for managing environment-specific settings.

Please read subsection 4, 'Edit the templates'. Focus on the part that introduces the ConfigMap template and how it's used to manage application.properties. Pay attention to the use of toYaml and the trick to force a pod restart when the configuration changes.

Let's implement this powerful pattern.

  1. Add application properties to values.yaml:
    Add a new section for your application properties. Remember Spring Boot's relaxed binding rules: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK in an environment variable maps to logging.level.org.springframework in application.properties. It's best practice to use the environment variable format in your values.yaml to avoid any confusion.

    # values.yaml
    # Add this new section at the end of the file
    application:
      properties:
        WELCOME_MESSAGE: "Hello from Helm!"
        SPRING_DATASOURCE_URL: "jdbc:postgresql://localhost:5432/mydb"
    
  2. Create templates/configmap.yaml:
    Create a new file my-spring-boot-app/templates/configmap.yaml with the following content:

    {{- if .Values.application.properties }}
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: {{ include "my-spring-boot-app.fullname" . }}-properties
    data:
      {{- toYaml .Values.application.properties | nindent 6 }}
    {{- end }}
    
    • {{- if .Values.application.properties }}: This makes the creation of the ConfigMap conditional.
    • {{- toYaml .Values.application.properties | nindent 6 }}: This is the magic part. It takes the YAML block from values.yaml and renders it directly into the data section of the ConfigMap.
  3. Mount the ConfigMap in deployment.yaml:
    Finally, edit templates/deployment.yaml to mount this ConfigMap as environment variables. Find the containers section and add the envFrom block:

    # templates/deployment.yaml
          containers:
            - name: {{ .Chart.Name }}
              # ... existing properties like securityContext, image, etc.
              envFrom:
                - configMapRef:
                    name: {{ include "my-spring-boot-app.fullname" . }}-properties
              ports:
              # ... existing ports, probes, etc.
    

    Now, when you helm install or helm upgrade, these properties will be available as environment variables to your Spring Boot application.

Conclusion

Congratulations! You have successfully created and deployed your first Helm chart for a Spring Boot microservice. You've gone beyond a simple deployment by incorporating best practices like actuator-based health probes and externalized configuration via ConfigMaps.

Key Takeaways:

  • You can scaffold a chart with helm create.
  • Customizing a chart for Spring Boot involves key changes in values.yaml: updating the image.repository, setting the service.port to 8080, and configuring probes to use actuator endpoints.
  • The core Helm CLI commands for managing a release are helm lint, helm template, helm install, helm ls, and helm uninstall.
  • You can manage Spring Boot properties by creating a ConfigMap from values.yaml and mounting it using envFrom in your Deployment.

In this lesson, we focused on the creation and initial deployment. In our next session, we will dive deeper into application lifecycle management by learning to manage application releases using Helm commands, including upgrade and rollback, which are critical for implementing zero-downtime deployment strategies.

Can't find a good explanation? Sign up and we'll make it for you

Sign up