注: 文中示例信息来自istio官方book示例.
istio中的边车代理envoy会拦截到两类流量:
1) 入流量: 其他Pod访问当前Pod中业务服务的流量。入流量访问的集群以inbound开头命名:
inbound|9080|v1|ratings.default.svc.cluster.local
2) 出流量: 当前Pod中业务服务访问其他服务的流量,包括其他POD中的业务服务和istio系统相关的服务。入流量访问的集群命名以outbound开头: outbound|9080|v1|ratings.default.svc.cluster.local
入流量的上游集群比较简单,一般只有一个:1
2
3
4
5
6
7
8"hosts": [
{
"socket_address": {
"address": "127.0.0.1",
"port_value": 9080
}
}
]
这个Endpoint(127.0.0.1:9080)指向本地服务。出流量的上游集群包括所有的服务集群,因为当前POD的本地服务有访问任何服务的可能。
Envoy代理拦截到出流量之后,会根据被访问service的域名,URL等相关信息定位到特定的路由,然后到特定的集群,再按集群内部的负载算法获取特定的Endpoint地址,将流量发送给这个Endpoint。流量图大体如下:
这个复杂的过程中,有两个重要的参数:
1) litener.use_original_dst:
如果采有iptables重定向连接, 那么envoy接受连接的监听端口与请求连接的原始目的地址是不同的。如果listener该属性设置为true,该listener将接收到的连接转交给符合请求原始地址的Listener。(透明代理获取原始地址?)由新的listener接受和处理该连接请求。前一个Listener相当于只分发连接。在istio中,这个Listener命名为命virtual。到达envoy的流量统一重定向到virtual listener中(监听地址为0.0.0.0:15001),由它来选择合适的Listener处理流量。
2) litener.bind_to_port
这个属性在api-v2中找不到了,也没找到新替代者的说明。在istio 1.0版本中仍然使用他,但标记已过期。该属性表示Listener是否绑定主机端口。那么不绑定的端口的Listener,如何接受流量?是由标识use_original_dst的Listener(上文中的virtual Listener)接受流量,并转发给他。0.0.0.0_9080和10.244.2.20_9080都是bind_to_port为false的Listener,等待virtual listener分发的流量。0.0.0.0_9080接收所有9080端口的出流量,10.244.2.20_9080接受入流量。
9080本地服务的端口,15000是envoy代理的管理端口,0.0.0.0:15001就是virtual listener的监听地址,envoy用来接收流量。在evnoy的配置中看到其他listener都没有绑定端口。
Note:
获取envoy全配置的方法:
kubectl exec productpage-v1-f5fcbd489-s7tfz -c istio-proxy – curl http://127.0.0.1:15000/config_dump