×

部署策略用于在不中断服务的情况下更改或升级应用程序,以至于用户几乎不会注意到任何变化。

由于用户通常通过路由器处理的路由访问应用程序,因此部署策略可以专注于DeploymentConfig对象功能或路由功能。专注于DeploymentConfig对象功能的策略会影响使用该应用程序的所有路由。使用路由器功能的策略则针对单个路由。

大多数部署策略都通过DeploymentConfig对象支持,而一些额外的策略则通过路由器功能支持。

选择部署策略

选择部署策略时,请考虑以下因素:

  • 必须优雅地处理长期连接。

  • 数据库转换可能很复杂,必须与应用程序一起完成和回滚。

  • 如果应用程序是微服务和传统组件的混合体,则可能需要停机才能完成转换。

  • 您必须具备执行此操作的基础设施。

  • 如果您拥有非隔离的测试环境,则可能会破坏新旧版本。

部署策略使用就绪性检查来确定新的 Pod 是否已准备好使用。如果就绪性检查失败,则DeploymentConfig对象会重试运行 Pod 直到超时。默认超时时间为10m,此值在dc.spec.strategy.*params中的TimeoutSeconds中设置。

滚动策略

滚动部署会缓慢地将应用程序先前版本的实例替换为应用程序新版本的实例。如果在DeploymentConfig对象上未指定任何策略,则滚动策略是使用的默认部署策略。

滚动部署通常会在将旧组件缩减之前等待新的 Pod 通过就绪性检查变为ready。如果出现重大问题,则可以中止滚动部署。

何时使用滚动部署

  • 当您希望在应用程序更新期间不中断服务时。

  • 当您的应用程序支持同时运行旧代码和新代码时。

滚动部署意味着您同时运行着旧版和新版的代码。这通常要求您的应用程序处理 N-1 兼容性。

滚动策略定义示例
kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
  name: example-dc
# ...
spec:
# ...
  strategy:
    type: Rolling
    rollingParams:
      updatePeriodSeconds: 1 (1)
      intervalSeconds: 1 (2)
      timeoutSeconds: 120 (3)
      maxSurge: "20%" (4)
      maxUnavailable: "10%" (5)
      pre: {} (6)
     post: {}
1 各个 Pod 更新之间等待的时间。如果未指定,此值默认为1
2 更新后轮询部署状态之间等待的时间。如果未指定,此值默认为1
3 等待扩容事件的超时时间。可选;默认为600。此处,“超时”意味着自动回滚到之前的完整部署。
4 maxSurge 为可选参数,如果未指定,则默认为 25%。请参见以下步骤下面的信息。
5 maxUnavailable 为可选参数,如果未指定,则默认为 25%。请参见以下步骤下面的信息。
6 prepost 都是生命周期钩子。

滚动策略

  1. 执行任何 pre 生命周期钩子。

  2. 根据 surge 计数扩容新的副本控制器。

  3. 根据 max unavailable 计数缩容旧的副本控制器。

  4. 重复此缩放过程,直到新的副本控制器达到所需的副本数量,并且旧的副本控制器已缩容到零。

  5. 执行任何 post 生命周期钩子。

缩容时,滚动策略会等待 Pod 变为就绪状态,以便确定进一步缩容是否会影响可用性。如果扩容后的 Pod 始终无法就绪,部署过程最终将超时并导致部署失败。

maxUnavailable 参数是在更新期间可以不可用的 Pod 的最大数量。maxSurge 参数是可以比原始 Pod 数量多调度出的 Pod 的最大数量。这两个参数都可以设置为百分比(例如,10%)或绝对值(例如,2)。两者的默认值均为 25%

这些参数允许调整部署以平衡可用性和速度。例如:

  • maxUnavailable*=0maxSurge*=20% 确保在更新期间保持满负荷容量并快速扩容。

  • maxUnavailable*=10%maxSurge*=0 使用无额外容量执行更新(就地更新)。

  • maxUnavailable*=10%maxSurge*=10% 快速扩容和缩容,但可能导致容量损失。

通常,如果您需要快速部署,请使用 maxSurge。如果您需要考虑资源配额并且可以接受部分不可用性,请使用 maxUnavailable

OpenShift Dedicated 中所有机器配置池的 maxUnavailable 默认设置为 1。建议不要更改此值,并一次更新一个控制平面节点。不要将此值更改为控制平面池的 3

金丝雀部署

OpenShift Dedicated 中的所有滚动部署都是金丝雀部署;在新版本(金丝雀)部署之前,会对其进行测试,然后再替换所有旧实例。如果就绪检查从未成功,则会删除金丝雀实例,并且DeploymentConfig 对象将自动回滚。

就绪检查是应用程序代码的一部分,可以根据需要进行复杂的设置,以确保新实例已准备好使用。如果您必须实现更复杂的应用程序检查(例如,将真实用户工作负载发送到新实例),请考虑实现自定义部署或使用蓝绿部署策略。

创建滚动部署

滚动部署是 OpenShift Dedicated 中的默认类型。您可以使用 CLI 创建滚动部署。

步骤
  1. 基于在Quay.io中找到的示例部署镜像创建应用程序。

    $ oc new-app quay.io/openshifttest/deployment-example:latest

    此镜像不公开任何端口。如果您想通过外部 LoadBalancer 服务公开您的应用程序或启用通过公共互联网访问应用程序,请在完成此步骤后使用oc expose dc/deployment-example --port=<port>命令创建一个服务。

  2. 如果您已安装路由器,请通过路由使应用程序可用,或直接使用服务 IP。

    $ oc expose svc/deployment-example
  3. 浏览到deployment-example.<project>.<router_domain>上的应用程序,以验证您是否看到了v1镜像。

  4. DeploymentConfig对象扩展到三个副本。

    $ oc scale dc/deployment-example --replicas=3
  5. 通过将新版本的示例标记为latest标签来自动触发新的部署。

    $ oc tag deployment-example:v2 deployment-example:latest
  6. 在您的浏览器中刷新页面,直到您看到v2镜像。

  7. 使用 CLI 时,以下命令显示有多少 Pod 使用版本 1,有多少 Pod 使用版本 2。在 Web 控制台中,Pod 会逐步添加到 v2 并从 v1 中移除。

    $ oc describe dc deployment-example

在部署过程中,新的副本控制器会逐渐扩容。在新 Pod 被标记为就绪(通过其就绪检查)后,部署过程继续。

如果 Pod 未准备好,则该过程将中止,并且部署将回滚到其之前的版本。

使用开发者视角编辑部署

您可以使用**开发者**视角编辑部署的部署策略、镜像设置、环境变量和高级选项。

前提条件
  • 您位于 Web 控制台的**开发者**视角。

  • 您已创建了一个应用程序。

步骤
  1. 导航到**拓扑**视图。

  2. 单击您的应用程序以查看**详细信息**面板。

  3. 在**操作**下拉菜单中,选择**编辑部署**以查看**编辑部署**页面。

  4. 您可以编辑部署的以下**高级选项**

    1. 可选:您可以通过单击**暂停部署**,然后选择**为此部署暂停部署**复选框来暂停部署。

      通过暂停部署,您可以在不触发部署的情况下更改应用程序。您可以随时恢复部署。

    2. 可选:单击**缩放**以通过修改**副本**数量来更改镜像的实例数量。

  5. 单击**保存**。

使用开发者视角启动滚动部署

您可以通过启动滚动部署来升级应用程序。

前提条件
  • 您位于 Web 控制台的**开发者**视角。

  • 您已创建了一个应用程序。

步骤
  1. 在**拓扑**视图中,单击应用程序节点以查看侧面板中的**概述**选项卡。请注意,**更新策略**设置为默认的**滚动**策略。

  2. 在**操作**下拉菜单中,选择**启动部署**以启动滚动更新。滚动部署将启动应用程序的新版本,然后终止旧版本。

    odc rolling update
    图 1. 滚动更新

重新创建策略

重新创建策略具有基本的部署行为,并支持生命周期钩子以将代码注入到部署过程中。

重新创建策略定义示例
kind: Deployment
apiVersion: apps/v1
metadata:
  name: hello-openshift
# ...
spec:
# ...
  strategy:
    type: Recreate
    recreateParams: (1)
      pre: {} (2)
      mid: {}
      post: {}
1 recreateParams 为可选参数。
2 premidpost 是生命周期钩子。

重新创建策略

  1. 执行任何 pre 生命周期钩子。

  2. 将之前的部署缩容到零。

  3. 执行任何mid生命周期钩子。

  4. 扩展新的部署。

  5. 执行任何 post 生命周期钩子。

在扩展过程中,如果部署的副本数量大于1,则会在完全扩展部署之前验证部署的第一个副本的准备情况。如果第一个副本的验证失败,则部署将被视为失败。

何时使用重新创建部署

  • 当您必须在新的代码启动之前运行迁移或其他数据转换时。

  • 当您不支持同时运行新旧版本的应用程序代码时。

  • 当您想要使用RWO卷时,它不支持在多个副本之间共享。

重新创建部署会造成停机时间,因为在短暂的时间内,没有您的应用程序实例正在运行。但是,您的旧代码和新代码不会同时运行。

使用开发者视角编辑部署

您可以使用**开发者**视角编辑部署的部署策略、镜像设置、环境变量和高级选项。

前提条件
  • 您位于 Web 控制台的**开发者**视角。

  • 您已创建了一个应用程序。

步骤
  1. 导航到**拓扑**视图。

  2. 单击您的应用程序以查看**详细信息**面板。

  3. 在**操作**下拉菜单中,选择**编辑部署**以查看**编辑部署**页面。

  4. 您可以编辑部署的以下**高级选项**

    1. 可选:您可以通过单击**暂停部署**,然后选择**为此部署暂停部署**复选框来暂停部署。

      通过暂停部署,您可以在不触发部署的情况下更改应用程序。您可以随时恢复部署。

    2. 可选:单击**缩放**以通过修改**副本**数量来更改镜像的实例数量。

  5. 单击**保存**。

使用开发者视角启动重新创建部署

您可以使用Web控制台中的**开发者**视角将部署策略从默认的滚动更新切换到重新创建更新。

前提条件
  • 确保您处于Web控制台的**开发者**视角。

  • 确保您已使用**添加**视图创建了应用程序,并在**拓扑**视图中看到它已部署。

步骤

切换到重新创建更新策略并升级应用程序

  1. 单击您的应用程序以查看**详细信息**面板。

  2. 在**操作**下拉菜单中,选择**编辑部署配置**以查看应用程序的部署配置详细信息。

  3. 在YAML编辑器中,将spec.strategy.type更改为Recreate,然后单击**保存**。

  4. 在**拓扑**视图中,选择节点以查看侧面板中的**概述**选项卡。**更新策略**现在设置为**重新创建**。

  5. 使用**操作**下拉菜单选择**启动滚动更新**以使用重新创建策略启动更新。重新创建策略首先终止旧版本应用程序的Pod,然后启动新版本的Pod。

    odc recreate update
    图2. 重新创建更新

自定义策略

自定义策略允许您提供自己的部署行为。

自定义策略定义示例
kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
  name: example-dc
# ...
spec:
# ...
  strategy:
    type: Custom
    customParams:
      image: organization/strategy
      command: [ "command", "arg1" ]
      environment:
        - name: ENV_1
          value: VALUE_1

在上面的示例中,organization/strategy容器镜像提供了部署行为。可选的command数组会覆盖镜像的Dockerfile中指定的任何CMD指令。提供的可选环境变量将添加到策略进程的执行环境中。

此外,OpenShift Dedicated向部署过程提供以下环境变量

环境变量 描述

OPENSHIFT_DEPLOYMENT_NAME

新部署(复制控制器)的名称。

OPENSHIFT_DEPLOYMENT_NAMESPACE

新部署的命名空间。

新部署的副本数最初将为零。策略的责任是使用最能满足用户需求的逻辑来激活新部署。

或者,使用customParams对象将自定义部署逻辑注入到现有的部署策略中。提供自定义shell脚本逻辑并调用openshift-deploy二进制文件。用户不必提供其自定义部署程序容器镜像;在这种情况下,将改为使用默认的OpenShift Dedicated部署程序镜像。

kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
  name: example-dc
# ...
spec:
# ...
  strategy:
    type: Rolling
    customParams:
      command:
      - /bin/sh
      - -c
      - |
        set -e
        openshift-deploy --until=50%
        echo Halfway there
        openshift-deploy
        echo Complete

这将导致以下部署

Started deployment #2
--> Scaling up custom-deployment-2 from 0 to 2, scaling down custom-deployment-1 from 2 to 0 (keep 2 pods available, don't exceed 3 pods)
    Scaling custom-deployment-2 up to 1
--> Reached 50% (currently 50%)
Halfway there
--> Scaling up custom-deployment-2 from 1 to 2, scaling down custom-deployment-1 from 2 to 0 (keep 2 pods available, don't exceed 3 pods)
    Scaling custom-deployment-1 down to 1
    Scaling custom-deployment-2 up to 2
    Scaling custom-deployment-1 down to 0
--> Success
Complete

如果自定义部署策略过程需要访问OpenShift Dedicated API或Kubernetes API,则执行策略的容器可以使用容器内可用的服务帐户令牌进行身份验证。

使用开发者视角编辑部署

您可以使用**开发者**视角编辑部署的部署策略、镜像设置、环境变量和高级选项。

前提条件
  • 您位于 Web 控制台的**开发者**视角。

  • 您已创建了一个应用程序。

步骤
  1. 导航到**拓扑**视图。

  2. 单击您的应用程序以查看**详细信息**面板。

  3. 在**操作**下拉菜单中,选择**编辑部署**以查看**编辑部署**页面。

  4. 您可以编辑部署的以下**高级选项**

    1. 可选:您可以通过单击**暂停部署**,然后选择**为此部署暂停部署**复选框来暂停部署。

      通过暂停部署,您可以在不触发部署的情况下更改应用程序。您可以随时恢复部署。

    2. 可选:单击**缩放**以通过修改**副本**数量来更改镜像的实例数量。

  5. 单击**保存**。

生命周期钩子

滚动和重新创建策略支持生命周期钩子或部署钩子,它们允许在策略中预定义的点注入部署过程中的行为。

pre生命周期钩子示例
pre:
  failurePolicy: Abort
  execNewPod: {} (1)
1 execNewPod是一个基于Pod的生命周期钩子。

每个钩子都有一个失败策略,它定义了当遇到钩子失败时策略应该采取的操作。

中止

如果钩子失败,则部署过程将被视为失败。

重试

应重试钩子执行,直到成功。

忽略

应忽略任何钩子失败,并继续部署。

钩子具有一个类型特定的字段,用于描述如何执行钩子。目前,基于Pod的钩子是唯一支持的钩子类型,由execNewPod字段指定。

基于Pod的生命周期钩子

基于Pod的生命周期钩子在从DeploymentConfig对象中的模板派生的新Pod中执行钩子代码。

以下简化的部署示例使用滚动策略。为了简洁起见,省略了触发器和其他一些次要细节。

kind: DeploymentConfig
apiVersion: apps.openshift.io/v1
metadata:
  name: frontend
spec:
  template:
    metadata:
      labels:
        name: frontend
    spec:
      containers:
        - name: helloworld
          image: openshift/origin-ruby-sample
  replicas: 5
  selector:
    name: frontend
  strategy:
    type: Rolling
    rollingParams:
      pre:
        failurePolicy: Abort
        execNewPod:
          containerName: helloworld (1)
          command: [ "/usr/bin/command", "arg1", "arg2" ] (2)
          env: (3)
            - name: CUSTOM_VAR1
              value: custom_value1
          volumes:
            - data (4)
1 helloworld名称指的是spec.template.spec.containers[0].name
2 command将覆盖openshift/origin-ruby-sample镜像定义的任何ENTRYPOINT
3 env是钩子容器的一组可选环境变量。
4 volumes是钩子容器的一组可选卷引用。

在这个例子中,pre钩子将使用来自helloworld容器的openshift/origin-ruby-sample镜像在新Pod中执行。钩子Pod具有以下属性:

  • 钩子命令是/usr/bin/command arg1 arg2

  • 钩子容器具有CUSTOM_VAR1=custom_value1环境变量。

  • 钩子失败策略是Abort,这意味着如果钩子失败,则部署过程将失败。

  • 钩子Pod继承了来自DeploymentConfig对象Pod的data卷。

设置生命周期钩子

您可以使用CLI为部署设置生命周期钩子或部署钩子。

步骤
  1. 使用oc set deployment-hook命令设置所需的钩子类型:--pre--mid--post。例如,要设置预部署钩子:

    $ oc set deployment-hook dc/frontend \
        --pre -c helloworld -e CUSTOM_VAR1=custom_value1 \
        --volumes data --failure-policy=abort -- /usr/bin/command arg1 arg2