Quarkus – Supersonic Subatomic Java, trying out Quarkus guide “Quarkus – Kubernetes extension” (part 3)

Marc Lameriks

In this article, you can read more about the Quarkus code guide I tried out, related to the following topic:

  • The ability to automatically generate Kubernetes resources by Quarkus

The guide covers generating and deploying Kubernetes resources based on sane defaults and user supplied configuration. In this article, I will focus on the automatic deployment of the generated resources to a target platform, in my case K3s (lightweight certified Kubernetes distribution).

Quarkus guide “Quarkus – Kubernetes extension”

I continue where I left the previous time, with the steps from the Quarkus guide “Quarkus – Kubernetes extension”, still using the code in my existing “getting-started” project (as described in my previous article) . You may remember that amongst the other files, two files named kubernetes.json and kubernetes.yml were created in the target/kubernetes/ directory.
If you look at either file you will see that it contains a Kubernetes ServiceAccount, Service and a Deployment.
[https://technology.amis.nl/2020/10/03/quarkus-supersonic-subatomic-java-trying-out-quarkus-guide-quarkus-kubernetes-extension-part-2/]

By the way, Quarkus has the ability to push a created container image to a registry before deploying the application to the target platform. I skipped trying that out for now.

Deployment targets

By default, when no deployment-target is set, then only vanilla Kubernetes resources are generated and deployed to a cluster (if quarkus.kubernetes.deploy has been set to true). That was fine by me.

Please see the documentation, for generating resources and deploying to a Kubernetes cluster like:
[https://quarkus.io/guides/deploying-to-kubernetes]

In my demo environment I had K3s (lightweight certified Kubernetes distribution) installed.
[https://k3s.io/]

Automatic deployment

To trigger building and deploying a container image you need to enable the quarkus.kubernetes.deploy flag (the flag is disabled by default – furthermore it has no effect during test runs or dev mode).
[https://quarkus.io/guides/deploying-to-kubernetes#deployment]

In order to build and deploy a container image, I used the following command on the Linux Command Prompt:

./mvnw clean package -Dquarkus.kubernetes.deploy=true

Unfortunately, I got the following build error, related to my demo environment:


[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:1.7.0.Final:build (default) on project getting-started: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR]         [error]: Build step io.quarkus.kubernetes.deployment.KubernetesDeployer#deploy threw an exception: java.lang.RuntimeException: Although a Kubernetes deployment was requested, it however cannot take place because there was an error during communication with the API Server at 'https://kubernetes.default.svc/'

So, apparently the Kubernetes API Server could not be contacted.

The code guide (after reading a few lines further down) gave me an answer about what was wrong.

When deployment is enabled, the Kubernetes extension will select the resources specified by quarkus.kubernetes.deployment.target and deploy them. This assumes that a .kube/config is available in your user directory that points to the target Kubernetes cluster. In other words, the extension will use whatever cluster kubectl uses. The same applies to credentials.
[https://quarkus.io/guides/deploying-to-kubernetes#deploying]

In order to create the .kube/config file in my user (/home/vagrant) directory on my demo environment, I used the following command on the Linux Command Prompt:

With the following output:


total 20
drwxr-xr-x 7 vagrant vagrant 4096 Sep 13 15:18 ..
drwxr-x--- 3 vagrant vagrant 4096 Sep 13 15:18 cache
drwxr-x--- 3 vagrant vagrant 4096 Sep 13 15:40 http-cache
drwxr-x--- 4 vagrant vagrant 4096 Sep 13 17:18 .
-rw-rw-r-- 1 vagrant vagrant 1044 Sep 13 17:39 config

In order to build and deploy a container image, again I used the following command on the Linux Command Prompt:

cd /vagrant/applications/getting-started
./mvnw clean package -Dquarkus.kubernetes.deploy=true

With the following output:


[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.acme:getting-started >----------------------
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ getting-started ---
[INFO] Deleting /vagrant/applications/getting-started/target
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:prepare (default) @ getting-started ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /vagrant/applications/getting-started/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:prepare-tests (default) @ getting-started ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /vagrant/applications/getting-started/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /vagrant/applications/getting-started/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ getting-started ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.acme.getting.started.GreetingResourceTest
2020-09-21 13:51:09,412 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.kubernetes.deploy" was provided; it will be ignored; verify that the dependency extension for this configuration is set or you did not make a typo
2020-09-21 13:51:10,202 INFO  [io.quarkus] (main) Quarkus 1.7.0.Final on JVM started in 4.759s. Listening on: http://0.0.0.0:8081
2020-09-21 13:51:10,202 INFO  [io.quarkus] (main) Profile test activated.
2020-09-21 13:51:10,203 INFO  [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 13.899 s - in org.acme.getting.started.GreetingResourceTest
2020-09-21 13:51:14,017 INFO  [io.quarkus] (main) Quarkus stopped in 0.045s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ getting-started ---
[INFO] Building jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:build (default) @ getting-started ---
[INFO] [org.jboss.threads] JBoss Threads version 3.1.1.Final
[WARNING] [io.quarkus.kubernetes.deployment.KubernetesDeployer] A Kubernetes deployment was requested, but the container image to be built will not be pushed to any registry because "quarkus.container-image.registry" has not been set. The Kubernetes deployment will only work properly if the cluster is using the local Docker daemon. For that reason 'ImagePullPolicy' is being force-set to 'IfNotPresent'.
[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building thin jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-runner.jar
[WARNING] [io.quarkus.kubernetes.deployment.KubernetesProcessor] No registry was set for the container image, so 'ImagePullPolicy' is being force-set to 'IfNotPresent'.
[INFO] Checking for existing resources in: /vagrant/applications/getting-started/src/main/kubernetes.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeploy] Kubernetes API Server at 'https://127.0.0.1:6443/' successfully contacted.
[INFO] [io.quarkus.container.image.docker.deployment.DockerWorking] Docker daemon found. Version:'19.03.12'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Building docker image for jar.
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Executing the following command to build docker image: 'docker build -f /vagrant/applications/getting-started/src/main/docker/Dockerfile.jvm -t vagrant/getting-started:1.0-SNAPSHOT /vagrant/applications/getting-started'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Sending build context to Docker daemon  11.09MB
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 1/11 : FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 91d23a64fdf2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 2/11 : ARG JAVA_PACKAGE=java-11-openjdk-headless
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 3818465cc8fa
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 3/11 : ARG RUN_JAVA_VERSION=1.3.8
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> c45c7ada9216
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 4/11 : ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> eea2c4e04c6c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 5/11 : RUN microdnf install curl ca-certificates ${JAVA_PACKAGE}     && microdnf update     && microdnf clean all     && mkdir /deployments     && chown 1001 /deployments     && chmod "g+rwX" /deployments     && chown 1001:root /deployments     && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh     && chown 1001 /deployments/run-java.sh     && chmod 540 /deployments/run-java.sh     && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> eedc98908837
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 6/11 : ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> ef0d7a761730
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 7/11 : COPY target/lib/* /deployments/lib/
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> d8153bf53db2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 8/11 : COPY target/*-runner.jar /deployments/app.jar
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 29c8cb2728a9
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 9/11 : EXPOSE 8080
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in 357e10f70946
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container 357e10f70946
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 6c0c45ae950a
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 10/11 : USER 1001
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in cc1e69f157cd
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container cc1e69f157cd
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 4f1a7ea4cc5f
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 11/11 : ENTRYPOINT [ "/deployments/run-java.sh" ]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in 6b9c8969b315
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container 6b9c8969b315
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> a4f6437458b3
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully built a4f6437458b3
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully tagged vagrant/getting-started:1.0-SNAPSHOT
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Built container image vagrant/getting-started:1.0-SNAPSHOT (a4f6437458b3)

[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Deploying to kubernetes server: https://127.0.0.1:6443/ in namespace: default.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: ServiceAccount my-quarkus-kubernetes-name.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Service my-quarkus-kubernetes-name.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Deployment my-quarkus-kubernetes-name.
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 15738ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  43.627 s
[INFO] Finished at: 2020-09-21T13:51:30Z
[INFO] ------------------------------------------------------------------------
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

Remark about the namespace:
As you can see in the output, namespace default is used, although in the Kubernetes manifests I used namespace nl-amis-development. This is to be expected because my custom namespace does not yet exist.

In order to check the resources that where created, I used the following command on the Linux Command Prompt:

kubectl get all --all-namespaces

With the following output:

NAMESPACE              NAME                                             READY   STATUS      RESTARTS   AGE
kube-system            pod/metrics-server-7566d596c8-gxrjt              1/1     Running     0          32d
kube-system            pod/helm-install-traefik-7mps6                   0/1     Completed   0          32d
kube-system            pod/local-path-provisioner-6d59f47c7-vtb4t       1/1     Running     0          32d
kube-system            pod/coredns-8655855d6-qxqhf                      1/1     Running     0          32d
kube-system            pod/svclb-traefik-hdxqf                          2/2     Running     0          32d
kube-system            pod/traefik-758cd5fc85-m4cvj                     1/1     Running     0          32d
kubernetes-dashboard   pod/kubernetes-dashboard-7b544877d5-l4qfb        1/1     Running     0          32d
kubernetes-dashboard   pod/dashboard-metrics-scraper-6b4884c9d5-hdxmn   1/1     Running     0          32d

NAMESPACE              NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default                service/kubernetes                   ClusterIP      10.43.0.1       <none>        443/TCP                      32d
kube-system            service/kube-dns                     ClusterIP      10.43.0.10      <none>        53/UDP,53/TCP,9153/TCP       32d
kube-system            service/metrics-server               ClusterIP      10.43.183.35    <none>        443/TCP                      32d
kube-system            service/traefik-prometheus           ClusterIP      10.43.50.120    <none>        9100/TCP                     32d
kube-system            service/traefik                      LoadBalancer   10.43.116.205   10.0.2.15     80:30676/TCP,443:31713/TCP   32d
kubernetes-dashboard   service/kubernetes-dashboard         ClusterIP      10.43.175.253   <none>        443/TCP                      32d
kubernetes-dashboard   service/dashboard-metrics-scraper    ClusterIP      10.43.5.8       <none>        8000/TCP                     32d
default                service/my-quarkus-kubernetes-name   NodePort       10.43.220.219   <none>        8090:31939/TCP               15m

NAMESPACE     NAME                           DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kube-system   daemonset.apps/svclb-traefik   1         1         1       1            1           <none>          32d

NAMESPACE              NAME                                         READY   UP-TO-DATE   AVAILABLE   AGE
kube-system            deployment.apps/metrics-server               1/1     1            1           32d
kube-system            deployment.apps/local-path-provisioner       1/1     1            1           32d
kube-system            deployment.apps/coredns                      1/1     1            1           32d
kube-system            deployment.apps/traefik                      1/1     1            1           32d
kubernetes-dashboard   deployment.apps/kubernetes-dashboard         1/1     1            1           32d
kubernetes-dashboard   deployment.apps/dashboard-metrics-scraper    1/1     1            1           32d
default                deployment.apps/my-quarkus-kubernetes-name   0/3     0            0           15m

NAMESPACE              NAME                                                    DESIRED   CURRENT   READY   AGE
kube-system            replicaset.apps/metrics-server-7566d596c8               1         1         1       32d
kube-system            replicaset.apps/local-path-provisioner-6d59f47c7        1         1         1       32d
kube-system            replicaset.apps/coredns-8655855d6                       1         1         1       32d
kube-system            replicaset.apps/traefik-758cd5fc85                      1         1         1       32d
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-7b544877d5         1         1         1       32d
kubernetes-dashboard   replicaset.apps/dashboard-metrics-scraper-6b4884c9d5    1         1         1       32d
default                replicaset.apps/my-quarkus-kubernetes-name-7845545ff5   3         0         0       15m

NAMESPACE     NAME                             COMPLETIONS   DURATION   AGE
kube-system   job.batch/helm-install-traefik   1/1           41s        32d

In order to check the ServiceAccount that was created, I used the following command on the Linux Command Prompt:

kubectl get serviceAccounts

With the following output:


NAME                         SECRETS   AGE
default                      1         32d
my-quarkus-kubernetes-name   1         18m

Remark:
Several resources are created, but no Pods!

When I checked the resources via the Kubernetes Dashboard, I saw the following error message:

So, as expected, an error occurred because the ServiceAccount with name my-quarkus-kubernetes-service-account does not exist. As I remarked earlier in my previous article, the service account that is used to run the pod, refers to a non-existing service account.
[https://technology.amis.nl/2020/10/03/quarkus-supersonic-subatomic-java-trying-out-quarkus-guide-quarkus-kubernetes-extension-part-2/]

To work around this problem. I opted to remark the configuration I set earlier in src/main/resources/application.properties.

# Kubernetes manifest service-account
#quarkus.kubernetes.service-account=my-quarkus-kubernetes-service-account

Creating the namespace

For creating the namespace, I used an existing yaml file, with the following content:

apiVersion: v1
kind: Namespace
metadata:
  name: "nl-amis-development"
  labels:
    name: "nl-amis-development"

In order to create the namespace, I used the following command on the Linux Command Prompt:

kubectl apply -f /vagrant/yaml/namespace-development.yaml

With the following output:


namespace/nl-amis-development created

Deleting the created resources

In order to delete the created Service, I used the following command on the Linux Command Prompt:

kubectl delete -n default service my-quarkus-kubernetes-name

With the following output:


service “my-quarkus-kubernetes-name” deleted

In order to delete the created ReplicaSet, I used the following command on the Linux Command Prompt:

kubectl delete -n default replicaset my-quarkus-kubernetes-name-7845545ff5

With the following output:


replicaset.apps “my-quarkus-kubernetes-name-7845545ff5” deleted

In order to delete the created Deployment, I used the following command on the Linux Command Prompt:

kubectl delete -n default deployment my-quarkus-kubernetes-name

With the following output:


deployment.apps “my-quarkus-kubernetes-name” deleted

In order to delete the created ServiceAccount, I used the following command on the Linux Command Prompt:

kubectl delete -n default serviceAccounts my-quarkus-kubernetes-name

With the following output:


serviceaccount “my-quarkus-kubernetes-name” deleted

Automatic deployment with a namespace created beforehand

In order to build and deploy a container image, again I used the following command on the Linux Command Prompt:

./mvnw clean package -Dquarkus.kubernetes.deploy=true

With the following output:


[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.acme:getting-started >----------------------
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ getting-started ---
[INFO] Deleting /vagrant/applications/getting-started/target
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:prepare (default) @ getting-started ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /vagrant/applications/getting-started/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:prepare-tests (default) @ getting-started ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /vagrant/applications/getting-started/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /vagrant/applications/getting-started/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ getting-started ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.acme.getting.started.GreetingResourceTest
2020-09-21 14:46:03,627 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.kubernetes.deploy" was provided; it will be ignored; verify that the dependency extension for this configuration is set or you did not make a typo
2020-09-21 14:46:04,421 INFO  [io.quarkus] (main) Quarkus 1.7.0.Final on JVM started in 4.530s. Listening on: http://0.0.0.0:8081
2020-09-21 14:46:04,422 INFO  [io.quarkus] (main) Profile test activated.
2020-09-21 14:46:04,422 INFO  [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 13.133 s - in org.acme.getting.started.GreetingResourceTest
2020-09-21 14:46:08,139 INFO  [io.quarkus] (main) Quarkus stopped in 0.032s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ getting-started ---
[INFO] Building jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:build (default) @ getting-started ---
[INFO] [org.jboss.threads] JBoss Threads version 3.1.1.Final
[WARNING] [io.quarkus.kubernetes.deployment.KubernetesDeployer] A Kubernetes deployment was requested, but the container image to be built will not be pushed to any registry because "quarkus.container-image.registry" has not been set. The Kubernetes deployment will only work properly if the cluster is using the local Docker daemon. For that reason 'ImagePullPolicy' is being force-set to 'IfNotPresent'.
[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building thin jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-runner.jar
[WARNING] [io.quarkus.kubernetes.deployment.KubernetesProcessor] No registry was set for the container image, so 'ImagePullPolicy' is being force-set to 'IfNotPresent'.
[INFO] Checking for existing resources in: /vagrant/applications/getting-started/src/main/kubernetes.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeploy] Kubernetes API Server at 'https://127.0.0.1:6443/' successfully contacted.
[INFO] [io.quarkus.container.image.docker.deployment.DockerWorking] Docker daemon found. Version:'19.03.12'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Building docker image for jar.
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Executing the following command to build docker image: 'docker build -f /vagrant/applications/getting-started/src/main/docker/Dockerfile.jvm -t vagrant/getting-started:1.0-SNAPSHOT /vagrant/applications/getting-started'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Sending build context to Docker daemon  11.09MB
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 1/11 : FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 91d23a64fdf2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 2/11 : ARG JAVA_PACKAGE=java-11-openjdk-headless
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 3818465cc8fa
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 3/11 : ARG RUN_JAVA_VERSION=1.3.8
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> c45c7ada9216
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 4/11 : ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> eea2c4e04c6c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 5/11 : RUN microdnf install curl ca-certificates ${JAVA_PACKAGE}     && microdnf update     && microdnf clean all     && mkdir /deployments     && chown 1001 /deployments     && chmod "g+rwX" /deployments     && chown 1001:root /deployments     && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh     && chown 1001 /deployments/run-java.sh     && chmod 540 /deployments/run-java.sh     && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> eedc98908837
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 6/11 : ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> ef0d7a761730
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 7/11 : COPY target/lib/* /deployments/lib/
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> d8153bf53db2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 8/11 : COPY target/*-runner.jar /deployments/app.jar
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 3df12d03be99
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 9/11 : EXPOSE 8080
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in bb78b4896889
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container bb78b4896889
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> e16d4e1becbb
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 10/11 : USER 1001
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in b451ee1e0bfa
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container b451ee1e0bfa
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 753eaa08a26d
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 11/11 : ENTRYPOINT [ "/deployments/run-java.sh" ]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in 505c90dddf04
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container 505c90dddf04
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> d2af95734312
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully built d2af95734312
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully tagged vagrant/getting-started:1.0-SNAPSHOT
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Built container image vagrant/getting-started:1.0-SNAPSHOT (d2af95734312)

[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Deploying to kubernetes server: https://127.0.0.1:6443/ in namespace: default.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: ServiceAccount my-quarkus-kubernetes-name.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Service my-quarkus-kubernetes-name.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Deployment my-quarkus-kubernetes-name.
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 12056ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  38.809 s
[INFO] Finished at: 2020-09-21T14:46:21Z
[INFO] ------------------------------------------------------------------------
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

So, the output is similar as the one from before, when the namespace didn’t already exist!

Remark about the namespace:
As you can see in the output, namespace default is used, although in the Kubernetes manifest I used namespace nl-amis-development. This is not what I expected because, this time, my custom namespace did already exist.

So, why didn’t this namespace thing work?

In order to check the resources that where created, again I used the following command on the Linux Command Prompt:

kubectl get all --all-namespaces

With the following output:


NAMESPACE              NAME                                              READY   STATUS      RESTARTS   AGE
kube-system            pod/metrics-server-7566d596c8-gxrjt               1/1     Running     0          32d
kube-system            pod/helm-install-traefik-7mps6                    0/1     Completed   0          32d
kube-system            pod/local-path-provisioner-6d59f47c7-vtb4t        1/1     Running     0          32d
kube-system            pod/coredns-8655855d6-qxqhf                       1/1     Running     0          32d
kube-system            pod/svclb-traefik-hdxqf                           2/2     Running     0          32d
kube-system            pod/traefik-758cd5fc85-m4cvj                      1/1     Running     0          32d
kubernetes-dashboard   pod/kubernetes-dashboard-7b544877d5-l4qfb         1/1     Running     0          32d
kubernetes-dashboard   pod/dashboard-metrics-scraper-6b4884c9d5-hdxmn    1/1     Running     0          32d
default                pod/my-quarkus-kubernetes-name-84995c96b7-jvzvt   1/1     Running     0          151m
default                pod/my-quarkus-kubernetes-name-84995c96b7-sqcfr   1/1     Running     0          151m
default                pod/my-quarkus-kubernetes-name-84995c96b7-2fjlp   1/1     Running     0          151m

NAMESPACE              NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
default                service/kubernetes                   ClusterIP      10.43.0.1       <none>        443/TCP                      32d
kube-system            service/kube-dns                     ClusterIP      10.43.0.10      <none>        53/UDP,53/TCP,9153/TCP       32d
kube-system            service/metrics-server               ClusterIP      10.43.183.35    <none>        443/TCP                      32d
kube-system            service/traefik-prometheus           ClusterIP      10.43.50.120    <none>        9100/TCP                     32d
kube-system            service/traefik                      LoadBalancer   10.43.116.205   10.0.2.15     80:30676/TCP,443:31713/TCP   32d
kubernetes-dashboard   service/kubernetes-dashboard         ClusterIP      10.43.175.253   <none>        443/TCP                      32d
kubernetes-dashboard   service/dashboard-metrics-scraper    ClusterIP      10.43.5.8       <none>        8000/TCP                     32d
default                service/my-quarkus-kubernetes-name   NodePort       10.43.242.139   <none>        8090:30526/TCP               151m

NAMESPACE     NAME                           DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kube-system   daemonset.apps/svclb-traefik   1         1         1       1            1           <none>          32d

NAMESPACE              NAME                                         READY   UP-TO-DATE   AVAILABLE   AGE
kube-system            deployment.apps/metrics-server               1/1     1            1           32d
kube-system            deployment.apps/local-path-provisioner       1/1     1            1           32d
kube-system            deployment.apps/coredns                      1/1     1            1           32d
kube-system            deployment.apps/traefik                      1/1     1            1           32d
kubernetes-dashboard   deployment.apps/kubernetes-dashboard         1/1     1            1           32d
kubernetes-dashboard   deployment.apps/dashboard-metrics-scraper    1/1     1            1           32d
default                deployment.apps/my-quarkus-kubernetes-name   3/3     3            3           151m

NAMESPACE              NAME                                                    DESIRED   CURRENT   READY   AGE
kube-system            replicaset.apps/metrics-server-7566d596c8               1         1         1       32d
kube-system            replicaset.apps/local-path-provisioner-6d59f47c7        1         1         1       32d
kube-system            replicaset.apps/coredns-8655855d6                       1         1         1       32d
kube-system            replicaset.apps/traefik-758cd5fc85                      1         1         1       32d
kubernetes-dashboard   replicaset.apps/kubernetes-dashboard-7b544877d5         1         1         1       32d
kubernetes-dashboard   replicaset.apps/dashboard-metrics-scraper-6b4884c9d5    1         1         1       32d
default                replicaset.apps/my-quarkus-kubernetes-name-84995c96b7   3         3         3       151m

NAMESPACE     NAME                             COMPLETIONS   DURATION   AGE
kube-system   job.batch/helm-install-traefik   1/1           41s        32d

The good news, however, is that the ReplicaSet was able to create the 3 Pods, because this time the correct service account name was used.

Manual deployment using the generated kubernetes.yml file

First, I wanted to check if there was a problem with the content of the generated kubernetes.yml file.

In order to manually deploy the resources, I used the following command on the Linux Command Prompt:

kubectl apply -f /vagrant/applications/getting-started/target/kubernetes/kubernetes.yml

With the following output:


unable to decode "/vagrant/applications/getting-started/target/kubernetes/kubernetes.yml": resource.metadataOnlyObject.ObjectMeta: v1.ObjectMeta.Namespace: Name: Labels: ReadString: expects " or n, but found 1, error found in #10 byte of ...|version":1},"name":"|..., bigger context ...|s_version","environment":"development","version":1},"name":"my-quarkus-kubernetes-name","namespace":|...
unable to decode "/vagrant/applications/getting-started/target/kubernetes/kubernetes.yml": resource.metadataOnlyObject.ObjectMeta: v1.ObjectMeta.Namespace: Name: Labels: ReadString: expects " or n, but found 1, error found in #10 byte of ...|version":1},"name":"|..., bigger context ...|s_version","environment":"development","version":1},"name":"my-quarkus-kubernetes-name","namespace":|...
unable to decode "/vagrant/applications/getting-started/target/kubernetes/kubernetes.yml": resource.metadataOnlyObject.ObjectMeta: v1.ObjectMeta.Namespace: Name: Labels: ReadString: expects " or n, but found 1, error found in #10 byte of ...|version":1},"name":"|..., bigger context ...|s_version","environment":"development","version":1},"name":"my-quarkus-kubernetes-name","namespace":|...
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

So, using the generated yaml file in this way, didn’t work. Apparently, there was something wrong with the label version and its value 1.0. There was an error for every resource that was going to be created.

For just the ServiceAccount part I created a new yaml file, with the following content:
[in bold, I highlighted the changes (except app.quarkus.io/build-timestamp)]

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    my_key1: key1_value
    my_key2: key2_value
    app.quarkus.io/build-timestamp: 2020-09-21 - 14:46:14 +0000
  labels:
    app.kubernetes.io/name: my-quarkus-kubernetes-name
    app.kubernetes.io/part-of: my_quarkus_kubernetes_part-of
    app.kubernetes.io/version: my_quarkus_kubernetes_version
    app: getting-started
    environment: development
    version: "1.0"
  name: my-quarkus-kubernetes-name
  namespace: nl-amis-development

Remark about a label value:
The label values must be strings. In yaml, that means all numeric values must be quoted.
[https://github.com/kubernetes/kubernetes/issues/57509]

As I also mentioned in my previous article, I tried to get the quotes around the label value by changing the configuration (using quarkus.kubernetes.labels.version) I set earlier in src/main/resources/application.properties, but I didn’t succeed. So, I changed it manually.
[https://technology.amis.nl/2020/10/03/quarkus-supersonic-subatomic-java-trying-out-quarkus-guide-quarkus-kubernetes-extension-part-2/]

Then, I used the following command on the Linux Command Prompt:

kubectl apply -f /vagrant/yaml/serviceaccount-getting-started.yaml

With the following output:


serviceaccount/my-quarkus-kubernetes-name created

In order to check the ServiceAccount that was created, I used the following command on the Linux Command Prompt:

kubectl get serviceAccounts --all-namespaces

With the following output:


NAMESPACE              NAME                                     SECRETS   AGE
kube-system            pv-protection-controller                 1         32d
kube-system            certificate-controller                   1         32d
kube-system            generic-garbage-collector                1         32d
kube-system            cronjob-controller                       1         32d
kube-system            node-controller                          1         32d
kube-system            service-controller                       1         32d
kube-system            coredns                                  1         32d
kube-system            clusterrole-aggregation-controller       1         32d
kube-system            endpoint-controller                      1         32d
kube-system            replication-controller                   1         32d
kube-system            daemon-set-controller                    1         32d
kube-system            job-controller                           1         32d
kube-system            local-path-provisioner-service-account   1         32d
kube-system            horizontal-pod-autoscaler                1         32d
kube-system            pvc-protection-controller                1         32d
kube-system            endpointslice-controller                 1         32d
kube-system            service-account-controller               1         32d
kube-system            replicaset-controller                    1         32d
kube-system            expand-controller                        1         32d
kube-system            metrics-server                           1         32d
kube-system            pod-garbage-collector                    1         32d
kube-system            namespace-controller                     1         32d
kube-system            disruption-controller                    1         32d
kube-system            statefulset-controller                   1         32d
kube-system            ttl-controller                           1         32d
kube-system            resourcequota-controller                 1         32d
kube-system            helm-traefik                             1         32d
kube-system            deployment-controller                    1         32d
kube-system            persistent-volume-binder                 1         32d
kube-system            attachdetach-controller                  1         32d
kube-system            default                                  1         32d
kube-public            default                                  1         32d
kube-node-lease        default                                  1         32d
default                default                                  1         32d
kube-system            traefik                                  1         32d
kubernetes-dashboard   kubernetes-dashboard                     1         32d
kubernetes-dashboard   default                                  1         32d
kubernetes-dashboard   admin-user                               1         32d
nl-amis-development    default                                  1         3h13m
nl-amis-development    my-quarkus-kubernetes-name               1         4m47s

So, doing it this way, a service account is created in my custom namespace.

By the way:
Service Account Controller manages ServiceAccount inside namespaces, and ensures a ServiceAccount named “default” exists in every active namespace.
[https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#service-account-controller]

Next, in a similar way like I did before, I removed all the created resources.

Deployment with namespace set in current Kubernetes context

Remember, in the Deployment, the environment variable KUBERNETES_NAMESPACE is used. Its value is derived from the Pod’s metadata.namespace field.

When the ‘namespace’ field is not added to the ‘metadata’ section of the generated manifest, this means that when the manifests are applied to a cluster, the namespace will be resolved from the current Kubernetes context (see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context for more details).
[https://quarkus.io/guides/all-config]

In order to permanently save the namespace for all subsequent kubectl commands in that context, I used the following command on the Linux Command Prompt:
[https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-context-and-configuration]

sudo kubectl config set-context --current --namespace=nl-amis-development

With the following output:

Context “default” modified.

In order to validate the current Kubernetes context, I used the following command on the Linux Command Prompt:
[https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#setting-the-namespace-preference]

kubectl config view --minify | grep namespace:

With the following output:

namespace: nl-amis-development

So now the kubeconfig settings are changed, on my demo environment, I had to recreate the .kube/config file in my user (/home/vagrant) directory. So, again I used the following command on the Linux Command Prompt:

With the following output:


total 20
drwxr-xr-x 7 vagrant vagrant 4096 Sep 13 15:18 ..
drwxr-x--- 3 vagrant vagrant 4096 Sep 13 15:18 cache
drwxr-x--- 4 vagrant vagrant 4096 Sep 21 13:49 .
-rw-rw-r-- 1 vagrant vagrant 1044 Sep 21 13:49 config
drwxr-x--- 3 vagrant vagrant 4096 Sep 22 14:42 http-cache

In order to build and deploy a container image, again I used the following command on the Linux Command Prompt:

cd /vagrant/applications/getting-started
./mvnw clean package -Dquarkus.kubernetes.deploy=true

With the following output:


[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.acme:getting-started >----------------------
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ getting-started ---
[INFO] Deleting /vagrant/applications/getting-started/target
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:prepare (default) @ getting-started ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /vagrant/applications/getting-started/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:prepare-tests (default) @ getting-started ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /vagrant/applications/getting-started/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /vagrant/applications/getting-started/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ getting-started ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.acme.getting.started.GreetingResourceTest
2020-09-22 14:50:35,938 WARN  [io.qua.config] (main) Unrecognized configuration key "quarkus.kubernetes.deploy" was provided; it will be ignored; verify that the dependency extension for this configuration is set or you did not make a typo
2020-09-22 14:50:36,914 INFO  [io.quarkus] (main) Quarkus 1.7.0.Final on JVM started in 5.126s. Listening on: http://0.0.0.0:8081
2020-09-22 14:50:36,917 INFO  [io.quarkus] (main) Profile test activated.
2020-09-22 14:50:36,917 INFO  [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.502 s - in org.acme.getting.started.GreetingResourceTest
2020-09-22 14:50:41,102 INFO  [io.quarkus] (main) Quarkus stopped in 0.055s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ getting-started ---
[INFO] Building jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- quarkus-maven-plugin:1.7.0.Final:build (default) @ getting-started ---
[INFO] [org.jboss.threads] JBoss Threads version 3.1.1.Final
[WARNING] [io.quarkus.kubernetes.deployment.KubernetesDeployer] A Kubernetes deployment was requested, but the container image to be built will not be pushed to any registry because "quarkus.container-image.registry" has not been set. The Kubernetes deployment will only work properly if the cluster is using the local Docker daemon. For that reason 'ImagePullPolicy' is being force-set to 'IfNotPresent'.
[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building thin jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-runner.jar
[WARNING] [io.quarkus.kubernetes.deployment.KubernetesProcessor] No registry was set for the container image, so 'ImagePullPolicy' is being force-set to 'IfNotPresent'.
[INFO] Checking for existing resources in: /vagrant/applications/getting-started/src/main/kubernetes.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeploy] Kubernetes API Server at 'https://127.0.0.1:6443/' successfully contacted.
[INFO] [io.quarkus.container.image.docker.deployment.DockerWorking] Docker daemon found. Version:'19.03.12'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Building docker image for jar.
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Executing the following command to build docker image: 'docker build -f /vagrant/applications/getting-started/src/main/docker/Dockerfile.jvm -t vagrant/getting-started:1.0-SNAPSHOT /vagrant/applications/getting-started'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Sending build context to Docker daemon  11.09MB
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 1/11 : FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 91d23a64fdf2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 2/11 : ARG JAVA_PACKAGE=java-11-openjdk-headless
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 3818465cc8fa
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 3/11 : ARG RUN_JAVA_VERSION=1.3.8
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> c45c7ada9216
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 4/11 : ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> eea2c4e04c6c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 5/11 : RUN microdnf install curl ca-certificates ${JAVA_PACKAGE}     && microdnf update     && microdnf clean all     && mkdir /deployments     && chown 1001 /deployments     && chmod "g+rwX" /deployments     && chown 1001:root /deployments     && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh     && chown 1001 /deployments/run-java.sh     && chmod 540 /deployments/run-java.sh     && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> eedc98908837
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 6/11 : ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> ef0d7a761730
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 7/11 : COPY target/lib/* /deployments/lib/
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> d8153bf53db2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 8/11 : COPY target/*-runner.jar /deployments/app.jar
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 59b825cb8990
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 9/11 : EXPOSE 8080
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in bde06af91dbf
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container bde06af91dbf
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 6b375d273b9d
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 10/11 : USER 1001
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in 4558ef2af8fb
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container 4558ef2af8fb
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> 8cf926c7f9f0
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 11/11 : ENTRYPOINT [ "/deployments/run-java.sh" ]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> Running in cd400ddd9c11
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container cd400ddd9c11
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  ---> afb3bc1d2ea1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully built afb3bc1d2ea1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully tagged vagrant/getting-started:1.0-SNAPSHOT
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Built container image vagrant/getting-started:1.0-SNAPSHOT (afb3bc1d2ea1)

[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Deploying to kubernetes server: https://127.0.0.1:6443/ in namespace: nl-amis-development.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: ServiceAccount my-quarkus-kubernetes-name.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Service my-quarkus-kubernetes-name.
[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Deployment my-quarkus-kubernetes-name.
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 12151ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  40.553 s
[INFO] Finished at: 2020-09-22T14:50:54Z
[INFO] ------------------------------------------------------------------------
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

So, this time, as you can see in the output, the correct nl-amis-development namespace is used. I am not sure however why the construction with the environment variable KUBERNETES_NAMESPACE in the generated Kubernetes manifest for Deployment didn’t work in my case. At least my work around for this problem did work.

Kubernetes Dashboard

Next, in the Web Browser on my Windows laptop, I started the Kubernetes Dashboard in my demo environment, in order to check the generated resources.

Below, you can see an overview of the Namespaces:

I changed the namespace to nl-amis-development. Below, you can see an overview of the Deployments:

Below, you can see an overview of the Replica Sets:

Below, you can see an overview of the Pods:

Here, again we can see that the ReplicaSet was able to create the 3 Pods.

Below, you can see some more details (including all the labels) of the first Pod:

I opened the log from the first Pod:

Below, you can see an overview of the Services:

I noticed something about the ports, so I clicked on Edit:

As you may remember, in my previous article I described how I changed the service type to NodePort and tried, but did not succeed, to set the values for nodePort, port and targetPort to respectively: 30010, 8190 and 8090. So, in the end, these settings were also not used in the deployed Service!

Then I closed the “Edit a resource” window.

Below, you can see some more details of the Service:

Here you can see the endpoints of the 3 Pods, I will be using later on.

So, this confirmed to me that everything was up and running.

For every one of the 3 Pods I quickly checked if they worked. Below you see the check I did for the first Pod (with the endpoint we saw earlier).

I used the following command on the Linux Command Prompt:

curl http://10.42.0.25:8090/hello

With the following output:


hello quarkus!

I used the following command on the Linux Command Prompt:

curl http://10.42.0.25:8090/hello/greeting/readers

With the following output:


hello readers

For the other two Pods, I did the same, using the host 10.42.0.26 and 10.42.0.27.

Besides already being able to use the Kubernetes Dashboard (in a Web Browser) on my Windows laptop (via port forwarding), I also wanted to be able to use a Web Browser on my Windows laptop, for sending requests to the Kubernetes my-quarkus-kubernetes-name Service on my guest (Ubuntu).

In order to determine the IP of the K3s node, I used the following command on the Linux Command Prompt, as I described in a previous article:
[https://technology.amis.nl/2020/04/30/creating-a-re-usable-vagrant-box-from-an-existing-vm-with-ubuntu-and-k3s-with-the-kubernetes-dashboard-and-adding-mysql-using-vagrant-and-oracle-virtualbox/]

nodeIP=$(kubectl get node ubuntu-bionic -o yaml | grep address: | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
echo "---$nodeIP---"

With the following output:


—10.0.2.15—

In order to forward local port 8090 to port 32171 on the K3s node ($nodeIP), I used the following command on the Linux Command Prompt, as I described in a previous article:
[https://technology.amis.nl/2020/04/30/creating-a-re-usable-vagrant-box-from-an-existing-vm-with-ubuntu-and-k3s-with-the-kubernetes-dashboard-and-adding-mysql-using-vagrant-and-oracle-virtualbox/]

socat tcp-listen:8090,fork tcp:$nodeIP:32171 &

With the following output:


[1] 19990
vagrant@ubuntu-bionic:~$

Then, in the Web Browser on my Windows laptop, I entered the URL: http://localhost:8090/hello

And I got the following result:

Then, in the Web Browser on my Windows laptop, I entered the URL: http://localhost:8090/hello/greeting/readers

And I got the following result:

So, running the application in a container using the produced executable worked.

Below, is a schematic overview of my demo environment with K3s (with the Kubernetes Dashboard) on top of an Ubuntu guest Operating System within an VirtualBox appliance, created using Vagrant:

So, I conclude this article. I shared with you the steps I took trying out the Quarkus code guide “Quarkus – Kubernetes extension”, and more specific the steps related the automatic deployment of the generated resources to a target platform, in my case K3s (lightweight certified Kubernetes distribution).

If you have read my last articles about this code quide, you know I had quite some problems trying to get the customizations I wanted into the generated Kubernetes manifests. Be aware that for a production environment you probably want to do things a bit different any way and have more control of what is going to be deployed. For a development situation it’s probably all right. At least the generated resources can provide a good base, for example for manually creating the final version of a particular resource and putting it in a version control system (like git).

I want to point out some remarks that are also made in the code guide itself, with regard to deploying to Minikube.


[https://quarkus.io/guides/deploying-to-kubernetes#deploying-to-minikube]

I also want to point out the part in the code guide about using existing resources.

Sometimes it’s desirable to either provide additional resources (e.g. a ConfigMap, a Secret, a Deployment for a database etc) or provide custom ones that will be used as a base for the generation process. Those resources can be added under src/main/kubernetes directory and can be named after the target environment (e.g. kubernetes.json, openshift.json, knative.json, or the yml equivalents). Each of these files may contain one or more Kubernetes resources.

Any resource found will be added in the generated manifests. Global modifications (e.g. labels, annotations etc) will also be applied to those resources. If one of the provided resources has the same name as one of the generated ones, then the generated resource will be created on top of the provided resource, respecting existing content when possible (e.g. existing labels, annotations, environment variables, mounts, replicas etc).

The name of the resource is determined by the application name and may be overridden by quarkus.kubernetes.name, quarkus.openshift.name and quarkus.knative.name.
[https://quarkus.io/guides/deploying-to-kubernetes#using-existing-resources]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Next Post

Deploy A Docker Container To AWS With Azure Pipelines

Facebook0TwitterLinkedinIntroduction In response to a demo I gave about deploying a docker container to the Azure platform, I received some questions about deploying a docker container to the AWS platform. I wrote a guide on how to deploy a docker container with Azure Pipelines here. In my opinion is Azure […]