大家好,我是二哥。
上一篇《综合题:一个请求如何从service到达Pod ?》,我们聊了一个话题:一个请求是如何从service到达Pod的。其实这个话题二哥只聊了一半,另外一半是:Pod的响应又是如何返回的呢?
来吧,我们接着上一篇的测试环境,看看这个问题的答案是什么。
再一次,我们把讨论的环境做一个限制,我们尽量从简单的具象场景展开讨论。
- K8s网络模型为基于veth bridge vtep所组成的Overlay,这也就意味着Pod跨Node通信时,需要VXLAN的介入。
- 参与这个游戏的各方都位于同一个K8s Cluster,它们是:client Pod,service Cluster-IP和响应请求的Pod。这里的service Cluster-IP也会被称为virtual IP。
- pod向service发起的请求会经过iptables进行NAT处理。
NAT是一个好东西。它可以细分为以下几类:
- SNAT:仅对源地址(source)进行转换。
- DNAT:仅对目的地址(destination)进行转换。
- Full NAT:同时对源地址和目的地址进行转换。
图 1:请求经过虚拟的service Cluster-IP时的iptables
图1所示的iptables还记得吗?上一篇我们仔细聊过当请求到达一个K8s Node时,kube-proxy通过iptables将Cluster-IP转换成Pod IP的过程。
在这个iptables的作用下,请求从源Pod到达目的Pod的过程中,因为DNAT的参与,dest IP会经过一些变化。如图2中的① ②这两个步骤所示,这个变化是由最先收到请求的那台Node上的iptables负责完成的。
假设请求的发起方是一个IP为10.204.0.6的Pod,它访问的service cluster-ip为172.16.255.220,并最终由一个IP为10.204.1.3的Pod负责处理这个请求。我们约定这两个Pod位于不同的Node,也就出现了跨Node通信的场景。
当目的Pod响应请求时,对于我们这里的仅有DNAT参与的情形,响应网络包就不需要再经过NAT了,图2中的③展示了这个过程。你一定发现了返程并没有经过kube-proxy所设置的iptables。这很好理解,因为只有当目的IP为172.16.255.220时,子链KUBE-SERVICES所定义的规则才会生效。
代码语言:javascript复制-A KUBE-SERVICES -d 172.16.255.220/32 -p tcp -m comment
--comment "LanceAndCloudnative/nginx-web-service: cluster IP" -m tcp --dport 80 -j KUBE-SVC-4LFXAAP7ALRXDL3I
需要强调的是,虽然步骤③用一根箭头代表了数据的流向,但实际上在我们这个网络模型下,当出现跨Node通信时,需要VXLAN的介入。
图 2:仅使用DNAT时,游戏三方通信时IP变化
图2所示的其实是负载均衡里常提到的“三角模式”,因为通信过程中网络包的流向类似于一个三角形,故得名于此。
那如果iptables使用的是full NAT的方式,IP又是如何变化的呢?要不怎么说二哥是贴心的男人呢?图3已为你准备好了。这是负载均衡的“反向代理模式”。
图 3:当使用full NAT时,游戏三方通信时IP变化