如下所示是Istio 1.1在典型环境下的完整组件列表,本节将介绍其中每个组件的功能和机制。
服务列表中的 istio-pilot是 Istio 的控制中枢 Pilot服务。如果把数据面的 Envoy 也看作一种Agent,则Pilot类似传统C/S架构中的服务端Master,下发指令控制客户端完成业务功能。和传统的微服务架构对比,Pilot 至少涵盖服务注册中心和 Config Server 等管理组件的功能。
如图 2-5 所示,Pilot 直接从运行平台提取数据并将其构造和转换成 Istio 的服务发现模型,因此Pilot只有服务发现功能,无须进行服务注册。这种抽象模型解耦了Pilot和底层平台的不同实现,可支持Kubernetes、Consul等平台。Istio 0.8还支持Eureka,但随着Eureka停止维护,Istio在1.0之后的版本中也删除了对Eureka的支持。
图2-5 Pilot的服务发现功能
除了服务发现,Pilot 更重要的一个功能是向数据面下发规则,包括 VirtualService、DestinationRule、Gateway、ServiceEntry 等流量治理规则,也包括认证授权等安全规则。Pilot 负责将各种规则转换成 Envoy 可识别的格式,通过标准的 xDS 协议发送给 Envoy,指导Envoy完成动作。在通信上,Envoy通过gRPC流式订阅Pilot的配置资源。如图2-6所示,Pilot将 VirtualService表达的路由规则分发到 Evnoy上,Envoy根据该路由规则进行流量转发。
图2-6 Pilot分发路由规则
istio-telemetry是专门用于收集遥测数据的Mixer服务组件。如服务列表所示,在部署上,Istio控制面部署了两个Mixer组件:istio-telemetry和istio-policy,分别处理遥测数据的收集和策略的执行。查看两个组件的 Pod 镜像会发现,容器的镜像是相同的,都是“/istio/mixer”。
Mixer是Istio独有的一种设计,不同于Pilot,在其他平台上总能找到类似功能的服务组件。从调用时机上来说,Pilot管理的是配置数据,在配置改变时和数据面交互即可;然而,对于Mixer来说,在服务间交互时Envoy都会对Mixer进行一次调用,因此这是一种实时管理。当然,在实现上通过在Mixer和Proxy上使用缓存机制,可保证不用每次进行数据面请求时都和Mixer交互。
如图2-7所示,当网格中的两个服务间有调用发生时,服务的代理Envoy就会上报遥测数据给 istio-telemetry 服务组件,istio-telemetry 服务组件则根据配置将生成访问 Metric等数据分发给后端的遥测服务。数据面代理通过 Report接口上报数据时访问数据会被批量上报。
图2-7 Mixer遥测
在架构上,Mixer 作为中介来解耦数据面和不同后端的对接,以提供灵活性和扩展能力。运维人员可以动态配置各种遥测后端,来收集指定的服务运行数据。
istio-policy是另外一个Mixer服务,和istio-telemetry基本上是完全相同的机制和流程。如图2-8所示,数据面在转发服务的请求前调用istio-policy的Check接口检查是否允许访问,Mixer 根据配置将请求转发到对应的 Adapter 做对应检查,给代理返回允许访问还是拒绝。可以对接如配额、授权、黑白名单等不同的控制后端,对服务间的访问进行可扩展的控制。
图2-8 Mixer策略控制
服务列表中的 istio-citadel是 Istio的核心安全组件,提供了自动生成、分发、轮换与撤销密钥和证书功能。Citadel一直监听 Kube-apiserver,以 Secret的形式为每个服务都生成证书密钥,并在Pod创建时挂载到Pod上,代理容器使用这些文件来做服务身份认证,进而代理两端服务实现双向TLS认证、通道加密、访问授权等安全功能,这样用户就不用在代码里面维护证书密钥了。如图 2-9 所示,frontend 服务对 forecast 服务的访问用到了HTTP方式,通过配置即可对服务增加认证功能,双方的Envoy会建立双向认证的TLS通道,从而在服务间启用双向认证的HTTPS。
istio-galley并不直接向数据面提供业务能力,而是在控制面上向其他组件提供支持。Galley作为负责配置管理的组件,验证配置信息的格式和内容的正确性,并将这些配置信息提供给管理面的 Pilot和 Mixer服务使用,这样其他管理面组件只用和 Galley打交道,从而与底层平台解耦。在新的版本中Galley的作用越来越核心。
图2-9 Citadel密钥证书维护
istio-sidecar-injector是负责自动注入的组件,只要开启了自动注入,在Pod创建时就会自动调用istio-sidecar-injector向Pod中注入Sidecar容器。
在 Kubernetes环境下,根据自动注入配置,Kube-apiserver在拦截到 Pod创建的请求时,会调用自动注入服务 istio-sidecar-injector 生成 Sidecar 容器的描述并将其插入原 Pod的定义中,这样,在创建的 Pod 内除了包括业务容器,还包括 Sidecar容器。这个注入过程对用户透明,用户使用原方式创建工作负载。
在本书和Istio的其他文档中,Envoy、Sidecar、Proxy等术语有时混着用,都表示Istio数据面的轻量代理。但关注Pod的详细信息,会发现这个容器的正式名字是istio-proxy,不是通用的Envoy镜像,而是叠加了Istio的Proxy功能的一个扩展版本。另外,在istio-proxy容器中除了有Envoy,还有一个pilot-agent的守护进程。未来如果能在istio-proxy中提供Mixer的部分能力,则将是一个非常紧凑的设计。
Envoy是用C++开发的非常有影响力的轻量级高性能开源服务代理。作为服务网格的数据面,Envoy提供了动态服务发现、负载均衡、TLS、HTTP/2 及 gRPC代理、熔断器、健康检查、流量拆分、灰度发布、故障注入等功能,本篇描述的大部分治理能力最终都落实到Envoy的实现上。
在Istio中,规则的描述对象都是类似forecast服务的被访问者,但是真正的规则执行位置对于不同类型的动作可能不同,可能在被访问服务的 Sidecar 拦截到 Inbound 流量时执行,也可能在访问者的Sidecar拦截到Outbound流量时执行,一般后者居多。当给forecast服务定义流量规则时,所有访问forecast服务的Sidecar都收到规则,并且执行相同的治理逻辑,从而对目标服务执行一致的治理。表2-1列出常用的服务访问治理规则和其执行位置。
表2-1 常用的服务访问治理规则和其执行位置
istio-ingressgateway 就是入口处的 Gateway,从网格外访问网格内的服务就是通过这个Gateway进行的。istio-ingressgateway比较特别,是一个Loadbalancer类型的Service,不同于其他服务组件只有一两个端口,istio-ingressgateway 开放了一组端口,这些就是网格内服务的外部访问端口。如图2-10所示,网格入口网关istio-ingressgateway的负载和网格内的 Sidecar是同样的执行体,也和网格内的其他 Sidecar一样从 Pilot处接收流量规则并执行。因为入口处的流量都走这个服务,会有较大的并发并可能出现流量峰值,所以需要评估流量来规划规格和实例数。Istio通过一个特有的资源对象Gateway来配置对外的协议、端口等,用法参照3.4节。
图2-10 网格入口网关从Pilot处接收流量规则并执行
除了以“istio”为前缀的以上几个Istio自有的组件,在集群中一般还安装Jaeger-agent、Jaeger-collector、Jaeger-query、Kiali、Prometheus、Tracing、Zipkin组件,这些组件提供了Istio的调用链、监控等功能,可以选择安装来完成完整的服务监控管理功能。