×

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

因为用户通常通过路由器处理的路由访问应用程序,所以部署策略可以侧重于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. 根据激增计数向上扩展新的副本控制器。

  3. 根据最大不可用计数向下扩展旧的副本控制器。

  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 Container Platform 中所有机器配置池的maxUnavailable默认设置为1。建议不要更改此值,并一次更新一个控制平面节点。不要将控制平面池的此值更改为3

金丝雀部署

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

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

创建滚动部署

滚动部署是 OpenShift Container Platform 中的默认类型。您可以使用 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 被标记为ready(通过传递其就绪检查)后,部署过程继续。

如果 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 Container Platform 还向部署流程提供以下环境变量:

环境变量 描述

OPENSHIFT_DEPLOYMENT_NAME

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

OPENSHIFT_DEPLOYMENT_NAMESPACE

新部署的命名空间。

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

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

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 Container Platform API 或 Kubernetes API,则执行该策略的容器可以使用容器内可用的服务帐户令牌进行身份验证。

使用开发者视角编辑部署

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

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

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

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

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

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

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

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

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

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

  5. 单击**保存**。

生命周期钩子

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

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

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

中止 (Abort)

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

重试 (Retry)

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

忽略 (Ignore)

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

钩子具有一个类型特定的字段,用于描述如何执行钩子。目前,基于 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