如何处理服务网格中的破坏性变更

4
我正在使用 Kubernetes 构建一个微服务应用的示例,以便了解最佳实践和一些模式,为未来的项目做参考。我正在使用 Istio 作为 Service Mesh 处理东西向流量,并对概念(VirtualServices、DestinationRules 等)有基本的理解。服务网格允许我轻松推出新版本的微服务并将流量重定向到新实例(例如使用加权分布)。在考虑语义化版本控制时,这对于补丁(Patch)和小更新(Minor)非常有效,因为它们在理论上没有改变现有合同,因此可以与现有服务进行无缝替换。现在,我想知道如何正确处理服务的破坏性更改,即主要(Major)版本更新。
很难找到关于此的信息,但是在我获得的有限信息中,我现在考虑两种方法:
1. 每个服务的主要版本(例如 `user-service`)都有自己的 `VirtualService`,以便客户端可以正确地寻址它(通过不同的服务名称,例如 `user-service-v1`)。然后使用 Istio 正确路由主要版本(例如 `1.*`)的流量到不同可用的服务(例如 `user-service v1.3.1` 和 `user-service v1.4.0`)。 2. 对于特定微服务(例如 `user-service`),我使用一个总的 `VirtualService`。此 `VirtualService` 包含许多路由定义,以使用客户端发送的标头(例如 `x-major-version=1`)匹配请求到目标。
总体上,这两种方法之间没有太大区别。显然,客户端需要指定要与哪个主要版本进行通信,可以通过设置标头或解析不同的服务名称来实现。这些描述的方法是否存在任何限制使得其中一种优于另一种?或者我完全漏掉了其他选项?非常感谢任何帮助和指针!

嗨@Simon,如果我们谈论这两个要点,我会建议你选择方法1,并使用目标规则与子集来正确分发流量。1.您所说的主版本更新是指旧应用程序仍在运行,而您正在创建具有新图像和新服务的新应用程序,并且您想检查它是否可以正确地使用您的istio配置?2.您看过金丝雀部署流量镜像吗? - Jakub
1个回答

2
TLDR
除了我在评论中提到的内容之外,在更详细地检查了这个主题后,我会选择“方法2”,使用一个总体的特定微服务的“虚拟服务”,进行“金丝雀部署”和“镜像”。
方法1
documentation中所述:
“在某些情况下,为特定主机定义完整的路由规则或策略不方便,可能更倾向于逐步在多个资源中指定主机的配置。如果它们绑定到网关,Pilot将合并这样的目标规则并合并这样的虚拟服务。”
因此,从理论上讲,您可以选择方法1,但是我认为那里有太多的配置,有更好的想法来做到这一点。
假设您有一个名为“v1.3.1”的旧应用程序和一个名为“v1.4.0”的新应用程序,则适当的虚拟服务如下所示。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-vervice1
spec:
  hosts:
  - '*'
  http:
  - name: "v1.3.1"
    route:
    - destination:
        host: service1.namespace.svc.cluster.local

---

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-service2
spec:
  hosts:
  - '*'
  http:
  - name: "v1.4.0"
    route:
    - destination:
        host: service2.namespace.svc.cluster.local

方法二

实际上,我会选择第二种方法。例如,你可以创建你的应用程序的两个版本,在下面的例子中是oldnew,然后为其配置虚拟服务和目标规则。

这里的问题是什么?因为至少对于我来说,它更容易管理,而且很容易在这里使用金丝雀部署和镜像,关于这个更多的内容在下面。

假设你已经部署了新应用程序,你想将1%的流量发送到这里,此外,你可以使用镜像,所以每个发送到旧服务的请求都会被镜像到新的服务进行测试。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-vervice
spec:
  hosts:
  - '*'
  http:
  - name: "old"
    route:
    - destination:
        host: service.namespace.svc.cluster.local
        subset: v1
      weight: 99
    mirror:
      host: service.namespace.svc.cluster.local
      subset: v2
    mirror_percent: 100
  - name: "new"
    route:
    - destination:
        host: service.namespace.svc.cluster.local
        subset: v2
      weight: 1

---


apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews-destination
spec:
  host: service.namespace.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1  <--- label on old pod
  - name: v2
    labels:
      version: v2  <--- label on new pod

测试新应用

客户显然需要指定要与哪个主要版本进行通信,可以通过设置标头或解析不同的服务名称来实现。

实际上这取决于配置,如果您使用 newold 版本的上述选项,则可以使用金丝雀部署,例如加权分配。您可以指定应发送到应用程序的新版本的流量百分比。当然,您可以在虚拟服务中指定标头或前缀,以便用户可以使用旧版或新版的应用。

金丝雀部署

此处所述。

Istio项目的一个好处是它提供了部署金丝雀服务所需的控制。金丝雀部署(或发布)的想法是通过先使用小部分用户流量测试新版本的服务,然后如果一切顺利,逐步增加百分比,同时逐步淘汰旧版本来引入服务的新版本。如果在此过程中出现问题,我们会中止并回滚到先前的版本。在最简单的形式中,发送到金丝雀版本的流量是随机选取的请求百分比,但在更复杂的方案中,它可以基于请求的区域、用户或其它属性。
根据您在这个领域的专业水平,您可能会想知道为什么需要Istio支持金丝雀部署,因为像Kubernetes这样的平台已经提供了一种进行版本发布和金丝雀部署的方式。问题解决了,对吧?嗯,并不完全是这样。虽然以这种方式进行发布在简单情况下是有效的,但在大规模云环境中接收大量(尤其是数量不同的)流量时非常受限,需要自动缩放。
与Kubernetes相比,Istio的流量路由和副本部署是两个完全独立的功能。实现服务的pod数目可以根据交通负载自由扩展和缩小,完全与版本流量路由控制无关。这使得在自动缩放存在的情况下管理金丝雀版本成为一个更简单的问题。实际上,自动缩放器可能会对交通路由变化导致的负载变化做出响应,但它们仍然是独立运行的,并且在负载因其他原因而改变时也不会有任何不同。
Istio的路由规则还提供了其他重要优点;您可以轻松地控制细粒度的流量百分比(例如,将1%的流量路由到不需要100个pod)并且可以使用其他标准来控制流量(例如,将特定用户的流量路由到金丝雀版本)。为了说明问题,让我们来看看部署helloworld服务并了解问题变得多么简单。

有一个示例

镜像

第二个经常用于测试应用程序新版本的东西是流量镜像。

此处所述:

使用 Istio,您可以使用流量镜像将流量复制到另一个服务。您可以将流量镜像规则作为金丝雀部署管道的一部分,允许您在向其发送实时流量之前分析服务的行为。

如果您正在寻找最佳实践,我建议从这个中等教程开始,因为这里解释得非常好。

流量镜像的工作原理

流量镜像是通过以下步骤进行的:
1. 部署应用程序的新版本并打开流量镜像。 2. 旧版本像以前一样响应请求,但也会异步地将副本发送到新版本。 3. 新版本处理流量,但不会向用户响应。 4. 运营团队监视新版本并向开发团队报告任何问题。

enter image description here

由于该应用程序处理实时流量,因此它有助于团队发现通常在预生产环境中无法发现的问题。您可以使用监控工具(例如Prometheus和Grafana)记录和监控测试结果。
此外,还有一个nginx示例,完美地展示了它应该如何工作。
值得一提的是,如果您使用写API(如订单或付款),那么镜像流量将意味着多次写入API(如订单)。这个主题由Christian Posta在这里中详细描述。
请告诉我,如果您还有其他想要讨论的事情。

1
非常感谢您的出色回答!如果我有更多需要讨论的架构问题,我会联系您的 ;) - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接