群集内流量的源IP地址转换

时间:2018-10-26 21:15:52

标签: kubernetes kube-proxy

我正在尝试深入研究K8s的网络模型,到目前为止,我认为我对此已经有了很好的了解,但是有一件事我无法理解。在Cluster Networking指南中,提到了以下内容:

  

Kubernetes对任何网络实施都施加以下基本要求(除非有任何故意的网络分段策略):

     
      
  • 所有容器无需NAT即可与所有其他容器通信
  •   
  • 所有节点无需NAT即可与所有容器通信(反之亦然)
  •   
  • 容器所看到的IP是相同的IP   被其他人视为
  •   

第二个要点指出,不使用NAT即可进行x节点容器通信。但是,当kube-proxy在iptables模式下运行时,情况并非如此。这是我的一个节点中的iptables转储:

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
KUBE-POSTROUTING  all  --  anywhere             anywhere             /* kubernetes postrouting rules */

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination         
MASQUERADE  all  --  anywhere             anywhere             /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000

/* sample target pod chain being marked for MASQ */
Chain KUBE-SEP-2BKJZA32HM354D5U (1 references)
target     prot opt source               destination         
KUBE-MARK-MASQ  all  --  xx.yyy.zzz.109       anywhere             /* kube-system/heapster: */
DNAT       tcp  --  anywhere             anywhere             /* kube-system/heapster: */ tcp to:xx.yyy.zzz.109:8082

Chain KUBE-MARK-MASQ (156 references)
target     prot opt source               destination         
MARK       all  --  anywhere             anywhere             MARK or 0x4000

就像K8一样,正在将标记出站数据包的源IP更改为节点的IP(用于ClusterIP服务)。他们甚至在Source IP for Services with Type=ClusterIP中明确提到了这一点:

  

从群集内部发送到ClusterIP的数据包从不作为源   如果您在iptables模式下运行kube-proxy,则进行NAT   从Kubernetes 1.2开始默认。 如果客户端Pod和服务器Pod位于   在同一节点上,client_address是客户端窗格的IP地址。   但是,如果客户端Pod和服务器Pod在不同的节点中,   client_address是客户端窗格的节点法兰IP地址。

首先说集群中的数据包从不进行SNAT,然后继续说发送到其他节点中的Pod的包实际上是SNAT。我对此感到困惑-我是否误解了所有节点都可以以某种方式与所有容器通信(反之亦然)而无需NAT 要求?

1 个答案:

答案 0 :(得分:1)

如果您阅读point 2

  

点对点通信:这是本文档的主要重点。

这仍然适用于群集中运行的所有容器和容器,因为它们都在PodCidr中:

  • 所有容器无需NAT即可与所有其他容器通信
  • 所有节点都可以与所有容器通信(反之亦然)
  • 没有NAT的容器所看到的IP就是同一IP 被其他人视为

基本上,所有Pod都具有唯一的IP地址,并且位于同一空间中,并且可以在IP层与每个Pod对话。

此外,如果您查看一个Kubernetes节点上的路由,您会在Calico上看到类似的内容,其中podCidr为192.168.0.0/16

default via 172.0.0.1 dev ens5 proto dhcp src 172.0.1.10 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.31.0.0/20 dev ens5 proto kernel scope link src 172.0.1.10
172.31.0.1 dev ens5 proto dhcp scope link src 172.0.1.10 metric 100
blackhole 192.168.0.0/24 proto bird
192.168.0.42 dev calixxxxxxxxxxx scope link
192.168.0.43 dev calixxxxxxxxxxx scope link
192.168.4.0/24 via 172.0.1.6 dev tunl0 proto bird onlink
192.168.7.0/24 via 172.0.1.55 dev tunl0 proto bird onlink
192.168.8.0/24 via 172.0.1.191 dev tunl0 proto bird onlink
192.168.9.0/24 via 172.0.1.196 dev tunl0 proto bird onlink
192.168.11.0/24 via 172.0.1.147 dev tunl0 proto bird onlink

您会看到带有192.168.x.x的数据包直接转发到连接到节点的隧道接口,因此在那里没有NAT。

现在,当您从外部连接PodCidr时,您的数据包肯定经过了NAT,例如通过服务通过外部主机进行。您肯定还会看到iptable规则,如下所示:

# Completed on Sat Oct 27 00:22:39 2018
# Generated by iptables-save v1.6.1 on Sat Oct 27 00:22:39 2018
*nat
:PREROUTING ACCEPT [65:5998]
:INPUT ACCEPT [1:60]
:OUTPUT ACCEPT [28:1757]
:POSTROUTING ACCEPT [61:5004]
:DOCKER - [0:0]
:KUBE-MARK-DROP - [0:0]