This project uses Quarkus, the Supersonic Subatomic Java Framework.
The goal of this project is to demonstrate with a practical example how to implement a Kubernetes operator using Quarkus and the Java Operator SDK. This operator manages the creation/update of one or more mockserver instances preconfigured with the setup defined in the CRD. Although this example is very simple, it represents an excellent template of an operator as it allows you to manage the configuration and updating of many "secondary resources". Starting from this example it is possible to solve more complex cases.
First you neet to configure your ~/. kube/config
because, when run locally the framework will use your Kubernetes client configuration to establish a connection to the cluster.
You can clone the git repository and run the application locally:
./mvnw compile quarkus:dev
this give you the opportunity to debug the code if you want.
TBD
The operator create a new CRD named Mockserver
that can be used to define our new Mockserver objects.
We can create a simple new Mockserver as the following:
kubectl apply -f - <<EOF
apiVersion: "rmarcello.mockserveroperator/v1"
kind: Mockserver
metadata:
name: mockserver-test
spec:
replica: 1
image: mockserver/mockserver:latest
ingressHost: mockserver.local
config: |
[
{
"httpRequest": {
"path": "/hello"
},
"httpResponse": {
"statusCode": 200,
"body": {
"json": {
"message": "Hello World"
}
}
}
}
]
EOF
we can see the following:
$ kubectl get Mockserver
NAME AGE
mockserver-test 26m
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mockserver-test ClusterIP 10.106.5.11 <none> 8080/TCP 9m13s
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
mockserver-test 1/1 1 1 9m43s
$ kubectl get cm
NAME DATA AGE
mockserver-test 1 10m
$ kubectl get ing
NAME DATA AGE
mockserver-test 1 10m
$ kubectl get mockserver mockserver-test -oyaml
apiVersion: rmarcello.mockserveroperator/v1
kind: Mockserver
metadata:
finalizers:
- mockservers.rmarcello.mockserveroperator/finalizer
generation: 1
name: mockserver-test
namespace: default
spec:
config: |
[
{
"httpRequest": {
"path": "/hello"
},
"httpResponse": {
"statusCode": 200,
"body": {
"json": {
"message": "Hello World"
}
}
}
}
]
image: mockserver/mockserver:latest
ingressHost: mockserver.local
replica: 1
status:
areWeGood: true
externalUrl: http://mockserver.local
internalUrl: http://mockserver-test.default.svc.cluster.local:8080
observedGeneration: 1
After the creation or the update of the Mockserver
the operator will work for us to change the kubernetes object status in order to reach the desired state.
The first time the Mockserver
is created, the object are created and the following time in case of update the operator will update these resources.
When the object is deleted, the operator will clean all the owned resources.
kubectl port-forward svc/mockserver-test 8080:8080
from your browser: http://localhost:8080/mockserver/dashboard:
we can see the initialization data.
curl http://localhost:8080/hello
from your browser: http://mockserver.local/mockserver/dashboard
or via API:
$ curl http://mockserver.local/hello
{
"message" : "Hello World"
}
When we change the CRD changing the configuration:
kubectl apply -f - <<EOF
apiVersion: "rmarcello.mockserveroperator/v1"
kind: Mockserver
metadata:
name: mockserver-test
spec:
replica: 1
image: mockserver/mockserver:latest
ingressHost: mockserver.local
config: |
[
{
"httpRequest": {
"path": "/hello"
},
"httpResponse": {
"statusCode": 200,
"body": {
"json": {
"message": "Updated message!!!"
}
}
}
}
]
EOF
The operator will update the Mockserver and add the new API:
$ curl http://localhost:8080/hello
{
"message" : "Updated message!!!"
}
When we delete the CRD:
$ kubectl delete Mockserver mockserver-test
mockserver.rmarcello.mockserveroperator "mockserver-test" deleted
the operator will clean the environment deleteing all the resources owned by the CRD.
The application can be packaged using:
./mvnw package
It produces the quarkus-run.jar
file in the target/quarkus-app/
directory.
Be aware that it’s not an über-jar as the dependencies are copied into the target/quarkus-app/lib/
directory.
The application is now runnable using java -jar target/quarkus-app/quarkus-run.jar
.
If you want to build an über-jar, execute the following command:
./mvnw package -Dquarkus.package.type=uber-jar
The application, packaged as an über-jar, is now runnable using java -jar target/*-runner.jar
.
You can create a native executable using:
./mvnw package -Pnative
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
./mvnw package -Pnative -Dquarkus.native.container-build=true
You can then execute your native executable with: ./target/mockserver-operator-1.0.0-SNAPSHOT-runner
If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling.