微服务运维减负:Istio Service Mesh原理+实战

王青 2018-04-25 20:36:24

作者介绍

王青,JFrog中国首席架构师,曾在新浪、爱奇艺、IBM、HPE、VIPKID从事架构研发与咨询,曾在中兴通讯、宜人贷、顺丰、易保科技等大型企业从事DevOps落地。专注于微服务架构、持续集成、持续交付、DevOps、容器化平台建设等等。

 

一、Istio的来源

 

 

随着微服务架构的普及,越来越多的应用已经拆分成了微服务的架构。而微服务架构落地的一个难点,就是如何让服务和服务之间进行稳定的通信。

 

 

部署微服务之后,如何做服务的负载均衡、容错性、服务监控、日志追踪以及熔断等功能都需要考虑周全。

 

 

还好,现在已经有很多开源工具帮你做这样的事情。例如:

 

  • Netflix的Eureka实现服务注册,它的优势在于实现跨数据中心的服务注册;

  • Ribbon – 客户端的负载均衡;

  • Hystrix – 微服务的熔断器;

  • Zipkin – 分布式的追踪组件;

  • Prometheus – 监控组件;

  • Grafana – 数据可视化的工具;

  • ……

 

 

于是,在写完我的微服务之后,我引入了更多的组件,带来了极大的部署复杂度,每个组件都需要高可用、负载均衡、熔断、日志收集等等。

 

为了让业务团队返璞归真,将所有精力集中在业务代码而不是配合微服务组件写大量非功能性需求的代码,Istio应运而生。

 

 

Istio是谷歌、IBM、Lyft等公司贡献的开源Service Mesh组件。它实现的目标就是让业务开发不再关注微服务之间如何调用、管理、监控等非功能性需求,而是让Istio来处理这些问题。Istio和Kubernetes有天然的支持。

 

Istio能轻松解决蓝绿发布和金丝雀发布的问题。

 

金丝雀发布有什么用?它的最大实际意义,是让运维不用在夜里加班上线,而是能够在白天工作时间进行上线。先上线1%的节点,如果失败了,立刻回滚。稍后会详细解释Istio如何支持蓝绿发布、金丝雀发布。

 

 

Istio提供Control Plane,让服务和服务之间能够实现实时请求,并且支持了自定义的路由规则、重试机制、熔断机制、性能监控以及追踪。而之前这些事情都是由程序员处理(Spring Cloud组件)。

 

 

使用Istio之后,再来看我们的微服务组件架构图,你会发现,之前的API网关、服务注册中心、负载均衡、熔断等组件都不需要了,这些都由Istio来处理。

 

没错,Istio就是要来取代部门Spring Cloud的功能。

 

 

所以你的微服务会只剩下服务本身和一个代理(SideCar)。Istio使用Envoy作为代理实现服务的动态发现、负载均衡、熔断等等。Envoy是基于C++开发的4/7层代理。

 

 

在Kubernetes集群里,你可以为每个微服务通过一个Policy文件描述代理服务,Istio Pilot会统一收集所有的代理注册信息,用来进行服务之间的请求调度。Istio的调度机制如下:

 

  • Service Mesh解析所有的请求,并把这些请求发送到本地的代理;

  • 负载均衡会将请求分发到某个代理实例;

  • 代理实例会进行检查,例如ACL、Quota等等;

  • 如果成功,目标服务返回结果给请求调用者。

 

 

所有的服务追踪信息可以统一通过Istio Mixer进行收集,并发送到Prometheus,用Grafana进行数据可视化展示。

 

二、Istio实战

 

 

先实现一个最简单的微服务,上述代码启动了一个最简单的HTTP服务器,注册了"/meet"路径,访问这个服务即开始Sleep 250毫秒。这个服务启动和一个会议服务。

 

 

再实现一个微服务,这个微服务启动HTTP客户端,注册"/work",实现对会议服务的访问。

 

OK,就这样,我们搭建了两个“微小的”微服务。并且,它实现了服务和服务之间的调用。我们将看看使用Istio如何实现服务和服务之间的智能调用。

 

在这里我们为Work服务建立两个版本的Docker镜像,做蓝绿发布。默认情况下,当我们把V1版本的服务和V2版本的服务都运行起来,Kubernetes会将流量均匀的分配到这两个实例。

 

 

 

如上图所示,同一个请求,返回的结果不同,V1版本返回的是4个会议,V2版本返回的是8个会议。

 

假设Work V2版本的服务有问题,我们:

 

  • 如何动态的将流量都切换到Meeting服务的V1版本?

 

 

只要执上面的行istioctl create –f route-to-v1.yaml 文件,即可实现将所有的流量都切换到V1版本。

 

 

如下图所示:

 

 

  • 如何实现自动重试?

 

 

如果服务出现503错误,此时再让服务接受请求,会造成服务的雪崩。这时,你可能的选择是让服务30秒之后再接受请求,而不是在线程数量达到峰值的时候仍然接受请求。

 

  • 如何实现熔断?

 

 

Spring Cloud提供的Hystrix作为熔断的工具,在Istio里,你可以定义你的CircuitBreaker的策略。比如,如果服务出现不能访问的情况,你可以允许服务出现连续5次错误,并且设置最大并发连接数为100,当连接数达到这个数目时,Istio不会将流量导入到这个服务里。

 

  • 如何追踪服务的调用栈?

 

 

使用Zipkin可以将服务的调用栈可视化,可以在这里发现,在服务调用之间有Istio-Mixer进行了服务的Check操作,此操作耗时大概1毫秒,它处理该目标服务是否符合Istio的路由规则,如果通过,则运维目标服务进行请求的处理,并返回给调用方。

 

  • 如何根据客户端的特征进行蓝绿发布?

 

例如,将所有Chrome的客户端请求都分发到V2版本,剩下的请求发送到V1版本?

 

 

你可以在你的Istio路由规则里配置根据User-Agent的关键字,做流量的规划,而不需要修改任何应用的代码。执行“Istio apply -f”之后可以看到以下效果:

 

 

Chrome的用户看到的是V2版本,而非Chrome的用户仍然看到的是老版本,这样就能轻松实现蓝绿发布。而通过配置本次发布的节点数,能够智能地让Istio来分配比如2%的流量给V2版本,做金丝雀发布的验证,如果成功了,再自动进行10%节点的升级和流量调度。

 

三、总结

 

 

Istio基本实现了Spring Cloud的很多非功能性的需求,如果是将微服务部署到Kubernetes集群,你可以使用Istio来简化你的Spring Cloud组件,为你的微服务运维减轻负担,让业务团队将更多的精力放在业务代码上。

 

如果想快速试用Istio,最好的方法是使用Kubernetes Helm Chart进行一键Istio部署:"helm install incubator/istio",即可在你的Kubernetes集群里部署Istio服务。

 

参考资料
 
  • https://www.youtube.com/watch?v=AGztKw580yQ&t=1893s

  • https://istio.io/

活动预告