本篇文章主要来讲解下流量劫持到envoy之后,envoy层面是如何处理,并成功找到它的下一跳服务的,当然也是我们平时说的upstream。
Envoy在实现层面,定义了listener、filter这些对象,具体如下所示:
Listener对应的是LDS里面的配置,通常一个LDS对应一个Listener,而它是一般格式是clusterIP Port的方式,如果多个serviceName对应一个LDS的话,会转换成0.0.0.0 Port的样子。
因为iptables劫持流量的时候,只会在Envoy中基于outbound流量出口15006创建一个真实的物理连接socket,所有的流量到了这个socket之后,会先匹配到对应Listener。
Listener可以理解成一个逻辑连接,存储在内存中,通过流量中的带下来的Host Port进行匹配,命中的话,就会走这个Listener进行处理。
Listener下面会挂载很多filterchains链,这些filterchains是用户根据不同的需求设置的filter数组,而每一个filter表示的是对流量某一段处理的逻辑对象。例如:处理http的filter,它会先将http包进行decode,然后去匹配RDS和CDS,以便找到这个服务对应的下一跳upstream。在找到之后,filter会通过encode在http的头里面,添加上客观性相关的数据头tag,并最终将消息发送到对应的upstream。
在istio原生的环境里面,outbound收到的消息一般是http://servicename:port/api这个格式,往往在匹配Listener之前,会先经过k8s的dns去找一波servicename对应的clusterIp,让后通过clusterIp Port去匹配Listener。
参考文档:
https://github.com/envoyproxy/envoy/blob/main/api/envoy/config/listener/v3/listener_components.proto
https://jimmysong.io/blog/envoy-proxy-config-deep-dive/