一文了解Envoy配置文件

# 简介

Envoy 是一个基于 C++实现的云原生高性能代理服务器。

首先,我想要介绍的是:Envoy 不是开箱即用的软件。它不是面向普通用户的,甚至不是面向运维人员的。所以它的配置文件相对 Nginx 来说会复杂很多。实际上我认为它就是面向开发人员的。

# 配置

Envoy 配置的基本逻辑是

  1. Listener 定义监听地址和端口
  2. Listener 附加 filter_chains 实现具体需求

# 一个最小配置

这时它就是一个开启了 8081 端口的 TCP 服务器,但没有任何功能

admin:
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9901

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          protocol: TCP
          address: 0.0.0.0
          port_value: 8081
      filter_chains: [{}]

# 一个 HTTP 反向代理配置

  1. 在 Listener 的 filter_chains 里面添加一个 http_connection_manager 的 filter
  2. 配置 http_connection_manager 的 route_config
  3. route_config 里配置一个目标 cluster
  4. Clusters 里定义一个 Cluster(类似 Nginx 的 upstream)
  5. 每个 Cluster 包含一组 Endpoints,支持负载均衡
admin:
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9901

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          protocol: TCP
          address: 0.0.0.0
          port_value: 8081
      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: saltbo
                http_filters:
                  - name: envoy.filters.http.router
                route_config:
                  name: saltbo
                  virtual_hosts:
                    - name: saltbo
                      domains: ["*"]
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            host_rewrite_literal: saltbo.cn
                            cluster: saltbo

  clusters:
    - name: saltbo
      connect_timeout: 0.3s
      type: STRICT_DNS
      dns_lookup_family: V4_ONLY
      load_assignment:
        cluster_name: saltbo
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: saltbo.cn
                      port_value: 80

# 给反向代理加个访问日志

为方便理解,已去除无关配置

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          protocol: TCP
          address: 0.0.0.0
          port_value: 8081
      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: saltbo
                access_log:
                  - name: envoy.access_loggers.stdout
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
                  - name: envoy.access_loggers.file
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
                      path: "/tmp/access.log"
                http_filters:
                  - name: envoy.filters.http.router

可以看到,新增了一个 access_log 字段,这个字段的配置仔细观察的话会发现跟 filter 的配置很像。 从这里可以了解到,Envoy 是通过 protobuf 来管理 api 的,filter 的配置基本都是通过@type 指定一个 protobuf 的地址。

# 动态配置

上面讲的都是静态配置。实际上在 Envoy 中只会用到少量的静态配置,因为它的配置太复杂了,如果全部用静态配置会很麻烦。所以它还有一个动态配置,然后它定义了一个 xDS 协议,通过这个协议可以实现动态的对配置进行变更。下面就是一个简单的动态配置例子: envoy.yaml

dynamic_resources:
  lds_config:
    path: /etc/envoy/lds.yaml
  cds_config:
    path: /etc/envoy/cds.yaml

/etc/envoy/lds.yaml

resources:
  - "@type": type.googleapis.com/envoy.config.listener.v3.Listener
    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
            http_filters:
              - name: envoy.filters.http.router
            route_config:
              name: local_route
              virtual_hosts:
                - name: local_service
                  domains:
                    - "*"
                  routes:
                    - match:
                        prefix: "/"
                      route:
                        cluster: example_proxy_cluster

/etc/envoy/cds.yaml

resources:
  - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
    name: example_proxy_cluster
    type: STRICT_DNS
    load_assignment:
      cluster_name: example_proxy_cluster
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: service1
                    port_value: 8080

可以看到,这是一个基于文件的 xds 例子,这只是为了方便测试与理解。

实际使用中,我们是使用如下配置:

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:
    - 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: go-control-plane
                      port_value: 18000

这种方式就是真实场景了,我们需要自行开发一个服务来管理 xds,详见:官方文档 (opens new window)

# xDS 对应关系

  • LDS:Listener
  • RDS:Route
  • EDS:Endpoint
  • CDS:Cluster
  • ADS:Aggreate
  • SDS:Secret
  • HDS:Health