Envoy简介
-
envoy的功能
-
-
区域感知路由,基于优先级/本地的负载均衡
-
中断
-
异常探测: 被动侦测
-
重试策略
-
超时
-
流量镜像
-
请求限速
-
访问日志
-
Envoy业已成为现代服务网格和边缘网关的“ 通用数据平面API ”,Istio、Ambassador和Gloo等项目均是为此数据平面代理提供的控制平面;
envoy基础配置介绍
Listener
-
独立部署时,建议每个主机仅部署单个Envoy实例,并在必要时于此实例上运行一到多个侦听器;
-
Enovy支持TCP和UDP两种类型的侦听器;
-
侦听器收到的连接请求将由其过滤器链中的各过滤器进行处理;
-
网络过滤器访问和操作L4连接上的原始数据,即TCP数据包
-
-
例如,TCP代理过滤器将客户端连接数据路由到上游主机,并生成连接统计信息等
-
network filter
-
Enovy内置了许多L3/L4过滤器,例如
-
代理类:TCP Proxy、HTTP connection manager、Thrift Proxy、Mongo proxy、Dubbo Proxy、ZooKeeper proxy、MySQL proxy和Redis proxy等,
-
其它:Client TLS authentication、Rate limit、Role Based Access Control (RBAC) Network Filter和Upstream Cluster from SNI等;
-
HTTP connection manager
-
HTTP connection manager自身是L3/L4过路器,它能够将原始字节转换为HTTP级别消息和事件(例如,headers和body等)
-
它还处理所有HTTP连接和请求共有的功能,例如访问日志记录、请求ID生成和跟踪、请求/响应头操作、路由表管理和统计信息等;
-
与L3/L4过滤器堆栈相似,Envoy还支持在HTTP连接管理器中使用HTTP级过滤器堆栈;
-
-
HTTP过滤器在L7运行,它们访问和操作HTTP请求和响应;例如,gRPC-JSON Transcoder Filter为gRPC后端公开REST API,并将请求和响应转换为相应的格式;
-
常用的HTTP过路器有Router、Rate limit、Health check、Gzip和Fault Injection等;
-
upstream cluster
Envoy可配置任意数量的上游集群,并使用Cluster Manager进行管理
-
由集群管理器负责管理的各集群可以由用户静态配置,也可借助于CDS API动态获取;
-
集群中的每个成员由endpoint进行标识,它可由用户静态配置,也可通过EDS或DNS服务动态发现;
-
-
Static:静态配置
-
Strict DNS:严格DNS,Envoy将持续和异步地解析指定的DNS目标,并将DNS结果中的返回的每个IP地址视为上游集群中可用成员;
-
Logical DNS:逻辑DNS,集群仅使用在需要启动新连接时返回的第一个IP地址,而非严格获取DNS查询的结果并假设它们构成整个上游集群;适用于必须通过DNS访问的大规模Web服务集群;
-
Original destination:当传入连接通过iptables的REDIRECT或TPROXY target或使用代理协议重定向到Envoy时,可以使用原始目标集群;
-
Endpoint discovery service (EDS):EDS是一种基于GRPC或REST-JSON API的xDS管理服务器获取集群成员的服务发现方式;
-
Custom cluster:Envoy还支持在集群配置上的cluster_type字段中指定使用自定义集群发现机制;
-
-
每个Cluster主要由集群名称,以及集群中的端点(通常是提供服务的IP地址和端口)所组成
-
Envoy Cluster支持纯静态定义方式来指定端点,也允许以动态方式发现各端点,甚至还支持自定义的发现机制
-
支持用户定义多种高级功能,例如,负载均衡策略、主动健康状态检查、被动健康状态检查和断路器等;
使用strict DNS配置服务发现
envoy的数据路径
Envoy组件拓扑
Envoy的基础组件
Envoy API术语
-
主机(Host):一个具有网络通信能力的端点,例如服务器、移动智能设备等
-
集群(Cluster):集群是Envoy连接到的一组逻辑上相似的端点;在v2中,RDS通过路由指向集群,CDS提供集群配置,而Envoy通过EDS发现集群成员,即端点;
-
下游(Downstream):下游主机连接到Envoy,发送请求并接收响应,它们是Envoy的客户端;
-
上游(Upstream):上游主机接收来自Envoy的连接和请求并返回响应,它们是Envoy代理的后端服务器;
-
端点(Endpoint):端点即上游主机,是一个或多个集群的成员,可通过EDS发现;
-
侦听器(Listener):侦听器是能够由下游客户端连接的命名网络位置,例如端口或unix域套接字等;
-
位置(Locality):上游端点运行的区域拓扑,包括地域、区域和子区域等;
-
管理服务器(Management Server):实现v3 API的服务器,它支持复制和分片,并且能够在不同的物理机器上实现针对不同xDS API的API服务;
-
地域(Region):区域所属地理位置;
-
区域(Zone):AWS中的可用区(AZ)或GCP中的区域等;
-
子区域:Envoy实例或端点运行的区域内的位置,用于支持区域内的多个负载均衡目标;
-
xDS:CDS 、EDS、HDS 、LDS、RLS(Rate Limit)、 RDS 、 SDS、VHDS和RTDS等API的统称;
-
Mesh和Envoy Mesh
Envoy的配置方式
-
Envoy的架构支持非常灵活的配置方式:简单部署场景可以使用纯静态配置,而更复杂的部署场景则可以逐步添加需要的动态配置机制;
-
-
纯静态配置:用户自行提供侦听器、过滤器链、集群及HTTP路由(http代理场景),上游端点的发现仅可通过DNS服务进行,且配置的重新加载必须通过内置的热重启(hot restart)完成;
-
仅使用EDS:EDS提供的端点发现功能可有效规避DNS的限制(响应中的最大记录数等);
-
使用EDS和CDS:CDS能够让Envoy以优雅的方式添加、更新和删除上游集群,于是,初始配置时,
-
-
Envoy无须事先了解所有上游集群;
-
-
EDS、CDS和RDS:动态发现路由配置;RDS与EDS、CDS一起使用时,为用户提供了构建复杂路由拓扑的能力(流量转移、蓝/绿部署等);
-
EDS、CDS、RDS和LDS:动态发现侦听器配置,包括内嵌的过滤器链;启用此四种发现服务后,除了较罕见的配置变动、证书轮替或更新Envoy程序之外,几乎无须再热重启Envoy;
-
EDS、CDS、RDS、LDS和SDS:动态发现侦听器密钥相关的证书、私钥及TLS会话票据,以及对证书验证逻辑的配置(受信任的根证书和撤销机制等)
-
Envoy配置中的重要概念
-
Bootstrap配置中几个重要的基础概念
-
-
node:节点标识,以呈现给管理服务器并且例如用于标识目的;
-
static_resources:静态配置的资源,用于配置静态的listener、cluster和secret;
-
dynamic_resources:动态配置的资源,用于配置基于xDS API获取listener、cluster和secret配置的lds_config、cds_config和ads_config;
-
admin:Envoy内置的管理接口;
-
tracing:分布式跟踪;
-
layered_runtime:层级化的运行时,支持使用RTDS从管理服务器动态加载;
-
hds_config:使用HDS从管理服务器加载上游主机健康状态检测相关的配置;
-
overload_manager:过载管理器;
-
stats_sinks:统计信息接收器;
-
-
一般来说,侦听器和集群是最为常用基础配置,无论是以静态或者是动态方式提供;
-
侦听器
-
-
接收客户端请求的入口端点,通常由监听的套接字及调用的过滤器链所定义
-
代理类的过滤器负责路由请求,例如tcp_proxy和http_connection_manager等
-
-
集群
-
-
一组上游主机的逻辑组合
-
每个主机映射为集群中的一个端点
-
下游的请求被调度至上游主机
-
简单静态配置示例
代理百度示例
-
编写envoy的yaml文件
root@ubuntu2204-4:~/envoy# pwd
/root/envoy
root@ubuntu2204-4:~/envoy# cat envoy-01.yaml
admin# 管理配置(非必要)
access_log_path/tmp/admin_access.log
address
socket_address
address0.0.0.0
port_value9999
static_resources# 表示静态资源配置
listeners# 监听配置
namelistener_0 # 监听器唯一标识
address
socket_address
address0.0.0.0 # 监听器的地址
port_value10000 # 监听器绑定的端口
## 过滤器链条
filter_chains# 过滤器链条
filters
# 指定要使用哪个过滤器
# 它还处理所有的HTTP连接和请求中常见的功能,例如访问日志、请求ID生成和跟踪、请求相应头操作
nameenvoy.filters.network.http_connection_manager
typed_config# 要指定特定类型,需要一个带有有效"@type" 名称的 "typed_config" 字段
"@type"type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefixingress_http_stangj # 统计信息的前缀
codec_typeAUTO # 编码类型
## 定义路由配置
route_config# 路由配置
namelocal_route # 路由表唯一标识
virtual_hosts# 虚拟主机配置
nameweb_service_1
domains"*" # 要匹配的主机名列表,* 表示匹配所有主机
routes# 路由组规则
match
prefix"/" # 匹配规则
route# 路由规则发送请求到下面的 local_cluster_baidu
clusterlocal_cluster_baidu # 转发到那个集群
max_grpc_timeout# 3s 最大超时时间
host_rewrite_literalwww.baidu.com # 更改HTTP请求入站的Host信息
## 定义http过滤链条
http_filters# 定义http过滤链条
nameenvoy.filters.http.router
typed_config
"@type"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # 路由过滤器
## 定义日志配置
access_log#日志配置
nameenvoy.access_loggers.stdout
typed_config
"@type"type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog # 日志输出类型(打印到终端)
clusters# 集群配置
namelocal_cluster_baidu # 集群唯一标识,需要和上面路由的cluster保持一致
connect_timeout1s # 连接超时时长
typeSTRICT_DNS # 服务发现类型 可用值 LOGICAL_DNS、STATIC
lb_policyROUND_ROBIN # 调度算法支持LEAST_REQUEST、RING_HASH、RANDOM、MAGLEV...
dns_lookup_familyV4_ONLY
load_assignment
cluster_namelocal_cluster_baidu
endpoints# 需要进行负载均衡的后端列表
lb_endpoints
endpoint
address
socket_address
addresswww.baidu.com
port_value443
transport_socket
nameenvoy.transport_sockets.tls
typed_config
"@type"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sniwww.baidu.com
-
验证
root@ubuntu2204-4:~/envoy# docker run --name envoy -d -p 80:10000 -p 9999:9999 -v ./envoy-01.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.28.0
root@ubuntu2204-4:~/envoy# docker logs -f envoy
将一个nginx配置转化为envoy示例
基本概念对应
-
upstream 在Nginx中表示一组后端服务器。在Envoy中,这可以通过定义一个或多个
Cluster来实现。 -
server 和 location 在Nginx中用于定义服务监听和路由规则。在Envoy中,这些可以通过
listeners和routes配置。
nginx配置
[root@lb01 conf.d]# vim pro.conf
upstream default {
server 192.168.139.100:80;
server 192.168.139.101:80;
}
upstream static {
server 192.168.139.98:80;
server 192.168.139.211:8080;
}
upstream upload {
server 192.168.139.96:80;
server 192.168.139.97:80;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://default;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_403 http_404 http_429;
}
location /static/ {
proxy_pass http://static;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_403 http_404 http_429;
}
location /upload/ {
proxy_pass http://upload;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_403 http_404 http_429;
}
}
转化后的envoy配置
root@ubuntu2204-4:~/envoy# cat envoy-02.yaml
static_resources
listeners
namemain_listener
address
socket_address
address0.0.0.0
port_value80
filter_chains
filters
nameenvoy.filters.network.http_connection_manager
typed_config
"@type"type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefixhttp
codec_typeAUTO
route_config
namelocal_route
virtual_hosts
namelocal_service
domains"*"
routes
match
prefix"/static/"
route
clusterstatic
match
prefix"/upload/"
route
clusterupload
match
prefix"/"
route
clusterdefault
http_filters
nameenvoy.filters.http.router
typed_config
"@type"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # 路由过滤器
access_log#日志配置
nameenvoy.access_loggers.stdout
typed_config
"@type"type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
log_format
json_format
"start_time""%START_TIME%"
"method""%REQ(:METHOD)%"
"path""%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
"protocol""%PROTOCOL%"
"response_code""%RESPONSE_CODE%"
"response_flags""%RESPONSE_FLAGS%"
"bytes_received""%BYTES_RECEIVED%"
"bytes_sent""%BYTES_SENT%"
"duration""%DURATION%"
"upstream_service_time""%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%"
"x_forwarded_for""%REQ(X-FORWARDED-FOR)%"
"user_agent""%REQ(USER-AGENT)%"
"request_id""%REQ(X-REQUEST-ID)%"
"authority""%REQ(:AUTHORITY)%"
"upstream_host""%UPSTREAM_HOST%"
"upstream_cluster""%UPSTREAM_CLUSTER%"
"downstream_local_address""%DOWNSTREAM_LOCAL_ADDRESS%"
"downstream_remote_address""%DOWNSTREAM_REMOTE_ADDRESS%"
"requested_server_name""%REQUESTED_SERVER_NAME%"
"route_name""%ROUTE_NAME%"
clusters
namedefault
typeSTRICT_DNS
load_assignment
cluster_namedefault
endpoints
lb_endpoints
endpoint
address
socket_address
address192.168.139.211
port_value8080
endpoint
address
socket_address
address192.168.139.101
port_value80
namestatic
typeSTRICT_DNS
load_assignment
cluster_namestatic
endpoints
lb_endpoints
endpoint
address
socket_address
address192.168.139.211
port_value8080
endpoint
address
socket_address
address192.168.139.99
port_value80
nameupload
typeSTRICT_DNS
load_assignment
cluster_nameupload
endpoints
lb_endpoints
endpoint
address
socket_address
address192.168.139.96
port_value80
endpoint
address
socket_address
address192.168.139.97
port_value80
一个测试代理后端envoy配置示例
-
启动两个测试web容器
root@ubuntu2204-4:~/envoy# docker run --name envoy -d -p 80:80 -v ./envoy-03.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.28.0
root@ubuntu2204-4:~/envoy# cat envoy-03.yaml
static_resources
listeners
namemain_listener
address
socket_address
address0.0.0.0
port_value80
filter_chains
filters
nameenvoy.filters.network.http_connection_manager
typed_config
"@type"type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefixhttp
codec_typeAUTO
route_config
namelocal_route
virtual_hosts
namebackend
domains
"one.example.com"
"www.one.example.com"
routes
match
prefix"/"
route
clusterdefault_Cluster
http_filters
nameenvoy.filters.http.router
typed_config
"@type"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # 路由过滤器
access_log#日志配置
nameenvoy.access_loggers.stdout
typed_config
"@type"type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
log_format
json_format
"start_time""%START_TIME%"
"method""%REQ(:METHOD)%"
"path""%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
"protocol""%PROTOCOL%"
"response_code""%RESPONSE_CODE%"
"response_flags""%RESPONSE_FLAGS%"
"bytes_received""%BYTES_RECEIVED%"
"bytes_sent""%BYTES_SENT%"
"duration""%DURATION%"
"upstream_service_time""%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%"
"x_forwarded_for""%REQ(X-FORWARDED-FOR)%"
"user_agent""%REQ(USER-AGENT)%"
"request_id""%REQ(X-REQUEST-ID)%"
"authority""%REQ(:AUTHORITY)%"
"upstream_host""%UPSTREAM_HOST%"
"upstream_cluster""%UPSTREAM_CLUSTER%"
"downstream_local_address""%DOWNSTREAM_LOCAL_ADDRESS%"
"downstream_remote_address""%DOWNSTREAM_REMOTE_ADDRESS%"
"requested_server_name""%REQUESTED_SERVER_NAME%"
"route_name""%ROUTE_NAME%"
clusters
namedefault_Cluster
typeSTRICT_DNS
load_assignment
cluster_namedefault_Cluster
endpoints
lb_endpoints
endpoint
address
socket_address
address172.17.0.2
port_value80
endpoint
address
socket_address
address172.17.0.3
port_value80
-
启动envoy
root@ubuntu2204-4:~/envoy# docker run --name envoy -d -p 80:80 -v ./envoy-03.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.28.0
使用SSL/TLS保护流量示例
`起两个web的容器`
root@ubuntu2204-4:~/envoy# docker run -d katacoda/docker-http-server ; docker run -d katacoda/docker-http-server
root@ubuntu2204-4:~/envoy# pwd
/root/envoy
root@ubuntu2204-4:~/envoy# mkdir certs
root@ubuntu2204-4:~/envoy# cd certs/
`生成证书`
root@ubuntu2204-4:~/envoy/certs# openssl req -nodes -new -x509 \
-keyout example-com.key -out example-com.crt \
-days 365 \
-subj '/CN=example-com/O=stangj.com/C=CN'
-
配置envoy
root@ubuntu2204-4:~/envoy# cat envoy-04.yaml
static_resources:
listeners:
- name: main_listener_http
address:
socket_address:
address: 0.0.0.0
port_value: 8080
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: http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "one.example.com"
routes:
- match:
prefix: "/"
redirect:
path_redirect: "/"
https_redirect: true
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # 路由过滤器
- name: main_listener_https
address:
socket_address:
address: 0.0.0.0
port_value: 8443
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: http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "one.example.com"
routes:
- match:
prefix: "/service/1"
route:
cluster: service1
- match:
prefix: "/service/2"
route:
cluster: service2
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # 路由过滤器
access_log: #日志配置
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
log_format:
json_format:
{
"start_time": "%START_TIME%",
"method": "%REQ(:METHOD)%",
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
"protocol": "%PROTOCOL%",
"response_code": "%RESPONSE_CODE%",
"response_flags": "%RESPONSE_FLAGS%",
"bytes_received": "%BYTES_RECEIVED%",
"bytes_sent": "%BYTES_SENT%",
"duration": "%DURATION%",
"upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
"x_forwarded_for": "%REQ(X-FORWARDED-FOR)%",
"user_agent": "%REQ(USER-AGENT)%",
"request_id": "%REQ(X-REQUEST-ID)%",
"authority": "%REQ(:AUTHORITY)%",
"upstream_host": "%UPSTREAM_HOST%",
"upstream_cluster": "%UPSTREAM_CLUSTER%",
"downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
"downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
"requested_server_name": "%REQUESTED_SERVER_NAME%",
"route_name": "%ROUTE_NAME%"
}
# 证书配置
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain:
filename: "/etc/certs/example-com.crt"
private_key:
filename: "/etc/certs/example-com.key"
clusters:
- name: service1
type: STRICT_DNS
load_assignment:
cluster_name: service1
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 172.17.0.2
port_value: 80
- name: service2
type: STRICT_DNS
load_assignment:
cluster_name: service2
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 172.17.0.3
port_value: 80
-
启动envoy
root@ubuntu2204-4:~/envoy# chmod +r certs/example-com.key
root@ubuntu2204-4:~/envoy# docker run -it --name tls-envoy-proxy -p 80:8080 -p 443:8443 -v ./certs:/etc/certs/ -v ./envoy-04.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.28.0








文章评论