Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 83

Deploying Spring Boot to Kubernetes with Deployment Manifests

Recommended resources

Hello! Welcome to our next lesson on containerization with Kubernetes.

In our last session, we built a solid theoretical foundation by exploring the four essential Kubernetes objects: Pods, ReplicaSets, Deployments, and Services. We learned that you declare a desired state using a Deployment, and Kubernetes works tirelessly to maintain it, providing self-healing and scalability.

Today, we'll put that theory into practice. Your learning outcome is to deploy a Spring Boot application to Kubernetes using a Deployment manifest. We will translate our application requirements into a declarative YAML file that Kubernetes can understand and execute. This is a fundamental, hands-on skill you'll be expected to demonstrate in any senior engineering role involving microservices.

1. The Anatomy of a Deployment Manifest

A Kubernetes manifest is a YAML file that describes a resource. For a Deployment, this file is our contract with the cluster, detailing exactly how our Spring Boot application should run.

Every Kubernetes resource manifest has four top-level fields:

  • apiVersion: Specifies the Kubernetes API version to use for this object. For Deployments, this is typically apps/v1.
  • kind: The type of resource we are creating. In this case, Deployment.
  • metadata: Data that helps uniquely identify the object, such as its name.
  • spec: The most important field. This is where you declare the desired state for the resource—how many replicas, which container image to use, what configuration to apply, and more.

Kubernetes YAML File Explained - Deployment and Service | Kubernetes Tutorial 19

To start, let's watch a short, clear explanation of this fundamental structure from the 'Kubernetes YAML File Explained' video by TechWorld with Nana.

Watch from 00:32 to 03:30. Pay close attention to the distinction between the 'spec' (your desired state) and the 'status' (the actual state, managed by Kubernetes).

Now, let's look at a visual breakdown of a simple Deployment manifest. While this example uses Nginx, the structure is identical for any application, including our Spring Boot service.

Kubernetes Deployment Manifest Explained
This annotated diagram clearly breaks down the key fields of a Deployment manifest. Notice the nested structure, particularly the `template` field, which is the blueprint for the Pods.

2. Crafting the Deployment spec

The spec section is where the real work happens. It tells the Deployment controller how to manage your application's Pods. Let's focus on the most critical fields within spec.

Defining a Deployment

The article 'Developing and deploying Spring Boot microservices on Kubernetes' from LearnKube provides an excellent, detailed walkthrough of a Deployment manifest for a Java application. We'll use this as our primary reference.

Read the section titled 'Defining a Deployment'. Focus on understanding the purpose of replicas, selector, and the nested template fields. You don't need to create the files yourself yet; just absorb the concepts.

As you just read, the spec contains three key parts:

  1. replicas: A simple integer that defines how many identical copies (Pods) of your application you want running. This is the foundation for both high availability and scaling.

  2. selector: This tells the Deployment which Pods it is responsible for managing. It uses labels to make this connection. The matchLabels field must correspond to the labels defined in the Pod template. This is the glue that binds the Deployment to its Pods.

  3. template: This is a blueprint for the Pods that the Deployment will create. It has its own metadata (where we define the Pod's labels) and spec. The Pod spec is where we define the containers that will run inside it.

The Container Specification

Inside spec.template.spec, the containers array is where you define your Spring Boot application container. This is the most critical part for a developer.

Here's an example deployment.yaml for a typical Spring Boot application:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-springboot-app-deployment
spec:
  replicas: 2 # We want 2 running instances of our app
  selector:
    matchLabels:
      app: my-springboot-app
  template:
    metadata:
      labels:
        app: my-springboot-app # Pods get this label, matching the selector
    spec:
      containers:
      - name: springboot-app-container
        image: your-dockerhub-username/my-app:1.0.0 # The image we built previously
        imagePullPolicy: Always
        ports:
        - containerPort: 8080 # The port our Spring Boot app listens on
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "kubernetes"
        - name: DATABASE_URL
          value: "jdbc:postgresql://db-service:5432/mydatabase"

Let's break down the containers section:

  • name: A name for the container within the Pod.
  • image: This is the full name of the Docker image you pushed to a container registry (like Docker Hub) in our previous lessons.
  • ports: An array specifying which ports the container exposes. containerPort: 8080 tells Kubernetes that our application inside the container is listening on port 8080. This does not expose the port outside the Pod; a Service is required for that.
  • env: This is how you pass configuration to your application. It's an array of name-value pairs that are injected as environment variables. This is the standard way to provide profile-specific properties, database connection strings, or other external configurations to a Spring Boot application running in Kubernetes.

3. Deploying the Application

Once your deployment.yaml file is ready, you can submit it to the Kubernetes cluster using the kubectl command-line tool.

The command is straightforward:

kubectl apply -f deployment.yaml

Kubernetes will now read your manifest and work to achieve the desired state:

  1. The Deployment controller will create a ReplicaSet.
  2. The ReplicaSet controller will create 2 Pods (based on replicas: 2).
  3. The Kubernetes scheduler will find suitable nodes for these Pods.
  4. The Kubelet on each node will pull the specified Docker image (your-dockerhub-username/my-app:1.0.0) and start the container.

You can watch this happen with a few simple commands:

  • kubectl get deployments: Check the status of the Deployment itself.
  • kubectl get pods: See the Pods being created. Their status will transition from Pending to ContainerCreating to Running.
  • kubectl describe deployment my-springboot-app-deployment: Get detailed information and a log of events for the deployment, which is incredibly useful for debugging.

Deploy Springboot Microservices to Kubernetes Cluster | Full Example

To see this entire process in action with a Spring Boot application, let's watch a segment from the 'Deploy Springboot Microservices to Kubernetes Cluster' video. The example is more complex, but focus on the core process of creating the YAML and applying it.

Watch the following two segments: 27:37 - 31:36: Here, the presenter creates a user-service.yml file. Observe how he defines the Deployment and its container spec. He also defines a Service, which we will cover in the next lesson. 44:22 - 47:34: Watch as he applies all the configuration files using kubectl apply -f . and then verifies the created resources with kubectl get all.

Test your understanding! (Interview Question)

You've just run kubectl apply -f my-app-deployment.yaml to deploy a new version of your application. However, when you run kubectl get pods, you see that the new Pods are stuck in the ImagePullBackOff or ErrImagePull state. What are the most likely causes of this issue, and how would you investigate?

Show answer

This is a very common real-world problem and a frequent interview question. The ImagePullBackOff status means that Kubernetes tried to pull the container image but failed.

Likely Causes:

  1. Incorrect Image Name or Tag: You may have a typo in the image: field in your deployment.yaml. The repository name, image name, or tag might not exist.
  2. Private Repository without Credentials: If the image is in a private registry (like a private Docker Hub repo or a company's internal registry), Kubernetes needs credentials to access it. By default, it can only pull from public repositories.
  3. Network Issues: The Kubernetes node might not have network access to the container registry.

Investigation Steps:

  1. Describe the Pod: This is the most crucial first step. Run kubectl describe pod <pod-name>, replacing <pod-name> with the name of a failing pod. Look at the Events section at the bottom. It will contain a detailed error message, such as "image not found" or "authentication required."
  2. Check the Deployment Manifest: Carefully review the image: field in your deployment.yaml for any typos.
  3. Manual Image Pull: Try to SSH into one of the Kubernetes nodes (if possible) and manually run docker pull <image-name>:<tag>. This will confirm if the issue is with the image name or network connectivity from the node.
  4. Verify Secrets: If the repository is private, ensure you have created a docker-registry Secret in Kubernetes and referenced it in your Deployment's Pod template using the imagePullSecrets field.

This question tests your practical debugging skills within the Kubernetes ecosystem. The kubectl describe command is your best friend for troubleshooting Pod startup issues. (This scenario is adapted from the "Kubernetes Deployment fails after an upgrade" question in the DataCamp resource.)


Conclusion

Congratulations! You have now learned how to take a containerized Spring Boot application and define its deployment for a Kubernetes cluster. This process turns your static Docker image into a living, managed application.

Key Takeaways:

  • A Deployment manifest is a YAML file that declaratively defines how your application should run on Kubernetes.
  • The spec.template section is the Pod blueprint, where you specify the container image, ports, and crucial env variables for configuration.
  • Labels and selectors are the mechanism that connects the Deployment to the Pods it manages.
  • The command kubectl apply -f <filename> is used to submit your manifest to the cluster.
  • kubectl get and kubectl describe are your essential tools for verifying and debugging your deployment.

Preview of the Next Lesson:
Our application is now running in the cluster, but it's isolated and unreachable. In the next lesson, "Expose a Kubernetes Deployment to internal and external traffic using a Service," we will write a Service manifest. This will create a stable network endpoint, allowing other microservices within the cluster and users from the internet to communicate with our newly deployed Spring Boot application.