集群内流量的源 IP 地址转换
Source IP address translation for intra-cluster traffic
我正在尝试深入研究 K8s 网络模型,我认为到目前为止我对它有很好的理解,但有一件事我无法理解。 Cluster Networking 指南中提到了以下内容:
Kubernetes imposes the following fundamental requirements on any networking implementation (barring any intentional network segmentation policies):
- all containers can communicate with all other containers without NAT
- all nodes can communicate with all containers (and vice-versa) without NAT
- the IP that a container sees itself as is the same IP
that others see it as
第二个要点指定 x 节点容器通信应该可以在没有 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:
中明确提到了这一点
Packets sent to ClusterIP from within the cluster are never source
NAT’d if you’re running kube-proxy in iptables mode, which is the
default since Kubernetes 1.2. If the client pod and server pod are in
the same node, the client_address is the client pod’s IP address.
However, if the client pod and server pod are in different nodes, the
client_address is the client pod’s node flannel IP address.
首先是说集群内的数据包永远不会经过 SNAT,然后继续说发送到其他节点中的 pods 的数据包实际上是经过 SNAT 的。我对此感到困惑 - 我是否误解了 所有节点都可以在没有 NAT 要求的情况下与所有容器通信(反之亦然)?
如果你阅读point 2:
Pod-to-Pod communications: this is the primary focus of this document.
这仍然适用于集群中的所有容器和 pods 运行,因为它们都在 PodCidr
:
- 所有容器都可以在没有 NAT 的情况下与所有其他容器通信
- 所有节点都可以与所有容器通信(反之亦然)
- 在没有 NAT 的情况下,容器将自己视为相同的 IP
其他人将其视为
基本上,所有 pods 都有唯一的 IP 地址,并且在同一个 space 中,并且可以在 IP 层与每个人通信。
此外,如果您查看其中一个 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
的数据包直接转发到连接到节点的隧道接口,因此那里没有 NATing。
现在,当您从 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]
我正在尝试深入研究 K8s 网络模型,我认为到目前为止我对它有很好的理解,但有一件事我无法理解。 Cluster Networking 指南中提到了以下内容:
Kubernetes imposes the following fundamental requirements on any networking implementation (barring any intentional network segmentation policies):
- all containers can communicate with all other containers without NAT
- all nodes can communicate with all containers (and vice-versa) without NAT
- the IP that a container sees itself as is the same IP that others see it as
第二个要点指定 x 节点容器通信应该可以在没有 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:
中明确提到了这一点Packets sent to ClusterIP from within the cluster are never source NAT’d if you’re running kube-proxy in iptables mode, which is the default since Kubernetes 1.2. If the client pod and server pod are in the same node, the client_address is the client pod’s IP address. However, if the client pod and server pod are in different nodes, the client_address is the client pod’s node flannel IP address.
首先是说集群内的数据包永远不会经过 SNAT,然后继续说发送到其他节点中的 pods 的数据包实际上是经过 SNAT 的。我对此感到困惑 - 我是否误解了 所有节点都可以在没有 NAT 要求的情况下与所有容器通信(反之亦然)?
如果你阅读point 2:
Pod-to-Pod communications: this is the primary focus of this document.
这仍然适用于集群中的所有容器和 pods 运行,因为它们都在 PodCidr
:
- 所有容器都可以在没有 NAT 的情况下与所有其他容器通信
- 所有节点都可以与所有容器通信(反之亦然)
- 在没有 NAT 的情况下,容器将自己视为相同的 IP 其他人将其视为
基本上,所有 pods 都有唯一的 IP 地址,并且在同一个 space 中,并且可以在 IP 层与每个人通信。
此外,如果您查看其中一个 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
的数据包直接转发到连接到节点的隧道接口,因此那里没有 NATing。
现在,当您从 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]