Envoy配置使用

Envoy配置使用

Envoy代理有两个常见用途。一是用作服务代理(sidecar),二是用作网关。

用作sidecar时,Envoy是一个位于服务旁边的四层或七层的应用代理,可以生成指标、应用策略和控制流量。

用作API网关时,Envoy作为一个“前置代理”接受inbound流量,核对请求中的信息并将其定向到目的地。本文的例子将演示如何使用Envoy作为前置代理。我们将编写一个静态配置,返回例如HTTP和IPv4等不会改变的静态数据。正如你将在本例中看到的那样,这一用途很简单,适合处理几乎不变化的信息。

envoy基本请求流程

img
  • listener:与端口绑定并监听到达网关的inbound请求,listener 的监听地址是互斥的,两个 listener 不能监听同一个 socket 地址
  • filter chain:请求被listener接受进入Envoy后应当被如何处理,它由一些filter组成,filter决定请求能否被传递到下一个filter或发生短路。filter chains是network filter,可以有多组。
  • Route:请求通过所有filter后,route将会将请求定向到正确的服务

编写yaml文件

#声明静态资源
static_resources:
  listeners:
    - address:
        socket_address:
          address: 0.0.0.0
          port_value: 8080
      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
                codec_type: auto
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/service/1"
                          route:
                            cluster: service1
                        - match:
                            prefix: "/service/2"
                          route:
                            cluster: service2
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config: {}
  clusters: #设置集群
    - name: service1
      connect_timeout: 0.25s
      type: strict_dns
      lb_policy: round_robin
      http2_protocol_options: {}
      load_assignment:
        cluster_name: service1
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 10.244.1.1
                      port_value: 8000
    - name: service2
      connect_timeout: 0.25s
      type: strict_dns
      lb_policy: round_robin
      http2_protocol_options: {}
      load_assignment:
        cluster_name: service2
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: service2
                      port_value: 8000
admin:
  access_log_path: "/dev/null"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 8001

envoy动态配置方法

Listener、Cluster等除了在配置文件中静态配置,还可以从控制平面动态获取。下发动态配置的服务叫做控制平面,它的地址以cluster的形式在配置文件中静态配置,然后在dynamic_resources中引用这个cluster。可以动态下发的配置主要有:CDS、LDS、EDS、RDS、SDS,其中只有CDS和LDS的发现地址是在dynamic_resources中指定的。

配置文件中使用同样ID和Cluster的envoy才会接受这个控制平面下发的配置。

基于文件方式

基于文件的方式需要在envoy容器中指定xDS的配置文件路径,envoy将使用inotify来监视文件系统的更改,并在更新时解析文件中的DiscoveryResponse原型。

node:
  id: id_1
  cluster: test

dynamic_resources:
  cds_config:
    path: /var/lib/envoy/cds.yaml
  lds_config:
    path: /var/lib/envoy/lds.yaml

admin:
  access_log_path: "/dev/null"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 19000

其中cds_config和las_config内容和静态配置方式内容一样:

#cds内容
resources:
- "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
  name: example_proxy_cluster
  connect_timeout: 1s
  type: strict_dns
  http2_protocol_options: {}
  load_assignment:
    cluster_name: example_proxy_cluster
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: service1
              port_value: 8080
 -----
 
 
 #lds内容
 resources:
- "@type": type.googleapis.com/envoy.config.listener.v3.Listener
  name: listener_0
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 10001
  filter_chains:
  - filters:
      name: envoy.http_connection_manager
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
        stat_prefix: ingress_http
        http_filters:
        - name: envoy.router
        route_config:
          name: local_route
          virtual_hosts:
          - name: local_service
            domains:
            - "*"
            routes:
            - match:
                prefix: "/"
              route:
                cluster: example_proxy_cluster

使用这种方式,虽说可以动态修改envoy路由,但仍需要手动更改xds配置文件,并且每次修改后需要重新启动envoy才能刷新。

基于控制平面方式

用XDS下发配置

首先在配置文件中静态配置控制平面的地址,然后在cds_config和lds_config中引用前面配置的xds_cluster。

dynamic_resources:
  cds_config:
    api_config_source:
      api_type: GRPC
      grpc_services:
        envoy_grpc:
          cluster_name: xds_cluster
  lds_config:
    api_config_source:
      api_type: GRPC
      grpc_services:
        envoy_grpc:
          cluster_name: xds_cluster

用ADS下发配置

Cds_config和las_config是分开的,这意味着cluster和listener配置可以从不同的控制平面获取,这样会遇到配置不同步的问题,即时他们用的是同一个控制平面也可能因为到达次序不同而不同步。譬如 listenerA 中使用了 clusterA,但是 listenerA 的配置可能在 clusterA 之前下发到 envoy ,使 envoy 认为 listenerA 使用了一个不存在的 clusterA。

ADS 支持所有类型动态配置的下发,并且会处理配置间的依赖,保证配置的下发顺序,是优先选用的配置发现方法,实现原理见配置下发协议的说明 xDS REST and gRPC protocol

node:
  cluster: test-cluster
  id: test-id

dynamic_resources:
  ads_config:
    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
    http2_protocol_options: {}
    name: xds_cluster
    load_assignment:
      cluster_name: xds_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: go-control-plane
                port_value: 18000

admin:
  access_log_path: /dev/null
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 19000

envoy 的 lds/cds/rds/sds/eds

dynamic_resources 配置中只有 lds_configcds_configads_config,分别对应 listenter、cluster 和聚合发现。但可以动态下发的配置不只有 listener 和 cluster。

cluster 中的 endpoint、tls 用到的 secret、HttpConnectionManager 中用到 route 也可以动态下发,对应的发现服务分别是 edssdsrds。这些发现服务不在 dynamic_resources 中配置,而是独立配置或者在用到它们的 filter 中配置。

控制平面实现

Go-control-plane的基本用法

go-control-plane 是一个框架,提供了配置下发接口,在它的基础上根据自己的需要开发其它功能。

动态配置是关联到 envoy 的 ,每个 envoy 的动态配置都要单独维护。

在 envoy 的配置文件中有一段 node 配置,标注了当前 envoy 所属的 cluster 和 id,envoy 只接受使用同样的 cluster 和 id 的动态配置,使用 go-control-plane 实现的控制平面要为每个 envoy 实例维护一份配置:

node := &core.Node{
    Id:      "envoy-64.58",
    Cluster: "test",
}

node_config := &NodeConfig{
    node:      node,
    endpoints: []cache.Resource{}, //[]*api_v2.ClusterLoadAssignment
    clusters:  []cache.Resource{}, //[]*api_v2.Cluster
    routes:    []cache.Resource{}, //[]*api_v2.RouteConfiguration
    listeners: []cache.Resource{}, //[]*api_v2.Listener
}

Go-control-plane中filter定义与下发

Listener是envoy中最复杂的配置,其中filter又是Listerner中最繁琐的。从 socket 中收取的请求先经过 listener_filters 处理,然后再由 filter_chains 处理,前者包含的 filter 称为 listener filter,后者包含的 filter 称为 network filter。因为 listener_filters 先起作用,因此它可以修改请求的信息,从而影响 filter_chains 的匹配。filter一共有以下几大类:

Listener filters
Network filters
HTTP filters
Thrift filters
Common access log types
Common fault injection types
Dubbo filters

Filter 是填充在 listener 中作为 listener 配置下发的,listener 在 go-control-plane/envoy/api/v2/lds.pb.go中定义,filter 的接口在 envoy/api/v2/listener/listener.pb.go 中定义,filter 的实现在 go-control-plane/envoy/config/filter/

posted @ 2022-03-08 09:48  尹瑞星  阅读(2643)  评论(0编辑  收藏  举报