Kubernetes中的Network

Kubernetes 处理网络的方式和Docker不同,主要需要解决四种问题:

  1. 高度耦合的Container之间的网络通信:这个由Pod和localhost通信解决了;
  2. Pod和Pod之间的网络通信,这个是本篇的主要内容;
  3. Pod和Service之间的通信,这个是由Service解决的;
  4. 外部Service和内部Service之间的通信,这个也是由Service解决的。

简介

Kubernetes 假设 Pod 之间可以互相通信,无论它们在哪个主机上。我们给每个Pod一个单独的IP地址,那么我们就不用专门在Pod之间创建链接,或者映射container的port到主机的port来使得外部可以访问到container了。这使得我们创建了一个非常干净,向后兼容的模型,在这个模型里面Pod可以就被当做为一个VM或者甚至一个物理机,这给了我们很多方面的方便,比如port的分配,命名,服务注册、发现,负载均衡,应用程序设置和迁移等。

为了达成这个目标,我们必须规定如何设置集群的网络。

Docker的模型

在讨论Kubernetes处理网络的方法之前,我们需要先复习一下Docker是如何处理网络的。在默认情况下,Docker用的是主机私有的网络,默认情况下会创建一个叫做docker0的虚拟网桥,并且分配一段子网给它。对于每个Docker创建的container,都会分配一个虚拟的附加于这个网桥的网络设备(被称为veth),这个veth其实是通过linux的namespace来映射到container里面的eth0的。这个容器里的eth0会被分配一个虚拟网桥的网段里面的IP地址。

结果就是,Docker的容器只能和在同一个机器(也就是在同一个网桥)里面的容器交流,不能和外部别的机器上的容器之间建立连接。事实上,不同机器上的容器,可能会有同样的网段和IP地址。

如果说要让Docker容器能跨Node交流,那么必须给他们分配主机上的port,并通过这个port和主机IP来唯一确定一个容器的地址,然后主机会把请求转发给container。这显然会带来很多的问题。

Kubernetes的模型

在大量的开发者之间协调port的使用很明显是非常难以扩展和管理的。动态分配port又会给系统带来很大的复杂性——每一个应用程序都必须把port作为一个flag,API Server必须知道如何去把动态的port插入到配置块里面,Service必须知道如何去找到彼此,等等。与其解决这么多的问题,不如咱们自己干,重头设计。

Kubernetes规定了如下的网络实现规范(除非有意不这么做):

  • 所有的container都可以在不使用NAT的情况下访问到任何别的container
  • 所有的node都可以在不使用NAT的情况下访问到任何别的container(反之亦然)
  • 每个container自己看到的自己的IP地址,和被人看到的是一样的

这些要求其实就是说,你不能直接在两台机器上装上Docker,然后指望Kubernetes会工作,你必须保证这些基础要求被满足。

这个模型不止简单了很多,而且还吻合了Kubernetes对于把app从vm迁移到container的方便性要求。意思是,如果你之前的app是运行在vm里面的,那么vm和vm之间能通过IP地址互相通信是一个基本的要求。反之,放到container里面也是这样。

不过事实上,Kubernetes中并不是每一个container都会有自己的IP地址,其实Kubernetes是以Pod作为最小的分配IP地址的单位的——Pod中的container会共享同一个IP地址——也就是共享同一个network namespace。这使得所有的同一个Pod里面的container都能通过localhost直接访问到彼此。不过这个带来的问题是每个Pod里面的container需要协调好port的使用,防止冲突,但是这个和在VM里面是相同的,所以并不是什么太大的问题。我们称之为“IP-per-pod”模型。

在Docker里面,请求一个host port是可行的,但是这个模型使得操作更加简单。我们会在每个host Node上分配一个port,并把所有的traffic都转发给Pod。Pod本身并不需要知道这些,只当自己是一个vm或者甚至物理机就好了。

如何实现

目前有很多方法能实现这个网络模型,比如说如下的这些方案:

Cilium

Cilium是一个开源的网络模型,实现了L3-L7层的安全策略,具体的可以看一下文档。

Contiv

Contiv提供了可设置的网络模型。

Flannel

Flannel是一个非常简单的网络层,不过很多人都说好用。

总结

实现的方案非常多,我就不一一列举了,大家可以直接去参考官方文档中的内容。

网络是个很复杂的东西,很多时候问题都会出在网络上,不同的业务模型需要使用不同的网络插件,没有万金油的解决方案。