kube-dns 的 iptables 规则

iptables rules for kube-dns

我查看了 kube-dns 使用的 iptables 规则,我对子链“KUBE-SEP-V7KWRXXOBQHQVWAT”有点困惑,该子链的内容如下:
我的问题是当源 IP 地址 (172.168.1.5) 是 kube-dns IP 地址时,为什么我们需要目标“KUBE-MARK-MASQ”。根据我的理解,目标 IP 地址应该是 kube-dns pod 的地址 172.168.1.5,而不是源 IP 地址。因为所有的 DNS 查询都来自其他地址(服务),DNS 查询不能来自它自己。

# iptables -t nat -L KUBE-SEP-V7KWRXXOBQHQVWAT
Chain KUBE-SEP-V7KWRXXOBQHQVWAT (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  all  --  172.18.1.5           anywhere             /* kube-system/kube-dns:dns-tcp */
DNAT       tcp  --  anywhere             anywhere             /* kube-system/kube-dns:dns-tcp */ tcp to:172.18.1.5:53

这里是全链信息:

# iptables -t nat -L KUBE-SERVICES
Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-MARK-MASQ  tcp  -- !172.18.1.0/24        10.0.62.222          /* kube-system/metrics-server cluster IP */ tcp dpt:https
KUBE-SVC-QMWWTXBG7KFJQKLO  tcp  --  anywhere             10.0.62.222          /* kube-system/metrics-server cluster IP */ tcp dpt:https
KUBE-MARK-MASQ  tcp  -- !172.18.1.0/24        10.0.213.2           /* kube-system/healthmodel-replicaset-service cluster IP */ tcp dpt:25227
KUBE-SVC-WT3SFWJ44Q74XUPR  tcp  --  anywhere             10.0.213.2           /* kube-system/healthmodel-replicaset-service cluster IP */ tcp dpt:25227
KUBE-MARK-MASQ  tcp  -- !172.18.1.0/24        10.0.0.1             /* default/kubernetes:https cluster IP */ tcp dpt:https
KUBE-SVC-NPX46M4PTMTKRN6Y  tcp  --  anywhere             10.0.0.1             /* default/kubernetes:https cluster IP */ tcp dpt:https
KUBE-MARK-MASQ  udp  -- !172.18.1.0/24        10.0.0.10            /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SVC-TCOU7JCQXEZGVUNU  udp  --  anywhere             10.0.0.10            /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-MARK-MASQ  tcp  -- !172.18.1.0/24        10.0.0.10            /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SVC-ERIFXISQEP7F7OF4  tcp  --  anywhere             10.0.0.10            /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-NODEPORTS  all  --  anywhere             anywhere             /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL
# iptables -t nat -L KUBE-SVC-ERIFXISQEP7F7OF4
Chain KUBE-SVC-ERIFXISQEP7F7OF4 (1 references)
target     prot opt source               destination
KUBE-SEP-V7KWRXXOBQHQVWAT  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns-tcp */ statistic mode random probability 0.50000000000
KUBE-SEP-BWCLCJLZ5KI6FXBW  all  --  anywhere             anywhere             /* kube-system/kube-dns:dns-tcp */
# iptables -t nat -L KUBE-SEP-V7KWRXXOBQHQVWAT
Chain KUBE-SEP-V7KWRXXOBQHQVWAT (1 references)
target     prot opt source               destination
KUBE-MARK-MASQ  all  --  172.18.1.5           anywhere             /* kube-system/kube-dns:dns-tcp */
DNAT       tcp  --  anywhere             anywhere             /* kube-system/kube-dns:dns-tcp */ tcp to:172.18.1.5:53

你可以把iptables中的kubernetes服务路由想成如下步骤:

  1. 循环持有所有 kubernetes 服务的链
  2. 如果您命中匹配的服务地址和 IP,请转到服务链
  3. 服务链将从端点列表中随机 select 一个端点(使用概率)
  4. 如果端点 selected 与流量的源地址具有相同的 IP,稍后将其标记为 MASQUERADE(这就是您要询问的 KUBE-MARK-MASQ)。换句话说,如果一个 pod 试图与一个服务 IP 对话,并且该服务 IP“解析”到 pod 本身,我们需要稍后将其标记为 MASQUERADE(实际的 MASQUERADE 目标在 POSTROUTING 链中,因为它只允许在那里发生)
  5. 对 selected 端点和端口执行 DNAT。无论 3) 是否发生,都会发生这种情况。

如果您查看 iptables -t nat -L POSTROUTING,将会有一条规则正在寻找标记的数据包,而这正是 MASQUERADE 实际发生的地方。

KUBE-MARK-MASQ 规则必须存在的原因是发夹 NAT。详细解释为什么有点复杂,但这是我最好的尝试:

如果 MASQUERADE 没有 发生,流量将离开 pod 的网络命名空间为 (pod IP, source port -> virtual IP, virtual port),然后被 NAT 到 (pod IP, source port-> pod IP, service port) 并立即发送回到吊舱。因此,此流量随后将到达服务,源为 (pod IP, source port)。因此,当此服务回复时,它将回复 (pod IP, source port),但是 pod(实际上是内核)期望流量返回到它发送的相同 IP 和端口最初的流量,即 (virtual IP, virtual port),因此流量会在返回途中丢失。