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