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

进程无关架构
Envoy 是一个自组织的模块,与应用 Server 并无直接依赖。所有的 Envoy 构建了一个透明的服务网格 Service Mesh,处于其中的应用只需要简单的与本地的 Envoy 进行收发信息,并不需要关注整个网络拓扑。这种架构对于应用通信有两大好处:Envoy可以让任何的编程语言编写的服务通信,协同工作,Envoy帮你屏蔽了服务之间的沟壑。
- 任何曾经在大型微服务开发中工作过的人都知道发布一个库更新是多么的痛苦。
Envoy可以以一种透明的方式快速的发布更新整个基础架构中的版本。
高级负载均衡
分布式系统中不同模块间的负载均衡是一个复杂的问题。因为
Envoy 是一个自组织的代理,所以它能在一个地方实现高级负载均衡技术并使他们可被访问。当前 Envoy 支持自动重试、断路器、全局限速、阻隔请求、异常检测,将来还会支持按计划进行请求速率控制。动态配置
Envoy 提供了可选的一系列的分层的动态配置 API,使用这些 API 可以构建出复杂的集中式部署管理。正向代理支持
虽然
Envoy 设计初衷是服务和服务之间通信系统,得益于其监视、管理、服务发现和负载均衡算法的实现,Enovy 包含了足够多的特性为绝大多数 Web 服务做正向代理。除了这些之外还有对
HTTP/2 的支持,L3、L4、L7 代理,可以实现 TCP Proxy、HTTP Proxy 等功能。线程模型
Envoy 使用单进程多线程架构,其中一个扮演主线程的控制各种协调任务,而一些工作线程负责监听、过滤和转发。一旦某个链接被监听器 Listener 接受,那么这个链接将会剩余的生命周期绑定在这个 Woker 线程。这种架构会使得大部分工作工作在单线程的情况下,只有少量的工作会涉及到线程间通信,Envoy 代码是 100% 非阻塞的。Listener 监听器
- 一个
Envoy进程可以设置多个不同的Listener,建议一台机器只使用一个Envoy实例。
- 每一个
Listener的网络层L3/L4过滤器是独立配置的。并且一个Listener是可以通过配置来完成多种任务的,比如:访问限制、TLS 客户端校验、HTTP 链接管理等。
Listener也有自己的非网络层过滤器,它可以修改链接的Metadata信息,通常用来影响接下来链接是如何被网络层过滤器处理的。
- 无论网络层过滤器还是
Listener过滤器都可以提前终止后续的过滤器链的执行。
- HTTP 连接管理器
Envoy是完整支持HTTP/1.1、Websockets和HTTP/2,不支持SPDY。
- 这层过滤器主要是将原始的传递数据转变成
HTTP层级的信息和事件,如收到Headers、收到Body数据,同样它也可以做接入日志、Request ID生成和追踪、Req/Res头部修改工作、路由表管理、统计分析。
- 每一个
HTTP链接管理器有一个相匹配的路由表,路由表可以静态指定,也可以动态地通过RDS API来设置route-dynamic。
- 其内部还有
HTTP过滤器,可以支持在HTTP层级。在无需关注使用什么协议 (HTTP/1.1或HTTP/2) 实现的情况下进行操作HTTP内容,支持Encode、Decode、Encode/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/UP、UDS,上游可接受的协议 HTTP 1.1/2。Cluster 管理器既可以静态配置,也可以使用 CDS-Cluster-Discovery-Service API 来动态配置。集群在正式使用之前有一个 “加热” Warming 的过程:先做服务发现必要的初始化,比如 DNS 记录更新、EDS 更新,然后进行健康检查,当进行完上述的过程,会进入Becoming available 状态,这个阶段 Envoy 不会把流量指向它们; 在更新集群时,也不会把正在处理流量的集群处理掉,而是用新的去替换老的那些还未进行任何流量的集群。与 Nginx 的区别
Envoy对HTTP/2的支持比Nginx更好,支持包括upstream和downstream在内的双向通信,而Nginx只支持downstream的连接。
- 高级负载均衡功能是免费的,
Nginx的高级负载均衡功能则需要付费的Nginx Plus支持。
Envoy支持热更新,Nginx配置更新之后需要Reload。
Envoy更贴近Service Mesh的使用习惯,Nginx更贴近传统服务的使用习惯。
Envoy 术语
要深入理解
Envoy,首先需要先了解一下 Envoy 中的一些术语。
Host:能够进行网络通信的实体(如服务器上的应用程序)。
Downstream:下游主机连接到Envoy,发送请求并接收响应。
Upstream:上游主机接收来自Envoy连接和请求并返回响应。
Listener:可以被下游客户端连接的命名网络(如端口、Unix套接字)。一般是每台主机运行一个Envoy,使用单进程运行,但是每个进程中可以启动任意数量的Listener(监听器),每个监听器都独立配置一定数量的(L3/L4)网络过滤器。
Cluster:Envoy连接到的一组逻辑上相似的上游主机。
Mesh:以提供一致的网络拓扑的一组主机。
Runtime Configuration:与Envoy一起部署的外置实时配置系统。
Listener Filter:Listener使用Listener Filter(监听器过滤器)来操作链接的元数据,它的作用是在不更改Envoy的核心功能的情况下添加更多的集成功能。
Http Route Table:HTTP的路由规则,例如请求的域名,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
docker run -d --network=container:envoyproxy_1002a_1 --name envoyproxy_1002a_1 nginx
- 验证
web访问 10000端口

