4.3. 使用 DeploymentConfig 策略
部署策略是更改或升级应用程序的一种方法。其目的是在无需停机的前提下进行修改,从而使用户几乎不会注意到这些变化。
因为最终用户通常通过由路由器控制的路由访问应用程序,所以部署策略侧重于 DeploymentConfig 功能或路由功能。侧重于 DeploymentConfig 的策略会影响到所有使用应用程序的路由。侧重于路由功能的策略则会影响到单个的路由。
许多部署策略通过 DeploymentConfig 支持,一些额外的策略则通过路由器功能支持。本节将讨论 DeploymentConfig 策略。
选择部署策略
选择部署策略时请考虑以下几点:
- 长时间运行的连接必须被恰当处理。
- 数据库转换可能比较复杂,且必须和应用程序一同执行并回滚。
- 如果应用程序由微服务和传统组件构成,则可能需要停机才能完成转换。
- 您必须拥有进行此操作的基础架构。
- 如果您的测试环境没有被隔离,则可能会破坏到新版本和旧版本。
部署策略使用就绪状态检查来确定新 Pod 是否准备就绪。如果未通过就绪状态检查,DeploymentConfig 会重新尝试运行 Pod,直到超时为止。默认超时为 10m
,其值在 dc.spec.strategy.*params
的 TimeoutSeconds
中设置。
4.3.1. Rolling 策略
滚动部署会逐渐将应用程序旧版本实例替换为应用程序的新版本实例。如果 DeploymentConfig 中没有指定任何策略,则 Rolling 策略就是默认的部署策略。
在缩减旧组件前,滚动部署通常会借助 readiness check
等待新 Pod 变为 ready
。如果发生严重问题,可以中止 Rolling 部署。
何时使用 Rolling 部署:
- 希望在应用程序更新过程中不需要停机时。
- 应用程序同时支持运行旧代码和新代码时。
Rolling 部署意味着您可以同时运行旧版和新版本的代码。这通常需要您的应用程序可以处理 N-1 兼容性。
Rolling 策略定义示例
strategy: type: Rolling rollingParams: updatePeriodSeconds: 1 1 intervalSeconds: 1 2 timeoutSeconds: 120 3 maxSurge: "20%" 4 maxUnavailable: "10%" 5 pre: {} 6 post: {}
Rolling 策略:
-
执行任何
pre
生命周期 hook。 - 根据激增数扩展新的 ReplicationController。
- 根据最大不可用数,缩减旧的 ReplicationController。
- 重复此扩展,直到新的 ReplicationController 达到所需的副本数,并且旧的 ReplicationController 已缩减到零。
-
执行任何
post
生命周期 hook。
在缩减时,Rolling 策略会等待 Pod 准备就绪,以便它能决定进一步缩放是否会影响到可用性。如果扩展 Pod 永不就绪,部署过程将最终超时并导致部署失败。
maxUnavailable
参数是在更新过程中不可用的 Pod 的最大数量。maxSurge
参数是原始 Pod 数之上最多可以调度的 Pod 数。这两个参数可以设定为百分比(如 10%
)或绝对值(如 2
)。两者的默认值都是 25%
。
这些参数允许对部署的可用性和速度进行调优。例如:
-
maxUnavailable*=0
和maxSurge*=20%
可确保在更新和快速扩展过程中保持全部容量。 -
maxUnavailable*=10%
和maxSurge*=0
在执行更新时不使用额外容量(原位更新)。 -
maxUnavailable*=10%
和maxSurge*=10%
可以快速缩放,可能会有一些容量损失。
一般而言,如果您想要快速推出部署,请使用 maxSurge
。如果您需要考虑资源配额并可以接受资源部分不可用的情况,则可使用 maxUnavailable
。
4.3.1.1. Canary 部署
OpenShift Container Platform 中的所有 Rolling 部署都属于 Canary 部署;在替换所有旧实例前测试新的版本(Canary)。如果就绪度检查永不成功,则移除该 Canary 实例,并且自动回滚 DeploymentConfig。
就绪度检查是应用程序代码的一部分,并且可以尽可能的精密,确保新实例就绪可用。如果您必须对应用程序进行更复杂的检查(比如向新实例发送真实用户负载),请考虑实施自定义部署或使用蓝绿部署策略。
4.3.1.2. 创建 Rolling 部署
在 OpenShift Container Platform 中,Rolling 部署是默认类型。您可以使用 CLI 创建 Rolling 部署。
流程
根据 DockerHub 中找到的示例部署镜像创建一个应用程序:
$ oc new-app openshift/deployment-example
如果您安装了路由器,请通过路由(或直接使用服务 IP)提供应用程序。
$ oc expose svc/deployment-example
-
通过
deployment-example.<project>.<router_domain>
访问应用程序,验证您能否看到v1
镜像。 将 DeploymentConfig 扩展至三个副本:
$ oc scale dc/deployment-example --replicas=3
通过为示例的新版本标上
latest
标签(tag),自动触发新部署:$ oc tag deployment-example:v2 deployment-example:latest
-
在浏览器中刷新页面,直到您看到
v2
镜像。 在使用 CLI 时,以下命令显示版本 1 上的 Pod 数以及版本 2 上的数量。在 Web 控制台中,Pod 逐渐添加到 v2 中并从 v1 中移除:
$ oc describe dc deployment-example
在部署过程中,新 ReplicationController 以递增方式扩展。新 Pod 标记为 ready
(通过就绪度检查)后,部署过程将继续。
如果 Pod 尚未就绪,该过程中止,并且 DeploymentConfig 回滚到之前的版本。
4.3.2. Recreate 策略
Recreate 策略具有基本的推出部署行为,并支持使用生命周期 hook 将代码注入到部署过程中。
Recreate 策略定义示例
strategy: type: Recreate recreateParams: 1 pre: {} 2 mid: {} post: {}
Recreate 策略:
-
执行任何
pre
生命周期 hook。 - 将上一部署缩减到零。
-
执行任何
mid
生命周期 hook。 - 向上扩展新的部署。
-
执行任何
post
生命周期 hook。
在扩展过程中,如果部署副本数大于一,则先对部署的第一副本进行就绪状态验证,然后再全面扩展部署。如果第一副本验证失败,部署将被视为失败。
何时使用 Recreate 部署:
- 需要在新代码启动前进行迁移或进行其他数据转换时。
- 不支持同时运行应用程序代码的新旧版本时。
- 当使用 RWO 卷时,不支持在多个副本间共享该卷。
Recreate 部署会出现停机的情况,这是因为在短时间内会出现没有运行您的应用程序实例的情况。然而,旧代码和新代码不会被同时运行。
4.3.3. Custom 策略
Custom 策略允许您提供自己的部署行为。
Custom 策略定义示例
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 为部署过程提供以下环境变量:
环境变量 | 描述 |
---|---|
| 新部署 (ReplicationController) 的名称。 |
| 新部署的命名空间。 |
新部署的副本数最初为零。该策略负责使新部署积极使用最能满足用户需求的逻辑。
另外,也可使用 customParams
将自定义部署逻辑注入现有的部署策略中。提供自定义 shell 脚本逻辑并调用 openshift-deploy
二进制文件。用户不必提供自定义的部署器容器镜像;本例中使用默认的 OpenShift Container Platform 部署器镜像:
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,执行该策略的容器可以使用容器中的服务帐户令牌进行身份验证。
4.3.4. 生命周期 hook
Rolling 和 Recreate 策略支持 生命周期 hook 或部署 hook,它允许在策略的预定义点将行为注入到部署过程中:
pre
生命周期 hook 示例
pre:
failurePolicy: Abort
execNewPod: {} 1
- 1
execNewPod
是基于 Pod 的生命周期 hook。
每个 hook 都有 failurePolicy
,定义在遇到 hook 失败时策略应执行的操作:
| 如果 hook 失败,部署过程将被视为失败。 |
| 应重试 hook 执行过程,直到成功为止。 |
| 所有 hook 失败都应忽略,部署应继续进行。 |
Hook 具有特定类型的字段,用于描述如何执行 Hook。目前,基于 Pod 的 hook 是唯一受支持的 hook 类型,通过 execNewPod
字段指定。
基于 Pod 的生命周期 hook
基于 Pod 的生命周期 hook 在来自 DeploymentConfig 模板的新 Pod 中执行 hook 代码。
以下简化 DeploymentConfig 示例使用了 Rolling 策略。为简明起见,省略了触发器和其他一些次要的细节:
kind: DeploymentConfig apiVersion: 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
在本例中,将使用 helloworld
容器中的 openshift/origin-ruby-sample
镜像在新 Pod 中执行 pre
hook。hook Pod 具有以下属性:
-
hook 命令是
/usr/bin/command arg1 arg2
。 -
hook 容器包含
CUSTOM_VAR1=custom_value1
环境变量。 -
hook 失败策略是
Abort
;即 hook 失败时部署过程也会失败。 -
hook Pod 从 DeploymentConfig Pod 继承
data
卷。
4.3.4.1. 设置生命周期 hook
您可以使用 CLI 为 DeploymentConfig 设置生命周期 hook 或部署 hook。
流程
使用
oc set deployment-hook
命令设定您想要的 hook 类型:--pre
、--mid
或--post
。例如,设置部署前 hook:$ oc set deployment-hook dc/frontend \ --pre -c helloworld -e CUSTOM_VAR1=custom_value1 \ -v data --failure-policy=abort -- /usr/bin/command arg1 arg2