基于Envoy的服务发现

Envoy Service Discovery

Posted by alovn on April 5, 2021

服务网格(Service Mesh)是微服务的基础架构,它是微服务的通信层。每个服务都有自己的Sidecar(代理服务),服务实例直接不会直接互相调用,每个往返于服务之间的请求都经过Sidecar。假如服务A要调用服务B,它不会直接调用目标服务,而是由服务A先将请求路由到本地代理,再由本地代理将请求路由到目标服务,所有的代理服务组合在一起,就形成了服务网格。

1
2
3
4
ProxyA---------->ProxyB
   ↑               ↑
   |               ↓
ServiceA        ServiceB

Envoy可作为服务网格中边缘代理的一个选择,但不是唯一的选择,类似的产品还有nginx、Traefik等。

Envoy还提供了负载均衡、服务发现、限流、熔断、分布式追踪、认证等功能,可以避免将这些功能耦合到业务代码中,。

Envoy中的术语

  • Host: 进行网络通信的实体。
  • Downstream: 连接到Envoy的下游主机,发送请求并接收响应。
  • Upstream:上游主机,接受来自Envoy的连接与请求并返回响应。
  • Listener:可被下游客户端连接的网络,如端口、unix套接字。
  • Cluster:Envoy连接的上游主机集群。
  • XDS:即 * Discovery Service, 提供动态配置的API接口,如
    • EDS(Endpoint Discovery Service) 发现upstream服务
    • CDS(Cluster Discovery Service) 发现upstream cluster,可动态更新cluster
    • RDS(Route Discovery Service) 发现路由规则
    • VHDS(Virtual Host Discovery Service) 发现虚拟主机
    • LDS(Listener Discovery Service) 发现动态的Listener配置,含所有filter配置
    • SDS(Secret Discovery Service) 发现listener上配置的秘钥,如证书私钥等
    • SRDS(Scoped Route Discovery Service) 将route table切分为几个小块。
    • RTDS(RunTime Discovery Service)
    • ECDS(Extension Config Discovery Service)
    • ADS(Aggregated Discovery Service) 即将CDS/EDS/LDS/RDS等动态配置聚合为一个ADS

启动Envoy

Envoy 通过指定 -c 参数指定配置文件,Envoy的配置分为两种:静态配置和动态配置。

  • 静态配置: 所有的信息都放在配置文件中,配置指定该Envoy进程属于哪个cluster,在启动时加载。
  • 动态配置:配置XDS,然后通过一个Envoy的服务端动态提供Envoy需要的服务发现接口。

启动:

1
envoy -c envoy.yaml

静态配置

envoy-static.yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
admin: # 管理端
  access_log_path: /var/log/envoy/envoy_admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources: # 静态配置
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 } # 监听端口
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" } # 路由匹配规则
                route: { cluster: some_service } # 路由到的服务集群
          http_filters:
          - name: envoy.filters.http.router
  clusters:
  - name: some_service
    connect_timeout: 0.25s
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: some_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 172.16.10.13 # 直接指定后端服务
                port_value: 3000

Envoy启动后,就可以通过Envoy的10000端口访问到后端 172.16.10.13:3000 提供的服务。

动态配置

动态配置是通过一个 EDS(Endpoint Dicovery Service) 服务动态提供服务发现。ADS则聚合了EDS、CDS、LDS等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
node:
  cluster: test-cluster
  id: test-id

dynamic_resources: # 动态配置
  ads_config: # ADS聚合
    api_type: GRPC
    transport_api_version: V3
    grpc_services:
    - envoy_grpc:
        cluster_name: xds_cluster
  cds_config:
    resource_api_version: V3
    ads: {}
  lds_config:
    resource_api_version: V3
    ads: {}

static_resources:
  clusters:
  - connect_timeout: 1s
    type: STRICT_DNS
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    name: xds_cluster
    load_assignment:
      cluster_name: xds_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 172.16.10.15 # EDS服务
                port_value: 18000

admin:
  access_log_path: /var/log/envoy/envoy_admin_access.log
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 19000

然后再使用 go-control-plane 提供XDS服务。go-control-plane 是Envoy提供的开发库,基于它可以方便的实现基于gRPC协议的服务发现,XDS在协程中接收并处理来自Envoy的gRPC请求。这样XDS通过一系列的gRPC接口实现了为Envoy动态提供配置的功能。

代码有点多,就不帖这里了,可到github查看: Demo