--- title: Kubernetes for the Busy Neo4j Developer tags: Workshop description: View the slide with "Slide Mode". --- # Kubernetes for the Busy Neo4j Developer! [![hackmd-github-sync-badge](https://hackmd.io/k7mOYp-PSWSeP7hsu3C_ng/badge)](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 ``` ![Screenshot 2024-04-13 at 18.52.04](https://hackmd.io/_uploads/B1SUUBueR.png) ## 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. ![Screenshot 2024-04-15 at 14.51.35](https://hackmd.io/_uploads/r1LxQsqxR.png) ### 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` ![Screenshot 2024-04-15 at 16.56.11](https://hackmd.io/_uploads/S1KGgTceR.png) 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`