4.4. 使用基于路由的部署策略

部署策略为应用程序的演进提供了一个途径。有些策略使用 DeploymentConfig 进行对解析到应用程序的所有路由用户可见的更改。其他高级策略,例如本节中描述的策略,结合使用路由器功能和 DeploymentConfig 来影响特定的路由。

最常用的基于路由型策略是使用蓝绿部署。新版本(蓝色版本)上线进行测试和评估,同时用户仍然使用稳定版本(绿色版本)。准备就绪后,用户切换到蓝色版本。如果出现问题,您可以切回到绿色版本。

一个常见的替代策略是使用同时活跃的 A/B 版本;一些用户使用一个版本,另一些用户使用另一个版本。这可用于试验用户界面变化和其他功能,以获取用户反馈。它还可用来在影响有限用户的生产环境中验证正确的操作。

Canary 部署会测试新版本,但在检测到问题时,迅速回退到上一版本。这可以通过以上两个策略实现。

基于路由的部署策略不会缩放服务中的 Pod 数。要保持所需的性能特性,部署配置可能必须要扩展。

4.4.1. 代理分片和流量分割

在生产环境中,您可以精确控制特定分片上的流量分布。在处理大量实例时,可以使用相对比例的独立分片来实现基于百分比的流量分布。这可与代理分片良好结合,将接收到的流量转发或分割到在其他位置运行的单独服务或应用程序。

在最简单的配置中,代理会原封不动转发请求。在比较复杂的设置中,可以复制传入的请求,同时将它们发送到独立集群以及应用程序的本地实例,并且比较其结果。其他模式包括使 DR 安装的缓存保持活跃,或抽样传入的流量来满足分析需要。

任何 TCP(或 UDP)代理都可以在所需的分片下运行。使用 oc scale 命令更改代理分片下服务请求的相对数量。对于更复杂的流量管理,请考虑使用比例平衡功能自定义 OpenShift Container Platform 路由器。

4.4.2. N-1 兼容性

同时运行新旧代码的应用程序必须要谨慎处理,以确保新代码写入的数据能被旧版代码读取和处理(或恰当忽略)。这有时被称为架构演进,而且是一个复杂的问题。

这可采用多种形式:数据存储在磁盘、数据库或临时缓存中,或作为用户浏览器会话的一部分。虽然大多数 Web 应用程序都支持滚动部署,但务必要测试并设计您的应用程序以便能处理它。

在一些应用程序中,同时运行新旧代码的时间是短暂的,因此程序错误或一些用户事务失败是可以接受的。至于其他应用程序,失败模式可能会导致整个应用程序无法运作。

验证 N-1 兼容性的一种方法是使用 A/B 部署:在测试环境中以受控的方式同时运行旧代码和新代码,并验证流向新部署的流量不会导致旧部署失败。

4.4.3. 恰当终止

OpenShift Container Platform 和 Kubernetes 会留出时间,让应用程序实例关机后再从负载均衡轮转中移除。但是,应用程序必须保证在用户退出前彻底终止用户连接。

在关闭时,OpenShift Container Platform 会向容器中的进程发送一个 TERM 信号。在接收 SIGTERM 时,应用程序代码停止接受新的连接。这样可确保负载均衡器将流量路由到其他活跃实例。然后,应用程序代码会等到所有开启的连接都关闭(或在下次机会出现时恰当终止独立的连接)后再退出。

在恰当终止周期到期后,还未退出的进程会收到 KILL 信号,该信号会立即结束此进程。Pod 或 Pod 模板的 terminationGracePeriodSeconds 属性可控制恰当终止的时间(默认为 30 秒),并可根据需要对单个应用程序进行独立设置。

4.4.4. 蓝绿部署

蓝绿部署涉及同时运行应用程序的两个版本,并将流量从生产版本(绿色版本)移动到更新版本(蓝色版本)。您可以使用 Rolling 策略或切换路由中的服务。

由于许多应用程序依赖于持久性数据,您必须有支持 N-1 兼容性的应用程序;这意味着,通过创建数据层的两个副本在数据库、存储或磁盘间共享数据并实现实时迁移。

以测试新版本时使用的数据为例。如果是生产数据,新版本中的错误可能会破坏生产版本。

4.4.4.1. 设置蓝绿部署

蓝绿部署使用两个 DeploymentConfig。这两者都在运行,生产环境中的 DeploymentConfig 依赖于路由指定的服务,每个 DeploymentConfig 都公开给不同的服务。

注意

路由适用于 Web(HTTP 和 HTTPS)流量,因此这种技术最适合 Web 应用程序。

您可以创建指向新版本的新路由并进行测试。准备就绪后,将生产路径中的服务更改为指向新服务,使新(蓝色)版本上线。

如果需要,可以通过将服务切回到之前的版本以回滚到老版本(绿色)。

流程

  1. 创建示例应用程序的两个副本:

    $ oc new-app openshift/deployment-example:v1 --name=example-green
    $ oc new-app openshift/deployment-example:v2 --name=example-blue

    这会创建两个独立的应用程序组件:一个在 example-green 服务下运行 v1 镜像,另一个使用 example-blue 服务下的 v2 镜像。

  2. 创建指向旧服务的路由:

    $ oc expose svc/example-green --name=bluegreen-example
  3. 通过 example-green.<project>.<router_domain> 访问应用程序,验证您能否看到 v1 镜像。
  4. 编辑路由并将服务名称改为 example-blue

    $ oc patch route/bluegreen-example -p '{"spec":{"to":{"name":"example-blue"}}}'
  5. 要验证路由是否已改变,请刷新浏览器直到您看到 v2 镜像。

4.4.5. A/B 部署

A/B 部署策略允许您在生产环境中以有限的方式尝试应用程序的新版本。您可以指定生产版本获得大多数用户请求,同时让有限比例的请求进入新版本。

由于您掌控进入每个版本的请求比例,因此随着测试的推进,您可以增加进入新版本的请求的比例,最终停止使用旧版本。当您调整每个版本的请求负载时,可能需要扩展各个服务中的 Pod 数,以提供预期的性能。

除了升级软件外,您还可以使用此功能来试验用户界面的不同版本。由于部分用户会使用旧版本,而另外的一部分用户会使用新版本,因此您可以评估用户对不同版本的反应,以做出明智的设计决策。

若要使此功能凑效,新旧两个版本必须足够相似,让两个版本能够同时运行。这常用于对程序错误修复的发布,也适用于新功能不会影响到旧功能的情况。各个版本需要支持 N-1 兼容性才能正常工作。

OpenShift Container Platform 通过 Web 控制台和 CLI 支持 N-1 兼容性。

4.4.5.1. A/B 测试负载均衡

用户使用多个服务设置路由。每个服务负责应用程序的一个版本。

每个服务分配到一个 weight,进入每个服务的请求的比例等于 service_weight 除以 sum_of_weights。每个服务的 weight 分布到该服务的端点,使得端点 weight 的总和等于服务 weight

路由最多可有四个服务。服务的 weight 可以在 0256 范围内。当 weight 等于 0 时,服务不参与负载均衡,但继续为现有的持久连接服务。当服务 weight 不为 0 时,每个端点的最小 weight1。因此,拥有大量端点的服务会得到高于必要值的 weight。这时,可以减少 Pod 数量来获得所需的负载均衡 weight

流程

设置 A/B 环境:

  1. 创建两个应用程序并使用不同的名称。各自创建一个 DeploymentConfig。应用程序是同一程序的不同版本;一个是当前生产版本,另一个是提议的新版本:

    $ oc new-app openshift/deployment-example --name=ab-example-a
    $ oc new-app openshift/deployment-example --name=ab-example-b

    两个应用程序都已部署,也创建了服务。

  2. 通过路由对外提供应用程序。此时您可以公开其中任一个。先公开当前生产版本,稍后修改路由来添加新版本,这可能比较方便。

    $ oc expose svc/ab-example-a

    通过 ab-example-<project>.<router_domain> 访问应用程序,以验证您能否看到所需的版本。

  3. 当您部署路由时,路由器会根据为服务指定的 weight 来均衡流量。此时,存在具有默认 weight=1 的单一服务,因此所有请求都会进入该服务。添加其他服务作为 alternateBackend 并调整 weight,即可激活 A/B 设置。这可通过 oc set route-backends 命令或编辑路由来完成。

    如果将 oc set route-backend 设为 0,则服务不参与负载均衡,但继续为现有的持久连接服务。

    注意

    对路由的更改只会改变流量进入各个服务的比例。您可能需要扩展 DeploymentConfig 来调整 Pod 数量,以处理预期的负载。

    若要编辑路由,请运行:

    $ oc edit route <route_name>
    ...
    metadata:
      name: route-alternate-service
      annotations:
        haproxy.router.openshift.io/balance: roundrobin
    spec:
      host: ab-example.my-project.my-domain
      to:
        kind: Service
        name: ab-example-a
        weight: 10
      alternateBackends:
      - kind: Service
        name: ab-example-b
        weight: 15
    ...
4.4.5.1.1. 使用 Web 控制台管理权重

流程

  1. 导航到 Route 详情页面 (Applications/Routes)。
  2. 从 Actions 菜单中选择 Edit
  3. 选中 Split traffic across multiple services
  4. Service Weights 滑块设置发送到各个服务的流量的百分比。

    如果在超过两个服务之间进行流量分割,各个服务的相对权重通过 0 到 256 范围内的整数来指定。

    在分割流量的应用程序的展开行中 Overview 上会显示流量加权情况。

4.4.5.1.2. 使用 CLI 管理权重

流程

  1. 要管理由路由均衡负载的服务以及对应的权重,请使用 oc set route-backends 命令:

    $ oc set route-backends ROUTENAME \
        [--zero|--equal] [--adjust] SERVICE=WEIGHT[%] [...] [options]

    例如,以下命令将 ab-example-a 设为主服务 ( weight=198) 并将 ab-example-b 设为第一替代服务 (weight=2):

    $ oc set route-backends ab-example ab-example-a=198 ab-example-b=2

    这意味着 99% 的流量发送到服务 ab-example-a,1% 发送到 ab-example-b

    此命令不扩展 DeploymentConfig。您可能需要进行此操作,才能有足够的 Pod 来处理请求负载。

  2. 不带标志运行命令来验证当前配置:

    $ oc set route-backends ab-example
    NAME                    KIND     TO           WEIGHT
    routes/ab-example       Service  ab-example-a 198 (99%)
    routes/ab-example       Service  ab-example-b 2   (1%)
  3. 要改变个别服务相对于自身或主服务的权重,请使用 --adjust 标志。指定百分比来调整服务相对于主服务或第一替代服务(如果指定了主服务)的权重。如果还有其他后端,它们的权重会与更改后的值保持比例。

    例如:

    $ oc set route-backends ab-example --adjust ab-example-a=200 ab-example-b=10
    $ oc set route-backends ab-example --adjust ab-example-b=5%
    $ oc set route-backends ab-example --adjust ab-example-b=+15%

    --equal 标志将所有服务的 weight 设为 100

    $ oc set route-backends ab-example --equal

    --zero 标志将所有服务的 weight 设为 0。之后,所有请求都会返回 503 错误。

    注意

    并非所有路由器都支持多个后端或加权后端。

4.4.5.1.3. 一个服务,多个 DeploymentConfig

流程

  1. 创建一个新应用程序,添加对所有分片都通用的 ab-example=true 标签:

    $ oc new-app openshift/deployment-example --name=ab-example-a

    应用程序完成部署,并创建了服务。这是第一个分片。

  2. 通过路由(或直接使用服务 IP)提供应用程序:

    $ oc expose svc/ab-example-a --name=ab-example
  3. 通过 ab-example-<project>.<router_domain> 访问应用程序,验证您能否看到 v1 镜像。
  4. 创建第二个分片,它基于与第一分片相同的源镜像和标签,但使用不同的标记版本和独特的环境变量:

    $ oc new-app openshift/deployment-example:v2 \
        --name=ab-example-b --labels=ab-example=true \
        SUBTITLE="shard B" COLOR="red"
  5. 在这一刻,路由下同时提供了两组 Pod。但是,由于两个浏览器(通过使连接保持打开)和路由器(默认借助 Cookie)都试图保留后端服务器的连接,您可能不会看到两个分片都返回给您。

    使浏览器强制到其中一个分片:

    1. 使用 oc scale 命令将 ab-example-a 的副本数减少到 0

      $ oc scale dc/ab-example-a --replicas=0

      刷新浏览器以显示 v2shard B(红色)。

    2. ab-example-a 扩展为 1 个副本,ab-example-b 调到 0

      $ oc scale dc/ab-example-a --replicas=1; oc scale dc/ab-example-b --replicas=0

      刷新浏览器以显示 v1shard A(蓝色)。

  6. 如果您对其中任一分片触发部署,那么只有该分片中的 Pod 会受到影响。您可以通过在任一 DeploymentConfig 中更改 SUBTITLE 环境变量来触发部署:

    $ oc edit dc/ab-example-a

    $ oc edit dc/ab-example-b

为了尽快向用户提供最新的信息,本文档可能会包括由机器自动从英文原文翻译的内容。如需更多信息,请参阅此说明。