Kubernetes网络一直是一个非常复杂的主题。本文将介绍Kubernetes实际如何创建网络以及如何为Kubernetes集群设置网络。
本文不包括如何设置Kubernetes集群。这篇文章中的所有例子都将使用Rancher 2.0集群(其他平台也同样适用)。即使你打算使用其他的公有云管理Kubernetes服务,也希望你对Kubernetes网络的工作原理有更好的了解。
如何使用Kubernetes网络
许多Kubernetes部署指南中包含了在K8S部署中部署Kubernetes网络CNI的说明。但是如果你的K8S集群已经运行,并且尚未部署任何网络,那么部署网络就像在K8S上运行其提供的配置文件一样简单(对于大多数网络和基本用例而言)。例如,要部署flannel:
这样,从网络的角度来看,K8S已经可以使用。为了测试一切是否正常,我们创建了两个Pod。
这将创建两个pod,它们正在使用我们的驱动器。查看其中一个容器,我们发现网络的IP地址范围为10.42.0.0/24。
在另一个Pod进行的快速ping测试表明,网络运行正常。
与Docker网络相比,Kubernetes网络如何工作?
Kubernetes通过Docker之上的CNI管理网络,并将设备附加到Docker。尽管有Docker Swarm的Docker也具有自己的联网功能(例如overlay、macvlan、bridging等),但CNI也提供了类似类型的功能。
还有一点十分重要,K8S并不使用docker0(这是Docker的默认网桥),而是创建自己的网桥,名为cbr0,该网桥需要与docker0区分开来。
为什么我们需要Overlay网络?
诸如vxlan或ipsec之类的overlay网络(如果你设置过安全VPN,你应该对此比较熟悉)可以将数据包封装到另一个数据包中。这使得实体在另一台计算机的范围之外依旧可以寻址。Overlay网络的替代方案包括如macvtap(lan)之类的L3解决方案,甚至包括ivtap(lan)之类的L2解决方案,但是这些方案具有一定的局限性。
L2或L3上的任何解决方案都可以让pod在网络上寻址。这意味着pod不仅在Docker网络内部访问,还能直接从Docker网络外部访问。这些是公共IP地址或私有IP地址。
然而,在L2上进行通信比较麻烦,并且你的经验会因为网络设备而异。某些交换机需要一些时间来注册你的Mac地址,然后才能将其实际连接到网络的其余部分。你还可能会遇到一些麻烦,因为系统中其他主机的neighbor(ARP) table仍在过时的缓存上运行,并且始终需要使用dhcp运行而不是host-local,这样可以避免主机之间的ip冲突。Mac地址和neighbor table问题是诸如ipvlan之类的解决方案存在的原因。这些解决方案不会注册新的mac地址,而是在现有地址上路由流量(尽管它们也有自己的问题)。
因此,我的建议是,对于大多数用户而言,将overlay网络作为默认解决方案应该足够了。但是,一旦工作负载变得更加高级并提出了更具体的要求,你将需要考虑其他的解决方案,如BGP和直接路由。
Kubernetes网络如何工作?
在Kubernetes中首先要了解的是,pod实际上并不等同于容器,而是容器的集合。在同一集合的容器中共享一个网络堆栈。Kubernetes通过在暂停容器上设置网络来进行管理,你可以在你所创建的每个pod中找到这些暂停容器。所有其他pod都连接到暂停容器的网络,该容器本身除了提供网络外不执行任何操作。因此,也可以使一个容器通过localhost与不同容器中的服务进行通信,此时该容器具有相同pod的相同定义。
除了本地通信之外,pod之间的通信看起来与Docker网络中的container-to-container通信几乎相同。
Kubernetes流量路由
我将以两种场景为例,详细地说明如何在Pod之间路由流量。
1、 在同一主机上路由流量:
在两种情况下,流量不会离开主机。一是当调用的服务在同一节点上运行,一是单个pod中的同一个容器集合。
如果从第一个pod中的容器1调用localhost:80并在容器2中运行服务,则流量将通过网络设备并将数据包转发到其他目的地。在这种情况下,路由流量的路线很短。
如果我们想要与其他pod进行通信,时间会更长一些。首先,流量将传递到cbr0,接下来cbr0将会注意到我们在同一个子网通信,因此它会将流量转发到目标Pod,过程如下图所示: