Kubernetes 和 iptables 不混合:连接内容丢失?

Kubernetes 和 iptables 不混合:连接内容丢失?

我正在使用裸机 Kubernetes 集群(使用 calico CNI 插件),在将外部流量重定向到节点时遇到了麻烦。我设置了 nginx kubernetes 入口控制器,以便通过NodePort(在端口 30528 上)公开 HTTPS 服务。我可以在端口 30528 上正常访问该服务,因此流量在 kubernetes 中被正确重定向。

当然,我希望将其暴露在端口 443 上,而不是 30528 上,因此我使用了通常用于服务器进行端口重新映射的工具 --- 端口重定向 iptables 规则。这个特定的系统使用 shorewall 来管理 iptables 规则,我对此很熟悉,所以很好。我从一个测试 shorewall 规则开始,将端口 1443 重定向到 30528。shorewall 规则如下所示:

REDIRECT        net             30528           tcp     1443

对于那些不熟悉 shorewall 的人来说,这会在PREROUTING表中生成一个条目,如下所示:

$ iptables -t nat -L -v -n
Chain PREROUTING (policy ACCEPT 160 packets, 8642 bytes)
 pkts bytes target     prot opt in     out     source               destination         
        <snip k8s/calico rules>
    0     0 REDIRECT   tcp  --  eth0   *       192.168.1.0/24       0.0.0.0/0            tcp dpt:1443 redir ports 30528
        <snip following rules>
<snip following chains>

当我尝试从服务器外部连接到该端口时,发生了一些奇怪的事情。

$ curl -v -v https://<server-ip>:1443/
*   Trying 192.168.3.1:1443...
* Connected to <hostname> (<server-ip>) port 1443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):

然后 TCP 连接就会挂起,直到我将其终止。Wireshark 显示正在发送 TLS Client Hello、服务器ACK正在发送数据包,以及每 60 秒发送一次的 TCP Keep-Alive,但没有任何内容能够到达 Kubernetes。如果我使用redir从 1443 到 30528 的反弹连接,一切都会正常工作。(当然,如果我将 1443 重定向到端口 2000 并使用 netcat 监听端口 2000,一切都会按预期工作,所以我不会思考设置的其他部分是否存在任何异常。

有人知道这里可能出了什么问题吗?对我来说最有意义的事情是,由于 calico/kubernetes 在PREROUTINGiptables 之前将其自己的重定向规则插入表中redir,因此由于排序而错过了对端口 30528 的处理。不过,在这种情况下,我真的很困惑为什么连接实际上是建立的 --- 我本以为它只是简单地失败!

(由于这台机器位于另一个用于 NAT 的防火墙后面,我可以调整防火墙,将发往端口 443 的流量重定向到 30528,这个问题易溶,但我更愿意弄清楚发生了什么,以供将来参考......)

相关内容