🌟

envoy - 说明文档

介绍

Envoy 是一款 CNCF 旗下的开源项目,由 Lyft 开源。Envoy 采用 C++ 实现,是面向 Service Mesh 的高性能网络代理服务。它与应用程序并行运行,通过以平台无关的方式提供通用功能来抽象网络。当基础架构中的所有服务流量都通过 Envoy 网格时,通过一致的可观测性,很容易地查看问题区域,调整整体性能。
Envoy 也是 Istio Service Mesh 中默认的 Data Plane,本文我们将讲解 Envoy 的一些基本概念,并采用一些实例来介绍如何在本地环境中快速使用 Envoy 作为 Service Mesh 的数据平面,以帮助读者理解 IstioData Panel 层实现。
官网:https://www.envoyproxy.io
 

Envoy 特性

整体架构

notion image

进程无关架构

Envoy 是一个自组织的模块,与应用 Server 并无直接依赖。所有的 Envoy 构建了一个透明的服务网格 Service Mesh,处于其中的应用只需要简单的与本地的 Envoy 进行收发信息,并不需要关注整个网络拓扑。这种架构对于应用通信有两大好处:
  • Envoy 可以让任何的编程语言编写的服务通信,协同工作,Envoy 帮你屏蔽了服务之间的沟壑。
  • 任何曾经在大型微服务开发中工作过的人都知道发布一个库更新是多么的痛苦。Envoy 可以以一种透明的方式快速的发布更新整个基础架构中的版本。

高级负载均衡

分布式系统中不同模块间的负载均衡是一个复杂的问题。因为 Envoy 是一个自组织的代理,所以它能在一个地方实现高级负载均衡技术并使他们可被访问。当前 Envoy 支持自动重试、断路器、全局限速、阻隔请求、异常检测,将来还会支持按计划进行请求速率控制。

动态配置

Envoy 提供了可选的一系列的分层的动态配置 API,使用这些 API 可以构建出复杂的集中式部署管理。

正向代理支持

虽然 Envoy 设计初衷是服务和服务之间通信系统,得益于其监视、管理、服务发现和负载均衡算法的实现,Enovy 包含了足够多的特性为绝大多数 Web 服务做正向代理。
除了这些之外还有对 HTTP/2 的支持,L3L4L7 代理,可以实现 TCP ProxyHTTP Proxy 等功能。

线程模型

Envoy 使用单进程多线程架构,其中一个扮演主线程的控制各种协调任务,而一些工作线程负责监听、过滤和转发。一旦某个链接被监听器 Listener 接受,那么这个链接将会剩余的生命周期绑定在这个 Woker 线程。这种架构会使得大部分工作工作在单线程的情况下,只有少量的工作会涉及到线程间通信,Envoy 代码是 100% 非阻塞的。

Listener 监听器

  • 一个 Envoy 进程可以设置多个不同的 Listener,建议一台机器只使用一个 Envoy 实例。
  • 每一个 Listener 的网络层 L3/L4 过滤器是独立配置的。并且一个 Listener 是可以通过配置来完成多种任务的,比如:访问限制、TLS 客户端校验、HTTP 链接管理等。
  • Listener 也有自己的非网络层过滤器,它可以修改链接的 Metadata 信息,通常用来影响接下来链接是如何被网络层过滤器处理的。
  • 无论网络层过滤器还是 Listener 过滤器都可以提前终止后续的过滤器链的执行。
  1. HTTP 连接管理器
  • Envoy 是完整支持 HTTP/1.1WebsocketsHTTP/2,不支持 SPDY
  • 这层过滤器主要是将原始的传递数据转变成 HTTP 层级的信息和事件,如收到 Headers、收到 Body 数据,同样它也可以做接入日志、Request ID 生成和追踪、Req/Res 头部修改工作、路由表管理、统计分析。
  • 每一个 HTTP 链接管理器有一个相匹配的路由表,路由表可以静态指定,也可以动态地通过 RDS API 来设置 route-dynamic
  • 其内部还有 HTTP 过滤器,可以支持在 HTTP 层级。在无需关注使用什么协议 (HTTP/1.1HTTP/2) 实现的情况下进行操作 HTTP 内容,支持 EncodeDecodeEncode/Decode 三种不同类型过滤器。

HTTP 路由器

  • 经常用在做边缘/反向代理和构建内部 Envoy Mesh 发挥巨大作用。
  • HTTP 路由器可以支持请求重试配置:最大重试次数和设置重试条件,比如某些 5XX 错误和具有幂等性操作的 4XX 错误。
  • Envoy 自己使用 HTTP/2 链接管理器实现了 gRPC 协议,将原来官方的 Google gRPC 内置的很多功能,比如重试、超时、Endpoint 发现、负载均衡、负载报告、健康检查等功能都实现了。将来除非特殊特性必须,都可以使用 Envoy gRPC 来实现。

Cluster 管理器

Cluster 管理器暴露 API 给过滤器,并允许过滤器可以得到链接到上游集群的 L3/L4 链接或者维持一个抽象的 HTTP 连接池用来链接上游集群(上游主机支持 HTTP 1.1 还是 HTTP 2 都是被隐藏的)。过滤器决定是使用 L3/L4 链接还是 HTTP Stream 来链接上游集群。而对于集群管理器来说,它负责所有集群内主机的可用性、负载均衡、健康度、线程安全的上游链接数据,上游链接类型 TCP/UPUDS,上游可接受的协议 HTTP 1.1/2
Cluster 管理器既可以静态配置,也可以使用 CDS-Cluster-Discovery-Service API 来动态配置。集群在正式使用之前有一个 “加热” Warming 的过程:先做服务发现必要的初始化,比如 DNS 记录更新、EDS 更新,然后进行健康检查,当进行完上述的过程,会进入Becoming available 状态,这个阶段 Envoy 不会把流量指向它们; 在更新集群时,也不会把正在处理流量的集群处理掉,而是用新的去替换老的那些还未进行任何流量的集群。

与 Nginx 的区别

  • EnvoyHTTP/2 的支持比 Nginx 更好,支持包括 upstreamdownstream 在内的双向通信,而 Nginx 只支持 downstream 的连接。
  • 高级负载均衡功能是免费的,Nginx 的高级负载均衡功能则需要付费的 Nginx Plus 支持。
  • Envoy 支持热更新,Nginx 配置更新之后需要 Reload
  • Envoy 更贴近 Service Mesh 的使用习惯,Nginx 更贴近传统服务的使用习惯。

Envoy 术语

要深入理解 Envoy,首先需要先了解一下 Envoy 中的一些术语。
notion image
  • Host:能够进行网络通信的实体(如服务器上的应用程序)。
  • Downstream:下游主机连接到 Envoy,发送请求并接收响应。
  • Upstream:上游主机接收来自 Envoy 连接和请求并返回响应。
  • Listener:可以被下游客户端连接的命名网络(如端口、Unix 套接字)。一般是每台主机运行一个 Envoy,使用单进程运行,但是每个进程中可以启动任意数量的 Listener(监听器),每个监听器都独立配置一定数量的( L3/L4 )网络过滤器。
  • ClusterEnvoy 连接到的一组逻辑上相似的上游主机。
  • Mesh:以提供一致的网络拓扑的一组主机。
  • Runtime Configuration:与 Envoy 一起部署的外置实时配置系统。
  • Listener FilterListener 使用 Listener Filter(监听器过滤器)来操作链接的元数据,它的作用是在不更改 Envoy 的核心功能的情况下添加更多的集成功能。
  • Http Route TableHTTP 的路由规则,例如请求的域名,Path 符合什么规则,转发给哪个 Cluster

静态部署

  • 配置文件 envoy.yaml
    • admin: access_log_path: /tmp/admin_access.log address: socket_address: { address: 127.0.0.1, 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.http_connection_manager config: 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.router clusters: - name: some_service connect_timeout: 0.25s type: STATIC lb_policy: ROUND_ROBIN hosts: [{ socket_address: { address: 127.0.0.1, port_value: 80 }}]
  • 创建容器
    • 创建envoy
      • docker run -d -p 10000:10000 -v `pwd`/envoy.yaml:/etc/envoy/envoy.yaml \ --name envoyproxy_1002a_1 10.30.38.116/uos-1002a/envoy:v1.14.0
    • 创建nginx
      • docker run -d --network=container:envoyproxy_1002a_1 --name envoyproxy_1002a_1 nginx
         
  • 验证
    • web访问 10000端口
      notion image