我们知道,当应用程度到达了一定程度大的时候,必然会走到分布式,而微服务是作为分布式的一种极致表现。谈到微服务,不得不去提微服务治理,在这之前,我们了解下分布式架构治理模式的演进。
服务治理在早期的治理能是是嵌入在业务代码中的,典型技术如:SOA,ESB,开发人员把服务治理的代码写入到程序中来实现服务发现,符在均衡,熔断容错,动态路由。这意味着每个开发人员都需要在自己的模块内维护一个这些功能。
而到了SDK实现的时候应用的典型技术就变成了spring cloud,dubbo来实现这些,这些通过SDK提供框架,只要程序引入库的功能,并编写业务就能完成。但是,一旦使用SDK,同框架的语言就只能使用一个。并且一旦这个框架有漏洞,修复就会导致所有程序需要重新编译和部署、
到了现在,服务治理到了服务网络。为了减少SDK之间的耦合,SDK被独立成一个应用程序,这个应用程序通过代理的方式运行,服务本身通过同一个某协议通信,如:grp,http,restfullapi等,代理程序来代理这些。程序员只需要开发自己的业务代码逻辑,基于分布式框架对接即可。
这三个阶段分别称为:内嵌于应用程序,SDK,代理
前言
而istio就是这么一个组件。程序只需要部署在istio之上,istio会添加一个代理来完成服务代理的功能。程序员不需要关心服务治理的关系。这就是服务网格的价值。
分布式程序本身遇到的网络现状是需要重传,重试,超时,重新连接机制,如果程序本身不能解决,构建分布式应用是很容易出现问题的,而在服务和服务之间网络协作的网络管理功能是独立出来的,各微服务框架此类的解决方案往往和基础组件一起使用,如zookeeper或者eureka等。
kubernetes是应用程序生命周期管理机制。在这之上service mesh作为基础设施向应用提供的。这样一来,就从研发人员的开发中解耦出来,应用层只关注应用本身。在kubernetes中,istio是以kubernetes的扩展提供的,因为istio是作为Kubernetes的某个CRD控制器,它通过的是资源类型,只需要通过声明式API即可调用API接口来编写对应的程序,并apply到集群即可。只要了解这些就能够在过去建立的Kubernetes体系和工具来管理能够被istio治理的微服务。
在Service MESH中,CNCF定义了UDPA和SMI标准,数据平面和控制平面,而在istio出现之前,likerd是在2016年9月出现,随着linkerd加入CNCF后,2017年五月Istio发布0.1版本,随后Envory加入CNCF,当2018年7月发布了istio的1.0版本,2019年的1.1版本,直到2020的1.5版本,istio的组件发生了不同的变化。
服务网格
服务网格源于Buoyant 公司的 CEO Willian Morgan 在的文章 WHAT’S A SERVICE MESH? AND WHY DO I NEED ONE?
指向专注于处理服务间通信的基础设施,她负责在现代云原生应用组成的复杂拓扑中可靠的传递请求。除了处理业务逻辑的相关功能,每个微服务还必须实现此前单体应用模型中用于网络间通信的基础功能,甚至还包括分布式应用程序之间的通信环境中应该实现的其他网络功能。例如:熔断,限流,应用追踪,指标采集,服务发现和符在均衡等。而实现模型经过三代演进:内嵌于应用程序,SDK,代理(sidecar)
而sitio就是服务网格,而服务网格又分为两个部分:数据平面和控制平面
控制平面:控制平面负责生成和部署数据平面行为的相关配置:控制平面通常包括API接口,命令行界面和用于管理应用程序的图形用户界面等。
如果要为每个微服务实例构建一个服务代理,这在Kubernetes中将会是在同pod内的两个容器。代理程序将被称为sidecar,业务容器通常被称为主容器。而在控制平面中有可以被下发的每一个代理的信息,并允许用户进行修改,一旦修改后可以向网格内下发配置。
而微服务一旦需要更新的时候,借助于底层Kubernetes进行部署,但是在这个过程中的流量,以及通信直接是加密的,就需要向控制平面进行配置下发到proxy,也就是sidecar来实现。
- 而这个proxy是进行二次开发过的envoy
数据平面:服务网格应用程序中管理实例之间的网络流量部分称为数据平面,而支持数据平面的就是sedecar-envoy
在过去,deployment从镜像A更新到镜像B的时候,是滚动的。现在istio是可以监控到部署了几个pod,并为每个pod自动注入一个sedecar,我们只需要像过去使用deployment那样使用。一旦注入完成,pod之间通讯都是通过sedecar来完成。无论pod中的程序是怎么监听的,sedecar都会截取来往pod之间的流量
istio体系
istio主要功能分为四部分,流量治理,安全,可观测性,网格。istio主要组件,pIlot,citadel,mixer,但是这在1.0,1.1,1.5有一些区别。
mixer在1.0的时候是通过插件扩展和第三方来支持遥测的,而到了1.1,又换成了adapter,通过网络通信来做遥测,并添加了一个galley来支持适配其他平台。但迎之而来的是性能下降,因为proxy每次都需要想mixer上报指标,这损耗的大量的资源。在istio1.5后,丢弃Mixer这种分布式,遥测功能交给envoy自行完成,将pilot,citadel,galley和sidecar injector整合到一个单体应用istiod。
istiod充当控制平面,讲配置分发到sidecar代理和网关,它能够为支持网络的应用实现智能化的负载均衡机制,且相关流量绕过了kube-proxy
service之所以可以转换ipvs或者iptables规则,把每一个节点当作负载均衡使用,就是通过kube-proxy监控apiserver上的service变动,实时反应到节点上实现
service是同样应用,不同实例提供一个固定的访问入口。每个集群中的service,下面都有对应的pod,这其实都是istio中的微服务。因为istiod读取的是apiserver中的每个service来确定整个网格当中有多少个微服务的。除此之外,还会将service的pod转换为网格中sidecar listner,客户端转换为cluster并生成默认的路由(所有满足listner请求的url都路由到这个cluster)。因此,网格部署后这些会自动转换。
pilot在1.4中作为独立组件,而在1.5后是被整合在一起。到apiserver发现service,配置sidecar,还有其他配置增强功能,如:AB测试,故障转移,灰度发布等
除此之外还有一些其他证书管理工具,如:citadel,vault
但是envoy需要扩展,就需要重新编译,这种退回增强了性能,但是envoy变得复杂。因此envoy提供了一种基于wasm的接口,envoy支持动态装载这些模块。
ingress/egress gateway
在多数时间,更多的流量都是服务和服务之间的访问,而在外层总有一层是接入外部流量的,在集群外部的流量叫南北,而在集群内的网格称为东西流量。而ingress gateway就是管理入向流量网关,也就是南北流量。当客户端作为外部访问集群内部的接入层服务时候,从ingress gateway才能到网格内。而客户端作为网格内访问集群外部就是egress gateway出向流量网关,是否需要做流量统一治理就需要一个出向网关,但是它是可选的。而ingress gateway是必须的。如下图:
这里的ingress gateway并非是ingress controller,也不能像配置kubernetes ingress资源那样进行配置,而是网格专用的网关。
对于一些入口,流量到了入口在发送给那个应用,这些都是在ingress-gateway上进行配置的。这个是独立运行的,并且网格内的流量是不需要经过它的,因而它的配置有别与网格中每个sidecar配置的,进出流量是通过独有的CR来定义的。
对于流出网格流量是通过egress只有在需要配置的时候进行配置,并非必要。但是它的配置也是不同的,通过service entry来进行定义的。
对于入口流量,内部流量,出口流量都需要单独进行治理。而入口流量和出口流量多数情况下配置与他们是无关的,只有在需要的时候才会进行配置。
ingress和egress一直都是独立的
并且,他们的配置策略,接口都是不一样的。一旦部署好istio后,istio sidecar injector会自动注入,这些依托于admission controller来完成的。当然也可以使用istioctl客户端手动注入。
-
自动注入:使用istio sidecar injector自动完成注入过程(借助于Mutating admission)
利用k8s webhook实现
创建pod自动注入发生在admission controller的mutaion阶段,根据自动注入配置,kube-apiservier拦截到pod创建请求时调用自动注入服务istio-sidecar-injector生成的sidecar容器描述并将插入到pod清单
- 手工注入:使用istioctl工具进行注入
数据平面是实现南北和东西流量治理完成,控制平面不涉及客户端和流量通讯,只是负责为业务代码注入一个sidecar proxy,并进行下发流量管里配置的控制臂中心。
kiali
istio有辅助插件kiali来完成 web ui的,kiali本身只能显示简单的绘图功能,其他依赖于promehteus,skywaling,grafana,jaeger来展示数据等。这些需要单独部署才能使用。
它能够提供以下功能:
- 服务拓扑的动态绘制
- 分布式跟踪
- 指标度量收集
- 配置校验
- 健康检查和提示
kiali基于go语言开发 ,由kiali front-end和back-end组件构成,分别提供ui和后端应用。同时它依赖k8s外部服务和组件,如: prometheus,cluster api, jaeger, grafana。将这些结合起来统一展示
CR
为了便于使用,这些功能被抽象成CR。istio所有规则和控制策略都基于k8s crd实现,这这些配置策略定义保存在etcd中,提供的CR如下:
- network:
流量治理,包括virtualService,destinationRule,Gateway,serviceEntry,sidecar,EnvoyFilter,WorkLoadEntry和WorkloadGroup等8个CR
- security:
网络安全,包括AuthorizationPilicy, PeerAuthenticaiton和RequestAuthentication等3个CR
- telemetry:
网络遥测,目前仅包括Telemetry一个
- extensions:
扩展机制,目前仅包括WasmPlugin
- istioOperator:
ItioOperator,目前仅包括一个,IstioOperator
但是这并非所有,很多envoy的功能仍然需要用户自行定义