如前面章节所述,Envoy是由JSON或YAML格式的配置文件驱动的智能代理,对于已经熟悉Envoy或Envoy配置的用户来说,相信应该已经知道了Envoy的配置也有不同的版本。初始版本v1是Envoy启动时配置Envoy的原始方式。此版本已被弃用,以支持Envoy配置的v2版本。Envoy的参考文档(https://www.envoyproxy.io/docs)还提供了明确区分v1和v2的文档。本书中将只关注v2配置,因为它是最新的版本,也是Istio使用的版本。
Envoy版本v2的配置API建立在gRPC之上,v2 API的一个重要特性是可以在调用API时利用流功能来减少Envoy代理汇聚配置所需的时间。实际上,这也消除了轮询API的弊端,允许服务器将更新推送到Envoy代理,而不是定期轮询代理。
Envoy的架构使得使用不同类型的配置管理方法成为可能。部署中采用的方法将取决于实现者的需求。简单部署可以通过全静态配置来实现,更复杂的部署可以递增地添加更复杂的动态配置。主要分为以下几种情况:
·全静态:在全静态配置中,实现者提供一组监听器和过滤器链、集群和可选的HTTP路由配置。动态主机发现仅能通过基于DNS的服务发现。配置重载必须通过内置的热重启机制进行。
·仅SDS/EDS:在静态配置之上,Envoy可以通过该机制发现上游集群中的成员。
·SDS/EDS和CDS:Envoy可以通过该机制发现使用的上游集群。
·SDS/EDS、CDS和RDS:RDS可以在运行时发现用于HTTP连接管理器过滤器的整个路由配置。
·SDS/EDS、CDS、RDS和LDS:LDS可以在运行时发现整个监听器。这包括所有的过滤器堆栈,包括带有内嵌到RDS的应用的HTTP过滤器。
1.静态配置
我们可以使用Envoy的配置文件指定监听器、路由规则和集群。如下示例提供了一个非常简单的Envoy配置:
static_resources:
listeners:
- name: httpbin-demo
address:
socket_address: { address: 0.0.0.0, port_value: 15001 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
stat_prefix: egress_http
route_config:
name: httpbin_local_route
virtual_hosts:
- name: httpbin_local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
auto_host_rewrite: true
cluster: httpbin_service
http_filters:
- name: envoy.router
clusters:
- name: httpbin_service
connect_timeout: 5s
type: LOGICAL_DNS
# Comment out the following line to test on v6 networks
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
hosts: [{ socket_address: { address: httpbin, port_value: 8000 }}]
在这个简单的Envoy配置文件中,我们声明了一个监听器,它在端口15001上打开一个套接字并为其附加一个过滤器链。过滤器http_connection_manager在Envoy配置中使用路由指令(在此示例中看到的简单路由指令是匹配所有虚拟主机的通配符),并将所有流量路由到httpbin_service集群。配置的最后一部分定义了httpbin_service集群的连接属性。在此示例中,我们指定端点服务发现的类型为LOGICAL_DNS、与上游httpbin服务通信时的负载均衡算法为ROUND_ROBIN。
这是一个简单的配置文件,用于创建监听器传入的流量,并将所有流量路由到httpbin集群。它还指定要使用的负载均衡算法的设置以及要使用的连接超时配置。
你会注意到很多配置是明确指定的,例如指定了哪些监听器,路由规则是什么,我们可以路由到哪些集群等。这是完全静态配置文件的示例。
有关这些参数更多信息的解释,请参阅Envoy的文档(www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/service_discovery#logical-dns)。
在前面的部分中,我们指出Envoy能够动态配置其各种设置。下面将介绍Envoy的动态配置以及Envoy如何使用xDS API进行动态配置。
2.动态配置
Envoy可以利用一组API进行配置更新,而无需任何停机或重启。Envoy只需要一个简单的引导配置文件,该配置文件将配置指向正确的发现服务API,其余动态配置。Envoy进行动态配置的API通常统称为xDS服务,具体包括如下:
·监听器发现服务(LDS):一种允许Envoy查询整个监听器的机制,通过调用该API可以动态添加、修改或删除已知监听器;每个监听器都必须具有唯一的名称。如果未提供名称,Envoy将创建一个UUID。
·路由发现服务(RDS):Envoy动态获取路由配置的机制,路由配置包括HTTP标头修改、虚拟主机以及每个虚拟主机中包含的单个路由规则。每个HTTP连接管理器都可以通过API独立地获取自身的路由配置。RDS配置隶属于监听器发现服务LDS的一部分,是LDS的一个子集,用于指定何时应使用静态和动态配置,以及指定使用哪个路由。
·集群发现服务(CDS):一个可选的API,Envoy将调用该API来动态获取集群管理成员。Envoy还将根据API响应协调集群管理,根据需要添加、修改或删除已知的集群。在Envoy配置中静态定义的任何集群都不能通过CDS API进行修改或删除。
·端点发现服务(EDS):一种允许Envoy获取集群成员的机制,基于gRPC或RESTJSON的API,它是CDS的一个子集;集群成员在Envoy术语中称为端点(Endpoint)。对于每个集群,Envoy从发现服务获取端点。EDS是首选的服务发现机制。
·密钥发现服务(SDS):用于分发证书的API;SDS最重要的好处是简化证书管理。如果没有此功能,在Kubernetes部署中,必须将证书创建为密钥并挂载到Envoy代理容器中。如果证书过期,则需要更新密钥并且需要重新部署代理容器。使用密钥发现服务SDS,那么SDS服务器会将证书推送到所有Envoy实例。如果证书过期,服务器只需将新证书推送到Envoy实例,Envoy将立即使用新证书而无需重新部署。
·聚合发现服务(ADS):上述其他API的所有更改的序列化流;你可以使用此单个API按顺序获取所有更改;ADS并不是一个实际意义上的xDS,它提供了一个汇聚的功能,在需要多个同步xDS访问的时候,ADS可以在一个流中完成。
配置可以使用上述服务中的一个或其中几个的组合,不必全部使用它们。需要注意的一点是,Envoy的xDS API是建立在最终一致性的前提下,正确的配置最终会收敛。例如,Envoy最终可能会使用新路由获取RDS的更新,该路由将流量路由到尚未在CDS中更新的集群。这意味着,路由可能会引入路由错误,直到更新CDS。Envoy引入了聚合发现服务ADS来解决这种问题,而Istio实现了聚合发现服务ADS,并使用ADS进行代理配置的更改。
例如,Envoy代理要动态发现监听器,可以使用如下配置:
dynamic_resources:
lds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
clusters:
- name: xds_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
hosts: [{ socket_address: { address: 127.0.0.3, port_value: 5678 }}]
通过上面的配置,我们不需要在配置文件中显式配置每个监听器。我们告诉Envoy使用LDS API在运行时发现正确的监听器配置值。但是,我们需要明确配置一个集群,这个集群就是LDS API所在的位置,也就是该示例中定义的集群xds_cluster。
图3-6在静态配置的基础上,比较直观地表示出各个发现服务所提供的信息。

图3-6 xDS服务信息