【译】为什么有Kubernetes了还要Istio?

原文 https://thenewstack.io/why-do-you-need-istio-when-you-already-have-kubernetes/

K8s本质上是对基于声明式配置的应用 做生命周期管理,Istio本质上是做应用内流量治理,安全治理和可观察性。如果你已经用K8s构建了一个稳定的应用,你如何在两个服务之间配置一个负载均衡和流控?这时我们就需要Istio登场了。

Envoy引入的xDS协议,被包含Istio,MOSN在内的众多开源软件支持。Istio开源了xDS作为ServiceMesh,云原生基础设置。Envoy能胜任可基于API配置的,多种现代的代理场景,如API网关,ServiceMesh边车代理网关,边界网关。

本文包含如下内容:

  1. kube-proxy角色的描述
  2. K8s对于微服务治理的局限性。
  3. 对istio能力的介绍
  4. 对一些概念的对比,K8s,Envoy,ServiceMesh

Kubernetes vs Service Mesh

下面的示意图K8s和ServiceMesh(每Pod1sidecar模型)在服务访问上的区别。
1

流量转发

每个K8s的节点都部署了一个可以和APIServer通信的kube-proxy,获取集群信息,配置iptables,把请求直接发给EndPoint。

服务发现

2
Istio可以使用K8s的服务注册,也可以通过控制面的适配器(Adapter)对接其他服务发现系统生成数据面的透明代理的配置(作为CRD保存在etcd中)。数据面的透明代理作为边车容器部署在每个应用的Pod中,所有这些边车容器都会请求控制面来同步代理配置。这里说代理是“透明”的,是因为应用容器完全感觉不到代理的存在。kube-proxy组件也需要拦截流量,区别在于kube-proxy拦截进出K8s Node的流量,而边车(sidecar)代理是拦截进出Pod的流量。

ServiceMesh的缺点

当K8s每个节点都跑了大量Pod时,给每个Pod添加原始路由转发将会增加响应的延迟,这是因为边车拦截带来了更多的跳数也消耗了更多资源。为了细粒度管理流量,Istio引入了一系列抽象,这会带来更多的学习成本,但是随着Istio逐渐流行,这个情况会缓解。

ServiceMesh的优点

首先,kube-proxy的配置是全局的,不能从服务的粒度管理,然而,Istio基于边车代理能做到更细的流量管理,带来更多弹性。

Kube-proxy的缺点

首先,当某个Pod不能正常工作时,它不会自动尝试另一个Pod。每个Pod都有健康检查机制,当Pod健康检查出问题时,kubelet将会重启Pod,kube-proxy将会移除相关转发规则。此外,NodePort模式的Service不支持TLS,或者其他更负责的路由机制。

kube-proxy实现同一个Service的多个Pod之间的负载均衡。但是你怎么做多个Service之间的细粒度管理,比如根据应用的版本,按照百分比切分流量(他们都是同一个Service,但是不同的部署)或者做金丝雀发布(灰度发布)或者蓝绿发布?

Kubernetes社区给出了一种方式来用部署做金丝雀发布:本质上就是通过给部署的Pod打标签。

Kubernetes Ingress vs. Istio Gateway

Kubernetes Ingress

如上面所说,kube-proxy只能路由K8s集群内的流量。K8s的Pod是通过CNI创建的网络中定位的。Ingress  是专门用于和集群外通信的K8s中的资源对象,是由位于K8s边缘节点的Ingress控制器来驱动的,负责管理南北向流量。Ingress必须依赖Ingress控制器,比如nginx controller和 traefik。Ingress只适配Http流量,非常简单易用。它只能通过匹配有限的几个字段来路由流量,比如service,port,path等。路由比如mysql,redis和其他rpc等tcp流量是不可能的。这就是为何你在ingress资源注解中别人会写nginx配置语言。直接路由南北流量的唯一方式就是使用Service的LoadBalancer模式或者NodePort模式,前者依赖云供应商的支持,后者需要额外的端口管理。

Istio Gateway

Istio Gateway功能上和Ingress 类似,那就是负责南北向流量进出集群。Istio Gateway规范描述了负责在网格边缘接收链接的负载均衡。规范还描述了一系列端口和使用这些端口的协议,比如负载均衡的SNI配置。Gateway是CRD扩展也服用了边车代理的能力,看这里的详细配置 https://istio.io/latest/docs/reference/config/networking/gateway/?utm_source=thenewstack&utm_medium=website&utm_campaign=platform

Envoy

Envoy是Istio的默认边车代理。Istio扩展了其基于xDS控制面的协议。我们在讨论xDS协议之前需要先熟悉下相关术语。下图是协议的基本项和他们在Envoy中的结构,看这里有细节:

https://www.envoyproxy.io/?utm_source=thenewstack&utm_medium=website&utm_campaign=platform

3

基本术语

  • 下游(Downstream)下游Host链接Envoy,发送请求,接收响应;就是我们发送请求的Host。

  • 上游(Upstream)上游接收来自Envoy的链接和请求,返回响应;也就是接收请求的Host。

  • 监听器(Listener)listener是实名网络地址(比如端口,unix domain socket)下游客户端能链接监听器,Envoy会暴露一两个监听器给下游Host来连接。

  • 集群(Cluster)一个集群是一组供Envoy连接的逻辑独立的上游Host。Envoy通过服务发现发现集群的成员。集群的成员的健康状态由主动健康检查决定,Envoy根据负责均衡策略决定路由到集群那个成员。

Envoy可以配置多个Listener,每个Listener可以配置一个过滤器链,过滤器链是可扩展的,我们可以简单的修改流量的行为,比如加密和私有rpc等。
xDS协议是Envoy提议的,是Istio默认边车代理,但是只要实现了xDS协议,那它理论上就能当作Istio的边车代理,比如蚂蚁集群开源的MOSN。

4

Istio是功能丰富的ServiceMesh,包含如下能力:

  • 流量治理:Istio最基本的功能

  • 策略控制:访问控制,遥测,配额管理,账单。

  • 可观察性:在边车代理中实现。

  • 安全认证:Citadel组件负责key和证书管理。

流量治理

下面的CRD是Istio用来做流量治理的:

  • Gateway:描述了一个运行在边缘网络的负载均衡器用来接收入站出站的TCP,Http连接。

  • VirtualService:实际上把Gateway和K8s Service 连接到一起。还提供了额外的操作:比如定义一组能应用于某个Host上的流量路由规则。

  • DestinationRule:DestinationRule定义了路由后的流量策略。简单来说,它定义了流量是如何路由的。此外还能定义负载均衡策略,连接池大小,还有一些探测(比如从连接池中移除不健康的节点)。

  • EnvoyFilter:此配置描述了proxy的过滤器,一般由pilot自动生成,通常很少有用户会用到。

  • ServiceEntry:默认情况下,Istio ServiceMesh中的Service没有能力对mesh外部做服务发现。ServiceEntry允许额外的服务加入到Isito的服务注册中来,并允许mesh内自动发现的服务访问并路由那些手动加入的service。

Kubernetes vs. xDS vs. Istio

回顾过k8s kube-proxy,xDS, and Istio组件的流量治理抽象后,我们来对比下流量治理这方面三者的组件,协议(注意,它们并不完全等价):

Kubernetes xDS Istio service mesh
Endpoint Endpoint WorkloadEntry
Service Route VirtualService
kube-proxy Route DestinationRule
kube-proxy Listener EnvoyFilter
Ingress Listener Gateway
Service Cluster ServiceEntry

总结

  • k8s的职责在于应用的生命周期管理,尤其是部署和管理(扩展,自动回复,释放)。

  • k8s为微服务提供了一个可扩展,高可靠的部署管理平台。

  • service mesh是基于透明代理的,在服务之间通过边车拦截流量,通过控制面管理流量的。

  • service mesh将流量治理从k8s中解耦出来,消除了service mesh内流量治理对于kube-proxy的依赖;通过提供更接近微服务应用层的抽象,来管理Service的流量,安全,可观察性。

  • xDS是ServiceMesh配置的标准协议之一。

  • ServiceMesh是K8s的服务的更高层次的抽象。

结论

如果说K8s管理的对象是Pod,那么ServiceMesh管理的对象就是Service,实际上就是K8s来管理微服务在上层应用ServiceMesh。如果你甚至不想管理微服务,你可以使用KNative这样的Serverless平台,但这是后话了。