). Envoy
Envoy 于 2017 年 9 月作为孵化项目加入 CNCF。从孵化到毕业,Envoy 都是 CNCF 增长最快的项目之一
Envoy 在吞吐量和延迟方面都表现良好。这在大型云原生部署中至关重要
Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线,体积小,性能高
Envoy 是一个开源的边缘服务代理,也是 Istio Service Mesh 默认的数据平面,专为云原生应用程序设计
够接收请求的流量后,然后对请求的数据做一些微处理,例如添加 Header 头或校验某个 Header 字段的内容。根据来源数据的不同,又可以分为 L3(网络层)、L4(传输层)、L7(应用层),然后转发请求,如果后端是一个集群,需要从中挑选一台机器,又涉及到负载均衡
镜像说明
alpine
的发行镜像alpine
的 Nightly
版本发行镜像Ubuntu
的发行镜像Ubuntu
的 Nightly
版本发行镜像Envoy的启动配置文件分为两种方式:静态配置和动态配置
# 起一个容器测试一下
docker run -it --rm -p 9901:9901 -p 10000:10000 --name envoy-test -d -v /root/envoy/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.18.3
curl localhost:10000
envoy.yaml
网络代理程序的流程,比如作为一个代理,首先要能获取请求流量,通常是采用监听端口的方式实现;其次拿到请求数据后需要对其做微处理,例如附加
Header
或校验某个Header
字段的内容等,这里针对来源数据的层次不同,可以分为L3/L4/L7
,然后将请求转发出去;转发这里又可以衍生出如果后端是一个集群,需要从中挑选一台机器,如何挑选又涉及到负载均衡等
listener
: 监听器定义了 Envoy 如何处理入站请求,Envoy 会暴露一个或多个 Listener 来监听客户端的请求,目前 Envoy 仅支持基于 TCP 的监听器,一旦建立连接之后,就会将该请求传递给一组过滤器(filter)进行处理filter
: 过滤器。在 Envoy 中指的是一些 可插拔和可组合的逻辑处理层,是 Envoy 核心逻辑处理单元,过滤器是处理入站和出站流量的链式结构的一部分, 在过滤器链上可以集成很多特定功能的过滤器,例如,通过集成GZip
过滤器可以在数据发送到客户端之前压缩数据route_config
: 路由规则配置。即将请求路由到后端的哪个集群, 路由用来将流量转发到具体的目标实例,目标实例在 Envoy 中被定义为集群cluster
: 服务提供方集群。Envoy 通过服务发现定位集群成员并获取服务,具体路由到哪个集群成员由负载均衡策略决定, 集群定义了流量的目标端点,同时还包括一些其他可选配置,如负载均衡策略等
最终配置
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: 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
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
#host_rewrite_literal: www.envoy-demo.com
cluster: envoy-demo
http_filters:
- name: envoy.filters.http.router
clusters:
- name: envoy-demo
connect_timeout: 30s
type: STATIC
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: envoy-demo
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 172.164.100.34
port_value: 899
- endpoint:
address:
socket_address:
address: 172.164.100.34
port_value: 900
docker run -it -p 9901:9901 -p 10000:10000 --name envoy -d -v /root/envoy/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.18.3
# 启动2个被代理的 nginx demo
docker run -it --name nginx-test -p 899:80 -d nginx
docker run -it --name nginx-exam -p 900:80 -d nginx
# 最总结果是可以通过 envoy 访问到 nginx 首页
curl 127.0.0.1:10000
默认 Envoy 的配置文件
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: 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
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
host_rewrite_literal: www.envoyproxy.io
cluster: service_envoyproxy_io
http_filters:
- name: envoy.filters.http.router
clusters:
- name: service_envoyproxy_io
connect_timeout: 30s
type: LOGICAL_DNS
# Comment out the following line to test on v6 networks
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_envoyproxy_io
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: www.envoyproxy.io
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: www.envoyproxy.io
admin:
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 9901
listeners
(监听器) 可以配置 多个 filter_chains
, filter_chains
中的 filters
是过滤器定义,Envoy 内置了很多 filters
filters
过滤器类型:
- envoy.filters.network.connection_limit
- envoy.filters.network.direct_response
- envoy.filters.network.dubbo_proxy
- envoy.filters.network.echo
- envoy.filters.network.envoy_mobile_http_connection_manager
- envoy.filters.network.ext_authz
- envoy.filters.network.http_connection_manager
- envoy.filters.network.local_ratelimit
- envoy.filters.network.mongo_proxy
- envoy.filters.network.ratelimit
- envoy.filters.network.rbac
- envoy.filters.network.redis_proxy
- envoy.filters.network.set_filter_state
- envoy.filters.network.sni_cluster
- envoy.filters.network.sni_dynamic_forward_proxy
- envoy.filters.network.tcp_proxy
- envoy.filters.network.thrift_proxy
- envoy.filters.network.wasm
- envoy.filters.network.zookeeper_proxy
以下扩展仅在contrib图像中可用:
- envoy.filters.network.client_ssl_auth
- envoy.filters.network.generic_proxy
- envoy.filters.network.golang
- envoy.filters.network.kafka_broker
- envoy.filters.network.kafka_mesh
- envoy.filters.network.mysql_proxy
- envoy.filters.network.postgres_proxy
- envoy.filters.network.rocketmq_proxy
- envoy.filters.network.sip_proxy
static_resources:
listeners:
- name: listener_0 # 监听器的名称,可以自己定义
address:
socket_address:
protocol: TCP
address: 0.0.0.0 # 监听器的地址
port_value: 10000 # 监听器的端口
filter_chains: # 配置过滤器链
- filters: # 过滤器
# 指定要使用哪个过滤器,下面是 envoy 内置的网络过滤器,如果请求是 HTTP 它将通过此 HTTP 过滤器
- name: envoy.filters.network.http_connection_manager
typed_config:
# 需要配置下面的类型,启用 http_connection_manager 过滤器,除了该过滤器,Envoy 中还内置了一些其他过滤器,包括 Redis、Mongo、TCP 等
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log: # 连接管理器发出的 HTTP 访问日志的配置
- name: envoy.access_loggers.stdout # 输出日志到 stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
route_config: # 路由配置
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"] # 要匹配的主机名列表,*表示匹配所有主机
routes:
- match:
prefix: "/" # 要匹配的 URL 前缀
route: # 路由规则配置
host_rewrite_literal: www.envoy-demo.com
cluster: envoy-demo # 在下面的 clusters 中会定义一个 envoy-demo
http_filters: # 定义http过滤器链
- name: envoy.filters.http.router # 调用7层的路由过滤器
static_resources
的配置将主机定义为访问 HTTPS 的 www.envoy-demo.com
域名,如果定义了多个主机,Envoy 将执行轮询策略
STATIC
(DEFAULT) ?Refer to the static discovery type for an explanation
STATIC
是最简单的服务发现类型,配置显式指定每个上游主机的已解析网络名称(IP 地址/端口、unix 域套接字等)STRICT_DNS
?Refer to the strict DNS discovery type for an explanation
当使用
STRICT_DNS
类型的服务发现时,Envoy 将持续并异步地解析指定的 DNS 目标,DNS 结果中每个返回的 IP 地址将被视为上游集群中的显式主机。这意味着如果查询返回三个 IP 地址,Envoy 将假定该集群有三台主机,并且所有三台主机应该负载均衡。如果有主机从 DNS 返回结果中删除,则 Envoy 会认 为它不再存在,并且会将它从所有的当前连接池中排除LOGICAL_DNS
?Refer to the logical DNS discovery type for an explanation
EDS
?Refer to the service discovery type for an explanation
ORIGINAL_DST
?Refer to the original destination discovery type for an explanation
clusters:
- name: envoy-demo
connect_timeout: 30s
type: STATIC # 当选择 V4_ONLY 时,DNS 解析器将仅执行 IPv4 系列中的地址查找
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: envoy-demo
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 172.164.100.34
port_value: 899
- endpoint:
address:
socket_address:
address: 172.164.100.34
port_value: 900
transport_socket
部分告诉 Envoy 使用 HTTPS transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: www.envoyproxy.io