Quarkus - Generating Kubernetes resources

This guide covers generating Kubernetes resources based on sane defaults and user supplied configuration.

Prerequisites

To complete this guide, you need:

  • roughly 10 minutes

  • an IDE

  • JDK 1.8+ installed with JAVA_HOME configured appropriately

  • Apache Maven 3.5.3+

  • access to a Kubernetes or cluster (Minikube is a viable options)

Creating the Maven project

First, we need a new project that contains the Kubernetes extension. This can be done using the following command:

  1. mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create \
  2. -DprojectGroupId=org.acme \
  3. -DprojectArtifactId=kubernetes-quickstart \
  4. -DclassName="org.acme.rest.GreetingResource" \
  5. -Dpath="/greeting" \
  6. -Dextensions="kubernetes"
  7. cd kubernetes-quickstart

Enable Kubernetes support

Quarkus offers the ability to automatically generate Kubernetes resources based on sane defaults and user supplied configuration. The implementation that takes careof generating the actual Kubernetes resources is provided by dekorate. Currently it supports the generation of resources forvanilla Kubernetes and OpenShift.

When we added the kubernetes extension to the command line invocation above, the following dependency was added to the pom.xml

  1. <dependency>
  2. <groupId>io.quarkus</groupId>
  3. <artifactId>quarkus-kubernetes</artifactId>
  4. </dependency>

By adding this dependency, we now have the ability to configure the Kubernetes resource generation and application using the usual application.properties approach that Quarkus provides.The configuration items that are available can be found in: io.quarkus.kubernetes.deployment.KubernetesConfig class.Furthermore, the items provided by io.quarkus.deployment.ApplicationConfig affect the Kubernetes resources.

By using the following configuration for example:

  1. kubernetes.group=yourDockerUsername # this is optional and defaults to your username if not set.
  2. quarkus.application.name=test-quarkus-app # this is also optional and defaults to the project name if not set

and following the execution of ./mvnw package you will notice amongst the other files that are created, two files namedkubernetes.json and kubernetes.yaml in the target/kubernetes/ directory.

If you look at either file you will see that it contains both a Kubernetes Deployment and a Service.

The full source of the kubernetes.json file looks something like this:

  1. {
  2. "apiVersion" : "v1",
  3. "kind" : "List",
  4. "items" : [ {
  5. "apiVersion" : "apps/v1",
  6. "kind" : "Deployment",
  7. "metadata" : {
  8. "labels" : {
  9. "app" : "test-quarkus-app",
  10. "version" : "1.0-SNAPSHOT",
  11. "group" : "yourDockerUsername"
  12. },
  13. "name" : "test-quarkus-app"
  14. },
  15. "spec" : {
  16. "replicas" : 1,
  17. "selector" : {
  18. "matchLabels" : {
  19. "app" : "test-quarkus-app",
  20. "version" : "1.0-SNAPSHOT",
  21. "group" : "yourDockerUsername"
  22. }
  23. },
  24. "template" : {
  25. "metadata" : {
  26. "labels" : {
  27. "app" : "test-quarkus-app",
  28. "version" : "1.0-SNAPSHOT",
  29. "group" : "yourDockerUsername"
  30. }
  31. },
  32. "spec" : {
  33. "containers" : [ {
  34. "env" : [ {
  35. "name" : "KUBERNETES_NAMESPACE",
  36. "valueFrom" : {
  37. "fieldRef" : {
  38. "fieldPath" : "metadata.namespace"
  39. }
  40. }
  41. } ],
  42. "image" : "yourDockerUsername/test-quarkus-app:1.0-SNAPSHOT",
  43. "imagePullPolicy" : "IfNotPresent",
  44. "name" : "test-quarkus-app"
  45. } ]
  46. }
  47. }
  48. }
  49. } ]
  50. }

An important thing to note about the Deployment is that is uses yourDockerUsername/test-quarkus-app:1.0-SNAPSHOT as the Docker image of the Pod.

Also the Service is configured to use container port 8080 (which is automatically picked up by the standard Quarkus configuration).

Add readiness and liveness probes

By default the Kubernetes resources do not contain readiness and liveness probes in the generated Deployment. Adding them however is just a matter of adding the Smallrye Health extension like so:

  1. <dependency>
  2. <groupId>io.quarkus</groupId>
  3. <artifactId>quarkus-smallrye-health</artifactId>
  4. </dependency>

The values of the generated probes will be determined by the configured health properties: quarkus.smallrye-health.root-path, quarkus.smallrye-health.liveness-path and quarkus.smallrye-health.readiness-path.More information about the health extension can be found in the relevant guide.

Tuning the generated resources using application.properties

The Kubernetes extension allows tuning the generated manifest, using the application.properties file.Here are some examples:

Changing the number of replicas:

To change the number of replicas from 1 to 3:

  1. kubernetes.replicas=3

Defining a docker registry and repository

The docker registry and the user of the docker image can be specified, with the following properties:

  1. kubernetes.group=myUser
  2. kubernetes.registry=http://my.docker-registry.net

Note: These options used to be quarkus.kubernetes.docker.registry and quarkus.kubernetes.group respectively.

Adding labels:

To add a new label to all generated resources, say foo=bar:

  1. kubernetes.labels[0].key=foo
  2. kubernetes.labels[0].value=bar

Customizing the readiness probe:

To set the initial delay of the probe to 20 seconds and the period to 45:

  1. kubernetes.readiness-probe.initial-delay-seconds=20
  2. kubernetes.readiness-probe.period-seconds=45

Here you can find a complete reference to all the available configuration options:

Configuration options

The table below describe all the available configuration options.

Table 1. Kubernetes
PropertyTypeDescriptionDefault Value
kubernetes.groupString
kubernetes.nameString
kubernetes.versionString
kubernetes.init-containersContainer[]
kubernetes.labelsLabel[]
kubernetes.annotationsAnnotation[]
kubernetes.env-varsEnv[]
kubernetes.working-dirString
kubernetes.commandString[]
kubernetes.argumentsString[]
kubernetes.replicasint1
kubernetes.service-accountString
kubernetes.hostString
kubernetes.portsPort[]
kubernetes.service-typeServiceTypeClusterIP
kubernetes.pvc-volumesPersistentVolumeClaimVolume[]
kubernetes.secret-volumesSecretVolume[]
kubernetes.config-map-volumesConfigMapVolume[]
kubernetes.git-repo-volumesGitRepoVolume[]
kubernetes.aws-elastic-block-store-volumesAwsElasticBlockStoreVolume[]
kubernetes.azure-disk-volumesAzureDiskVolume[]
kubernetes.azure-file-volumesAzureFileVolume[]
kubernetes.mountsMount[]
kubernetes.image-pull-policyImagePullPolicyIfNotPresent
kubernetes.image-pull-secretsString[]
kubernetes.liveness-probeProbe
kubernetes.readiness-probeProbe
kubernetes.sidecarsContainer[]
kubernetes.exposebooleanfalse
kubernetes.docker-fileStringDockerfile
kubernetes.registryString
kubernetes.auto-deploy-enabledbooleanfalse

Properties that use non standard types, can be referenced by expanding the property.For example to define a kubernetes-readiness-probe which is of type Probe:

  1. kubernetes.readiness-probe.initial-delay-seconds=20
  2. kubernetes.readiness-probe.period-seconds=45

In this example initial-delay and period-seconds are fields of the type Probe.Below you will find tables describing all available types.

Basic Types
Table 2. Annotation
PropertyTypeDescriptionDefault Value
keyString
valueString
Table 3. Label
PropertyTypeDescriptionDefault Value
keyString
valueString
Table 4. Env
PropertyTypeDescriptionDefault Value
nameString
valueString
secretString
configmapString
fieldString
Table 5. Probe
PropertyTypeDescriptionDefault Value
—————————————————————+———————-http-action-pathString
exec-actionString
tcp-socket-actionString
initial-delay-secondsint
0period-secondsint
30timeout-secondsint
Table 6. Port
PropertyTypeDescriptionDefault Value
nameString
container-portint
hostPortint0
pathString/
protocolProtocolTCP
Table 7. Container
PropertyTypeDescriptionDefault Value
imageString
nameString
env-varsEnv[]
working-dirString
commandString[]
argumentsString[]
portsPort[]
mountsMount[]
image-pull-policyImagePullPolicyIfNotPresent
liveness-probeProbe
readiness-probeProbe

Mounts and Volumes

Table 8. Mount
PropertyTypeDescriptionDefault Value
nameString
pathString
sub-pathString
read-onlybooleanfalse
Table 9. ConfigMapVolume
PropertyTypeDescriptionDefault Value
volume-nameString
config-map-nameString
default-modeint384
optionalbooleanfalse
Table 10. SecretVolume
PropertyTypeDescriptionDefault Value
volume-nameString
secret-nameString
default-modeint384
optionalbooleanfalse
Table 11. AzureDiskVolume
PropertyTypeDescriptionDefault Value
volume-nameString
disk-nameString
disk-uriString
kindStringManaged
caching-modeStringReadWrite
fs-typeStringext4
read-onlybooleanfalse
Table 12. AwsElasticBlockStoreVolume
PropertyTypeDescriptionDefault Value
volume-nameString
volume-idString
partitionint
fs-typeStringext4
read-onlybooleanfalse
Table 13. GitRepoVolume
PropertyTypeDescriptionDefault Value
volume-nameString
repositoryString
directoryString
revisionString
Table 14. PersistentVolumeClaimVolume
PropertyTypeDescriptionDefault Value
volume-nameString
claim-nameString
read-onlybooleanfalse
Table 15. AzureFileVolume
PropertyTypeDescriptionDefault Value
volume-nameString
share-nameString
secret-nameString
read-onlybooleanfalse

Docker

Table 16. Docker
PropertyTypeDescriptionDefault Value
docker-fileStringDockerfile
registryString
auto-push-enabledboolean
falseauto-build-enabledboolean

OpenShift support

To enable the generation of OpenShift resources, you need to include OpenShift in the target platforms:

  1. kubernetes.deployment.target=openshift

If you need to generate resources for both platforms (vanilla Kubernetes and OpenShift), then you need to include both (coma separated).

  1. kubernetes.deployment.target=kubernetes, openshift

The OpenShift resources can be customized in a similar approach with Kubernetes.

Table 17. Openshift
PropertyTypeDescriptionDefault Value
openshift.groupString
openshift.nameString
openshift.versionString
openshift.init-containersContainer[]
openshift.labelsLabel[]
openshift.annotationsAnnotation[]
openshift.env-varsEnv[]
openshift.working-dirString
openshift.commandString[]
openshift.argumentsString[]
openshift.replicasint1
openshift.service-accountString
openshift.hostString
openshift.portsPort[]
openshift.service-typeServiceTypeClusterIP
openshift.pvc-volumesPersistentVolumeClaimVolume[]
openshift.secret-volumesSecretVolume[]
openshift.config-map-volumesConfigMapVolume[]
openshift.git-repo-volumesGitRepoVolume[]
openshift.aws-elastic-block-store-volumesAwsElasticBlockStoreVolume[]
openshift.azure-disk-volumesAzureDiskVolume[]
openshift.azure-file-volumesAzureFileVolume[]
openshift.mountsMount[]
openshift.image-pull-policyImagePullPolicyIfNotPresent
openshift.image-pull-secretsString[]
openshift.liveness-probeProbe( see Probe )
openshift.readiness-probeProbe( see Probe )
openshift.sidecarsContainer[]
openshift.exposebooleanfalse
openshift.auto-deploy-enabledbooleanfalse
Table 18. S2i
PropertyTypeDescriptionDefault Value
s2i.enabledbooleantrue
s2i.registryString
s2i.builder-imageStringfabric8/s2i-java:2.3
s2i.build-env-varsEnv[]
s2i.auto-push-enabledbooleanfalse
s2i.auto-build-enabledbooleanfalse