3

[免责声明:这个问题最初发布在 ServerFault 上。但是,由于官方 K8s文档声明“在 StackOverflow 上提出您的问题”,因此我也在此处添加它]

我正在尝试使用 OCI VM 实例在 Oracle Cloud 上部署测试 Kubernetes 集群 - 但是,我遇到了 pod 网络问题。

网络插件是 Calico - 它似乎安装正确,但没有流量通过隧道从一台主机传输到另一台主机。例如,这里我试图访问在另一个节点上运行的 nginx:

root@kube-01-01:~# kubectl get pod -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP              NODE              NOMINATED NODE
nginx-dbddb74b8-th9ns   1/1     Running   0          38s   192.168.181.1   kube-01-06   <none>
root@kube-01-01:~# curl 192.168.181.1
[ ... timeout... ]

使用 tcpdump,我看到 IP-in-IP(协议 4)数据包离开第一个主机,但它们似乎从未到达第二个主机(尽管所有其他数据包,包括 BGP 流量,都可以正常通过)。

root@kube-01-01:~# tcpdump -i ens3 proto 4 &
[1] 16642
root@kube-01-01:~# tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens3, link-type EN10MB (Ethernet), capture size 262144 bytes

root@kube-01-01:~# curl 192.168.181.1
09:31:56.262451 IP kube-01-01 > kube-01-06: IP 192.168.21.64.52268 > 192.168.181.1.http: Flags [S], seq 3982790418, win 28000, options [mss 1400,sackOK,TS val 9661065 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)
09:31:57.259756 IP kube-01-01 > kube-01-06: IP 192.168.21.64.52268 > 192.168.181.1.http: Flags [S], seq 3982790418, win 28000, options [mss 1400,sackOK,TS val 9661315 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)
09:31:59.263752 IP kube-01-01 > kube-01-06: IP 192.168.21.64.52268 > 192.168.181.1.http: Flags [S], seq 3982790418, win 28000, options [mss 1400,sackOK,TS val 9661816 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)

root@kube-01-06:~# tcpdump -i ens3 proto 4 &
[1] 12773
root@kube-01-06:~# tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens3, link-type EN10MB (Ethernet), capture size 262144 bytes

到目前为止我检查过的内容:

  1. Calico 路由网格很好用。我可以在数据包捕获中看到 BGP 流量,我可以使用 calicoctl 看到所有节点都“启动”

root@kube-01-01:~# ./calicoctl node status Calico 进程正在运行。

IPv4 BGP status
+--------------+-------------------+-------+----------+-------------+
| PEER ADDRESS |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+--------------+-------------------+-------+----------+-------------+
| 10.13.23.123 | node-to-node mesh | up    | 09:12:50 | Established |
| 10.13.23.124 | node-to-node mesh | up    | 09:12:49 | Established |
| 10.13.23.126 | node-to-node mesh | up    | 09:12:50 | Established |
| 10.13.23.129 | node-to-node mesh | up    | 09:12:50 | Established |
| 10.13.23.127 | node-to-node mesh | up    | 09:12:50 | Established |
| 10.13.23.128 | node-to-node mesh | up    | 09:12:50 | Established |
| 10.13.23.130 | node-to-node mesh | up    | 09:12:52 | Established |
+--------------+-------------------+-------+----------+-------------+
  1. 子网的安全规则允许所有流量。所有节点都在同一个子网中,并且我有一个无状态规则,允许来自子网内其他节点的所有流量(我还尝试添加一个明确允许 IP-in-IP 流量的规则 - 结果相同)。
  2. 在 K8s 节点上的所有 vNIC 上禁用源/目标检查。

我注意到的其他事情:

  1. 如果我在 IP 封装中为同一子网流量禁用 IP,并在子网内使用常规路由(如AWS此处所述),我可以让 calico 工作
  2. 其他网络插件(例如 weave)似乎可以正常工作。

所以我的问题是 - IP-in-IP 封装的流量发生了什么?还有什么我可以检查以弄清楚发生了什么吗?

是的,我知道我可以直接使用托管 Kubernetes 引擎,但其中的乐趣(和学习机会)在哪里?:D

编辑以解决 Rico 在下面的回答:

1)我也没有让任何 pod 到 pod 的流量流过(不同主机上的 pod 之间没有通信)。但是我无法捕获该流量,因此我以 node-to-pod 为例。

2)如果我在另一个节点上点击 NodePort svc 而不是运行 pod 的节点,我也会得到类似的结果 - 我看到来自第一个节点的传出 IP-in-IP 数据包,但它们从未出现在第二个节点(实际运行 pod 的节点):

root@kube-01-01:~# tcpdump -i ens3 proto 4 &
[1] 6499
root@kube-01-01:~# tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens3, link-type EN10MB (Ethernet), capture size 262144 bytes
root@kube-01-01:~# curl 127.0.0.1:32137
20:24:08.460069 IP kube-01-01 > kube-01-06: IP 192.168.21.64.40866 > 192.168.181.1.http: Flags [S], seq 3175451438, win 43690, options [mss 65495,sackOK,TS val 19444115 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)
20:24:09.459768 IP kube-01-01 > kube-01-06: IP 192.168.21.64.40866 > 192.168.181.1.http: Flags [S], seq 3175451438, win 43690, options [mss 65495,sackOK,TS val 19444365 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)
20:24:11.463750 IP kube-01-01 > kube-01-06: IP 192.168.21.64.40866 > 192.168.181.1.http: Flags [S], seq 3175451438, win 43690, options [mss 65495,sackOK,TS val 19444866 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)
20:24:15.471769 IP kube-01-01 > kube-01-06: IP 192.168.21.64.40866 > 192.168.181.1.http: Flags [S], seq 3175451438, win 43690, options [mss 65495,sackOK,TS val 19445868 ecr 0,nop,wscale 7], length 0 (ipip-proto-4)

第二个节点(kube-01-06实际运行 nginx pod 的节点)上没有任何内容:

root@kubespray-01-06:~# tcpdump -i ens3 proto 4
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens3, link-type EN10MB (Ethernet), capture size 262144 bytes

为了便于演示,我使用了 127.0.0.1 - 当然,当我从外部主机点击该 NodePort 时,也会发生完全相同的事情:

20:25:17.653417 IP kube-01-01 > kube-01-06: IP 192.168.21.64.56630 > 192.168.181.1.http: Flags [S], seq 980178400, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0 (ipip-proto-4)
20:25:17.654371 IP kube-01-01 > kube-01-06: IP 192.168.21.64.56631 > 192.168.181.1.http: Flags [S], seq 3932412963, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0 (ipip-proto-4)
20:25:17.667227 IP kube-01-01 > kube-01-06: IP 192.168.21.64.56632 > 192.168.181.1.http: Flags [S], seq 2017119223, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0 (ipip-proto-4)
20:25:20.653656 IP kube-01-01 > kube-01-06: IP 192.168.21.64.56630 > 192.168.181.1.http: Flags [S], seq 980178400, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0 (ipip-proto-4)
20:25:20.654577 IP kube-01-01 > kube-01-06: IP 192.168.21.64.56631 > 192.168.181.1.http: Flags [S], seq 3932412963, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0 (ipip-proto-4)
20:25:20.668595 IP kube-01-01 > kube-01-06: IP 192.168.21.64.56632 > 192.168.181.1.http: Flags [S], seq 2017119223, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0 (ipip-proto-4)

3)据我所知(如果我在这里错了,请纠正我),节点知道到 pod 网络的路由,并且 pod 到节点的流量也封装了 IP-in-IP(注意协议 4上面第一个捕获中的数据包)

root@kube-01-01:~# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE              NOMINATED NODE
alpine-9d85bf65c-2wx74   1/1     Running   1          23m   192.168.82.194   kube-01-08   <none>
nginx-dbddb74b8-th9ns    1/1     Running   0          10h   192.168.181.1    kube-01-06   <none>

root@kube-01-01:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
<snip>
192.168.181.0   10.13.23.127    255.255.255.192 UG    0      0        0 tunl0
4

3 回答 3

1

也许这是一个 MTU 问题:

通常,您的工作负载接口的 MTU 应该与网络 MTU 匹配。如果您需要 IP-in-IP,那么工作负载和隧道接口的 MTU 大小应该比您的网络的网络 MTU 小 20 个字节。这是由于隧道将添加到每个数据包的额外 20 字节标头。

在这里阅读更多。

于 2018-11-11T20:47:17.263 回答
0

您在从 Pod 连接到 Pod 时遇到问题吗?

这里的简短回答似乎是 PodCidr 数据包在与同一节点或另一个节点上的另一个 pod 通信时被封装。

笔记:

默认情况下,Calico 的 IPIP 封装适用于所有容器到容器的流量。

因此,如果您在 pod 内,您将能够连接到另一个节点上的 pod。例如,如果您使用kubectl exec -it <pod-name>.

这就是您无法连接到 pod/容器的原因,root@kube-01-01:~#因为您的节点/主机对 PodCidr 一无所知。它通过默认节点/主机路由发送 192.168.xx 数据包,但是,您的物理网络不是 192.168.xx,因此它们会丢失,因为没有其他节点/主机可以物理理解。

您连接到 nginx 服务的方式是通过Kubernetes Service,这与网络覆盖不同,它允许您连接到 PodCidr 之外的 pod。请注意,这些服务规则由kube-proxy管理,通常是iptables规则。此外,使用 iptables 你可以明确地做一些事情,比如如果你想与 IP AAAA 通信,你需要通过物理接口(即 tun0)或者你必须通过 IP BBBB

希望能帮助到你!

于 2018-11-11T19:33:45.890 回答
0

经过长时间和大量的测试,我认为这是由于 IP-in-IP(ipip 或 IP 协议 4)流量被 Oracle 云网络层阻止造成的。

尽管我无法在任何地方找到此文档,但它对于云提供商来说很常见(例如,Azure 做同样的事情 - 不允许 IP-in-IP 和未知 IP 流量)。

因此,此处可能的解决方法应该与Azure 的 Calico 文档中列出的解决方法相同:

  • 为同一子网流量禁用 IP-in-IP(正如我在问题中提到的)
  • 将 Calico 切换到 VXLAN 封装
  • 仅将 Calico 用于策略,将 flannel 用于封装 (VXLAN)
于 2021-08-04T12:12:18.830 回答