Let's try to build the simplest Java Spring application that runs as a pod in a Kubernetes cluster.
The full project can be found on my GitHub.
The project's structure:
├── Dockerfile
├── README.md
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── k8s
│ └── depl.yaml
├── settings.gradle
└── src
└── main
└── java
└── hello
├── App.java
└── HelloWorldCtrl.java
App.java
is our entry point:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
and our controller simply returns "hello world" on the root path:
package hello;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloWorldCtrl {
@RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
}
Now let's write a Dockerfile:
FROM gradle:jdk10 as builder
COPY --chown=gradle:gradle . /app
WORKDIR /app
RUN gradle build
EXPOSE 8080
WORKDIR /app
CMD java -jar build/libs/gs-spring-boot-0.1.0.jar
It uses Gradle in order to build the application, and the CMD
instruction runs the JAR file.
The K8s deployment is simple. It consists of a deployment and a service:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 2
template:
metadata:
labels:
app: hello-world
visualize: "true"
spec:
containers:
- name: hello-world-pod
image: marounbassam/hello-spring
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
labels:
visualize: "true"
name: hello-world-service
spec:
selector:
app: hello-world
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
The deployment defines two replicas of the pod that will be running the container that's built from the image specified in the image attribute.
The service is of type ClusterIP
(the default Kubernetes service). It gives us a service inside our cluster that other apps can access.
Creating the resources in your cluster:
kubectl create -f <yaml_file>
The resources can be visualized as follows:
+---------------------+
| hello-world-service |
| |
| 10.15.242.210 |
+---------O-----------+
|
+-------------O--------------------------O
| |
+---------O-----------+ +---------O-----------+
| pod 1 | | pod 2 |
| | | |
| hello-world | | hello-world |
+---------------------+ +---------------------+
Inside The Cluster
If you're using minikube for running the cluster locally, you might encounter issues (I really don't know why). But if you're running on a cloud provider, or something more "serious" than minikube, you should be able to do the following:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-5bb87c95-6h4kh 1/1 Running 0 7h
hello-world-5bb87c95-bz64v 1/1 Running 0 7h
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world-service ClusterIP 10.15.242.210 <none> 8080/TCP 5s
kubernetes ClusterIP 10.15.240.1 <none> 443/TCP 7h
$ kubectl exec -it hello-world-5bb87c95-6h4kh bash
$ (inside the pod) curl 10.15.242.210:8080
$ (inside the pod) Greetings from Spring Boot!
If you have any questions, please drop a comment.
Top comments (0)