阅读 671

Istio技术与实践05:如何用istio实现流量管理

Istio是什么?

Istio 1.0版本于8月1号凌晨准点发布,核心特性已支持上生产环境,各大微信公众号、博客纷纷发文转载。那么 Istio 到底是什么?能解决问题什么?

  • Istio 是 Google 继 Kubernetes 之后的又一开源力作,主要参与的公司包括 Google,IBM,Lyft 等,它提供了完整的非侵入式的微服务治理解决方案,解决微服务的管理、网络连接以及安全管理等应用网络治理问题
  • 它无需修改任何代码就能够实现微服务的负载均衡,服务与服务之间的认证授权以及流量监控和治理。从整个基础设施角度上看,可以将它理解为 PaaS 平台上的一个面向微服务管理平台的补充。

Istio与Kubernetes

Kubernetes 提供了部署、升级和有限的运行流量管理能力,利用 service 的机制来做服务注册和发现,转发,通过 kubeproxy 有一定的转发和负载均衡能力。但并不具备上层如熔断、限流降级、调用链治理等能力。 Istio 则很好的补齐了 k8s 在微服务治理上的这部分能力,同时是基于 k8s 构建的,但不是像 SpringCloud Netflix 等完全重新做一套。Istio 是谷歌微服务治理上的非常关键的一环。

Istio流量管理能力介绍

Istio,用于连接、保护、控制和观测服务。今天,我们就来谈谈 Istio 第一主打功能——连接服务。那么,便引出3个问题:

  • Istio 如何实现服务之间的连接?
  • 连接后具备哪些流量管理能力?
  • 如何告诉 Istio 发挥这些能力?

1、 Istio 如何实现服务的连接?

如上图所示的 Istio 架构图,让我们关注控制面的 Pilot,它是 Istio 实现流量管理的核心组件。 而在数据面,每个 Service,都会被注入1个 Proxy。Istio 通过 Pilot 下发配置信息给数据面每1个 Service 的 Proxy,从而通过这些 Proxy,间接地控制每1个Service之间以及和外部的连接。Proxy 通常采用另一个知名的开源项目 Envoy 来实现。 1个 Pilot 和(N+N)个( Service + Proxy )组合,便形成了 Service Mesh,即服务网格。有了这一套服务网格系统,对服务之间的流量进行管理,便不在话下。

2、连接后具备哪些流量管理能力?

从服务间的流量管理角度而言,Istio可以实现这4项功能:请求路由、服务发现和负载均衡、故障处理和故障注入。

A.请求路由

如上图所示,Istio 引入了服务版本的概念,可以通过(Current Version,Canary Version )2个版本对服务进行进一步的细分。基于这种划分,通过 Pilot,可以下发配置到 Service A 的 Proxy,使得其95%的流量路由至 Service B的 Current 版本,5%的流量路由至 Service B 的 Canary 版本。当然也可以选择雨露均沾,各分50%流量,或者霸道总裁,让 Canary 版本占有100%的流量。

如上图所示,除了按照百分比在不同版本之间分发流量,你还可以按照请求内容,将请求路由至不同的版本。例如,你可以发布一个 Canary 版本,只让用着 Macbook 笔记本,且安装了 windows 操作系统,还使用着360浏览器的用户能够访问到。 这一切改变,都只需要你改动一个叫 VirtualService 的配置文件(详见下章),眨个眼的功夫,Istio 就已经通过 Pilot 帮你把新的配置下发下去了。

B.服务发现和负载均衡

如上图所示,服务网格存在3个生命周期的动态循环:服务注册、服务发现、负载均衡。

通常 kubernetes,mesos 等容器管理平台已经提供了服务注册表,以跟踪服务的负载实例,所以 Pilot 能轻而易举地获知服务网格内的所有服务注册信息,并将这些信息告知所有服务里的 Proxy,Proxy 根据这些信息执行服务发现,并相应地动态更新其负载均衡池。一个服务通常有多个负载实例,Service A 请求 ServiceB 时,可以配置不同的负载均衡模式:轮询、随机和带权重的最少请求。假设此时Service B的某个负载实例出现故障,因为 Service A 中的 Proxy 会定期地执行服务发现,从而能及时将故障实例从其负载均衡池里排出。

C.故障处理

Envoy 提供了一套开箱即用,可选的故障处理功能,对应用中的服务大有裨益。这些功能包括:

  • 超时
  • 具备超时预算,并进行有限重试,重试之间的时长可抖动
  • 并发连接数和上游服务请求数限制
  • 对负载均衡池中的每个成员进行主动(定期)运行健康检查
  • 细粒度熔断器(被动健康检查)- 适用于负载均衡池中的每个实例

以 Service A 请求调用 Service B 为例。

对于功能1。若 Service B 明确地知道10s以后的超时,必定会带来失败,那将超时时长缩短,使得 Service A 可以更快得知结果并作出应对,不失为一个明智之举。

对于功能2。对超载的 Service B 来说,重试之间的抖动极大的降低了重试造成的影响,而超时预算确保 Service A在可预测的时间范围内获得响应(成功/失败)。

对于功能3。限制 Service A 或其他服务对 Service B的连接数和请求数,可以使得 Service B免于遭遇 DDOS 攻击,或承受过重的流量负担而崩溃。

对于功能4和5。主动和被动健康检查的组合最大限度地减少了在负载平衡池中访问不健康实例的机会。当与平台级健康检查(例如由 Kubernetes 或 Mesos 支持的检查)相结合时,应用程序可以确保将不健康的负载实例快速地从服务网格中去除,从而最小化请求失败和延迟产生影响。

总之,这些功能使得服务网格能够耐受故障节点,并防止本地故障导致的其他节点的稳定性下降。

D.故障注入

虽然 Proxy 为在 Istio 上运行的服务提供了上节所言的大量故障处理机制,但测试整个服务网格所组成应用的端到端的故障恢复能力依然是必须的。错误配置的故障恢复策略(例如,跨服务调用的不兼容/限制性超时)可能导致应用程序中的关键服务持续不可用,从而破坏用户体验。

Istio 能在不杀死负载实例的情况下,将协议特定的故障注入到网络中,在 TCP 层制造数据包的延迟或损坏。我们的理由是,无论网络级别的故障如何,应用层观察到的故障都是一样的,并且可以在应用层注入更有意义的故障(例如,HTTP 经典的4xx和5xx错误代码),以检验和改善应用的韧性。

运维人员可以为符合特定条件的请求配置故障,还可以进一步限制遭受故障的请求的百分比。可以注入两种类型的故障:延迟和中断。延迟是计时故障,模拟网络延迟上升或上游服务超载的情况。中断是模拟上游服务的崩溃故障。中断通常以 HTTP 错误代码或 TCP 连接失败的形式表现。

依旧以 Service A 请求调用 Service B 为例。

若给 Service B设定了10s的延时或503中断,则 Service A将至少10s后才能得到请求的响应或请求的响应为503错误,通过多种场景覆盖测试,可以得到 Service A 面对这些场景时的综合表现情况,从而做出针对性的改良,增加其韧性。

3、如何告诉Istio发挥这些能力?

Istio有4个配置文件,帮我们全方位地定制以上所有流量管理需求: VirtualService, DestinationRule, ServiceEntry和 Gateway:

  • 通过配置 VirtualService,可以实现请求路由的功能;
  • 通过配置 DestinationRule,可以实现服务发现和负载均衡、故障处理和故障注入的功能;
  • 通过配置 ServiceEntry,让服务网格内的服务,可以看到外面的世界;
  • 通过配置 Gateway,让服务网格的服务,可以被全世界看到;

有了以上4大法宝,我们对服务网格进行流量管理的所有需求,都可以被满足了。

限于篇幅,让我们举3个简单的栗子:

假设我们的服务网格存在1个服务 explorer,只有1个v1版本;存在另1个服务 helloworld,有v1,v2两个版本。

①若要使得 explorer 发起的所有请求,以75%的概率走向 helloworld 的v1版本,以25%走向v2版本,只要配置如下两个文件 VirtualService 和 DestinationRule,便可实现:

apiVersion:networking.Istio.io/v1alpha3
kind:VirtualService
metadata:
  name:helloworld
spec:
  hosts:
    - helloworld
  http:
  - route:
    - destination:
        host:helloworld
        subset:v1
      weight:75
    - destination:
        host: helloworld
        subset: v2
     weight: 25

apiVersion:networking.Istio.io/v1alpha3
kind:DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld
  subsets:
  - name:v1
    labels:
      version: v1
  - name: v2
   labels:
      version: v2
复制代码

②如果 helloworld 内部需要通过访问www.google.com 来获取一些信息,才能告诉 explorer 这个世界是怎么样的,需要配置如下2个文件 ServiceEntry 和 DestinationRule:

apiVersion:networking.Istio.io/v1alpha3
kind:ServiceEntry
metadata:
  name: googleapis
spec:
  hosts:
  - "*.google.com"
  ports:
  - number:443
    name:https
    protocol:http
 
apiVersion:networking.Istio.io/v1alpha3
kind:DestinationRule
metadata:
 name: googleapis
spec:
  host: "*.google.com"
复制代码

③如果 helloworld 需要被服务网格外,而不仅仅是 explorer 服务访问到,则需要配置如下2个文件 Gateway 和 VirtualService:

apiVersion:networking.Istio.io/v1alpha3
kind:Gateway
metadata:
 name: helloworld-gateway
spec:
   selector:
     Istio:ingressgateway
 servers:
 - port:
     number: 80
     name: http
     protocol: HTTP
   hosts:
   - 'helloworld.com'
  
apiVersion:networking.Istio.io/v1alpha3
kind:VirtualService
metadata:
name: bookinfo
spec:
hosts:
   - 'helloworld.com'
 gateways:
 - helloworld-gateway
 http:
 - route:
  - destination:
       host: helloworld
       port:
         number: 9080
复制代码

至此,我们做一个简单的总结:Istio 提供的 Pilot 和 Proxy,将成百上千个服务组成了一个服务网格。基于此,我们可以实现请求路由、服务发现和负载均衡、故障处理以及故障注入等流量管理能力,这一切,我们只需要通过对 VirtualService, DestinationRule, ServiceEntry 和 Gateway 这4个资源做简单的配置,即可实现。

关注下面的标签,发现更多相似文章
评论