$ oc new-app openshift/deployment-example:v1 --name=example-blue
部署策略为应用程序的演进提供了一种方式。某些策略使用Deployment
对象来进行更改,这些更改对解析到应用程序的所有路由的用户可见。其他高级策略(例如本节中描述的策略)将路由功能与Deployment
对象结合使用以影响特定路由。
最常见的基于路由的策略是使用蓝绿部署。新版本(绿色版本)启动进行测试和评估,而用户仍然使用稳定版本(蓝色版本)。准备就绪后,用户将切换到绿色版本。如果出现问题,您可以切换回蓝色版本。
或者,您可以使用A/B 版本策略,其中两个版本同时处于活动状态。使用此策略,一些用户可以使用版本 A,而其他用户可以使用版本 B。您可以使用此策略来试验用户界面更改或其他功能,以获取用户反馈。您也可以在生产环境中使用它来验证正确的操作,在生产环境中,问题会影响数量有限的用户。
金丝雀部署会测试新版本,但是当检测到问题时,它会快速回滚到以前的版本。这可以使用上述两种策略中的任何一种来完成。
基于路由的部署策略不会扩展服务中 Pod 的数量。为了保持所需的性能特性,可能需要扩展部署配置。
在生产环境中,您可以精确控制到达特定分片的流量分配。当处理大量实例时,您可以使用各个分片的相对规模来实现基于百分比的流量。这与代理分片很好地结合在一起,代理分片将其接收到的流量转发或拆分到其他地方运行的单独服务或应用程序。
在最简单的配置中,代理会原样转发请求。在更复杂的设置中,您可以复制传入的请求并将其发送到单独的集群以及应用程序的本地实例,然后比较结果。其他模式包括保持 DR 安装的缓存处于活动状态,或对传入流量进行采样以进行分析。
任何 TCP(或 UDP)代理都可以运行在所需的分片下。使用oc scale
命令来更改在代理分片下提供请求的实例的相对数量。对于更复杂的流量管理,请考虑使用具有比例平衡功能的 AWS 上的 Red Hat OpenShift 服务路由器进行自定义。
同时运行新代码和旧代码的应用程序必须小心确保新代码编写的可以被旧版代码读取和处理(或优雅地忽略)。这有时称为模式演变,这是一个复杂的问题。
这可以采取多种形式:存储在磁盘上、数据库中、临时缓存中或作为用户浏览器会话一部分的数据。虽然大多数 Web 应用程序都支持滚动部署,但重要的是要测试和设计您的应用程序以处理它。
对于某些应用程序,旧代码和新代码并行运行的时间段很短,因此错误或某些失败的用户事务是可以接受的。对于其他应用程序,故障模式可能导致整个应用程序无法正常运行。
验证 N-1 兼容性的一种方法是使用 A/B 部署:在受控的环境中同时运行旧代码和新代码,并验证流向新部署的流量不会导致旧部署出现故障。
AWS 上的 Red Hat OpenShift 服务和 Kubernetes 会在将应用程序实例从负载均衡轮换中移除之前,给予它们一些关闭时间。但是,应用程序还必须确保在退出之前干净地终止用户连接。
关闭时,AWS 上的 Red Hat OpenShift 服务会向容器中的进程发送TERM
信号。应用程序代码在接收到SIGTERM
后,停止接受新连接。这确保负载均衡器将流量路由到其他活动实例。然后,应用程序代码等待所有打开的连接关闭,或在下次机会优雅地终止单个连接,然后再退出。
优雅终止期限过期后,未退出的进程将收到KILL
信号,该信号会立即结束进程。Pod 或 Pod 模板的terminationGracePeriodSeconds
属性控制优雅终止期限(默认值为 30 秒),并且可以根据需要为每个应用程序进行自定义。
蓝绿部署涉及同时运行应用程序的两个版本,并将流量从生产版本(蓝色版本)移动到较新版本(绿色版本)。您可以使用滚动策略或切换路由中的服务。
因为许多应用程序依赖于持久性数据,所以您必须拥有支持N-1 兼容性的应用程序,这意味着它共享数据并通过创建数据层的两个副本在数据库、存储或磁盘之间实现实时迁移。
考虑用于测试新版本的数据。如果它是生产数据,则新版本中的错误可能会破坏生产版本。
蓝绿部署使用两个Deployment
对象。两者都在运行,生产中的一个依赖于路由指定的 service,每个Deployment
对象都暴露给不同的 service。
路由适用于 Web(HTTP 和 HTTPS)流量,因此此技术最适合 Web 应用程序。 |
您可以创建一个指向新版本的新路由并进行测试。准备就绪后,更改生产路由中的服务以指向新服务,新(绿色)版本即上线。
如有必要,您可以通过将服务切换回以前的版本来回滚到较旧的(蓝色)版本。
创建两个独立的应用程序组件。
创建示例应用程序的副本,该副本在example-blue
服务下运行v1
镜像。
$ oc new-app openshift/deployment-example:v1 --name=example-blue
创建第二个副本,该副本在example-green
服务下使用v2
镜像。
$ oc new-app openshift/deployment-example:v2 --name=example-green
创建一个指向旧服务的路由。
$ oc expose svc/example-blue --name=bluegreen-example
浏览到bluegreen-example-
处的应用程序,以验证您是否看到了v1
镜像。
编辑路由并将服务名称更改为example-green
$ oc patch route/bluegreen-example -p '{"spec":{"to":{"name":"example-green"}}}'
要验证路由是否已更改,请刷新浏览器,直到看到v2
镜像。
A/B 部署策略允许您以有限的方式在生产环境中试用新版本的应用程序。您可以指定生产版本获取大部分用户请求,而一小部分请求转到新版本。
由于您可以控制每个版本的请求比例,因此随着测试的进行,您可以增加对新版本的请求比例,并最终停止使用旧版本。调整每个版本的请求负载时,可能也需要调整每个服务中的 Pod 数量以提供预期的性能。
除了升级软件外,您还可以使用此功能来试验用户界面的不同版本。由于一些用户获得旧版本,而另一些用户获得新版本,因此您可以评估用户对不同版本的反应,从而为设计决策提供信息。
为了使此方法有效,旧版本和新版本必须足够相似,以便两者可以同时运行。这在错误修复版本以及新功能不会干扰旧功能的情况下很常见。版本需要 N-1 兼容性才能正常协同工作。
AWS 上的 Red Hat OpenShift 服务通过 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
来调整路由上的批注。对于 AWS 上的 Red Hat OpenShift 服务上的路由,默认负载均衡算法设置为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-
处的应用程序,以验证您是否看到了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