k8s:使用 iptables 从 public VIP 转发到 clusterIP
k8s: forwarding from public VIP to clusterIP with iptables
我试图深入了解从公开暴露的负载均衡器的第 2 层 VIP 到服务的集群 IP 的转发是如何工作的。我已经阅读了如何 MetalLB does it 的高级概述,并且我尝试通过设置 keepalived/ucarp VIP 和 iptables 规则来手动复制它。我一定是遗漏了一些东西,因为它不起作用 ;-]
我的步数:
创建了一个集群 kubeadm
由一个主节点 + 3 个节点组成 运行 k8s-1.17.2 + calico-3.12 on libvirt/KVM VMs on a single电脑。所有 VM 都在 192.168.122.0/24
虚拟网络中。
创建了一个简单的 2 pod 部署并将其作为 NodePort
服务公开,externalTrafficPolicy
设置为 cluster
:
$ kubectl get svc dump-request
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dump-request NodePort 10.100.234.120 <none> 80:32292/TCP 65s
我已经验证我可以从每个节点的 IP 上的主机的 32292 端口访问它。
在所有 3 个节点上用 ucarp
创建了一个 VIP:
ucarp -i ens3 -s 192.168.122.21 -k 21 -a 192.168.122.71 -v 71 -x 71 -p dump -z -n -u /usr/local/sbin/vip-up.sh -d /usr/local/sbin/vip-down.sh
(来自 knode1 的示例)
我已验证我可以 ping 192.168.122.71
VIP。我什至可以通过它连接到当前持有 VIP 的虚拟机。
现在,如果 kube-proxy 处于 iptables
模式,我也可以通过位于 http://192.168.122.71:32292
的 VIP 访问其节点端口上的服务。然而,令我惊讶的是,在 ipvs
模式下,这总是导致连接超时。
在每个节点上添加了一条 iptables 规则,用于将传入 192.168.122.71
的数据包转发到服务的集群 IP 10.100.234.120
:
iptables -t nat -A PREROUTING -d 192.168.122.71 -j DNAT --to-destination 10.100.234.120
(后来我也尝试将规则缩小到相关端口,但它并没有以任何方式改变结果:
iptables -t nat -A PREROUTING -d 192.168.122.71 -p tcp --dport 80 -j DNAT --to-destination 10.100.234.120:80
)
结果:
在 iptables
模式下,对 http://192.168.122.71:80/
的所有请求都会导致连接超时。
在 ipvs
模式下它部分工作:
如果 192.168.122.71
VIP 由其上有 pod 的节点持有,则大约 50% 的请求会成功,并且它们 always 由本地 pod 提供服务。该应用程序还获取了主机的真实远程 IP (192.168.122.1
)。其他 50%(大概被发送到另一个节点上的 pod)超时了。
如果 VIP 由没有 pods 的节点持有,那么所有请求都会超时。
我还检查了它是否以任何方式影响结果,以始终在所有节点上保留规则与仅在持有 VIP 的节点上保留规则并在释放 VIP 时将其删除:结果在这两种情况下都是一样的。
有谁知道为什么它不起作用以及如何解决它?我将不胜感激:)
还需要添加 MASQUERADE
规则,以便相应地更改源。例如:
iptables -t nat -A POSTROUTING -j MASQUERADE
通过 ipvs
测试
我试图深入了解从公开暴露的负载均衡器的第 2 层 VIP 到服务的集群 IP 的转发是如何工作的。我已经阅读了如何 MetalLB does it 的高级概述,并且我尝试通过设置 keepalived/ucarp VIP 和 iptables 规则来手动复制它。我一定是遗漏了一些东西,因为它不起作用 ;-]
我的步数:
创建了一个集群
kubeadm
由一个主节点 + 3 个节点组成 运行 k8s-1.17.2 + calico-3.12 on libvirt/KVM VMs on a single电脑。所有 VM 都在192.168.122.0/24
虚拟网络中。创建了一个简单的 2 pod 部署并将其作为
NodePort
服务公开,externalTrafficPolicy
设置为cluster
:
$ kubectl get svc dump-request NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE dump-request NodePort 10.100.234.120 <none> 80:32292/TCP 65s
我已经验证我可以从每个节点的 IP 上的主机的 32292 端口访问它。在所有 3 个节点上用
ucarp
创建了一个 VIP:
ucarp -i ens3 -s 192.168.122.21 -k 21 -a 192.168.122.71 -v 71 -x 71 -p dump -z -n -u /usr/local/sbin/vip-up.sh -d /usr/local/sbin/vip-down.sh
(来自 knode1 的示例)
我已验证我可以 ping192.168.122.71
VIP。我什至可以通过它连接到当前持有 VIP 的虚拟机。
现在,如果 kube-proxy 处于iptables
模式,我也可以通过位于http://192.168.122.71:32292
的 VIP 访问其节点端口上的服务。然而,令我惊讶的是,在ipvs
模式下,这总是导致连接超时。在每个节点上添加了一条 iptables 规则,用于将传入
192.168.122.71
的数据包转发到服务的集群 IP10.100.234.120
:
iptables -t nat -A PREROUTING -d 192.168.122.71 -j DNAT --to-destination 10.100.234.120
(后来我也尝试将规则缩小到相关端口,但它并没有以任何方式改变结果:
iptables -t nat -A PREROUTING -d 192.168.122.71 -p tcp --dport 80 -j DNAT --to-destination 10.100.234.120:80
)
结果:
在 iptables
模式下,对 http://192.168.122.71:80/
的所有请求都会导致连接超时。
在 ipvs
模式下它部分工作:
如果 192.168.122.71
VIP 由其上有 pod 的节点持有,则大约 50% 的请求会成功,并且它们 always 由本地 pod 提供服务。该应用程序还获取了主机的真实远程 IP (192.168.122.1
)。其他 50%(大概被发送到另一个节点上的 pod)超时了。
如果 VIP 由没有 pods 的节点持有,那么所有请求都会超时。
我还检查了它是否以任何方式影响结果,以始终在所有节点上保留规则与仅在持有 VIP 的节点上保留规则并在释放 VIP 时将其删除:结果在这两种情况下都是一样的。
有谁知道为什么它不起作用以及如何解决它?我将不胜感激:)
还需要添加 MASQUERADE
规则,以便相应地更改源。例如:
iptables -t nat -A POSTROUTING -j MASQUERADE
通过 ipvs