Deploying on OpenShift

本指南涵盖根据健全的默认配置和用户提供配置生成并部署 OpenShift 资源。

This guide covers generating and deploying OpenShift resources based on sane default and user supplied configuration.

Prerequisites

include::{includes}/prerequisites.adoc[]* 访问 OpenShift 集群(最小化是一个可行选项)* OpenShift CLI(可选,仅手动部署必需)

Unresolved directive in deploying-to-openshift.adoc - include::{includes}/prerequisites.adoc[] * Access to an OpenShift cluster (Minishift is a viable option) * OpenShift CLI (Optional, only required for manual deployment)

Bootstrapping the project

首先,我们需要一个包含 OpenShift 扩展的新项目。可以使用以下命令实现这一点:

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

Unresolved directive in deploying-to-openshift.adoc - include::{includes}/devtools/create-app.adoc[]

Quarkus 可自动生成基于健全默认值和用户提供的配置的 OpenShift 资源。OpenShift 扩展实际上是一个包装扩展,为 Kubernetes扩展配置了明智的默认值,使用户更容易在 OpenShift 上着手使用 Quarkus。

Quarkus offers the ability to automatically generate OpenShift resources based on sane defaults and user supplied configuration. The OpenShift extension is actually a wrapper extension that brings configures the Kubernetes extension with sensible defaults so that it’s easier for the user to get started with Quarkus on OpenShift.

当我们将 OpenShift 扩展添加到以上命令行调用时,以下依赖关系会添加到 pom.xml

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

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-openshift</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-openshift")

Log Into the OpenShift Cluster

在我们构建并部署应用程序之前,我们需要登录到一个 OpenShift 集群。您可以通过 OpenShift CLI登录:

Before we build and deploy our application we need to log into an OpenShift cluster. You can log in via the OpenShift CLI:

Log In - OpenShift CLI Example
oc login -u myUsername 1
1 You’ll be prompted for the required information such as server URL, password, etc.

或者,您可以使用 API 令牌登录:

Alternatively, you may log in using the API token:

Log In - OpenShift CLI With API Token Example
oc login --token=myToken --server=myServerUrl

您可以通过 OpenShift Web 控制台中的 _Copy Login Command_链接请求令牌。

You can request the token via the Copy Login Command link in the OpenShift web console.

最后,您根本不需要使用 OpenShift CLI。相反,设置 `quarkus.kubernetes-client.api-server-url`配置属性并通过 `quarkus.kubernetes-client.token`或 `quarkus.kubernetes-client.username`和 `quarkus.kubernetes-client.password`分别进行验证:

Finally, you don’t 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:

include::{includes}/devtools/build.adoc[]:!build-additional-parameters:

Unresolved directive in deploying-to-openshift.adoc - include::{includes}/devtools/build.adoc[] :!build-additional-parameters:

Build and Deployment

您可以在一个步骤中触发构建和部署或首先构建容器镜像,然后根据需要手动配置 OpenShift 应用程序 more control over the deployment configuration

You can trigger a build and deployment in a single step or build the container image first and then configure the OpenShift application manually if you need control_application_config.

触发在一个步骤中构建和部署:

To trigger a build and deployment in a single step:

include::{includes}/devtools/build.adoc[]:!build-additional-parameters:

Unresolved directive in deploying-to-openshift.adoc - include::{includes}/devtools/build.adoc[] :!build-additional-parameters:

如果您想立即测试您的应用程序,则将 quarkus.openshift.route.expose`配置属性设置为 `true`至 expose the service automatically,例如,向上述命令添加 `-Dquarkus.openshift.route.expose=true

If you want to test your application immediately then set the quarkus.openshift.route.expose config property to true to exposing_routes, e.g. add -Dquarkus.openshift.route.expose=true to the command above.

当使用 DeploymentConfig`和 Service Binding时,重新部署可能会删除 OpenShift 添加的配置,以允许服务发现。新的容器镜像构建会在 OpenShift 中触发 Quarkus 应用程序刷新: `-Dquarkus.container-image.build=true,这在大多数情况下可能就足够了。如果您需要更新 OpenShift 资源,则您需要先删除绑定,然后在新部署后再次创建它。

When using DeploymentConfig and Service Binding, re-deploying might remove the configuration added by OpenShift to allow service discovery. A new container image build will trigger a refresh of the Quarkus app in OpenShift: -Dquarkus.container-image.build=true which might be enough in most situations. If you need to update the OpenShift resources, you need to delete the binding first to create it again after new deployment.

此命令将本地构建您的应用程序,然后触发容器镜像构建,最后自动应用所生成的 OpenShift 资源。生成的资源使用 Kubernetes Deployment,但仍然使用 OpenShift 特定的资源,如 Route、`BuildConfig`等。

This command will build your application locally, then trigger a container image build and finally apply the generated OpenShift resources automatically. The generated resources use a Kubernetes Deployment, but still make use of OpenShift specific resources like Route, BuildConfig etc.

自 OpenShift 4.14 起, DeploymentConfig object has been deprecated

As of OpenShift 4.14, the DeploymentConfig object has been deprecated.

由于 Deployment`是 Kubernetes 资源而非 OpenShift 特定的资源,它不可能利用 `ImageStream`资源,就像 `DeploymentConfig`的情况一样。这意味着镜像引用需要包含承载镜像的容器镜像注册表。当镜像构建时,使用 OpenShift 构建(s2i 二进制和 Docker 策略),除非用户明确指定了另一个注册表,否则将使用 OpenShift 内部镜像注册表 `image-registry.openshift-image-registry.svc:5000。请注意,在内部注册表中,项目/名称空间名称被添加为镜像存储库的一部分: image-registry.openshift-image-registry.svc:5000/<project name>/<name>:<tag>,因此用户需要确保目标项目/名称空间名称与 `quarkus.container-image.group`保持一致。

Since Deployment is a Kubernetes resource and not OpenShift specific, it can’t possibly leverage ImageStream resources, as is the case with DeploymentConfig. This means that the image references need to include the container image registry that hosts the image. When the image is built, using OpenShift builds (s2i binary and docker strategy) the OpenShift internal image registry image-registry.openshift-image-registry.svc:5000 will be used, unless another registry has been explicitly specified by the user. Please note, that in the internal registry the project/namespace name is added as part of the image repository: image-registry.openshift-image-registry.svc:5000/<project name>/<name>:<tag>, so users will need to make sure that the target project/namespace name is aligned with the quarkus.container-image.group.

deprecation document包含有关如何设置/使用自动回滚、触发、生命周期挂钩和自定义策略的其他信息。

The deprecation document contains additional information about how to set up/use automatic rollbacks, triggers, lifecycle hooks, and custom strategies.

quarkus.container-image.group=<project/namespace name>

您可以使用 OpenShift Web 控制台验证上述命令是否已创建图像流、服务资源并已部署应用程序。或者,您可以运行以下 OpenShift CLI 命令:

You can use the OpenShift web console to verify that the above command has created an image stream, a service resource and has deployed the application. Alternatively, you can run the following OpenShift CLI commands:

oc get is 1
oc get pods 2
oc get svc 3
1 Lists the image streams created.
2 Get the list of pods.
3 Get the list of Kubernetes services.

请注意,服务默认情况下不对外界公开。因此,除非您已使用 quarkus.openshift.route.expose 配置属性自动公开创建的服务,否则您需要手动公开服务。

Note that the service is not exposed to the outside world by default. So unless you’ve used the quarkus.openshift.route.expose config property to expose the created service automatically you’ll need to expose the service manually.

Expose The Service - OpenShift CLI Example
oc expose svc/openshift-quickstart 1
oc get routes 2
curl http://<route>/hello 3
1 Expose the service.
2 Get the list of exposed routes.
3 Access your application.

Configure the OpenShift Application Manually

如果您需要对部署配置拥有更多控制权,那么您可以首先构建容器图像,然后手动配置 OpenShift 应用程序。

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

将执行的构建为 s2i binary 构建。构建的输入是已在本地构建的 jar,构建的输出是 ImageStream,该输出配置为自动触发部署。基本/构建器图像分别使用 base-jvm-imagebase-native-image 为 jvm 和本机模式指定。除非使用这些属性来引用内部 openshift 注册表中现有的 ImageStreamTag,否则将自动生成图像的 ImageStream。例如:

The build that will be performed is a s2i binary build. The input of the build is the jar that has been built locally and the output of the build is an ImageStream that is configured to automatically trigger a deployment. The base/builder image is specified 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.

在构建期间,您可能会发现由于自签名证书而导致 Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed 异常。要解决此问题,只需将以下行添加到您的 application.properties

During the build you may 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, just add the following line to your application.properties:

quarkus.kubernetes-client.trust-certs=true

有关更多信息,请参阅 deploying to Kubernetes

For more information, see deploying to Kubernetes.

构建完成后,我们可以从相关 ImageStream 创建一个新应用程序。

Once the build is done we 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.

完成此设置后,下一次构建容器图像时,将自动触发对 OpenShift 的部署。换句话说,您不必重复上述步骤。

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

Non-S2I Builds

开箱即用,OpenShift 扩展配置为使用 container-image-s2i。但是,仍然可以使用其他容器图像扩展,例如:

Out of the box the OpenShift extension is configured to use container-image-s2i. However, it’s still possible to use other container image extensions like:

当使用非 s2i 容器映像扩展时,将创建一个 ImageStream,该容器指向外部 dockerImageRepository。该图像构建后将推送到注册表中,而 ImageStream 将填充 dockerImageRepository 中可用的标记。

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

Customizing

所有可用的定制选项都可在 OpenShift configuration options 中找到。

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

以下章节中提供了一些示例:

Some examples are provided in the sections below:

Exposing Routes

若要为 Quarkus 应用程序公开 Route

To expose a Route for the Quarkus application:

quarkus.openshift.route.expose=true

你无需在 application.properties 中添加此属性。你可以将其作为命令行参数传递:

You don’t necessarily need to add this property in the application.properties. 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.

Securing the Route resource

为保护传入连接,OpenShift 提供了几种类型的 TLS 终止来服务认证。您可以在 the official OpenShift guide 中阅读有关如何保护路由的更多信息。

To secure the incoming connections, OpenShift provides several types of TLS termination to serve certifications. You can read more information about how to secure routes in the official OpenShift guide.

让我们看一个示例,了解如何通过添加 "quarkus.openshift.route.tls" 属性利用直通终止配置安全路由:

Let’s see an example about how to configure a secured Route using passthrough termination by simply 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

Labels

要在生成的资源中添加一个标签:

To add a label in the generated resources:

quarkus.openshift.labels.foo=bar

Annotations

要在生成的资源中添加注释:

To add an annotation in the generated resources:

quarkus.openshift.annotations.foo=bar

Environment variables

OpenShift 提供了多种定义环境变量的方法:

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

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

以上的命令将添加 MY_ENV_VAR=foobar 作为环境变量。请注意,键 my-env-var 将转换为大写,且破折号将替换为下划线,从而得到 MY_ENV_VAR

The command above will add MY_ENV_VAR=foobar as an environment variable. Please note that the key my-env-var will be converted to uppercase and dashes will be replaced by underscores resulting in MY_ENV_VAR.

Environment variables from Secret

要添加所有 Secret 键/值对作为环境变量,只需应用以下配置,并通过逗号 (,) 分隔用作源的每个 Secret

To add all key/value pairs of Secret as environment variables just 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 would generate the following in the container definition:

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

以下内容从 my-secret Secret 中提取由 keyName`字段标识的值,并放入 `foo 环境变量:

The following 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

这将在容器的 env 部分生成以下内容:

This would generate the following in the env section of your container:

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

Environment variables from ConfigMap

要将从 ConfigMap 中获取的所有键/值对用作环境变量,只需应用以下配置,并使用逗号 (,) 将各个 ConfigMap 分隔开以用作源:

To add all key/value pairs from ConfigMap as environment variables just 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 would generate the following in the container definition:

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

以下配置从 my-config-map ConfigMap 中提取 keyName 字段标识的一个值,并将其放入 foo 环境变量中:

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

这将在容器的 env 部分生成以下内容:

This would generate the following in the env section of your container:

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

Environment variables from fields

还可以使用另一个字段中的值来添加新的环境变量,为此需要指定要作为源使用的字段的路径,如下所示:

It’s also possible to 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, as follows:

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

Changing the generated deployment resource

除了通过 Deployment 生成资源外,您还可以选择通过 application.properties 访问 DeploymentConfigStatefulSetJobCronJob 资源:

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

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

要生成作业资源,您需要通过 application.properties 添加以下属性:

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

quarkus.openshift.deployment-kind=Job

如果您正在使用 Picocli 扩展,则默认情况下将生成 Job 资源。

If you are using the Picocli extension, by default the Job resource will be generated.

您可以通过属性 quarkus.openshift.arguments 提供 Kubernetes Job 将使用的参数。例如,添加属性 quarkus.openshift.arguments=A,B

You can provide the arguments that will be used by the Kubernetes Job via the property quarkus.openshift.arguments. For example, adding the property quarkus.openshift.arguments=A,B.

最后,Kubernetes Job 将在每次安装在 OpenShift 中时启动。您可以更多地了解如何在此处运行 Kubernetes Job link

Finally, the Kubernetes job will be launched every time that is installed in OpenShift. You can know more about how to run Kubernetes jobs in this link.

您可以使用 quarkus.openshift.job.xxx 中的属性配置 Kubernetes Job 的其他配置(请参见 link)。

You can configure the rest of the Kubernetes Job configuration using the properties under quarkus.openshift.job.xxx (see link).

Generating CronJob resources

如果您想要生成 CronJob 资源,您需要通过 “@12” 添加下列属性:

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

quarkus.openshift.deployment-kind=CronJob
# Cron expression to run the job every hour
quarkus.openshift.cron-job.schedule=0 * * * *

CronJob 资源需要 Cron 表达式以通过属性 quarkus.openshift.cron-job.schedule 指定何时启动作业。如果不提供,则构建将失败。

CronJob resources require the Cron expression to specify when to launch the job via the property quarkus.openshift.cron-job.schedule. If not provide, the build will fail.

您可以使用 quarkus.openshift.cron-job.xxx 中的属性配置 Kubernetes CronJob 的其他配置(请参见 link)。

You can configure the rest of the Kubernetes CronJob configuration using the properties under quarkus.openshift.cron-job.xxx (see link).

Validation

如果两个定义有冲突,例如,错误地同时指定一个值和指定变量来源于一个字段,将在构建时出现错误,这样你就有机会在将应用程序部署到集群中,在诊断问题根源会变得更困难前解决问题。

A conflict between two definitions, e.g. mistakenly assigning both a value and specifying that a variable is derived from a field, will result in an error being thrown at build time so that you get the opportunity to 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, e.g. defining an injection from the same secret twice, will not cause an issue but will indeed report a warning to let you know that you might not have intended to duplicate that definition.

Backwards compatibility

OpenShift 扩展的先前版本支持添加环境变量的不同语法。旧语法仍然受支持,但已弃用,建议您迁移到新语法。

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’s advised that you migrate to the new syntax.

Table 1. Old vs. 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

如果您重新定义相同的变量,同时使用新语法并保留旧语法,则会保留新版本,并发出警告以提醒您存在此问题。例如,如果您定义了 quarkus.openshift.env-vars.my-env-var.value=foobarquarkus.openshift.env.vars.my-env-var=newValue,则该扩展程序仅会生成环境变量 MY_ENV_VAR=newValue 并发出警告。

If you redefine the same variable using the new syntax while keeping the old syntax, ONLY the new version will be 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 will only generate an environment variable MY_ENV_VAR=newValue and issue a warning.

Mounting volumes

OpenShift 扩展程序允许用户为应用程序配置卷和装载。

The OpenShift extension allows the user to configure both volumes and mounts for the application.

可以通过简单配置装载任何卷:

Any volume can be mounted with a simple configuration:

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

这会针对路径 /where/to/mount 为卷 my-volume 添加一个装载到我的 Pod。

This will add a mount to my pod for volume my-volume to path /where/to/mount

卷本身可按以下部分中所示进行配置:

The volumes themselves can be configured as shown in the sections below:

Secret volumes

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

ConfigMap volumes

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

Persistent Volume Claims

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

Knative - OpenShift Serverless

OpenShift 还提供了通过 OpenShift Serverless 功能使用 Knative 的能力。

OpenShift also provides the ability to use Knative via the OpenShift Serverless functionality.

首要任务是通过设置来指示 Quarkus 生成 Knative 资源:

The first order of business is to instruct Quarkus to generate Knative resources by setting:

quarkus.kubernetes.deployment-target=knative

为了利用 OpenShift S2I 在集群上构建容器映像并将生成的容器映像用于 Knative 应用程序,我们需要设置几个配置属性:

In order to leverage OpenShift S2I to build the container image on the cluster and use the resulting container image for the Knative application, we need to set a couple of 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

然后可以通过启用标准 quarkus.kubernetes.deploy=true 属性将应用程序部署到 OpenShift Serverless。

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

Configuration Reference

@12:

Unresolved directive in deploying-to-openshift.adoc - include::{generated-dir}/config/quarkus-kubernetes_quarkus.openshift.adoc[]