换个角度看 istio route

WilliamGates
发布于 2023-7-28 16:39
浏览
0收藏

大家好,我是二哥。

话接上回,我在准备课程《图解 VPC & K8s networking model》的时候,需要讲述 iptables / netfilter 的概念和使用方法。内容既包括简单的诸如 drop package 之类的规则,也包括 istio 如何做到透明地劫持 workload 里面 app 的流量的。

说到透明流量劫持,对 service mesh 感兴趣的同学一定看到过 Jimmy Song 所画的下面这张图及其各个时期不同的版本。

换个角度看 istio route-鸿蒙开发者社区

这张图再搭配详细的 iptables ,食用起来别提有多爽。二哥就是把图和 iptables 内容都打印出来,仔细对比研究的。大神的分析真是透彻啊。

换个角度看 istio route-鸿蒙开发者社区

不过研究完后,二哥觉得有必要换个角度看一下这个问题。大神的图当然好,但隐藏了一些我觉得挺重要的的细节信息,于是我斗胆重新画了另一张图作为补充。

换个角度看 istio route-鸿蒙开发者社区

图 3 中的序号和图 1 中的序号所表示的作用一一对应。那这张图和 Jimmy 的那张有何不同呢?且听我慢慢道来。

不同之一我按照大家所熟悉的应用层和内核层的相对位置,把 Envoy / App container 和 位于内核的 iptables & route table 进行了上下方位的布置。原图左右布局看得二哥脖子都快扭伤了。

不同之二:我用黑线画出了请求的路径,用蓝线画出了响应路径。请求首先到达 Envoy 的 Inbound hanlder。请求和响应在 App container 里面相遇,响应首先从 App container  出发,经过 Envoy 的 Outbound handler 处理之后离开 Pod 。

在说到使用 iptables 做流量劫持存在的问题时,Jimmy 大神谈到:outbond 流量将两次穿越协议栈,在大并发场景下会损失转发性能。结合图 3 ,可以看到为了完成整个请求和响应,一共涉及到六次协议栈穿越。分别是① ⑤ ⑧ ⑨ ⑫ ⑬ 所在的那六条线。

当然即使不引入 sidecar ,也有两次协议栈穿越是必须的。所以 sidecar 虽好,多了四次额外的操作也难免让人心碎。

不同之三:istio 通过 iptables 规则来实现的透明流量劫持的方案,其实有两个主要的入口链:PREROUTING 链和 OUTPUT 链。虽然它定义了若干个以 ISTIO_XXX 为前缀的子链,但子链终归是子链,它只能影响流量,不能影响 netfilter 的框架和运行机制。二哥认为需要抓住这两个主要的入口链,才不会迷失在错综复杂的子链跳转以及子规则里面。

比如我们分析下面这段 iptables 内容,看到在 ISTIO_INBOUND 里面,当 target 为 RETURN 时表示什么?return 到哪里去了呢?

结合我新画的图,你可以很容易地看出来,它表示 ISTIO_OUTPUT 子链处理结束了,OUTPUT 入口链也结束了,下一步该进行路由选择和 POSTROUTING 链的处理了。

# OUTPUT chain: jumps all outbound packets to the ISTIO_OUTPUT chain.
Chain OUTPUT (policy ACCEPT 79 packets, 6761 bytes)
pkts bytes target     prot opt in     out     source               destination
  15   900 ISTIO_OUTPUT tcp -- any    any     anywhere             anywhere

Chain ISTIO_INBOUND (1 references)
pkts bytes target     prot opt in     out     source               destination
  0     0  RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh
  2   120  RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15090
2699 162K  RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15020
  0     0  ISTIO_IN_REDIRECT tcp -- any   any     anywhere             anywhere

二哥把 netfilter 里面的五条链都在相应的位置画了出来。我还特意给 PREROUTING 链和 OUTPUT 链用上了不同的颜色,以示特殊。当然路由选择也是非常重要的步骤,我不会忘记它的。

不同之四:我加上了 eth0 以及 loopback 这两个网络设备。在我看来这非常重要,因为我们需要搞清楚请求一开始是从哪里进入 Pod 的,被 Envoy 劫持后又是从哪个网络设备流向了 App container。反之亦是如此,我们需要清楚地看到响应流量是如何从 App container 经 loopback 流向了 Envoy ,又是如何从 eth0 离开了 Pod 。

加上这两个设备后,我们可以清晰地看出来,Envoy 和 App 之间是通过 loopback 通信的。当然这个过程对 App 而言是透明的、无感的。App 以为它把请求发给了 dest IP ,哪知道被改成了 127.0.0.1 ,而端口被改成了 15001。

结合“不同之三”,我们还需要知道:流量进/出 Envoy 以及 进/出 App container 时,首先遇到的是哪个入口链。只有搞清楚了这个,才能头脑清醒地去分析 iptables 。

不同之五:在学习大神的文章时,我突然想到一个事情。App container 无论是回复响应还是向 up stream 发起新的请求,iptables 都会通过 REDIRECT 将流量劫持到 Envoy 的 Outbound handler 那里。

Chain ISTIO_REDIRECT (1 references)
pkts bytes target     prot opt in     out     source               destination
  0     0  REDIRECT   tcp  --  any    any     anywhere             anywhere             redir ports 15001

我们来看看 REDIRECT 对流量干了啥事。

REDIRECT
This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains. It redirects the packet to the machine itself by changing the destination IP to the primary address of the incoming interface (locally-generated packets are mapped to the localhost address, 127.0.0.1 for IPv4 and ::1 for IPv6).

说白了,它会把 dest IP 和 dest Port 改成 127.0.0.1:15001 。这好理解,毕竟只有这样 IP 层才会把从 App container 出来的流量路由至 listen 在 15001 的 Outbound hanlder 去处理。

但问题是:当 Outbound handler 处理完它自己的工作后,它又是如何记得 App container 原来的 dest IP 和 dest Port 的呢?它得想起来这个,不然它没法代替 App container 把流量发出去。

答案是需要借助 getsockopt 方式(示例代码如下)或者 conntrack 获得。所以我把 conntrack 画在了图 3 里面,它是一个重要的组成部分,我们不能忽视它的存在。

#include <linux/netfilter_ipv4.h>

struct sockaddr_in addr;
socklen_t addr_sz = sizeof(addr);
memset(&addr, 0, addr_sz);
addr.sin_family = AF_INET;
getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, &addr, &addr_sz);

以上就是本文的全部内容。码字不易,画图更难。喜欢本文的话请帮忙转发或点击“在看”。您的举手之劳是对二哥莫大的鼓励。谢谢!


文章转载自公众号:二哥聊云原生

分类
已于2023-7-28 16:39:34修改
收藏
回复
举报
回复
    相关推荐