본문 바로가기

software engineering

Building SpringBoot application for Kubernetes on RaspberryPi

Prerequisite

Building SpringBoot application

spring initializer

spring initializer is a tool that creates bolier plate spring boot application code for you. All you have to do is just to enter some of the application meta informaion including project type, language, project metadata, and etc.

Gradle is my perference, so I selected it.

I selected JVM 8 because I am going to use hypriot/rpi-java in this tutorial which is compatible with JVM 8.

I also added Sprinng Boot Actuator as dependency, to make it easy to test. (and it is also usuful for healthcheck and metrics emission)

Click on "Generate" button once you've selected and entered all of the information.

The first build

Let's see if it builds fine.

$ ./gradlew build

BUILD SUCCESSFUL

And run the application. The jar file should be somewhere under the build directory.

$ java -jvar build/libs/<user-app-name>-<version>.jar

See if the actuator works good by sending a request using curl.

$ curl localhost:8080/actuator | jq .
{
  "_links": {
    "self": {
      "href": "http://localhost:8080/actuator",
      "templated": false
    },
    "health-path": {
      "href": "http://localhost:8080/actuator/health/{*path}",
      "templated": true
    },
    "health": {
      "href": "http://localhost:8080/actuator/health",
      "templated": false
    },
    "info": {
      "href": "http://localhost:8080/actuator/info",
      "templated": false
    }
  }
}

Containerize

You can make a container of the applicaion. Spring Boot plugin provides build target that creates it.

$ ./gradlew bootBuildImage

You can run the container locally.

$ docker run -p 8080:8080 <user-app-name>:<version>

See if it works fine.

$ curl localhost:8080/actuator/health

That's pretty simple and good.

Unfortunately, however, the image is not going to work on Pi unless you are using arm archtecture based machine. Next section will guide you how to cross build image that runs on Pi.

Containerize for Pi

Because I was not able to find a way to cross build image for arm architecture using spring boot plugin, I had to craete a Dockerfile to cross build the image. But don't worry, it's just as simple as using the plugin.

Let's create a Dockerfile.

FROM hypriot/rpi-java

ADD build/libs/<your-app-name>-<version>.jar /opt/<your-app-name>-<version>.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "/opt/<your-app-name>-<version>.jar"]

And build the image using docker command line tool.

$ docker build .

Sending build context to Docker daemon  29.19MB
Step 1/4 : FROM hypriot/rpi-java
 ---> 5a0a1862caef

...

Removing intermediate container 40c878931eec
 ---> 73713288f684
Successfully built 73713288f684

Let's copy the hash at the end of the lines to create a tag.

$ docker tag <hash> <your-docker-account>/<app-name>:<version>

For example,

$ docker tag 73713288f684 toysmars/demo:0.0.1-SNAPSHOT

And push the image to docer hub.

$ docker push <your-docker-account>/<app-name>

Kubernetes deployment

Now, it's time to deploy the image to Kubernetes on Pi.

Let's create deployment.yml and service.yml files first.

$ kubectl create deployment demo --image=<your-docker-account>/<app-name>:<version> --dry-run -o=yaml > deployment.yaml
$ kubectl create service clusterip demo --tcp=8080:8080 --dry-run -o=yaml > service.yaml

And apply them.

$ kubectl apply -f deployment.yml
$ kubectl apply -f service.yml

See if pods are ready, I replaced replica to 2 so that I can test it runs on my Kubernetes cluster.

$ kubectl get pods
NAME                   READY   STATUS    RESTARTS   AGE
demo-c848c6b8c-2k84r   1/1     Running   0          2m
demo-c848c6b8c-p8wm4   1/1     Running   0          2m

To connect to the service, I found it's easiest way to set SSH turnel for testing purpose.

$ kubectl port-forward service/demo 8080:8080

Check if it works fine.

$ curl localhost:8080/actuator/health | jq 
{
  "status": "UP",
  "groups": [
    "liveness",
    "readiness"
  ]
}