---
title: Kubernetes for the Busy Neo4j Developer
tags: Workshop
description: View the slide with "Slide Mode".
---
# Kubernetes for the Busy Neo4j Developer!
[](https://hackmd.io/k7mOYp-PSWSeP7hsu3C_ng)
GitHub: https://github.com/ojhughes/engineer-offsite-k8s
---
This is a collaborative, hands on workshop - you can use your own laptop or work with a buddy
---
## What we wll do
- Learn some basic Kubernetes (aka K8s) in a collaborative way
- Set up prerequesite tools
- Deploy a simple Java application to K8s
- Build a Docker image for the app
- Push the app to a Docker repo
- Create deployment and service descriptors for Kubernetes
- Deploy and run the app on Kubernetes
---
## Prerequesites
- A laptop to follow along with the examples. Ideally Linux, Mac or Windows with [ WSL installed ](https://learn.microsoft.com/en-us/windows/wsl/install). You can pair up with someone if you don't have a laptop.
- Basic knowledge of Maven and Linux command line (but don't worry we can help if you get stuch)
---
## Required Tools
We are going to need to install some tools on our machine to run through the workshop.
:::info
:question: **Please ask for help if you have trouble installing any of the tools**
:::
- [Java JDK 21 ](https://adoptium.net/en-GB/temurin/releases/)(**Not JRE**)
- The example can probably be downgraded to an earlier version if you want
- You can install the JDK using from
- [The Temurin relase page](https://adoptium.net/en-GB/temurin/releases/)
- Using Homebrew for Mac users
`brew tap homebrew/cask-versions`
`brew install --cask temurin`
- Using the [SDKMan](https://sdkman.io/install) tool
- Using a Linux package manager
- [git](https://github.com/git-guides/install-git)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [minikube](https://kubernetes.io/docs/tasks/tools/#minikube)
- [IntelliJ](https://www.jetbrains.com/help/idea/installation-guide.html)
- VSCode will also work
- Enable the [Kubernetes plugin](https://www.jetbrains.com/help/idea/kubernetes.html) for IntelliJ **or** [K8s extension for VSCode](https://code.visualstudio.com/docs/azure/kubernetes)
- Docker ([see here if running Mac or Windows](#Setting-up-Docker-Desktop--Colima-for-Minikube))
---
## Setting up Minikube
Minikube is a popular tool that allows developers to run Kubernetes locally. It simplifies the process of learning and experimenting with Kubernetes by enabling a single-node Kubernetes cluster.
### Setting up Docker Desktop / Colima for Minikube
:::success
This step doesn't apply to Linux users as you can install Docker natively
:::
If you have an M1 / M2 Mac, you will need to either install Docker Desktop or Colima to run Minikube. If you have an Intel based Mac you can either use Docker or the Hyperkit Driver to run Minikube (I haven't tested this!)
#### Option 1: Installing Docker Desktop
Note Docker Desktop is **Paid Software** but free for personal use
https://docs.docker.com/desktop/install/mac-install/
#### Option 2: Installing Colima
https://github.com/abiosoft/colima
### Starting Minikube
Assuming you have already installed Minikube in the previous step, start it up using the command;
```bash
minikube start
```
### Verifying the Installation
After starting Minikube, verify that it's running correctly:
```bash
minikube status
```
This should show the following output;
```bash
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
```
Next verify that the `kubectl` CLI is installed and configured correctly using the command;
```bash
kubectl get nodes
```
The output should look like this;
```bash
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 2d3h v1.28.3
```
### (Optional) Using the Minikube dashboard
Minikube includes a built-in dashboard for K8s, which provides a web-based user interface to interact with your cluster:
```bash
minikube dashboard
```

## Cloning and exploring the sample application
A simple "Hello World" Java API was created for the workshop. It is built using Dropwizard, which is a simple and lightweight Java web framework.
Grab the sample application by cloning it from GitHub
```bash
git clone git@github.com:ojhughes/engineer-offsite-k8s.git
cd engineer-offsite-k8s
```
Now verify that you can build the app using Maven;
```bash
./mvnw package
```
---
## Containerising the Java Application Using Jib
---
In order to deploy our application on K8s, we need to first package it as a Docker image. Conceptually, a docker image is quite similar to a Jar file. A docker image will usually contain a number of layers such as the base operating system, libraries and the application binaries.

### Using Jib to build the Docker Image
[Jib](https://github.com/GoogleContainerTools/jib) is a tool created at Google for building images for Java applications. It is packaged as both a Maven and Gradle plugin, so can easily be integrated with existing build processes. Jib is useful because it packages the Docker image in an efficient way and saves the effort of creating your own `Dockerfile`
### Setting Up Jib with Maven
To use Jib with Maven, you'll need to add the Jib Maven plugin to the `pom.xml` file.
Open the `pom.xml` in your editor and the following snippet inside of the `<plugins></plugins>` tags;
```xml!
<build>
<plugins>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>${jib-maven-plugin.version}</version>
<configuration>
<from>
<image>openjdk:21-jdk-slim</image>
</from>
<to>
<image>neo4jdev/dropwizard-jib-example:1</image>
</to>
<container>
<args>
<arg>server</arg>
<arg>${jib.container.appRoot}/resources/${dropwizard.server.config}</arg>
</args>
<ports>
<port>8080</port>
</ports>
<jvmFlags>
<jvmFlag>-server</jvmFlag>
<jvmFlag>-Djava.awt.headless=true</jvmFlag>
<jvmFlag>-XX:+UseG1GC</jvmFlag>
<jvmFlag>-Xms256m</jvmFlag>
<jvmFlag>-Xmx256m</jvmFlag>
</jvmFlags>
</container>
</configuration>
<executions>
<execution>
<id>dockerBuild</id>
<goals>
<goal>dockerBuild</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
```
:::danger
If you are using an M1 / M2 Mac - you need to add this configuration to use an arm64 base image
:::
```xml!
<configuration>
<from>
<platforms>
<platform>
<architecture>arm64</architecture>
<os>linux</os>
</platform>
</platforms>
</from>
```
### Building a Docker image
Jib will build the Docker image for us and load it to an image registry.
We have two choices here 1. Load the image into Minkubes docker daemon or 2. Create an account on Dockerhub and load the image to our own public image registry. These instructions will load the image into Minikube for simplicity.
```bash!
# This command sets the environment to use minikubes docker registry
eval $(minikube docker-env)
./mvnw compile jib:dockerBuild
```
Then we can see the image
```bash!
minikube image ls
```
---
## Create a K8s Deployment
Now we have an image for our app, we need to tell Kubernetes how to run this image is a container. We will create a Deployment resource, this will instruct Kubernetes where to find our image and what configuration we want to use to run it (such as environment variables or volume mounts). We don't have enough time to fully explain how deployments work, but you can read abou them here: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
First create a `k8s` directory in the `engineer-offsite-k8s` directory we cloned earlier
```
cd engineer-offsite-k8s
mkdir k8s
```
Then in your editor, create a new file `deployment.yaml`.
If you have the k8s plugin installed, you can use autocomplete to generate the file by typing `k`

The autocomplete will prompt you to complete the template for the deployment. You should end up with a file like this;
```yaml!
apiVersion: apps/v1
kind: Deployment
metadata:
name: dropwizard-jib-example
labels:
app: dropwizard-jib-example
spec:
replicas: 1
selector:
matchLabels:
app: dropwizard-jib-example
template:
metadata:
name: dropwizard-jib-example
labels:
app: dropwizard-jib-example
spec:
containers:
- name: dropwizard-jib-example
image: neo4jdev/dropwizard-jib-example:1
imagePullPolicy: Never
restartPolicy: Always
```
Note, we set `imagePullPolicy: Never` to force minikube to use the image in it's local Docker daemon instead trying to pull it from the internet.
### Running the Deployment
Now we have created the deployment manifest, we can apply it to the cluster. Doing this will create a new container from the image we built earlier
```bash!
kubectl apply -f k8s/deployment.yaml
```
Then we can check that the Pod has been created successfully.
```bash!
kubectl get pods
NAME READY STATUS RESTARTS AGE
dropwizard-jib-example-5c887757c7-f2k2w 1/1 Running 0 16m
```
And we can also look at the logs from our container
```bash!
kubectl logs deploy/dropwizard-jib-example
```
### Accessing the API
You can see from the logs, our container is running on port 8080. We can create a port forward to test the api
```bash!
kubectl port-forward deployments/dropwizard-jib-example 8080:8080
```
Then in another terminal or the browser you can check the API is working;
```bash!
curl localhost:8080/?name=ollie
{"id":1,"content":"${'Hello, ollie!'}"}%
```
And we can check the health endpoint is working
```bash!
curl http://localhost:8080/admin/healthcheck\?pretty\=true
{
"deadlocks" : {
"healthy" : true,
"duration" : 0,
"timestamp" : "2024-04-15T15:23:41.167Z"
},
"template" : {
"healthy" : true,
"duration" : 0,
"timestamp" : "2024-04-15T15:23:41.167Z"
}
}%
```
### Next steps
Sticking with the Unconference theme, we can freestyle and choose what to look at next... We could configure our health probes, add a `ConfigMap` or learn about some other `kubectl commands`