Voraussetzungen
docker / docker desktop
maven
-
MacOS:
brew install maven
-
Linux: maven is installed, but not maybe not the newest
Minikube
-
Minikube is also available in "docker desktop" and can be activated.
-
minikube can also installed independently of "docker desktop".
kubectl
-
Used for the communication with Minikube (and later on with the cloud).
-
It is highly recommended to install autocompletion für kubectl.
source <(kubectl completion zsh) # set up autocomplete in zsh into the current shell echo '[[ $commands[kubectl] ]] && source <(kubectl completion zsh)' >> ~/.zshrc # add autocomplete permanently to your zsh shell
1. Start minikube
We do not need minikube at the moment, but we will start to make sure that it is working.
minikube start
result
😄 minikube v1.32.0 on Darwin 14.3.1 (arm64) ✨ Automatically selected the docker driver 📌 Using Docker Desktop driver with root privileges 👍 Starting control plane node minikube in cluster minikube 🚜 Pulling base image ... 💾 Downloading Kubernetes v1.28.3 preload ... > preloaded-images-k8s-v18-v1...: 341.16 MiB / 341.16 MiB 100.00% 1.81 Mi > gcr.io/k8s-minikube/kicbase...: 410.57 MiB / 410.58 MiB 100.00% 1.36 Mi 🔥 Creating docker container (CPUs=2, Memory=7793MB) ... 🐳 Preparing Kubernetes v1.28.3 on Docker 24.0.7 ... ▪ Generating certificates and keys ... ▪ Booting up control plane ... ▪ Configuring RBAC rules ... 🔗 Configuring bridge CNI (Container Networking Interface) ... 🔎 Verifying Kubernetes components... ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5 🌟 Enabled addons: storage-provisioner, default-storageclass 🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
-
Falls die Meldung erscheint, dass der Cluster veraltet ist, dann
minikube stop
undminikube delete
. Beim anschließendenminikube start
wird ein Cluster mit aktueller kubernetes-Software erstellt. -
Check, in the "🌟 Enabled addons:"-section, that metrics-server and dashboard are installed.
-
When missing:
minikube addons enable metrics-server minikube addons enable dashboard
-
minikube addons list |grep enabled
| dashboard | minikube | enabled ✅ | Kubernetes | | default-storageclass | minikube | enabled ✅ | Kubernetes | | metrics-server | minikube | enabled ✅ | Kubernetes | | storage-provisioner | minikube | enabled ✅ | minikube |
1.1. Minikube configuration
-
For accessing minikube and later on k8s, we need kubectl.

-
check the correct configuration
kubectl config view
result
apiVersion: v1 clusters: - cluster: certificate-authority: /Users/stuetz/.minikube/ca.crt extensions: - extension: last-update: Sun, 17 Mar 2024 12:10:05 CET provider: minikube.sigs.k8s.io version: v1.32.0 name: cluster_info server: https://127.0.0.1:59820 name: minikube contexts: - context: cluster: minikube extensions: - extension: last-update: Sun, 17 Mar 2024 12:10:05 CET provider: minikube.sigs.k8s.io version: v1.32.0 name: context_info namespace: default user: minikube name: minikube current-context: minikube kind: Config preferences: {} users: - name: minikube user: client-certificate: /Users/stuetz/.minikube/profiles/minikube/client.crt client-key: /Users/stuetz/.minikube/profiles/minikube/client.key
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE * minikube minikube minikube default
2. Overview

-
First we create a simple REST-endpoint with quarkus.
-
We create an uber-jar.
-
We build a docker image with the jar-filee.
-
We push the docker image to an image registry (ghcr.io).
-
We deploy the docker image to minikube.
3. Create the quarkus Project
mvn io.quarkus.platform:quarkus-maven-plugin:3.8.2:create \
-DprojectGroupId=at.htl.minikube \
-DprojectArtifactId=minikube-demo \
-Dextensions='resteasy-reactive, smallrye-health'
or start the script create-project.sh
result
[INFO] Scanning for projects... [INFO] [INFO] ------------------< org.apache.maven:standalone-pom >------------------- [INFO] Building Maven Stub Project (No POM) 1 [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- quarkus:3.7.3:create (default-cli) @ standalone-pom --- [INFO] Looking for the newly published extensions in registry.quarkus.io [INFO] ----------- [INFO] selected extensions: - io.quarkus:quarkus-smallrye-health - io.quarkus:quarkus-resteasy-reactive [INFO] applying codestarts... [INFO] 📚 java 🔨 maven 📦 quarkus 📝 config-properties 🔧 tooling-dockerfiles 🔧 tooling-maven-wrapper 🚀 resteasy-reactive-codestart 🚀 smallrye-health-codestart [INFO] ----------- [SUCCESS] ✅ quarkus project has been successfully generated in: --> /Users/stuetz/work/_delete/minikube-demo ----------- [INFO] [INFO] ======================================================================================== [INFO] Your new application has been created in /Users/stuetz/work/_delete/minikube-demo [INFO] Navigate into this directory and launch your application with mvn quarkus:dev [INFO] Your application will be accessible on http://localhost:8080 [INFO] ======================================================================================== [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4.232 s [INFO] Finished at: 2024-02-19T08:12:54+01:00 [INFO] ------------------------------------------------------------------------
or create a project on quarkus.io - START CODING.
On quarkus.io you can also create a github-repo automatically. |

5. Request the REST-Endpoints
-
Create a REST-Client
-
New folder in project-Root:
http-requests
-
create a new file in this folder:
requests.http
-

-
you can also use cURL:
curl -i http://localhost:8080/hello (1)
1 | -i shows the header of the response. |
result
HTTP/1.1 200 OK content-length: 28 Content-Type: text/plain;charset=UTF-8 Hello from RESTEasy Reactive%
7. Create docker Image
-
Therefore, we need a
Dockerfile
. -
There are already Dockerfiles in
src/main/docker
- these are not needed and can be deleted -
Create a new Dockerfile in
src/main/docker
result
... ├── src │ ├── main │ │ ├── docker │ │ │ └── Dockerfile ...
FROM eclipse-temurin:17-jre
RUN mkdir -p /opt/application
COPY *-runner.jar /opt/application/backend.jar
WORKDIR /opt/application
CMD [ "java", "-jar", "backend.jar" ]

-
The following steps should be automated, but for now we do it manually:
cp src/main/docker/Dockerfile target
docker build --tag ghcr.io/htl-leonding/backend:latest ./target
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE ... gghcr.io/htl-leonding/backend latest ae27690f900d 53 seconds ago 263MB ...
8. Docker image push to Docker Registry
docker login ghcr.io
You need a personal token to authenticate (click for instructions)
-
github - profile picture - Settings - Developer Settings - Personal access tokens - Tokens (classic)


Troubleshooting:
-
When your gh-user-name contains uppercase letters, change the name to lowercase.
-
When it still, does not work, then delete
~/.docker/config.json
and try it again.
docker push ghcr.io/htl-leonding/backend:latest
result
The push refers to repository [ghcr.io/htl-leonding/backend] 5f70bf18a086: Layer already exists 2359f2e5d796: Pushed 08b2bdc5762e: Layer already exists 6e0f58883206: Layer already exists eed4bd617b87: Layer already exists 65bb8dcc703b: Layer already exists 63aa4237e067: Layer already exists 98d1994bf6c1: Layer already exists latest: digest: sha256:50c58e0426ad4b4335c791d7f60efcad24cc9c5554d5e7f35f0438186af508ca size: 1992
Make package public (click for instructions)




9. Configure kubernetes Deployment
mkdir k8s touch k8s/appsrv.yaml
# Quarkus Application Server
apiVersion: apps/v1
kind: Deployment
metadata:
name: appsrv
spec:
replicas: 1
selector:
matchLabels:
app: appsrv
template:
metadata:
labels:
app: appsrv
spec:
containers:
- name: appsrv
image: ghcr.io/htl-leonding/backend:latest (1)
# remove this when stable. Currently we do not take care of version numbers
imagePullPolicy: Always
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /q/health
port: 8080
timeoutSeconds: 5
initialDelaySeconds: 15
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /q/health
port: 8080
timeoutSeconds: 5
initialDelaySeconds: 60
periodSeconds: 120
---
apiVersion: v1
kind: Service
metadata:
name: appsrv
spec:
ports:
- port: 8080
targetPort: 8080
protocol: TCP
selector:
app: appsrv
1 | Check, that your image name is correct |
You could also generate this file with kubectl
kubectl create deployment appsrv --image=ghcr.io/htl-leonding/backend:latest --port=8080
deployment.apps/appsrv created
kubectl get deployments/appsrv -o yaml > appsrv.yaml
kubectl expose deployments/appsrv --port=8080
kubectl expose deployments/appsrv-depl --port=8080
10. Deploy to minikube the first time
kubectl apply -f k8s/appsrv.yaml
result
deployment.apps/appsrv created service/appsrv created
10.1. Check the Success
minikube dashboard
result
🤔 Verifying dashboard health ... 🚀 Launching proxy ... 🤔 Verifying proxy health ... 🎉 Opening http://127.0.0.1:53209/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...
-
The following site should be opened in your browser
-
if not just use
minikube --url
and copy the given url into your browser
-

-
We notice there are problems
11. Re-Deploy to minikube
build and push the image
./mvnw clean package cp src/main/docker/Dockerfile target docker build --tag ghcr.io/htl-leonding/backend:latest ./target docker push ghcr.io/htl-leonding/backend:latest
kubectl rollout restart deployment appsrv
-
Now you see the new pod is already running and the old (broken) pod is still alive.

-
The broken pods are now history

12. Port Forward from minikube
kubectl port-forward appsrv-xxxxxx-xxxxx 8080:8080
Use kubectl-autocomplete for the appsrv |
result
❯ kubectl port-forward appsrv-7964857d64-2bhcp 8080:8080 Forwarding from 127.0.0.1:8080 -> 8080 Forwarding from [::1]:8080 -> 8080