$ oc new-app openshift/deployment-example:v1 --name=example-blue
部署策略为应用程序的演进提供了一种方法。一些策略使用Deployment
对象来进行对所有解析到应用程序的路由的用户可见的更改。其他高级策略,例如本节中描述的策略,将路由器功能与Deployment
对象结合使用以影响特定路由。
最常见的基于路由的策略是使用蓝绿部署。新的版本(绿色版本)被启动进行测试和评估,而用户仍然使用稳定版本(蓝色版本)。准备就绪后,用户将切换到绿色版本。如果出现问题,您可以切换回蓝色版本。
或者,您可以使用A/B 版本策略,其中两个版本同时处于活动状态。使用此策略,一些用户可以使用版本 A,而其他用户可以使用版本 B。您可以使用此策略来试验用户界面更改或其他功能以获取用户反馈。您也可以在生产环境中使用它来验证正常运行,在生产环境中,问题会影响数量有限的用户。
金丝雀部署测试新版本,但是当检测到问题时,它会快速回退到之前的版本。这可以使用上述两种策略来完成。
基于路由的部署策略不会扩展服务中的 Pod 数量。为了保持所需的性能特性,可能必须扩展部署配置。
在生产环境中,您可以精确控制到达特定分片的流量分布。当处理大量实例时,您可以使用各个分片的相对规模来实现基于百分比的流量分配。这与代理分片结合得很好,代理分片将其接收到的流量转发或拆分到其他地方运行的单独服务或应用程序。
在最简单的配置中,代理会将请求原样转发。在更复杂的设置中,您可以复制传入的请求并同时发送到单独的集群以及应用程序的本地实例,然后比较结果。其他模式包括保持 DR 安装的缓存处于预热状态,或对传入流量进行采样以进行分析。
任何 TCP(或 UDP)代理都可以在所需分片下运行。使用oc scale
命令更改在代理分片下提供请求的实例的相对数量。对于更复杂的流量管理,请考虑使用具有比例平衡功能的 OpenShift Container Platform 路由器进行自定义。
同时运行新旧代码的应用程序必须小心确保新代码写入的数据可以被旧版本的代码读取和处理(或优雅地忽略)。这有时被称为模式演变,是一个复杂的问题。
这可能有多种形式:存储在磁盘上、数据库中、临时缓存中或作为用户浏览器会话一部分的数据。虽然大多数 Web 应用程序都支持滚动部署,但务必测试并设计您的应用程序以处理它。
对于某些应用程序,旧代码和新代码并行运行的时间很短,因此错误或某些失败的用户事务是可以接受的。对于其他应用程序,故障模式可能会导致整个应用程序无法运行。
验证 N-1 兼容性的一种方法是使用 A/B 部署:在测试环境中以受控方式同时运行旧代码和新代码,并验证流向新部署的流量不会导致旧部署失败。
OpenShift Container Platform 和 Kubernetes 会给应用程序实例一些时间来关闭,然后再将其从负载均衡轮换中移除。但是,应用程序必须确保在退出之前干净地终止用户连接。
关闭时,OpenShift Container Platform 会向容器中的进程发送TERM
信号。应用程序代码在接收到SIGTERM
后,停止接受新连接。这确保负载均衡器将流量路由到其他活动实例。然后,应用程序代码等待所有打开的连接关闭,或在下一个机会优雅地终止单个连接,然后再退出。
优雅终止期限到期后,尚未退出的进程会收到KILL
信号,该信号会立即结束进程。pod 或 pod 模板的terminationGracePeriodSeconds
属性控制优雅终止期限(默认为 30 秒),可以根据需要为每个应用程序自定义。
蓝绿部署涉及同时运行应用程序的两个版本,并将流量从生产版本(蓝色版本)移动到较新版本(绿色版本)。您可以使用滚动策略或在路由中切换服务。
由于许多应用程序依赖于持久性数据,因此您必须拥有支持N-1 兼容性的应用程序,这意味着它共享数据并在数据库、存储或磁盘之间实现实时迁移,方法是创建数据层的两个副本。
考虑用于测试新版本的数据。如果它是生产数据,则新版本中的错误可能会破坏生产版本。
蓝绿部署使用两个Deployment
对象。两者都在运行,生产中的一个依赖于路由指定的service,每个Deployment
对象都暴露给不同的service。
路由适用于 Web(HTTP 和 HTTPS)流量,因此此技术最适合 Web 应用程序。 |
您可以创建一个指向新版本的新路由并对其进行测试。准备好后,更改生产路由中的服务以指向新服务,新的(绿色)版本就会上线。
如有必要,您可以通过将服务切换回先前版本来回滚到较旧的(蓝色)版本。
创建两个独立的应用程序组件。
创建运行v1
镜像的示例应用程序副本,该副本位于example-blue
服务下
$ oc new-app openshift/deployment-example:v1 --name=example-blue
创建第二个副本,该副本使用v2
镜像,位于example-green
服务下
$ oc new-app openshift/deployment-example:v2 --name=example-green
创建一个指向旧服务的路由
$ oc expose svc/example-blue --name=bluegreen-example
浏览到bluegreen-example-<project>.<router_domain>
处的应用程序,以验证您是否看到v1
镜像。
编辑路由并将服务名称更改为example-green
$ oc patch route/bluegreen-example -p '{"spec":{"to":{"name":"example-green"}}}'
要验证路由是否已更改,请刷新浏览器,直到您看到v2
镜像。
A/B 部署策略允许您在生产环境中以有限的方式尝试应用程序的新版本。您可以指定生产版本获得大部分用户请求,而一小部分请求转到新版本。
由于您可以控制每个版本的请求部分,因此随着测试的进行,您可以增加对新版本的请求比例,并最终停止使用旧版本。调整每个版本的请求负载时,可能还需要调整每个服务中的 pod 数量以提供预期的性能。
除了升级软件外,您还可以使用此功能来试验用户界面的不同版本。由于有些用户获得旧版本,有些用户获得新版本,因此您可以评估用户对不同版本的反应,为设计决策提供信息。
为了使这有效,旧版本和新版本必须足够相似,以便两者可以同时运行。这在错误修复版本以及新功能不会干扰旧功能时很常见。版本需要 N-1 兼容性才能正常协同工作。
OpenShift Container Platform 通过 Web 控制台和 CLI 支持 N-1 兼容性。
用户设置具有多个服务的路由。每个服务都处理应用程序的一个版本。
每个服务都会分配一个weight
(权重),每个服务的请求比例由service_weight
(服务权重)除以sum_of_weights
(总权重)计算得出。每个服务的weight
(权重)会分配到该服务的端点,使得端点weights
(权重)之和等于服务的weight
(权重)。
路由最多可以包含四个服务。服务的weight
(权重)可以在0
到256
之间。当weight
(权重)为0
时,该服务不参与负载均衡,但会继续为现有的持久连接提供服务。当服务weight
(权重)不为0
时,每个端点的最小weight
(权重)为1
。因此,具有大量端点的服务最终可能具有比预期更高的weight
(权重)。在这种情况下,请减少 Pod 数量以获得预期的负载均衡weight
(权重)。
设置 A/B 环境
创建两个应用程序并为它们命名。每个应用程序都创建一个Deployment
对象。这些应用程序是同一程序的不同版本;通常一个版本是当前的生产版本,另一个版本是建议的新版本。
创建第一个应用程序。以下示例创建一个名为ab-example-a
的应用程序。
$ oc new-app openshift/deployment-example --name=ab-example-a
创建第二个应用程序
$ oc new-app openshift/deployment-example:v2 --name=ab-example-b
两个应用程序都已部署,并且已创建服务。
通过路由使应用程序可在外部访问。此时,您可以公开任一应用程序。建议先公开当前的生产版本,然后再修改路由以添加新版本。
$ oc expose svc/ab-example-a
浏览到ab-example-a.<project>.<router_domain>
处的应用程序,以验证是否看到了预期的版本。
部署路由后,路由器将根据为服务指定的weights
(权重)平衡流量。此时,只有一个服务,其默认weight=1
,因此所有请求都将发送到该服务。添加另一个服务作为alternateBackends
并调整weights
(权重)可以启动 A/B 设置。这可以通过oc set route-backends
命令或编辑路由来完成。
使用 |
将oc set route-backend
设置为0
表示该服务不参与负载均衡,但会继续为现有的持久连接提供服务。
路由的更改只会改变发送到各种服务的流量比例。您可能需要扩展部署以调整 Pod 数量,以处理预期的负载。 |
要编辑路由,请运行
$ oc edit route <route_name>
apiVersion: route.openshift.io/v1
kind: Route
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
# ...
导航到**网络** → **路由**页面。
单击要编辑的路由旁边的选项菜单并选择**编辑路由**。
编辑 YAML 文件。将weight
(权重)更新为0
到256
之间的整数,该整数指定目标相对于其他目标引用对象的相对权重。值0
会禁止对此后端的请求。默认值为100
。运行oc explain routes.spec.alternateBackends
以获取有关选项的更多信息。
单击**保存**。
导航到**网络** → **路由**页面。
单击**创建路由**。
输入路由**名称**。
选择**服务**。
单击**添加备用服务**。
输入**权重**和**备用服务权重**的值。输入0
到255
之间的数字,表示与其他目标相比的相对权重。默认值为100
。
选择**目标端口**。
单击**创建**。
要管理路由负载均衡的相应服务和权重,请使用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
。
此命令不会扩展部署。您可能需要这样做才能拥有足够的 Pod 来处理请求负载。
运行不带任何标志的命令以验证当前配置。
$ 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%)
要覆盖负载均衡算法的默认值,请通过将算法设置为roundrobin
来调整路由上的注释。对于 OpenShift Container Platform 上的路由,默认负载均衡算法设置为random
或source
值。
要将算法设置为roundrobin
,请运行以下命令:
$ oc annotate routes/<route-name> haproxy.router.openshift.io/balance=roundrobin
对于传输层安全性 (TLS) 直通路由,默认值为source
。对于所有其他路由,默认值为random
。
要更改单个服务相对于自身或主要服务的权重,请使用--adjust
标志。指定百分比会相对于主要服务或第一个备用服务(如果指定了主要服务)调整服务。如果存在其他后端,则它们的权重将保持与更改成比例。
以下示例更改ab-example-a
和ab-example-b
服务的权重:
$ 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 错误。
并非所有路由器都支持多个或加权后端。 |
Deployment
对象创建一个新的应用程序,添加一个标签ab-example=true
,该标签将对所有分片通用。
$ oc new-app openshift/deployment-example --name=ab-example-a --as-deployment-config=true --labels=ab-example=true --env=SUBTITLE\=shardA
$ oc delete svc/ab-example-a
应用程序已部署,并创建了一个服务。这是第一个分片。
通过路由使应用程序可用,或直接使用服务 IP。
$ oc expose deployment ab-example-a --name=ab-example --selector=ab-example\=true
$ oc expose service ab-example
浏览到ab-example-<project_name>.<router_domain>
处的应用程序,以验证是否看到了v1
镜像。
基于与第一个分片相同的源镜像和标签创建第二个分片,但使用不同的标记版本和唯一的环境变量。
$ oc new-app openshift/deployment-example:v2 \
--name=ab-example-b --labels=ab-example=true \
SUBTITLE="shard B" COLOR="red" --as-deployment-config=true
$ oc delete svc/ab-example-b
此时,两组 Pod 都正在路由下提供服务。但是,由于浏览器(通过保持连接打开)和路由器(默认情况下,通过 Cookie)都尝试将您的连接保留到后端服务器,因此您可能看不到返回给您的两个分片。
要强制浏览器使用其中一个分片:
使用oc scale
命令将ab-example-a
的副本数减少到0
。
$ oc scale dc/ab-example-a --replicas=0
刷新浏览器以显示v2
和分片 B
(红色)。
将ab-example-a
缩放至1
个副本,将ab-example-b
缩放至0
个副本。
$ oc scale dc/ab-example-a --replicas=1; oc scale dc/ab-example-b --replicas=0
刷新浏览器以显示v1
和分片 A
(蓝色)。
如果您触发任一分片的部署,则只有该分片中的 Pod 会受到影响。您可以通过更改任一Deployment
对象中的SUBTITLE
环境变量来触发部署。
$ oc edit dc/ab-example-a
或者
$ oc edit dc/ab-example-b
路由注解.