在实际的业务场景中,业务组件之间的关系十分复杂,特别是微服务概念的提出,应用部署的粒度更加细小和灵活。为了支持业务应用组件的通信联系,Kubernetes网络的设计主要致力于解决以下场景:
(1)紧密耦合的容器到容器之间的直接通信;
(2)抽象的Pod到Pod之间的通信;
(3)Pod到Service之间的通信;
(4)集群外部与内部组件之间的通信。
在同一个Pod内的容器(Pod内的容器是不会跨宿主机的)共享同一个网络命名空间,共享同一个Linux协议栈。所以对于网络的各类操作,就和它们在同一台机器上一样,它们甚至可以用localhost地址访问彼此的端口。这么做的结果是简单、安全和高效,也能减少将已经存在的程序从物理机或者虚拟机移植到容器的难度。
如下图中的阴影部分就是Node上运行着的一个Pod实例。容器1和容器2共享了一个网络的命名空间,共享一个命名空间的结果就是它们好像在一台机器上运行似的,它们打开的端口不会有冲突,可以直接用Linux的本地IPC进行通信。它们之间互相访问只需要使用localhost就可以。每一个Pod都有一个真实的全局IP地址,同一个Node内的不同Pod之间可以直接采用对房Pod的IP地址通信,而不需要使用其他发现机制,例如DNS、Consul或者etcd。Pod既有可能在同一个Node上运行,也有可能在不用的Node上运行,所以通信也分为两类:同一个Node内的Pod之间的通信和不同Node上的Pod之间的通信。
1)同一个Node内的Pod之间的通信
如图,可以看出,Pod1和Pod2都是通过Veth连接在同一个Docker0网桥上的,它们的IP地址IP1、IP2都是从Docker0的网段上自动获取的,它们和网桥本身的IP3是同一个网段的。另外,在Pod1、Pod2的Linux协议栈上,默认路由都是Docker0的地址,也就是说所有非本地的网络数据,都会被默认发送到Docker0网桥上,由Docker0网桥直接中转,它们之间是可以直接通信的。