我正在尝试深入研究 K8s 网络模型,并且我认为到目前为止我对它已经有了很好的理解,但是有一件事我无法理解。在Cluster Networking指南中,提到了以下内容:
Kubernetes 对任何网络实现都提出了以下基本要求(除非任何有意的网络分段策略):
- 所有容器都可以在没有 NAT 的情况下与所有其他容器通信
- 所有节点都可以在没有 NAT 的情况下与所有容器通信(反之亦然)
- 容器认为自己的 IP 与其他人认为的 IP 相同
第二个要点指定 x-node 容器通信应该可以在没有 NAT 的情况下进行。然而,当 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
看起来 K8s 正在将标记的出站数据包的源 IP 更改为节点的 IP(对于 ClusterIP 服务)。他们甚至在Source IP for Services with Type=ClusterIP中明确提到了这一点:
如果你在 iptables 模式下运行 kube-proxy,从集群内部发送到 ClusterIP 的数据包永远不会进行源 NAT,这是自 Kubernetes 1.2 以来的默认设置。如果客户端 Pod 和服务器 Pod 在同一个节点中,则 client_address 是客户端 Pod 的 IP 地址。但是,如果客户端 pod 和服务器 pod 位于不同的节点中,则 client_address 是客户端 pod 的节点 flannel IP 地址。
首先说集群中的数据包从不经过 SNAT,然后继续说发送到其他节点中的 pod 的包实际上是经过 SNAT 的。我对此感到困惑 - 我是否误解了所有节点都可以在没有 NAT要求的情况下与所有容器通信(反之亦然) ?