Istio v1.6深度解读:Simplify

来源: Istio v1.6深度解读

Istio 1.6正式发布,距离1.5版本发布大约2个半月时间,细心的读者已经发现本版本发布是自从去年9月份以来发布周期最为正常的一次版本,这归功于所有社区开发者共同的努力。

Simplify

“简化”这个词很好地诠释了Istio 1.6的主题,为什么这么说呢?

  1. 首先,本次版本中单体的Istiod彻底将pilot,sidecar-injector,citadel,galley融合为一体,citadel,sidecar-injector,和galley彻底被删除,并且不再支持单独部署。

  2. 如果用户使用Kubernetes 1.18,并且使用服务端口的 “AppProtocol”描述应用协议,那么可以不再必须按照Istio规范定义端口名称。

  3. 更好的控制面生命周期管理,持续的提高安装及升级的用户体验。

  • 新增金丝雀升级,更加安全https://istio.io/docs/setup/upgrade/#canary-upgrades
  • 原地升级
  1. 简化虚拟机支持,新增了WorkloadEntry API,使得运行的虚拟机、裸金属机器的工作负载描述变得更加容易。

  2. 通过支持VirtualService级联的方式,解耦多服务路由定义。

细细品味,不难发现1.6版本比较重大的更新与前不久发布的路标《Istio in 2020 - Following the Trade Winds》完全一致。下面简单回顾一下Istio 2020年路标。

Istio 2020 RoadMap

今年三月份,Istio社区发布了2020 roadmap 。其中重点包括了:

1. 更时尚,更快,更流畅

Istio从创建开始一直到1.4一直使用Mixer提供可扩展性。然而,这种在数据面通道中增加一个进程外组件的形式达到增加了请求的开销。彻底移除Mixer,充分利用Envoy的扩展机制提供遥测信息,成为2020年的一大目标。

基准测试表明,这种新的遥测模型,能够降低50%的延迟和CPU消耗,提供行业领先的性能。

2. 可扩展性新模型

在Envoy中实现Wasm的运行时,能够最大化的提供扩展能力,目前Istio的遥测能力已经通过Wasm实现。关于Wasm,感兴趣的读者可以参考

可以预见Wasm将会为Istio扩展机制提供最佳利器。

3. 更少的组件

Istio控制面组件由上图简化为下图,只包含Istiod和Istio-agent组件。

4. 改进的生命周期管理

Istio本身提供了非常多的参数,允许用户个性化配置自己的网格属性,因此,Istio控制面本身的安装部署以及升级变得非常棘手。为了改进Istio控制面的生命周期管理,

Istio社区推荐使用基于Operator的安装模型

本文下面选取用户比较关心的几个重要特性进行深入解读。至于为何选择这几个特性,与End-User密切相关。如果对其他功能特性感兴趣,可以参考社区相关文档或者实现。

新增WorkloadEntry对象API

WorkloadEntry是一种全新的资源类型,目的是为了描述K8s集群外的工作负载,比如虚拟机或者裸金属服务器上的负载。更好的支持混合部署模型。

Istio 1.6之前,虚拟机工作负载的声明只能嵌入到ServiceEntry内部的Endpoint中。如下所示:

apiVersion: networking.istio.io/v1beta1

kind: ServiceEntry

metadata:

  name: httpbin

  namespace : httpbin-ns

spec:

  hosts:

  - httpbin.com

  location: MESH_INTERNAL

  ports:

  - number: 80

    name: http

    protocol: HTTP

  resolution: STATIC

  endpoints:

  - address: 2.2.2.2

  - address: 3.3.3.3

  subjectAltNames:

  - "spiffe://cluster.local/ns/httpbin-ns/sa/httpbin-service-account"

不难想象,这种耦合的API模型带来很多问题:

  • 当工作负载非常多的情况下,ServiceEntry变得很大,更新极易出错,同时很大的资源对象更新必将带来额外的开销。

  • 同时,不支持一个服务的容器和虚拟机混合部署。比如说httpbin服务同时部署在Kubernetes集群以及虚拟机上,集群内的服务由K8s Service、Pod表示,虚拟机上的只能通过ServiceEntry表示,这种部署模型在老版本中很难无缝集成。

WorkloadEntry的出现,完全解决了上述问题,虚拟机、裸机工作负载由WorkloadEntry独立表示,类似K8s中的Pod。

type WorkloadEntry struct {
// 工作负载地址,类似Pod IP.
 Address string

   // 端口,类似K8s Endpoint端口.
Ports map[string]uint32

   // 标签,类似Pod Label.
 Labels map[string]string
// 网络 ID,主要用于多网络,多集群场景.
Network string
// 工作负载位置拓扑信息,例如us/us-east-1/az-1,可用于基于位置感知的流量分发.
Locality string

   // 负载均衡权重信息,值越大,接收到的请求越多.
Weight uint32
// 工作负载身份信息,类似Pod Sa身份
ServiceAccount       string
}

ServiceEntry(类似K8s Service)可以通过标签选择对应的工作负载(WorkloadEntry),避免了用户维护一个超大耦合的ServiceEntry,这种解耦的模型用户体验更好。

同时,1. 6中支持ServiceEntry选择Pod,也就是说目前ServiceEntry可以同时选择WorkloadEntry和Pod作为Endpoint,因此很好地解决了跨虚拟机以及K8s集群部署服务的管理难题。

细心的读者可能发现既然ServiceEntry能够选择Pod,反过来为什么不支持K8s Service选择WorkloadEntry。理论上完全行得通,这种反选的模型刚刚实现,计划将会包含在下一个版本中。

由此可见,Istio社区为了支持混合部署所做的努力,用户如果有难以容器化的服务,但是仍然想使用网格提供的非侵入、语言无关的服务治理能力, Istio是一个非常理想的选择。。

VirtualService级联

现实中,多个微服务共用同一个域名,以URI路径路由的方式十分常见。

自从Istio VirtualService v1alpaha3引进以来,所有的流量规则都是耦合在一起,不支持任何形式的级联或者合并。针对以上场景,需要用户将所有的服务路由信息定义放在一个VirtualService中,如下:

image

在实际使用中,经常会出现动辄近千行的一个大的VirtualService,带来的维护难度可想而知。在微服务大行其道的今天,每个服务的开发维护往往是独立的。

上述耦合的路由模型势必会带来:

  • 任何一个微服务的自身的路由升级都要修改这个大的VirtualService规则,实际使用中同时升级经常会导致微服务路由更新冲突;

  • 极易出错,任何的规则配置错误,势必会影响数据面工作异常,甚至导致所有的服务访问受影响。

  • 配置冗余和耦合,没有级联来解耦,当前平铺的配置中,很多公共的配置不得不通过条件AND的方式分配到各个Route中,导致一个路由匹配条件的修改可能会影响多个Route。

如上图示例:

  • 当一个应用系统有多个服务需要外部访问时,每个服务都有各自的流量规则,需要把多个Route都定义在一个大的VirtualService上,修改任何一个服务的灰度规则需要在这个全局配置上修改,可能影响其他服务的流量规则;每个URI的映射不得不和类似Header的灰度条件耦合在一起,灰度规则和入口流量路由区分不开,条件配置极其复杂;

  • 当一个内部服务有多个版本时,URI需要和每个版本的Match条件AND在一起,配置冗余,修改URI的映射时需要在涉及该服务的每个Route的Match条件上修改。

VirtualService级联方案

很多用户受此问题困扰了两年之久

Istio 1.6通过扩展VirtualService,引入了Delegate机制,实现了VirtualService级联的方案。实现级联之后,流量规则无需耦合在一个大的VirtualService中,各服务维护者可以专心维护本服务的路由规则,而根VirtualService则由集群管理员统一维护。 大大降低了服务路由规则更新带来的风险 ,促进服务独立部署、升级。

image

如下图所示,通过级联的VirtualService解耦了服务各自的流量规则定义,每个服务的流量规则可以使用单独的VirtualService来定义,修改外部路由映射只需修改Root VirtualService一个地方,而对于内部流量规则的变更只要修改服务对应的VirtualService即可,简化了维护难度。

VirtualService级联用法

该方案由最早由华为云工程师根据客户场景设计和开发,并在华为云应用服务网格ASM服务中广泛使用,解决了内部客户Welink基于网格进行大规模复杂场景下的灰度发布规则定义和流水线集成。

PR:

提交到社区后,获得了社区热烈的反馈和讨论,解决了一大类类似场景的客户问题。VirtualService级联使用姿势比较简单:

  1. 首先设置PILOT_ENABLE_VIRTUAL_SERVICE_DELEGATE=true,打开特性开关。
  2. 定义服务的根路由,推荐按照二元组域名+端口拆分。
  3. 定义各服务的子路由,为了区分根路由与子路由,同时不引入其他字段,使用Hosts是否为空来区分。子路由共享根路由的Hosts,因此不用设置。

K8s Service APIs支持

K8s Service APIs

是K8s网络组提出的一种用于取代Ingress的网络API,用于暴露K8s集群的服务。K8s Service APIs不仅限于HTTP,还支持TLS,TCP等,目前正在重度开发演变中。

K8s Service APIs主要包含Gateway,HTTPRoute, TCPRoute等顶层资源对象,本质上这与Istio的Gateway以及VirtualService是完全对等的关系。

很多人曾经提出过类似的疑问:为什么Istio要支持一个目前处于高速演进的,alpha状态的K8s非核心API呢?

Google内部 Istio团队与K8s团队网络组有比较密切的关系。当前K8s Service APIs定位很高,目标就是取代Ingress,Istio团队将会帮助K8s团队推动Service APIs的发展。但是从用户角度来看,目前并不适合做第一个吃螃蟹的人,首先,K8s Service APIs的高速演进,意味着目前并不够成熟,过早的使用可能会带来额外的适配工作量。同时随着Istio自身Gateway及VirtualService的演进以及日趋成熟,迁移到新的API的动力也略显不足。