Let\'s try to build the simplest Java Spring application that runs as a pod in a Kubernetes cluster.
\n\nThe full project can be found on my GitHub.
\n\nThe project\'s structure:
\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Dockerfile\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradle\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 wrapper\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradle-wrapper.jar\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 gradle-wrapper.properties\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 gradlew\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 k8s\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 depl.yaml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 settings.gradle\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 java\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hello\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 App.java\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 HelloWorldCtrl.java\n
App.java
is our entry point:
\n
package hello;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class App {\n\n public static void main(String[] args) {\n SpringApplication.run(App.class, args);\n }\n\n}\n
and our controller simply returns "hello world" on the root path:
\n
package hello;\n\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@RestController\npublic class HelloWorldCtrl {\n\n @RequestMapping("/")\n public String index() {\n return "Greetings from Spring Boot!";\n }\n\n}\n
Now let\'s write a Dockerfile:
\n
FROM gradle:jdk10 as builder\n\nCOPY --chown=gradle:gradle . /app\nWORKDIR /app\nRUN gradle build\n\nEXPOSE 8080\nWORKDIR /app\n\nCMD java -jar build/libs/gs-spring-boot-0.1.0.jar\n
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:
\n
apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n name: hello-world\nspec:\n replicas: 2\n template:\n metadata:\n labels:\n app: hello-world\n visualize: "true"\n spec:\n containers:\n - name: hello-world-pod\n image: marounbassam/hello-spring\n ports:\n - containerPort: 8080\n---\napiVersion: v1\nkind: Service\nmetadata:\n labels:\n visualize: "true"\n name: hello-world-service\nspec:\n selector:\n app: hello-world\n ports:\n - name: http\n protocol: TCP\n port: 8080\n targetPort: 8080\n type: ClusterIP\n
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.
\n\nThe 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:
\n
kubectl create -f <yaml_file>\n
The resources can be visualized as follows:
\n
+---------------------+\n| hello-world-service |\n| |\n| 10.15.242.210 |\n+---------O-----------+\n |\n +-------------O--------------------------O\n | |\n +---------O-----------+ +---------O-----------+\n | pod 1 | | pod 2 |\n | | | |\n | hello-world | | hello-world |\n +---------------------+ +---------------------+\n
\n \n \n Inside The Cluster\n
\n\nIf 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:
\n
$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nhello-world-5bb87c95-6h4kh 1/1 Running 0 7h\nhello-world-5bb87c95-bz64v 1/1 Running 0 7h\n$ kubectl get svc\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\nhello-world-service ClusterIP 10.15.242.210 <none> 8080/TCP 5s\nkubernetes ClusterIP 10.15.240.1 <none> 443/TCP 7h\n$ kubectl exec -it hello-world-5bb87c95-6h4kh bash\n$ (inside the pod) curl 10.15.242.210:8080\n$ (inside the pod) Greetings from Spring Boot!\n
If you have any questions, please drop a comment.
\n\n\n