Learnitweb

Deploying Spring Boot application in Kubernetes in local

Introduction

In this tutorial, we’ll create a simple Hello World application and deploy in Kubernetes cluster. In localhost, we are using Docker Desktop and have enabled Kubernetes. This is a single node cluster.

Creating the application

Create a Spring Boot application. Following is the pom.xml:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.learnitweb</groupId>
<artifactId>helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helloworld</name>
<description>Demo project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>helloworld</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.4.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.learnitweb</groupId> <artifactId>helloworld</artifactId> <version>0.0.1-SNAPSHOT</version> <name>helloworld</name> <description>Demo project for Spring Boot</description> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <finalName>helloworld</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.learnitweb</groupId>
	<artifactId>helloworld</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>helloworld</name>
	<description>Demo project for Spring Boot</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<finalName>helloworld</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Create the HelloWorldController:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloWorldController {
@GetMapping("/hello")
public String sayHello() {
return "Hello, World!";
}
}
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class HelloWorldController { @GetMapping("/hello") public String sayHello() { return "Hello, World!"; } }
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloWorldController {

    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, World!";
    }
}

Create the Docker file

In the root folder of your application, create a Dockerfile:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/*.jar helloworld.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "helloworld.jar"]
FROM openjdk:17-jdk-slim WORKDIR /app COPY target/*.jar helloworld.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "helloworld.jar"]
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/*.jar helloworld.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "helloworld.jar"]

Now build the image:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
docker build -t hello-world-app .
docker build -t hello-world-app .
docker build -t hello-world-app .

Since you’re using a single-node cluster (Docker Desktop), you don’t need to push the image to Docker Hub. Instead, you can use the locally built image.

Create a Kubernetes Deployment

Create a new file named deployment.yaml in your project root:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-deployment
spec:
replicas: 1
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: hello-world-app # Using locally built image
imagePullPolicy: Never # Prevents Kubernetes from pulling from Docker Hub
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-service
spec:
selector:
app: hello-world
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer # Exposes service externally (on Docker Desktop, use port-forward)
apiVersion: apps/v1 kind: Deployment metadata: name: hello-world-deployment spec: replicas: 1 selector: matchLabels: app: hello-world template: metadata: labels: app: hello-world spec: containers: - name: hello-world image: hello-world-app # Using locally built image imagePullPolicy: Never # Prevents Kubernetes from pulling from Docker Hub ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: hello-world-service spec: selector: app: hello-world ports: - protocol: TCP port: 80 targetPort: 8080 type: LoadBalancer # Exposes service externally (on Docker Desktop, use port-forward)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: hello-world-app  # Using locally built image
          imagePullPolicy: Never  # Prevents Kubernetes from pulling from Docker Hub
          ports:
            - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: hello-world-service
spec:
  selector:
    app: hello-world
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer  # Exposes service externally (on Docker Desktop, use port-forward)

Apply the Deployment

Run the following commands to deploy:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl apply -f deployment.yaml
kubectl apply -f deployment.yaml
kubectl apply -f deployment.yaml
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
>kubectl apply -f deployment.yml
deployment.apps/hello-world-deployment created
service/hello-world-service created
>kubectl apply -f deployment.yml deployment.apps/hello-world-deployment created service/hello-world-service created
>kubectl apply -f deployment.yml
deployment.apps/hello-world-deployment created
service/hello-world-service created

Since Docker Desktop Kubernetes doesn’t assign an external IP, use:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl port-forward svc/hello-world-service 8080:80
kubectl port-forward svc/hello-world-service 8080:80
kubectl port-forward svc/hello-world-service 8080:80
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
>kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-deployment-857c5cfcf8-cdtjp 1/1 Running 0 35m
>kubectl get pods NAME READY STATUS RESTARTS AGE hello-world-deployment-857c5cfcf8-cdtjp 1/1 Running 0 35m
>kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
hello-world-deployment-857c5cfcf8-cdtjp   1/1     Running   0          35m

Access the application

Now access the application:

http://localhost:8080/api/hello