OpenShift is a Kubernetes-based platform for developing and running containerized applications. Quarkus offers the ability to automatically generate OpenShift resources based on sane defaults and user-supplied configuration.

As an application developer, you can deploy your Quarkus applications to OpenShift. This functionality is provided by the quarkus-openshift extension, which supports multiple deployment options:

1. Overview of OpenShift build strategies

Docker build

This strategy builds the artifacts outside the OpenShift cluster, locally or in a CI environment, and provides them to the OpenShift build system together with a Dockerfile. The artifacts include JAR files or a native executable. The container gets built inside the OpenShift cluster and is provided as an image stream.

The OpenShift Docker build strategy is the preferred build strategy because it supports Quarkus applications targeted for JVM or compiled to native executables. However, for compatibility with earlier Quarkus versions, the default build strategy is S2I. To select the OpenShift Docker build strategy, use the quarkus.openshift.build-strategy property.

Source to Image (S2I)

The build process is performed inside the OpenShift cluster. Quarkus fully supports using S2I to deploy Quarkus as a JVM application.

Binary S2I

This strategy uses a JAR file as input to the S2I build process, which speeds up the building and deploying of your application.

1.1. Build strategies supported by Quarkus

The following table outlines the build strategies that Quarkus supports:

Build strategy Support for Quarkus tools Support for JVM Support for native Support for JVM Serverless Support for native Serverless

Docker build

YES

YES

YES

YES

YES

S2I Binary

YES

YES

NO

NO

NO

Source S2I

NO

YES

NO

NO

NO

2. Bootstrapping the project

First, you need a new project that contains the OpenShift extension. Then, before you build and deploy our application, you must log into an OpenShift cluster.

2.1. Adding the OpenShift extension

To build and deploy your applications as a container image that runs inside your OpenShift cluster, you must add the Quarkus OpenShift extension quarkus-openshift as a dependency to your project.

This extension also generates OpenShift resources such as image streams, build configuration, deployment, and service definitions. If your application includes the quarkus-smallrye-health extension, OpenShift can access the health endpoint and verify the startup, liveness, and readiness of your application.

From Quarkus 3.8, the DeploymentConfig object, deprecated in OpenShift, is also deprecated in Quarkus. Deployment is the default and preferred deployment kind for the quarkus-openshift extension. If you redeploy applications that you deployed before by using DeploymentConfig, by default, those applications use Deployment but do not remove the previous DeploymentConfig. This leads to a deployment of both new and old applications, so, you must remove the old DeploymentConfig manually. However, if you want to continue to use DeploymentConfig, it is still possible to do so by explicitly setting quarkus.openshift.deployment-kind to DeploymentConfig.

Prerequisites
  • You have a Quarkus Maven project.

Procedure
  1. To add the quarkus-openshift extension to your project, use one of the following methods:

    • Configure the pom.xml file:

      pom.xml
      <dependency>
          <groupId>io.quarkus</groupId>
          <artifactId>quarkus-openshift</artifactId>
      </dependency>
    • Enter the following command on the OpenShift CLI:

      ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-openshift"
    • Enter the following command on the Quarkus CLI:

      quarkus extension add 'quarkus-openshift'

3. Logging in to an OpenShift cluster

You can log in to an OpenShift cluster by using the OpenShift CLI (oc). For more information, see Getting started with the OpenShift CLI:

Example: Log in by using the OpenShift CLI
oc login -u myUsername (1)
1 You are prompted for the required information such as server URL, password, and so on.

Alternatively, you can log in by using the API token:

Example: Log in by using the OpenShift CLI with API token
oc login --token=myToken --server=myServerUrl
You can request the token by using the Copy Login Command link in the OpenShift web console.

Finally, you do not need to use the OpenShift CLI at all. Instead, set the quarkus.kubernetes-client.api-server-url config property and authenticate with the quarkus.kubernetes-client.token, or quarkus.kubernetes-client.username and quarkus.kubernetes-client.password respectively:

CLI
quarkus build quarkus deploy openshift
Maven
./mvnw install -Dquarkus.kubernetes-client.api-server-url=myServerUrl -Dquarkus.kubernetes-client.token=myToken
Gradle
./gradlew build -Dquarkus.kubernetes-client.api-server-url=myServerUrl -Dquarkus.kubernetes-client.token=myToken

3.1. Switching to the required OpenShift project

You can use the OpenShift CLI to create applications and manage your OpenShift projects. Use the information provided to create an OpenShift project or to switch to an existing one.

Prerequisites
  • You have access to an OpenShift cluster and the latest compatible version of the oc tool installed.

Procedure
  1. Log in to the oc tool:

    oc login
  2. To show the current project space, enter the following command:

    oc project -q
  3. Use one of the following steps to go to the required OpenShift project:

    1. If the project already exists, switch to the project:

      oc project <project_name>
    2. If the project does not exist, create a new project:

      oc new-project <project_name>

4. Building and deploying

You can build and deploy by using any of the following deployment options:

4.1. Configuring the OpenShift application manually

If you need more control over the deployment configuration, you can build the container image first and then configure the OpenShift application manually.

To trigger a container image build:

./mvnw clean package -Dquarkus.container-image.build=true

The build that is performed is a s2i binary build. The input of the build is the JAR file that has been built locally and the build output is an ImageStream that is configured to automatically trigger a deployment. The base or builder image is specified by using base-jvm-image and base-native-image for JVM and native mode respectively. An ImageStream for the image is automatically generated, unless these properties are used to reference an existing ImageStreamTag in the internal openshift registry. For example:

quarkus.openshift.base-jvm-image=image-registry.openshift-image-registry.svc:5000/some-project/openjdk-11:17.1.16.

During the build you might find the Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed exception due to self-signed certificate. To solve this, add the following line to your application.properties file:

quarkus.kubernetes-client.trust-certs=true

For more information, see deploying to Kubernetes.

After the build is finished, you can create a new application from the relevant ImageStream.

oc get is (1)
oc new-app --name=greeting <project>/openshift-quickstart:1.0.0-SNAPSHOT (2)
oc get svc
oc expose svc/greeting (3)
oc get routes (4)
curl http://<route>/hello (5)
1 Lists the image streams created. The image stream of our application should be tagged as <project>/openshift-quickstart:1.0.0-SNAPSHOT.
2 Create a new application from the image source.
3 Expose the service to the outside world.
4 Get the list of exposed routes.
5 Access your application.

After this setup the next time the container image is built a deployment to OpenShift is triggered automatically. In other words, you do not need to repeat the above steps.

4.2. Non-S2I builds

The OpenShift extension is configured to use container-image-s2i. However, it is still possible to use other container image extensions, such as:

When a non-s2i container image extension is used, an ImageStream is created that is pointing to an external dockerImageRepository. The image is built and pushed to the registry and the ImageStream populates the tags that are available in the dockerImageRepository.

To select which extension will be used for building the image:

quarkus.container-image.builder=docker

or

quarkus.container-image.builder=jib

5. Customizing

All available customization options are available in the OpenShift configuration options.

Some examples are provided in the sections below:

5.1. Exposing routes

To expose a Route for the Quarkus application:

quarkus.openshift.route.expose=true

You do not need to add this property in the application.properties file. Instead, you can pass it as a command-line argument:

./mvnw clean package -Dquarkus.openshift.route.expose=true

The same applies to all properties listed below.

5.1.1. Securing the Route resource

To secure the incoming connections, OpenShift provides several types of TLS termination to serve certifications.

For more information about how to secure routes, see OpenShift Container Platform documentation.

The following example shows how to configure a secured Route by using passthrough termination by adding the "quarkus.openshift.route.tls" properties:

quarkus.openshift.route.expose=true
quarkus.openshift.route.target-port=https
## Route TLS configuration:
quarkus.openshift.route.tls.termination=passthrough
quarkus.openshift.route.tls.insecure-edge-termination-policy=None

5.2. Labels

To add a label in the generated resources:

quarkus.openshift.labels.foo=bar

5.3. Annotations

To add an annotation in the generated resources:

quarkus.openshift.annotations.foo=bar

5.4. Environment variables

OpenShift provides multiple ways of defining environment variables:

  • Key/value pairs

  • Import all values from a Secret or ConfigMap

  • Interpolate a single value identified by a given field in a Secret or ConfigMap

  • Interpolate a value from a field within the same resource

5.4.1. Environment variables from key/value pairs

To add a key/value pair as an environment variable in the generated resources:

quarkus.openshift.env.vars.my-env-var=foobar

The above command adds MY_ENV_VAR=foobar as an environment variable. The key my-env-var will convert to uppercase and dashes will be replaced by underscores resulting in MY_ENV_VAR.

5.4.2. Environment variables from Secret

To add all key/value pairs of Secret as environment variables, apply the following configuration, separating each Secret to be used as source by a comma (,):

quarkus.openshift.env.secrets=my-secret,my-other-secret

which generates the following in the container definition:

envFrom:
  - secretRef:
      name: my-secret
      optional: false
  - secretRef:
      name: my-other-secret
      optional: false

The following code extracts a value identified by the keyName field from the my-secret Secret into a foo environment variable:

quarkus.openshift.env.mapping.foo.from-secret=my-secret
quarkus.openshift.env.mapping.foo.with-key=keyName

which generates the following in the env section of your container:

- env:
  - name: FOO
    valueFrom:
      secretKeyRef:
        key: keyName
        name: my-secret
        optional: false

5.4.3. Environment variables from ConfigMap

To add all key/value pairs from ConfigMap as environment variables, apply the following configuration, separating each ConfigMap to be used as source by a comma (,):

quarkus.openshift.env.configmaps=my-config-map,another-config-map

which generates the following in the container definition:

envFrom:
  - configMapRef:
      name: my-config-map
      optional: false
  - configMapRef:
      name: another-config-map
      optional: false

The following extracts a value identified by the keyName field from the my-config-map ConfigMap into a foo environment variable:

quarkus.openshift.env.mapping.foo.from-configmap=my-configmap
quarkus.openshift.env.mapping.foo.with-key=keyName

which generates the following in the env section of your container:

- env:
  - name: FOO
    valueFrom:
      configMapKeyRef:
        key: keyName
        name: my-configmap
        optional: false

5.4.4. Environment variables from fields

You can also use the value from another field to add a new environment variable by specifying the path of the field to be used as a source. For example:

quarkus.openshift.env.fields.foo=metadata.name

5.4.5. Changing the generated deployment resource

Beside generating a Deployment resource, you can also choose to get either a DeploymentConfig, StatefulSet, Job, or a CronJob resource instead by using application.properties:

quarkus.openshift.deployment-kind=StatefulSet
5.4.5.1. Generating Job resources

If you want to generate a Job resource, you need to add the following property by using the application.properties:

quarkus.openshift.deployment-kind=Job
If you are using the Picocli extension, by default the Job resource will be generated.

You can provide the arguments that Kubernetes Job uses through the quarkus.openshift.arguments property. For example, adding the property quarkus.openshift.arguments=A,B.

Finally, the Kubernetes job will be launched every time that it is installed in OpenShift. For more information about how to run Kubernetes jobs, see Running an example job.

You can configure the rest of the Kubernetes Job configuration by using the properties under quarkus.openshift.job.xxx. For more information, see quarkus.openshift.job.parallelism.

5.4.5.2. Generating CronJob resources

If you want to generate a CronJob resource, you need to add the following property by using the application.properties file:

quarkus.openshift.deployment-kind=CronJob
# Cron expression to run the job every hour
quarkus.openshift.cron-job.schedule=0 * * * *
CronJob resources require the Cron expression to specify when to launch the job through the quarkus.openshift.cron-job.schedule property. If they are not provided, the build fails.

You can configure the rest of the Kubernetes CronJob configuration by using the properties under quarkus.openshift.cron-job.xxx (for more information, see quarkus.openshift.cron-job.parallelism).

5.4.6. Validation

A conflict between two definitions, for example, mistakenly assigning both a value and specifying that a variable is derived from a field, results in an error being thrown at build time. You can fix the issue before you deploy your application to your cluster, where it might be more difficult to diagnose the source of the issue.

Similarly, two redundant definitions, for example, defining an injection from the same secret twice, does not cause an issue but reports a warning to inform you that you might not have intended to duplicate that definition.

5.4.6.1. Backwards compatibility

Previous versions of the OpenShift extension supported a different syntax to add environment variables. The older syntax is still supported but is deprecated, and it is advised that you migrate to the new syntax.

Table 1. Old syntax versus new syntax

Old

New

Plain variable

quarkus.openshift.env-vars.my-env-var.value=foobar

quarkus.openshift.env.vars.my-env-var=foobar

From field

quarkus.openshift.env-vars.my-env-var.field=foobar

quarkus.openshift.env.fields.my-env-var=foobar

All from ConfigMap

quarkus.openshift.env-vars.xxx.configmap=foobar

quarkus.openshift.env.configmaps=foobar

All from Secret

quarkus.openshift.env-vars.xxx.secret=foobar

quarkus.openshift.env.secrets=foobar

From one Secret field

quarkus.openshift.env-vars.foo.secret=foobar

quarkus.openshift.env.mapping.foo.from-secret=foobar

quarkus.openshift.env-vars.foo.value=field

quarkus.openshift.env.mapping.foo.with-key=field

From one ConfigMap field

quarkus.openshift.env-vars.foo.configmap=foobar

quarkus.openshift.env.mapping.foo.from-configmap=foobar

quarkus.openshift.env-vars.foo.value=field

quarkus.openshift.env.mapping.foo.with-key=field

If you redefine the same variable by using the new syntax while keeping the old syntax, only the new version is kept, and a warning will be issued to alert you of the problem.
For example, if you define both `quarkus.openshift.env-vars.my-env-var.value=foobar` and `quarkus.openshift.env.vars.my-env-var=newValue`, the extension generates an environment variable `MY_ENV_VAR=newValue` and issues a warning.

5.5. Mounting volumes

The OpenShift extension allows you to configure both volumes and mounts for the application. You can mount any volume with a simple configuration:

quarkus.openshift.mounts.my-volume.path=/where/to/mount

This will add a mount to my pod for volume my-volume to path /where/to/mount. You can configure the volumes themselves as shown in the sections below:

5.5.1. Secret volumes

quarkus.openshift.secret-volumes.my-volume.secret-name=my-secret

5.5.2. ConfigMap volumes

quarkus.openshift.config-map-volumes.my-volume.config-map-name=my-config-map

5.5.3. Persistent volume claims

quarkus.openshift.pvc-volumes.my-pvc.claim-name=my-pvc

6. Knative - OpenShift Serverless

OpenShift also provides the ability to use Knative by using the OpenShift Serverless functionality.

First, you instruct Quarkus to generate Knative resources:

quarkus.kubernetes.deployment-target=knative

To leverage OpenShift S2I to build the container image on the cluster and use the resulting container image for the Knative application, set the following configuration properties:

# set the Kubernetes namespace which will be used to run the application
quarkus.container-image.group=geoand
# set the container image registry - this is the standard URL used to refer to the internal OpenShift registry
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000

You can then deploy the application to OpenShift Serverless by enabling the standard quarkus.kubernetes.deploy=true property.

7. Configuration Reference