1、简介
Envoy 是一个高性能的开源边缘和服务代理,由 Lyft 开发并开源。它在微服务架构中作为一个网络中间件,用于处理服务间的通信、负载均衡、安全和监控。在 Kubernetes 中,Envoy 被广泛用作服务网格的数据平面代理,能够高效地管理微服务架构中的流量。
2、特点
高性能:Envoy 使用 C++ 编写,具有极高的性能和低延迟,能够处理大规模的请求流量。
动态配置:支持动态配置更新,无需重启即可更改配置,确保系统的高可用性。
高级负载均衡:支持多种负载均衡策略,如轮询、随机、基于权重的负载均衡等。
丰富的路由规则:提供基于路径、主机名、HTTP 方法等的路由规则,灵活管理流量。
全面的可观察性:内置了丰富的监控和日志功能,支持分布式追踪,如与 Zipkin、Jaeger 集成。
安全性:支持 TLS 加密、身份验证和授权机制,确保服务间通信的安全性。
3、应用场景
服务网格:在 Kubernetes 中,Envoy 通常作为服务网格的一部分,用于管理服务间的通信。例如,Istio 是一个流行的服务网格实现,它使用 Envoy 作为数据平面代理,通过 sidecar 容器的方式在每个 pod 中部署 Envoy 代理。
API 网关:Envoy 可以作为 Kubernetes 集群的入口网关,处理进入集群的外部流量,并将其路由到合适的服务。
边缘代理:Envoy 可以用作边缘代理,处理从外部网络进入 Kubernetes 集群的流量,执行负载均衡、SSL 终止和安全策略等操作。
4、架构

Downstream
下游(downstream)主机连接到 Envoy,发送请求并或获得响应。
Upstream
上游(upstream)主机获取来自 Envoy 的链接请求和响应。
监听器
除了过滤器链之外,还有一种过滤器叫监听器过滤器(Listener filters),它会在过滤器链之前执行,用于操纵连接的元数据。这样做的目的是,无需更改 Envoy 的核心代码就可以方便地集成更多功能。
每个监听器都可以配置多个过滤器链(Filter Chains),监听器会根据
filter_chain_match
中的匹配条件将流量转交到对应的过滤器链,其中每一个过滤器链都由一个或多个网络过滤器(Network filters
)组成。这些过滤器用于执行不同的代理任务,如速率限制,TLS
客户端认证,HTTP
连接管理,MongoDB
嗅探,原始 TCP 代理等。
<!--其中每一个环节可以静态配置,也可以动态服务发现,也就是所谓的 `xDS`,这里的 `x` 是一个代词,是 `lds`、`rds`、`cds`、`eds`、`sds` 的总称,即服务发现,后 2 个字母 `ds` 就是 `discovery service`。-->
5、静态配置与动态服务发现
Envoy 作为一个高性能的开源边缘和服务代理,支持静态配置和动态服务发现两种配置方式。静态配置在 Envoy 启动时加载并保持不变,而动态服务发现则允许在运行时动态更新配置,使 Envoy 更加灵活和适应性强。本文将详细探讨这两种配置方式,以及它们在实际应用中的优缺点。
静态配置
静态配置是指在 Envoy 启动前,通过 YAML 文件定义所有的配置项,包括监听器(Listener)、集群(Cluster)、路由(Route)和端点(Endpoint)等。静态配置的优点在于简单、易于管理和调试,适用于配置较为固定、不频繁变化的场景。
动态服务发现
动态服务发现利用 Envoy 的 xDS API(包括 LDS、RDS、CDS 和 EDS)实现配置的动态更新。这些 API 允许 Envoy 在运行时通过 gRPC 从远程配置服务器获取配置信息。动态服务发现的优点在于灵活性和可扩展性,适用于配置频繁变化或需要根据实时情况调整的场景。
动态服务架构
xDS 服务器:提供动态配置的源,包含 LDS、RDS、CDS 和 EDS 服务。
Envoy:通过 gRPC 与 xDS 服务器通信,获取最新的配置。
静态配置与动态服务发现的对比
| 特性 | 静态配置 | 动态服务发现 |
|---|---|---|
| 配置方式 | 预定义的 YAML 文件 | 通过 gRPC 动态获取 |
| 配置更新 | 需要重启 Envoy | 实时更新,无需重启 |
| 适用场景 | 配置固定、不频繁变化 | 配置频繁变化或需动态调整 |
| 管理复杂性 | 较低 | 较高 |
| 弹性和适应性 | 较低 | 高 |
实际应用中的考虑
在实际应用中,可以根据具体需求选择静态配置或动态服务发现,或者两者结合使用。例如,对于一些基础设施组件或服务,可以使用静态配置,而对于需要高灵活性和动态调整的服务,可以使用动态服务发现。此外,还可以通过在静态配置中包含动态服务发现的配置,使得 Envoy 在启动时加载基础配置,同时支持运行时动态更新。
LDS、RDS、CDS 和 EDS 是 Envoy 中强大的动态配置机制,使得 Envoy 可以在不重启的情况下动态更新其配置。这些服务通过 gRPC 接口与 xDS 服务器通信,提供灵活的配置和管理能力。在 Kubernetes 中,结合这些动态配置服务,可以实现高效的流量管理和服务治理,提高系统的可靠性和可扩展性。
6、动态配置机制
Envoy 作为一个高性能的开源边缘和服务代理,提供了多种动态配置机制来管理网络流量。这些机制包括 Listener Discovery Service (LDS)、Route Discovery Service (RDS)、Cluster Discovery Service (CDS) 和 Endpoint Discovery Service (EDS)。这些服务使得 Envoy 可以动态地更新其配置,而无需重启,从而保持高可用性和灵活性。
Listener Discovery Service (LDS)
LDS 是用于动态发现和配置 Envoy 监听器的服务。监听器是 Envoy 接收传入连接的地方。每个监听器绑定到一个特定的网络地址和端口,并定义了如何处理进入的连接。
Route Discovery Service (RDS)
RDS 是用于动态发现和配置 Envoy 路由的服务。路由决定了如何将请求从一个 listener 转发到具体的 cluster。RDS 允许在运行时动态更新路由配置。
Cluster Discovery Service (CDS)
CDS 是用于动态发现和配置 Envoy 集群的服务。集群是 Envoy 用来将请求转发到上游服务的逻辑组。CDS 允许在运行时动态更新集群配置,包括负载均衡策略和健康检查设置。
Endpoint Discovery Service (EDS)
EDS 是用于动态发现和配置 Envoy 端点的服务。端点是具体的上游服务实例。EDS 允许在运行时动态更新集群中的端点信息,如 IP 地址和端口。

LDS、RDS、CDS 和 EDS 是 Envoy 中强大的动态配置机制,使得 Envoy 可以在不重启的情况下动态更新其配置。这些服务通过 gRPC 接口与 xDS 服务器通信,提供灵活的配置和管理能力。在 Kubernetes 中,结合这些动态配置服务,可以实现高效的流量管理和服务治理,提高系统的可靠性和可扩展性。
7、流量分发

启动阶段
istiod拦截pod创建请求,识别为指定namepsace则根据configmap配置生成带有Envoy两个容器的创建POD请求,修改过的创建请求被 kubelet接收,并在节点创建POD。
istio-init容器添加用于配置容器网络内iptables规则 • istio-proxy容器启动pilot-agent进程,使用UID=1337 GID=1337创建Envoy启动命令行与配置文件 。
可以通过自定义deployment内istio注解sidecar.istio.io/inject: “false”跳过自动注入过程,或修改部分启动参数。
控制面通信
Pilot-agent进程本身创建UDS接收Envoy连接,用于证书更新下发。并且与istiod建立证书更新通道。
Envoy 通过pilot-agent转发机制与istiod建立长连接,通过xDS协议接收系统下发的监听器、路由、集群节点等更新信息。
数据面通信
客户端请求进入容器网络,并被iptables规则拦截,经过DNAT后进入Envoy virtualOutbound监听器 。
virtualOutbound经过监听过滤器恢复用于原始目标服务,并找到后端处理器处理新连接。
后端处理器在配置中指定处理协议,根据协议相关的网络过滤器处理读取到的数据。
如果为http协议,再经过请求过滤器处理http协议头部,如路由选择等功能并创建上游连接。
将修改及编码后的http消息通过网络发送到对端Envoy的容器网络。
Iptables识别为入流量则进入virtualInbound端口。
ORIGINAL_DST恢复原始目标后,根据virtualInbound配置的监听过滤器找到对应的本地服务器地址。并发起localhost的请求。
请求进入本地服务器内进行处理并返回响应。
8、流量拦截

Init 容器中使用的的 iptables 版本是
v1.6.0
,共包含 5 张表:注:在本示例中只用到了
nat
表,不同的表中的具有的链类型如下表所示:规则名称 raw filter nat mangle security PREROUTING ✓ ✓ ✓ INPUT ✓ ✓ ✓ ✓ OUTPUT ✓ ✓ ✓ ✓ POSTROUTING ✓ ✓ FORWARD ✓ ✓ ✓ ✓ raw
用于配置数据包,raw
中的数据包不会被系统跟踪。filter
是用于存放所有与防火墙相关操作的默认表。nat
用于 网络地址转换 (例如:端口转发)。mangle
用于对特定数据包的修改(参考损坏数据包 )。security
用于强制访问控制 网络规则。

9、Nginx 与 Envoy 对比
监听器
#nginx
server {
listen 80;
server_name one.example.com www.one.example.com;
#Envoy
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
过滤器
#nginx
location {
proxy_pass http://targetCluster/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
#Envoy
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "one.example.com"
- "www.one.example.com"
routes:
- match:
prefix: "/"
route:
cluster: targetCluster
http_filters:
- name: envoy.router
upstream
#nginx
upstream targetCluster {
172.18.0.3:80;
172.18.0.4:80;
}
#Envoy
clusters:
- name: targetCluster
connect_timeout: 0.25s
type: STRICT_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
hosts: [
{ socket_address: { address: 172.18.0.3, port_value: 80 }},
{ socket_address: { address: 172.18.0.4, port_value: 80 }}
]
访问日志
#nginx
access_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
#Envoy
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
access_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
route_config:
10、部署envoy
编写envoy.yaml
[root@mast01 istio]# kubectl get svc -n istio-demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bill-service ClusterIP 10.108.203.9 <none> 9999/TCP 2d1h
[root@mast01 istio]# vim 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: 2s
type: STATIC
lb_policy: ROUND_ROBIN
hosts: [{ socket_address: { address: 10.108.203.9, port_value: 9999 }}]
listener
: Envoy 的监听地址。Envoy 会暴露一个或多个 Listener 来监听客户端的请求。filter
: 过滤器。在 Envoy 中指的是一些“可插拔”和可组合的逻辑处理层,是 Envoy 核心逻辑处理单元。route_config
: 路由规则配置。即将请求路由到后端的那个集群。cluster
: 服务提供方集群。Envoy 通过服务发现定位集群成员并获取服务,具体路由到哪个集群成员由负载均衡策略决定。
启动容器
#启动服务
[root@mast01 istio]# docker run -d --name envoy -v `pwd`/envoy.yaml:/etc/envoy/envoy.yaml -p 10000:10000 envoyproxy/envoy-alpine:v1.15.2
Unable to find image 'envoyproxy/envoy-alpine:v1.15.2' locally
v1.15.2: Pulling from envoyproxy/envoy-alpine
df20fa9351a1: Pull complete
9ba6eb908515: Pull complete
f53211bb95b2: Pull complete
15b31d4c3abe: Pull complete
fb469efafc06: Pull complete
d19200a72c8a: Pull complete
5f76566f0fae: Pull complete
Digest: sha256:0ecbcf739f313958cf84886beb63788907d624ddd19410d34c51c32856a3cb34
Status: Downloaded newer image for envoyproxy/envoy-alpine:v1.15.2
569886add6cf3585d946bdff4e59dd525816e0efa8d5ea7166102a62fefa0327
#查看状态
[root@mast01 istio]# docker ps |grep envoy
569886add6cf envoyproxy/envoy-alpine:v1.15.2 "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:10000->10000/tcp, :::10000->10000/tcp envoy
#请求测试
[root@mast01 istio]# curl 127.0.0.1:10000
this is bill-service-v1
[root@mast01 istio]# curl 127.0.0.1:10000
hello, this is bill-service-v2
[root@mast01 istio]# curl 127.0.0.1:10000
this is bill-service-v1
[root@mast01 istio]# curl 127.0.0.1:10000
this is bill-service-v1
[root@mast01 istio]# curl 127.0.0.1:10000
hello, this is bill-service-v2
[root@mast01 istio]# curl 127.0.0.1:10000
this is bill-service-v1
[root@mast01 istio]# curl 127.0.0.1:10000
this is bill-service-v1
[root@mast01 istio]# curl 127.0.0.1:10000
hello, this is bill-service-v2
[root@mast01 istio]# curl 127.0.0.1:10000
hello, this is bill-service-v2
[root@mast01 istio]# curl 127.0.0.1:10000
this is bill-service-v1
欢迎大家扫码关注:

本公众号只写原创,不接广告、不接广告、不接广告。下期小伙伴想学习什么技术,可以私信发我吆。





