0. 简介

官网地址: www.envoyproxy.io/

Envoy 是一款 CNCF 旗下的开源项目. Envoy 选用 C++ 实现,是面向 Service Mesh 的高性能网络署理服务. Envoy 署理能够供给以下功用:

  • 负载均衡:envoy 署理能够依据不同的算法和战略,将流量分配到上游的服务或运用.
  • 服务发现:envoy 署理能够动态地发现上游的服务或运用,无需手动装备.
  • 路由:envoy 署理能够依据恳求的属性,如路径、头部、参数等,将流量路由到不同的目标.
  • 观察性:envoy 署理能够搜集和陈述各种目标,如延迟、吞吐量、错误率等,以及生成拜访日志和追踪信息.
  • 安全性:envoy 署理能够支撑多种协议和机制,如 TLS、mTLS、JWT、OAuth2 等,来保证流量的安全性和身份验证.

Envoy 署理能够以 sidecar 的形式布置在每个服务或运用的周围,形成一个通明的通讯网格,也能够以边际署理或 API 网关的形式布置在系统的鸿沟,处理入站或出站的流量. envoy 署理能够经过动态(XDS)装备来习惯不同的场景和需求,而无需重启或修正.

1. 快速开端

1.1 重要概念

  • 署理(Proxy):Envoy 是一个署理服务器,坐落客户端和后端服务之间,用于处理网络流量的转发和办理。它能够作为边际署理、通明署理或双向署理,经过阻拦恳求和呼应来供给一些功用,如负载均衡、流量操控、故障康复和安全性。

  • 过滤器(Filter):Envoy 的中心功用是经过过滤器链处理恳求和呼应。每个过滤器能够履行特定的使命,如鉴权、路由、日志记载、监控等。过滤器链中的过滤器依照次序依次处理网络流量,并且每个过滤器能够修正恳求或呼应的内容。

  • 上游和下流(Upstream and Downstream):在 Envoy 中,上游(Upstream)表明客户端或恳求的来源,而下流(Downstream)表明后端服务或呼应的目标。Envoy 署理作为客户端与上游服务进行通讯,一起作为服务器与下流服务进行通讯。

  • 集群(Cluster):Envoy 将多个后端服务组织为一个逻辑集群。集群中的每个成员都具有相同的服务接口,Envoy 能够依据负载均衡战略将恳求分发给集群中的成员。

  • 路由(Routing):Envoy 供给了灵活的路由装备,能够依据恳求的特征将流量转发到不同的后端服务。路由规矩能够基于恳求的路径、主机、头部信息等进行匹配和过滤,以确认恳求应该转发到哪个集群或服务。

  • 端点(Endpoint) 是指后端服务的网络地址和端口。每个后端服务都被视为一个 Endpoint。

  • 动态装备(XDS):Envoy 能够动态地更新路由规矩和负载均衡战略,

  • 健康查看(Health Checking):Envoy 能够定期对后端服务进行健康查看,以确认服务的可用性。健康查看能够运用不同的协议和方法,如 TCP、HTTP、gRPC,以及自定义的查看逻辑。依据健康查看结果,Envoy 能够主动排除不可用的服务节点。

  • TLS(Transport Layer Security):Envoy 供给了对传输层安全性的支撑,能够运用 TLS 加密和认证来保护网络通讯。它能够装备双向认证(即客户端和服务端都要验证对方身份)以及传输层加密,保证通讯的机密性和完好性

1.2 运转瞧瞧

参阅文档: www.envoyproxy.io/docs/envoy/…

  • 发动 envoy 咱们需求先预备一个测验服务, 这儿选用 nginx, 接下来都会运用 docker 进行布置envoy.

    # docker run --name ngxv1 -d  nginx:1.18-alpine
    
  • 因为咱们需求运用 envoy 进行署理流量转发到 nginx 上, 所以需求知道 nginx 的 ip.

    # docker inspect ngxv1 # 获取 ip 地址
    
  • 编写 envoy.yaml, 装备后续会再做详细解释, 先跑起来再说;

    admin:
      # 办理后台的监听地址, 这是一个简易的ui界面
      address:
        socket_address: { address: 0.0.0.0, port_value: 9901 }
    static_resources:
      listeners:
          # 发动一个监听器
        - name: listener_0
          # 监听地址 0.0.0.0:8080
          address:
            socket_address:  { address: 0.0.0.0, port_value: 8080 }
          # 过滤链, 这是 envoy 的重中之重  
          filter_chains:
            - filters:
                - name: envoy.filters.network.http_connection_manager
                  # typed_config 是一个插件调用的要害字
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                    stat_prefix: ingress_http
                    codec_type: AUTO
                    # 由 HttpConnectionManager 插件供给的路由装备
                    route_config:
                      name: shadow_route
                      # 装备虚拟主机
                      virtual_hosts:
                        - name: myhost
                          # 匹配的主机头
                          domains: ["*"]
                          routes:
                              # 路由匹配
                            - match: {prefix: "/"}
                              # 路由到上游集群, 即下方装备的 cluster
                              route: {cluster: shadow_cluster_config}
                    # 启用http链
                    http_filters:
                       # 启用路由链
                      - name: envoy.filters.http.router
      clusters:
        # 装备静态集群
        - name: shadow_cluster_config
          connect_timeout: 1s
          type: Static
          dns_lookup_family: V4_ONLY
          lb_policy: ROUND_ROBIN
          load_assignment:
            cluster_name: shadow_cluster
            endpoints:
              - lb_endpoints:
                 # 装备端点
                  - endpoint:
                      address:
                        socket_address:
                          # 需求修正为 ngxv1 的 ip
                          address: 172.17.0.5
                          # 署理端口
                          port_value: 80
    
  • 选用 docker 快速装置, 先进行镜像下载

    # docker pull envoyproxy/envoy-alpine:v1.21.0
    
  • 发动 docker 镜像, 把装备映射进去方便后续对 envoy.yaml 进行调整

    # docker run --name=envoy -d -p 9901:9901 -p 8081:8080 -v /opt/envoy/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy-alpine:v1.21.0
    
  • 从主机上进行测验, 测验经过证明你已经是经过 envoy 反向署理了你布置的 nginx.

    # curl 127.0.0.1:8081 # 测验是否能拜访 nginx
    # curl 127.0.0.1:9901 # 测验是否能拜访 admin
    

2. 授人以渔

官方文档: www.envoyproxy.io/docs/envoy/…

2.1 原理简介

[K8S] Envoy 入门介绍 (1)

  • 从上图能够看出恳求的流量经过监听器进入, 然后会经过一系列的 Filter 的处理, 而在每种 Filter 中其实会支撑不同的插件装备 (在装备中体现为 typed_config.@type). 从 Filter 中出来后便会路由到集群(Cluster), 最终抵达 Endpoint (图中的 Service).

2.2 文档导读

  • 在第一章节的描绘中,咱们开端了解了 Envoy 的一些重要概念。从上述的 envoy.yaml 装备中,咱们能够感受到 Envoy 的装备相对较为复杂。一起,Envoy 被广泛认为是一项具有挑战性的署理使命之一,其学习曲线也相应地峻峭。此外,初学者可能会发现 Envoy 的文档索引令人困惑,难以精确找到所需的信息并进行正确的装备。因此,在本章节中,咱们将经过装备2个案例来帮助您更好地查询文档并正确进行装备。

2.2.1 Accesslog 装备

  • 本示例展现怎么装备 access_log, 以及怎么查找相应的示例和参数; 从下方装备能够看到, 咱们需求先装备 http_connection_manager 过滤器, 然后再往下装备 access_log 字段, 继续往下装备envoy.access_loggers.stdout 扩展插件, 插件指出把日志输出到终端上.

  • 从下方装备你能够看到 filters 其实能够理解为 4层 (TCP、UDP等) 装备, 而 http_filters 则是 http_connection_manager 下表明装备 7 层的 http 相关功用, 在 http_filters 中装备了 envoy.filters.http.router 插件;

    static_resources:
      listeners:
      - 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
              codec_type: AUTO
              stat_prefix: ingress_http
              access_log:
              - name: envoy.access_loggers.stdout
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
              route_config:
                name: local_route
                virtual_hosts:
                - name: services
                  domains:
                  - "*"
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      cluster: frontend_service
              http_filters:
              - name: envoy.filters.http.router
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
      clusters:
      - name: frontend_service
        type: STRICT_DNS
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: frontend_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: frontend-service
                    port_value: 8080
    
  • 接下来,咱们将介绍怎么从文档中找出这些参数并进行正确装备。首要,让咱们先来了解一下装备概览页面。您能够参阅下面的概览页面. 你能够再下图表明 [1] ,该示意图展现了一些根底装备的概览,有助于您进行学习的展开。

    [K8S] Envoy 入门介绍 (1)

  • 在上述装备咱们看到了3种扩展插件(以typed_config.@type来表明的), 姓名分别是 envoy.filters.network.http_connection_managerenvoy.filters.http.routerenvoy.access_loggers.stdout. 接下来咱们将一一在文档中找出这些装备并且从中大致了解怎么寻觅装备.

  • envoy.filters.network.http_connection_manager, 截图内只截取了咱们上述装备的要害装备.

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

  • 咱们开端寻觅这个 envoy.access_loggers.stdout 扩展, 联接上图的标识 [5].

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

  • 接下来寻觅最终一个扩展 envoy.filters.http.router, 需求联接 Http connection manager 图的标识 [4] 描绘的 http_filters.

[K8S] Envoy 入门介绍 (1)

[K8S] Envoy 入门介绍 (1)

[K8S] Envoy 入门介绍 (1)

  • envoy.filters.http.router 扩展中咱们并没有装备任何的字段, 为什么呢? 在上图中有个 configuration overview

    [K8S] Envoy 入门介绍 (1)

    官方文档:

    envoy.filters.network.http_connection_manager

    envoy.filters.http.router

    envoy.access_loggers.stdout

2.2.2 Cors 插件装备

  • 经过上一章节的装备, 应该对 envoy 文档怎么进行查阅的技巧有所明白. 接下来再用一个跨域插件装备的例子进一步的稳固一下怎么进行查阅.

  • 跨域装备在 envoy 有好几种方法, 我这儿装备跨域装备插件只是朴实为了演示, 不一定再装备跨域时按着我的装备.

  • 众所周知 cors 的装备属于http 范畴, 所以咱们应该能够想到直接寻觅 http_filters.

  • 先看看装备

    static_resources:
      listeners:
      - 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
              codec_type: AUTO
              stat_prefix: ingress_http
              access_log:
              - name: envoy.access_loggers.stdout
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
              route_config:
                name: local_route
                virtual_hosts:
                - name: www
                  domains:
                  - "*"
                  typed_per_filter_config:
                    # 装备大局跨域
                    envoy.filters.http.cors:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy
                      allow_origin_string_match:
                      - safe_regex:
                          regex: \*
                      allow_methods: "GET"
                      filter_enabled:
                        default_value:
                          numerator: 100
                          denominator: HUNDRED
                        runtime_key: cors.www.enabled
                      shadow_enabled:
                        default_value:
                          numerator: 0
                          denominator: HUNDRED
                        runtime_key: cors.www.shadow_enabled
                  routes:
                  - match:
                      prefix: "/cors/open"
                    route:
                      cluster: backend_service
                  - match:
                      prefix: "/cors/disabled"
                    route:
                      cluster: backend_service
                    typed_per_filter_config:
                      # 单一匹配后进行跨域操控
                      envoy.filters.http.cors:
                        "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy
                        filter_enabled:
                          default_value:
                            numerator: 0
                            denominator: HUNDRED
                  - match:
                      prefix: "/cors/restricted"
                    route:
                      cluster: backend_service
                    typed_per_filter_config:
                     # 单一匹配后进行跨域操控
                      envoy.filters.http.cors:
                        "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy
                        allow_origin_string_match:
                        - safe_regex:
                            regex: .*\.envoyproxy\.io
                        allow_methods: "GET"
                  - match:
                      prefix: "/"
                    route:
                      cluster: backend_service
              http_filters:
              # 启用跨域装备插件
              - name: envoy.filters.http.cors
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
              - name: envoy.filters.http.router
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
      clusters:
      - name: backend_service
        type: STRICT_DNS
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: backend_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: backend-service
                    port_value: 8080
    
  • 开端寻觅文档中怎么装备

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    [K8S] Envoy 入门介绍 (1)

    官方文档: envoy.filters.http

3. 参阅

  • www.envoyproxy.io/docs/envoy/…
  • github.com/envoyproxy/…

4. 写在最终

  • 经过今日的文章, 你应该大致了解 envoy 的装备以及一些根底概念; 后续我还会继续编写 envoy 相关的文章形成相对完好的入门系列:

    • Envoy 作为 Sidecar 接管 Pod 的流量 [2]
    • Envoy XDS 入门 (Golang) [3]
    • Envoy wasm 插件入门 (Golang) [4]
  • Envoy 的装备的确挺复杂, 特别刚开端接触文档会非常头晕被绕来绕去的. envoy 的复杂度其实大约来自两点, 一是来自envoy的强壮灵活性, 二是咱们自身对各类传输协议的了解缺乏;

  • 点赞、关注➕、收藏、留言. 下篇文章见