Envoy是Lyft于2017年开源的网络反向代理工具,现属于CNCF基金会的毕业项目.
和Nginx和HAProxy相比,功能更强大,开源更彻底(提供的许多功能是其他产品的付费功能).
作为新兴代理,与微服务紧密结合,可以提高强大的可观察性功能,通常做为入口代理/边缘代理/中间代理等. 流行的Service Mesh框架istio就是基于Envoy构建而成.
Envoy本身用C++开发,并发模型与Nginx类似,具有很高的处理性能.属于L4层代理,但支持7层HTTP协议栈。
本文聚焦于Envoy代理本身所提供的丰富功能,个别地方也会引入微服务和Service Mesh的概念,读者可以再做深入了解.
sending (egress) and receiving (ingress) service。
使用和部署
官方提供两种部署方式.
本地编译
在Ubuntu 18.04下编译,具体参考官方说明.
安装bazel参考这里
# 安装依赖
apt-get install ninja-build
# 本地编译
bazel build //source/exe:envoy-static
编译后的文件位于 /bazel-bin/source/exe/envoy-static
使用docker容器的方式
快速验证
docker pull envoyproxy/envoy-dev:8d1ad35aa724962f64f7535531e408c9a93d364c
docker run --rm -d -p 10000:10000 envoyproxy/envoy-dev:8d1ad35aa724962f64f7535531e408c9a93d364c
# 默认使用10000端口
curl -v localhost:10000
定制和扩展
基于配置规则创建自己的envoy.yaml
docker run --name=envoy -d \
-p 10000:10000 \
-v $(pwd)/envoy.yaml:/etc/envoy/envoy.yaml \
envoyproxy/envoy:latest
或者创建自己镜像:
# Dockfile
FROM envoyproxy/envoy-dev:8d1ad35aa724962f64f7535531e408c9a93d364c
COPY envoy.yaml /etc/envoy/envoy.yaml
构建新的定制镜像
docker build -t envoy:v1 .
# 9901为管理端口
docker run -d --name envoy -p 9901:9901 -p 10000:10000 envoy:v1
curl -v localhost:10000
调试
- 访问管理接口 /logging
- 传递日志参数
-l <string>, --log-level <string> --log-path <path string>
部署方式
Front Proxy
作为公网客户请求的主负载均衡,也叫做edge proxy/load balancer (南北流量).
同时适合做中心认证,重试,健康检查.
Service Mesh
处理内部服务间流量(东西流量).
k8s作为sidecar 配置服务发送所有出口(outbound)流量到该sidecar.
配置
静态配置文件默认位于 /etc/envoy/envoy.yaml
概念
路由配置:
- Route: 映射虚拟主机到集群的一组规则集.
- Cluster: 一组相似的上游主机/端口,用于负载均衡流量
- Endpoint: IP和端口,负责具体的服务处理
- Listener: 命名的网络地址,用来接受下游客户端的网络连接.
动态配置
动态配置支持文件和API(配置服务器)两种方式.
- Control Plane/控制平面
- Data Plane/数据平面
最佳实践:基于数据中心/区域或服务类型做配置分隔.
基于文件的动态配置
参考文档: 动态配置路由
配置服务器实现
官方提供了Go和Java两个默认实现
常见应用场景
官方文档的沙箱部分是个很好的开始.
熔断
配置项定义在cluster下
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 1000
max_requests: 1000
- priority: HIGH
max_connections: 2000
max_requests: 2000
max_retries: xxx
注: HTTP/1.1使用max_connections, HTTP/2 使用max_requests
自动重试
重试策略:
# 在route下定义retry
retry_on: "5xx"
num_retries: 1 # 默认值
per_try_timeout_ms: 2000
- 不要重试会改变重试结果的请求(建议先尝试GET操作)
- 不要重试昂贵的请求
要仔细考虑设置策略,比如上游timeout_ms不应该设置过长避免不能在指定时间完成重试,全局timeout_ms也不应该设置过长避免并发请求超时造成系统负担.
健康检查
可以分主动检查和被动检查,配置项在cluster下定义.
- 健康检查/Health Checking
- 异常检测/Outlier Detection
# 健康检查例子
health_checks:
- timeout: 1s
interval: 60s
interval_jitter: 1s
unhealthy_threshold: 3
healthy_threshold: 3
tcp_health_check: {}
# http_health_check
host: "servicehost"
path: "/health"
service_name: "authentication"
异常检测: 效果更好一些,可以排除健康检查的短暂异常情况.
# 一般不常用
consecutive_5xx: "3"
base_ejection_time: "30s"
# 基于统计的检查更可靠,需要流量支持
interval: "10s"
base_ejection_time: "30s"
success_rate_minimum_hosts: "10"
success_rate_request_volume: "500"
success_rate_stdev_factor: "1000" # divided by 1000 to get a double
监控/统计/追踪
envoy内置常用的统计,可以访问管理台/stats查看具体metrics.
用于响应统计通常结合Prometheus和Grafana实现,参考这里/Demo代码.
分布式追踪通常结合Jaeger/Zipkin使用, 结合Jaeger的实现参考官方文档沙箱部分或这里.
分流/蓝绿发布/流量复制
Traffic mirroring/shadowing: 用于生产环境服务的验证测试, 镜像功能发送一部分生产流量副本到镜像服务,镜像请求采用fire&forgot模式,响应被丢弃.
可参考:
扩展阅读
与其他代理的比较
- 与其他主流代理的比较
- traefik反向代理/负载均衡: Go实现,支持kubernetes编排服务和etcd/consul服务注册
学习资源
- Envoy中文文档
- kata在线实验环境
- 基础
- learnenvoy: 不再维护
应用
将硬件负载均衡器替换为软件解决方案,在每个集群的边缘上有一个“north-south”网关,用来管理所有针对外部的传入和传出流量.