为 Kubernetes 设置网络

Setting up the network for Kubernetes

我正在阅读 Kubernetes "Getting Started from Scratch" Guide and have arrived at the dreaded Network Section,他们说:

Kubernetes imposes the following fundamental requirements on any networking implementation
(barring any intentional network segmentation policies):
* all containers can communicate with all other containers without NAT
* all nodes can communicate with all containers (and vice-versa) without NAT
* the IP that a container sees itself as is the same IP that others see it as

我的第一个困惑来源是:这个 与 "standard" Docker 模型有何不同 Docker 有何不同 w.r.t。这 3 个 Kubernetes 要求?

文章接着总结了 GCE 如何实现这些要求:

For the Google Compute Engine cluster configuration scripts, we use advanced routing to assign each VM a subnet (default is /24 - 254 IPs). Any traffic bound for that subnet will be routed directly to the VM by the GCE network fabric. This is in addition to the "main" IP address assigned to the VM, which is NAT'ed for outbound internet access. A linux bridge (called cbr0) is configured to exist on that subnet, and is passed to docker's --bridge flag.

我的问题是:本段针对以上 3 项中的哪一项要求?更重要的是,它如何 达到要求? 我想我只是不明白 1-subnet-per-VM 是如何完成的:容器-容器通信、节点-容器通信和静态 IP。


而且,作为一个 bonus/stretch 问题:为什么 Marathon 没有遇到与 Kubernetes 在这里解决的网络问题相同的问题?

Docker的标准networking configuration picks a container subnet for you out of its chosen defaults。只要它不与主机上的任何接口冲突,Docker 就可以。

然后,Docker 插入一个 iptables MASQUERADE 规则,允许容器使用主机的默认接口与外部世界对话。

Kubernetes 的 3 要求违反了以下事实:仅根据主机上使用的地址选择子网,这强制要求使用 MASQUERADE 规则对所有容器流量进行 NAT。

考虑以下 3 主机 Docker 设置(有点做作以突出显示内容):

主持人 1:

eth0: 10.1.2.3

docker0: 172.17.42.1/16

容器-A: 172.17.42.2

主持人 2:

eth0: 10.1.2.4

docker0: 172.17.42.1/16

容器-B: 172.17.42.2

主持人 3:

eth0: 172.17.42.2

docker0: 172.18.42.1

假设 container-B 想要访问 container-A 的端口 80 上的 HTTP 服务。您可以获得 docker 以在 Host 1 上的某处公开 container-A 的端口 80。然后 container-B 可能会向 10.1.2.3:43210 发出请求。这将在 container-A 的端口 80 上接收,但看起来它来自 10.1.2.4 上的某个随机端口,因为 NAT 在离开 [=51= 的路上]主机2。这违反了所有容器在没有 NAT 的情况下进行通信并且容器与其他容器看到相同的 IP 要求。尝试直接从 Host 2 访问 container-A 的服务,你会得到你的 节点可以在没有 NAT 的情况下与容器通信违规。

现在,如果这些容器中的任何一个想要与 Host 3 通信,它们就是 SOL(只是一个一般的论点,要小心自动分配的 docker 0 个子网)。

Kubernetes 在 GCE/AWS/Flannel/... 上的方法是 assign 每个主机 VM 一个从平面专用网络中划分出来的子网。没有子网与 VM 地址或彼此重叠。这让容器和 VM 可以无 NAT 通信。