Dawn's Blogs

分享技术 记录成长

0%

Istio学习笔记 (5) Pilot 配置和服务发现概述

在 Istio 架构中,Pilot 属于最核心的组件,Pilot 的一个主要职责就是将服务信息和配置数据转换为 xDS 接口的标准数据结构,通过 Grpc stream 下发到数据平面的 Envoy。Polit 的输入来源主要有两个:

  • 服务数据:来源于各个服务注册表(Service Registry),如 Kubernetes 和 Consul。
  • 配置规则:各种配置规则,包括路由规则和流量管理等规则。

image-20231018112119194

Istio Pilot 代码分为 pilot-agent 和 pilot-discovery,其中 pilot-agent 主要在数据平面负责管理 Envoy 的生命周期,pilot-discovery 是控制平面组件,本节主要分析 pilot-discovery。

Pilot-Discovery 代码结构

下图是 pilot-discovery 的主要代码结构,Pilot-Discovery 的入口函数为 pilot/cmd/pilot-discovery/main.go 中的 main 方法。main 方法中创建了 Discovery Server,Discovery Server 主要包括三个部分:

  • Config Controller
  • Service Controller
  • Xds Server

pilot-discovery-struct

Config Controller

Config Controller用于管理各种配置数据,包括用户创建的流量管理规则和策略。Config Controller 包括:

  • Kubernetes:对接 Kubernetes CRD,从 kube-apiserver 中 watch VirtualService、DestinationRules 等配置信息,有则推送至 XdsServer。
  • MCP(Mesh Configuration Protocol):使用 Kubernetes 来存储数据会导致 Istio 和 Kubernetes 的耦合,限制 Istio 在非 Kubernetes 环境下的使用。所以,Istio 提出了 MCP,MCP 定义了一个向 istio 控制平面下发配置数据的标准协议,istio pilot 作为 MCP Client,任何实现了 MCP 协议的 Server 都可以通过 MCP 协议向 istio 下发配置,从而解除了 istio 和 kubernetes 的耦合。
  • Memory:内存实现,主要用于测试。

istio 中的配置包括:VirtualService、DestinationRule、Gateway、ServiceEntry 等。

Service Controller

Service Controller 用于管理各种注册中心,包括:

  • Kubernetes:对接 Kubernetes,可以将 Kubernetes 定义的服务采集到 istio 中。
  • Consul:使用 Consul 作为注册中心。
  • ServiceEntryStore:描述的是集群外部的服务信息(ServiceEntry),将集群外部的服务信息同步到 istio 中,纳入网格统一进行流量控制和路由。
  • MCP:与具体的注册中心解耦,从 MCP Server 中获取服务注册信息。
  • Mock:用于测试。

Discovery Service

Discovery Service 中主要包含下述逻辑:

  • 启动 Grpc Server 并接收来自 Envoy 端的连接请求。
  • 接收 Envoy 端的 xDS 请求,从 Config Controller 和 Service Controller 中获取配置和服务信息生成响应消息发送给 Envoy
  • 监听来自 Config Controller 的配置变化消息和来自 Service Controller 的服务变化消息,并将配置和服务变化内容通过 xDS 接口推送到 Envoy

Pilot-Discovery 业务流程

pilot-discovery主要包括以下业务流程:

初始化组件

在 main 方法中,创建了 Pilot Server,Server 做了一些初始化的工作:

  • 创建并初始化 Config Controller

  • 创建并初始化 Service Controller

  • 创建并初始化 Discovery Server,pilot 创建了 Envoy v3 版本的 API 的 Grpc Discovery Server。

  • 将 Discovery Server 注册为 Config Controller 和 Service Controller 的 Event Handler,监听配置和服务变化消息。

image-20231018144618394

创建Grpc Server 并接收 Envoy 连接请求

pilot 创建了一个 Grpc Server,用于监听和接受来自 Envoy 的 xDS 请求。ploit/pkg/xds/ads.go 中的 DiscoveryServer.StreamAggregatedResources 方法被注册为 Grpc Server 的服务处理方法。

当 Grpc Server 收到 Envoy 的连接时:

  • 调用 DiscoveryServer.StreamAggregatedResources 方法,在该方法中创建一个 xds.Connection 对象,并开启一个 goroutine 从该连接中接收客户端的 xDS 请求并处理
  • 如果控制面的配置/服务注册信息发生变化,pilot 也会通过该 connection 把配置变化主动推送到 Envoy 端

image-20231018145100932

配置变化后向 Envoy 推送更新

这是 pilot 中最为复杂的部分,因为采用了多个 channel 和 queue 对变化消息进行合并和转发。流程如下:

  • Config Controller 和 Service Controller 在配置或者服务发生变化时通过回调方法通知 Discovery Server,Discovery Server 将变化的消息推至 Push Channel 中
  • Discovery Server 通过一个 goroutine 从 Push Channel 中接收变化消息,将一段时间内连续发生的变化消息进行合并(debounce)。如果超过指定时间没有新的变化消息,则将合并后的消息加入到一个队列 Push Queue 中
  • 另一个 goroutine 从 Push Queue 中取出变化消息,生成 XdsEvent,发送到每个客户端连接的 Push Channel 中
  • (每一个 Grpc 客户端连接)在 DiscoveryServer.StreamAggregatedResources 方法中从 Push Channel 中取出 XdsEvent,然后根据上下文生成符合 xDS 接口规范的 DiscoveryResponse,通过 GRPC 推送给 Envoy

image-20231018151458887

响应 Envoy 主动发起的 xDS 请求

pilot 和 envoy 之间建立的是双向 stream grpc 连接,所以 pilot 可以在配置变化时向 envoy 推送,envoy 也可以主动发起 xDS 请求获取配置信息。Envoy 主动发起 xDS 请求的流程如下:

  • Envoy 通过建立好的 Rrpc 连接发送一个 DiscoveryRequest
  • Discovery Server 通过一个 goroutine 从 xds.Connection 中接收来自 Envoy 的 DiscoveryRequest,并将请求发送到 ReqChannel 中
  • Discovery Server 通过另一个 goroutine 从 ReqChannel 中接收 DiscoveryRequest,根据上下文生成符合 xDS 规范的 DiscoveryResponse,返回给 envoy

image-20231018150822915