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