3.3.3 Envoy静态与动态配置

如前面章节所述,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服务信息