Envoy 是一个开源的边缘服务代理,也是 Istio Service Mesh 默认的数据平面,专为云原生应用程序设计。
与HAProxy以及Nginx等传统Proxy依赖静态配置文件来定义各种资源以及数据转发规则不同,Envoy几乎所有配置都可以通过订阅来动态获取。对应的发现服务以及各种各样的API统称为xDS。Envoy与xDS之间通过Proto约定请求和响应的数据模型,不同类型资源,对应的数据模型也不同。
1 Envoy整体架构
Envoy 的架构如图所示:
Envoy 中也可能有多个 Listener,每个 Listener 中可能会有多个 filter 组成了 chain。
Envoy 接收到请求后,会先走 FilterChain,通过各种 L3/L4/L7 Filter 对请求进行微处理,然后再路由到指定的集群,并通过负载均衡获取一个目标地址,最后再转发出去。
在Envoy中,具有最为核心的四种资源:Listener,Router,Cluster,以及Filter。
1.1 Listener:Envoy工作的基础
简单理解,Listener是Envoy打开的一个监听端口,用于接收来自Downstream(客户端)连接。Envoy可以支持复数个Listener。多个Listener之间几乎所有的配置都是隔离的。Listener配置中核心包括监听地址、Filter链等。
Listener对应的配置/资源发现服务称之为LDS。LDS是Envoy正常工作的基础,没有LDS,Envoy就不能实现端口监听(如果启动配置也没有提供静态Listener的话),其他所有xDS服务也失去了作用。
1.2 Cluster:对上游服务的抽象
在Envoy中,每个Upstream上游服务都被抽象成一个Cluster。Cluster包含该服务的连接池、超时时间、endpoints地址、端口、类型(类型决定了Envoy获取该Cluster具体可以访问的endpoint方法)等等。
Cluster对应的配置/资源发现服务称之为CDS。一般情况下,CDS服务会将其发现的所有可访问服务全量推送给Envoy。与CDS紧密相关的另一种服务称之为EDS。CDS服务负责Cluster资源的推送。而当该Cluster类型为EDS时,说明该Cluster的所有endpoints需要由xDS服务下发,而不使用DNS等去解析。下发endpoints的服务就称之为EDS。
1.3 Router:上下游之间的桥梁
Listener可以接收来自下游的连接,Cluster可以将流量发送给具体的上游服务,而Router则决定Listener在接收到下游连接和数据之后,应该将数据交给哪一个Cluster处理。它定义了数据分发的规则。虽然说到Router大部分时候都可以默认理解为HTTP路由,但是Envoy支持多种协议,如Dubbo、Redis等,所以此处Router泛指所有用于桥接Listener和后端服务(不限定HTTP)的规则与资源集合。
Route对应的配置/资源发现服务称之为RDS。Router中最核心配置包含匹配规则和目标Cluster,此外,也可能包含重试、分流、限流等等。
1.4 Filter:强大源于可扩展
Filter,通俗的讲,就是插件。通过Filter机制,Envoy提供了极为强大的可扩展能力。
利用Filter机制,Envoy理论上可以实现任意协议的支持以及协议之间的转换,可以对请求流量进行全方位的修改和定制。强大的Filter机制带来的不仅仅是强大的可扩展性,同时还有优秀的可维护性。Filter机制让Envoy的使用者可以在不侵入社区源码的基础上对Envoy做各个方面的增强。
- 网络过滤器(Network Filters): 工作在 L3/L4,是 Envoy 网络连接处理的核心,处理的是原始字节,分为 Read、Write 和 Read/Write 三类。
- HTTP 过滤器(HTTP Filters): 工作在 L7,由特殊的网络过滤器 HTTP connection manager 管理,专门处理 HTTP1/HTTP2/gRPC 请求。它将原始字节转换成 HTTP 格式,从而可以对 HTTP 协议进行精确控制。
2 配置
Envoy流程中每一个环节可以静态配置,也可以动态服务发现。
2.1 静态配置
下面的配置将所有流量代理到 baidu.com,配置完成后我们应该能够通过请求 Envoy 的端点就可以直接看到百度的主页了,而无需更改 URL 地址。
static_resources:
# 1. 监听器
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 10000 }
# 2. 过滤器
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { host_rewrite: www.baidu.com, cluster: service_baidu }
http_filters:
- name: envoy.router
# 3. 集群
clusters:
- name: service_baidu
connect_timeout: 0.25s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
hosts: [{ socket_address: { address: www.baidu.com, port_value: 443 }}]
tls_context: { sni: baidu.com }
# 4. 管理
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
2.2 动态配置xDS协议(动态服务发现)
Envoy 通过查询文件或管理服务器来动态发现资源。这些发现服务及其相应的 API 被统称为 xDS。
Envoy 通过订阅(subscription)方式来获取资源,如监控指定路径下的文件、启动 gRPC 流(streaming)或轮询 REST-JSON URL。后两种方式会发送 DiscoveryRequest 请求消息,发现的对应资源则包含在响应消息 DiscoveryResponse 中。
xDS 协议是 “X Discovery Service” 的简写,这里的 “X” 表示它不是指具体的某个协议,是一组基于不同数据源的服务发现协议的总称:
- CDS:Cluster Discovery Service
- EDS:Endpoint Discovery Service
- SDS:Secret Discovery Service
- RDS:Route Discovery Service
- LDS:Listener Discovery Service
xDS 协议是由 Envoy 提出的,目前已成为服务网格的协议标准之一。
Envoy是 Istio 中默认的 sidecar 代理,但只要实现了 xDS 协议,理论上也可以作为 Istio 中的 sidecar 代理 —— 比如蚂蚁集团开源的 MOSN。
比如每个 Envoy 流以发送一个 DiscoveryRequest 开始,包括了列表订阅的资源、订阅资源对应的类型 URL、节点标识符和空的 version_info。EDS 请求示例如下:
version_info:
node: { id: envoy }
resource_names:
- foo
- bar
type_url: type.googleapis.com/envoy.api.v2.ClusterLoadAssignment
response_nonce
管理服务器可立刻或等待资源就绪时发送 DiscoveryResponse 作为响应,示例如下:
version_info: X
resources:
- foo ClusterLoadAssignment proto encoding
- bar ClusterLoadAssignment proto encoding
type_url: type.googleapis.com/envoy.api.v2.ClusterLoadAssignment
nonce: A
参考
Envoy 入门教程
https://www.envoyproxy.io/docs/envoy/v1.18.3/