Kubernetes - Envoy
Kubernetes
Kubernetes 主要基于
Kernel
技术栈,缺少精细化
的高级流量治理
- Kubernetes 已有的流量治理能力:Service + Ingress
- Service 在 L4,基于 Kernel 技术栈,无法实现精细化的高级流量管理
- Ingress 在 L7,主要针对入站流量
架构演进
单体
访问服务
微服务
业务代码一般会集成统一的 SDK,耦合了很多平台侧的能力
Service Mesh
Sidecar
Service Instance 与 Sidecar Proxy 在同一个
Network Namespace
,相当于一个 loopback,可以明文传输
能力下沉
通过
Sidecar
来实现微服务治理
,业务部门更聚焦于业务逻辑
Istio
特性
HTTP
、gRPC
、WebSocket
、TCP
的自动负载均衡- 通过丰富的
路由规则
实现重试
、故障转移
、故障注入
,可以对流量行为进行细粒度控制
可插入
的策略层
和配置 API
,支持访问控制、速率限制和配额- 对出入集群
入口
和出口
中的所有流量的自动度量指标、日志记录和跟踪 - 通过强大的
基于身份
的验证和授权,在集群中实现安全
的服务间通信
功能
一套模型统一:入站流量 + 东西向流量 + 出站流量
Istio 同时支持 Kubernetes 的
Ingress
和Service API
如果将IngressClass
设置为 Istio,则 Istio 将充当Ingress Controller
的角色
流量
- 连接
- 通过简单的规则配置和流量路由,可以控制服务之间的流量和 API 调用
- 简化了
断路器
、超时
、重试
等服务级别属性的配置 - 可以轻松设置 A/B 测试、金丝雀部署、基于百分比的流量分割等任务
- 控制
- 通过更好地了解流量和
开箱即用
的故障恢复
功能,可以在问题出现之前先发现问题,使调用更可靠 - 如支持
熔断
和降级
- 通过更好地了解流量和
安全
- Istio 提供
底层
安全通信信道,并大规模管理服务通信的认证
、授权
和加密
- 在 Istio 中,服务通信在默认情况下都是安全的,允许
跨多种协议和运行时
实施一致的安全策略
- Istio 与
Kubernetes 网络策略
结合,在网络层
和应用层
保护Pod 间
或者服务间
的通信Kubernetes 网络策略
在L4
,基于 Kernel 技术栈Istio
在L7
,实现更精细的流量控制
可观测性
监控服务的
SLO
(Service Level Objective)
Metrics
- Istio 基于
延迟
、流量
、错误
、饱和
生成一系列的服务指标 - Istio 为
网格控制平面
提供更详细的指标,以及基于这些指标的仪表盘
- Istio 基于
Traces
- 为每个服务生成分布式追踪
Span
- 为每个服务生成分布式追踪
Logs
- 当流量进入网格中的服务时,Istio 可以生成每个请求的完整记录
架构
因
过度设计
而导致运维(问题排查
+版本升级
)负担重,从微服务架构回归
单体架构
Plane | Desc |
---|---|
Data plane | 由一组以 Sidecar 方式部署的代理 组成代理可以调节和控制 微服务之间 以及微服务与 Mixer 之间 所有的网络通信 |
Control plane | 配置代理 来路由流量 配置 Mixer 来实施策略 和收集遥测数据 |
- Istio 的数据面为 Envoy
- Istio 监听 API Server,主要关注 Kubernetes Service Endpoint 和 Istio CRD
- 将配置信息(
Istio CRD
)和状态信息(Kubernetes Service Endpoint
)整合成 Envoy 配置 - 然后
下发
给 Envoy
- 将配置信息(
- Envoy 是类似于 Nginx 的
反向代理
- 加载配置文件后,监听在某个端口,接收并转发请求
设计目标
最大化透明度
- Istio 将自身
自动注入
到服务间所有
的网络路径中 - Istio 使用
Sidecar
来捕获流量
,并且尽可能地自动编程网络层
来路由流量,对应用无侵入
- 在 Kubernetes 中,
代理
被注入到Pod
中,通过编写iptables
来捕获流量 - 所有组件和 API 在设计时必须考虑
性能
和规模
增量
- 只推送
增量策略
- 预计最大的需求为
扩展策略系统
集成
其它策略和控制来源- 将网格行为信息
传播
到其它系统进行分析
策略运行时
支持标准扩展机制
以便插入
到其它服务中
可移植性
- 基于 Istio 的服务的移植成本很低
- 使用 Istio 将同一个服务同时部署到多个环境中
策略一致性
- 通过一套模型
统一
所有流量 策略系统
作为独立服务
,具有自身的 API,并非将其放到 Sidecar 中
Envoy
L7 Proxy
计算选型:能力 -> 性能 -> 稳定性
Envoy | Nginx | HA Proxy | |
---|---|---|---|
HTTP/2 | 完整支持 HTTP/2同时支持 upstream 和 downstream HTTP/2 |
从 1.9.5 开始有限支持 HTTP/2 支持 upstream HTTP/2 仅支持 downstream HTTP/1.1 |
- |
Rate Limit | 通过插件 支持 |
支持基于配置 的限流只支持基于源 IP 的限流 |
|
ACL | 基于插件 实现 L4 ACL |
基于源/目标地址 实现 ACL |
|
Connection Draining | 支持 hot reload 通过 share memory 实现 connection draining |
Nginx Plus 收费版本支持 | 支持热启动 不保证连接不丢失 |
- 当反向代理重启时,已经存在的连接是不能丢弃的
- 新 Envoy 进程启动时,老 Envoy 进程依然存活
- 新接收的请求会通过
Socket 复制
,让新 Envoy 进程去处理 - 本身还在处理的旧请求,会争取在限定时间内处理完
- 新接收的请求会通过
- 当老的 Envoy 进程退出后,新的 Envoy 进程会继续监听端口
配置变更
后,反向代理一般都需要重启
才能使得配置生效
而Nginx
和HA Proxy
都不保证Connection Draining
优势
性能
- 在具备
大量特性
的同时,Envoy 提供了极高的吞吐量
和低尾部延迟差异
,而 CPU 和 Memory消耗
相对较少
- 在具备
可扩展性
- 在
L4
和L7
都同时提供了丰富的可插拔
过滤器的能力
- 在
API 可配置性
- 核心竞争力(监听端口,接收配置,配置热加载
,无需重启)- Envoy 提供了一组可以通过
控制平面
服务实现的管理 API
- 如果控制平面实现所有的管理 API,则可以使用
通用引导
配置在整个基础架构上运行 Envoy 配置更改
可以通过管理服务器
以无缝方式动态传送
,因此 Envoy不需要重新启动
- 所以 Envoy 可以成为
通用数据平面
,当其与一个足够复杂
的控制平面
相结合时,会极大地降低整体运维的复杂性
- Envoy 提供了一组可以通过
线程模式
- Envoy 采用
单进程多线程
模型主线程
负责协调
子线程
负责监听过滤和转发
- 当某个连接被监听器
接受
,那么该连接的全部生命周期
会与某线程绑定
- 例如
长连接
的情况,绑定的好处就是可以实现无锁
操作
- 例如
- Envoy 基于
同步非阻塞
模式(epoll
) - 建议 Envoy 配置的
Worker 数
与 Envoy 所在的硬件线程数
一致
架构
XDS API 基于
gRPC
协议Envoy 启动时会基于一个静态配置文件,表明需要哪些管理服务器来管理 Envoy 的配置
- Envoy 会尝试连接管理服务器,连接建立后,管理服务器会通过 XDS API 下发 Envoy 配置
Envoy 配置 - 即常规反向代理的配置 - 都有对应的
发现
机制 - 配置从哪里来ListenerManager -
LDS
- 明确监听端口
RouteConfigProvider -
RDS
- 提供路由信息或者转发规则,路径 A 对应 SVC_A,而
SVC
在 Envoy 中为Cluster
- 提供路由信息或者转发规则,路径 A 对应 SVC_A,而
ClusterManager -
CDS
- 记录 host / ip / endpoint 信息 - 来自于 SVC,相当于一个 VIP
TLS - Thread Local Slot
- Worker 线程的 TLS 来自于主线程的 TLS
- 当处理新请求时,Worker 线程将采用由主线程
最新推送
下来的 TLS 数据
ConnectionHandler 实际处理网络数据,libevent 是基于 epoll 的框架
发现机制
Istio 配置信息
:监听某个端口,且有对应的路由规则列表,Route 匹配 Cluster
1 | - Listener Discovery Service |
Kubernetes 状态信息
:Cluster 可以简单对应为 KubernetesService
1 | - Cluster Discovery Service |
- Secret Discovery Service
- 如果监听端口走 HTTPS 协议,通过 SDS 获取密钥对
- Istio 默认去 Kubernetes Service 发现
- Health Discovery Service - Istio 未使用
- 反向代理一般需要对 upstream 进行探活,如果反向代理副本数很多,探活可能会给应用带来很大压力
- 可以
委托
其中一个反向代理实例去执行探活,其余实例基于 HDS 获取探活结果
- Aggregated Discovery Service
- 其它 XDS 之间是有
依赖
关系的,因此可以聚合好才一起下发 - 一般是除了 EDS(变更频繁,增量),其余的 XDS 聚合在一起,通过 ADS 下发
- 其它 XDS 之间是有
过滤器模式
不支持正则
- TLSInspector - TLS server name
indication
- 一个 Envoy Pod 监听在某个端口,但可能承载了很多域名,不同的域名签出的证书是不一样的
- 客户端在做 TLS 握手的时候,需要携带
FQDN
,TLSInspector 再去匹配对应域名的证书
- HTTP Filter
- Mixer - 限流
- Router - 路由转发
- VirtualHost - 域名匹配
- 路由匹配成功后,会转发到对应的 Cluster,即 SVC,进而对应不同的 Endpoint
实践
Upstream
1 | apiVersion: apps/v1 |
Envoy
Config
1 | admin: |
- admin 部分为 Envoy 的标准配置,代表管理端口
- static_resources 与 XDS 发现机制无关,属于静态配置
- listeners 与 clusters 位于同一层级
- listeners.address.socket_address 代表监听的端口地址
- listeners.filter_chains.filters.typed_config.route_config 为具体的路由配置
- 匹配任何域名,前缀为
/
时,路由到 some_service
- 匹配任何域名,前缀为
- some_service 基于 LOGICAL_DNS,即会解析 Kubernetes Service,实际的 Endpoint 为 simple:80
Proxy
1 | apiVersion: apps/v1 |