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服务路由想成如下步骤:
- 循环持有所有 kubernetes 服务的链
- 如果您命中匹配的服务地址和 IP,请转到服务链
- 服务链将从端点列表中随机 select 一个端点(使用概率)
- 如果端点 selected 与流量的源地址具有相同的 IP,稍后将其标记为 MASQUERADE(这就是您要询问的
KUBE-MARK-MASQ
)。换句话说,如果一个 pod 试图与一个服务 IP 对话,并且该服务 IP“解析”到 pod 本身,我们需要稍后将其标记为 MASQUERADE(实际的 MASQUERADE 目标在 POSTROUTING 链中,因为它只允许在那里发生)
- 对 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)
,因此流量会在返回途中丢失。
我查看了 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服务路由想成如下步骤:
- 循环持有所有 kubernetes 服务的链
- 如果您命中匹配的服务地址和 IP,请转到服务链
- 服务链将从端点列表中随机 select 一个端点(使用概率)
- 如果端点 selected 与流量的源地址具有相同的 IP,稍后将其标记为 MASQUERADE(这就是您要询问的
KUBE-MARK-MASQ
)。换句话说,如果一个 pod 试图与一个服务 IP 对话,并且该服务 IP“解析”到 pod 本身,我们需要稍后将其标记为 MASQUERADE(实际的 MASQUERADE 目标在 POSTROUTING 链中,因为它只允许在那里发生) - 对 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)
,因此流量会在返回途中丢失。