当我们尝试在 Kubernetes 中使用 NodePort 或 LoadBalancer 类型的服务设施配置进行通信时,Istio 或许是一个非常流行、新兴的开源服务网格产品,其能够用于通信管理、可观察性、错误处理及安全性等。作为微服务架构体系的一部分,为了无需过多地使用重复的逻辑填充每个微服务代码,我们可以利用 Istio 服务网格在一个地方完成所有这些事情。
随着时间的推移,Istio 的各种其他功能以及它在基于微服务的应用程序开发中更具有广泛用途。由于大多数应用程序开发都采用基于微服务的架构,当两个服务之间的网络发生延迟时,将会抛出各种异常,因此,在实际的业务场景中,我们会要求每个微服务能够通过进行故障注入测试来关注其容错性,采用断路器模式或通过对应用程序进行金丝雀部署来安全部署服务,以观察应用程序的响应时间,并在底层微服务中定期更新。
在本文中,让我们聚焦基于 Istio 进行流量管理,通过部署一个 Sidecar 来为应用程序开发人员解决所有这些问题,该 Sidecar 负责为任何微服务应用程序执行所有横切功能。
在下面的内容中,我将讨论使用 Istio VirtualService 资源实现的应用服务流量路由的三种基本场景。在进入本文正题之前,我们先来了解一下 VirtualService 相关概念。
在 Istio 体系中,VirtualService 指示 Ingress Gateway 如何将允许的请求路由至所建设的容器集群中。
基于 VirtualServices 配置的路由,其简要拓扑如下所示:
基于上述拓扑展示,对于我们的应用程序请求,其主要通过 Http-Gateway 必须路由至如下下游 SA-Frontend、SA-Web-App 和 SA-Feedback 微服务。
我们来简单分解下路由至 SA-Frontend 的相关请求,具体如下所示:
1、Exact path(根路径)/ 应路由至 SA-Frontend 以获取 Index.html 等文件信息。
2、Prefix path(前缀路径)/static/* 应路由至 SA-Frontend 以获取前端所需的任何静态文件,例如,级联样式表和 JavaScript 等文件信息。
3、Paths matching the regex(匹配正则表达式) ^.*\.(ico|png|jpg)$ 的路径应路由到 SA-Frontend,因为它是页面需要显示的图像。
相关参考配置文件清单,如下所示:
kind: VirtualService metadata: name: external-services spec: hosts: - "*" gateways: - http-gateway # 1 http: - match: - uri: exact: / - uri: exact: /callback - uri: prefix: /static - uri: regex: '^.*\.(ico|png|jpg)$' route: - destination: host: sa-frontend # 2 port: number: 8080
基于特定的应用版本
每当我们想将任何微服务中的所有应用程序流量仅路由到一个特定版本时,可以通过向子集中的版本号添加路由来实现,如下所示,其中 HTTP 请求标头中的值路由所有传入的流量至指定版本的服务。Envoy 则会按照下面 VirtualService 资源中提到的路由规则来进行流量路由。
- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: dservice namespace: dev spec: hosts: - dservice http: - route: - destination: host: dservice subset: v1
基于加权路由
在某些场景下,基于业务独特性,我们需要将部分应用程序流量路由至 v1 版本服务,而将其余部分则路由至 v2 版本服务,例如,A/B 测试或金丝雀部署等。那么,此时,可以通过为不同版本的服务分配权重来实现,如下图所示,其中 60% 的流量将转发至 v1 版本服务,其余 40% 则将路由至 v2 版本服务。这样,所流经的请求能够按照特定的百分比路由至指定的服务实例。
当应用程序团队希望通过发布各种版本的 Web 服务并观察应用程序的 RED 指标来查看性能指标时,RED 方法的一个优点便是可以帮助我们考虑如何构建仪表板,将这三个指标放在每个服务的中心位置,并且错误率表示为请求率的比例。
此方案有助于进行 A/B 测试。
“ RED 方法定义了您应该为架构中的每个微服务测量的三个关键指标:
1、(Request)Rate - 服务每秒请求数。
2、(Request)Errors - 每秒失败的请求数。
3、(Request)Duration - 每个请求所用时间分布。
衡量这些指标非常简单,尤其是在使用 Prometheus(或其他云平台所托管的 Prometheus 服务)之类的工具时。 ”
- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: dservice namespace: dev spec: hosts: - dservice http: - route: - destination: host: dservice subset: v1 weight: 60 - destination: host: dservice subset: v2 weight: 40
基于用户路由
然而,除了上述场景外,还有一种场景便是应用程序服务需要先向特定的一组用户公开,然后再面向更大的用户群组发布生产最新版本。此种解决方案可以通过添加自定义 Header “最终用户”并将其映射到用户列表来实现,在下面的配置中,流量将先被路由至 v2 版本服务,而对于剩下的其他用户,流量则将被路由至 v1 版本服务。
此方案有助于对应用程序进行 Beta 测试。
- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: dservice namespace: dev spec: hosts: - dservice http: - match: - headers: end-user: exact: ram route: - destination: host: dservice subset: v2 - route: - destination: host: dservice subset: v1
综上所述,在实际的项目活动中,Istio 的流量路由功能可帮助开发人员根据特定用户集的需求来自定义配置其微服务迭代策略,并能够允许在生产上线之前在灰度和模拟环境中测试服务的多个版本以降低服务发布风险。当然,除了流量路由之外,Istio 还有其他各种功能,例如,故障注入、断路器、超时和重试等,所有这些功能特性支撑了微服务应用程序的稳定运行,大家若对 Istio 产品感兴趣,可以去官网进行沉浸式体验。