![ad6e5a8d30049a8e5ce4dc0f7b2e0f86.png](https://i-blog.csdnimg.cn/blog_migrate/f5d150a5c5c493f7e1a05766fae02ff0.jpeg)
我们先来看图示例,下面则个是k8s的网络模型图。
![60d6ed1c359e45e9f58e47e04ca5afd5.png](https://i-blog.csdnimg.cn/blog_migrate/2eff9303f820a6752aaa4925becaa37f.png)
我们知道,在k8s里面最小的管理单元是pod,一个主机可以跑多个pod,一个pod里面可以跑多个容器。
如上面所示,一个pod里面所有的容器共享一个网络命名空间(network namespace),所以,pod里面的容器之间通信,可以直接通过localhost来完成,pod里面的容器之间通过localhost+端口的方式来通信(这和应用程序在宿主机的通信方式是一样的)。
那么pod和pod之间的通信呢?通常来说,我们给应用程序定死端口会给应用程序水平扩展带来很多不便,所以k8s不会使用定死端口这样的方法,而是采用其他方法来解决pod之间寻址的问题
每个pod都会有一个自己的ip,可以将Pod像VM或物理主机一样对待。这样pod和pod之间的通信就不需要像容器一样,通过内外端口映射来通信了,这样就避免了端口冲突的问题。
特殊的情况下(比如运维做网络检测或者程序调试),可以在pod所在的宿主机想向pod的ip+端口发起请求,这些请求会转发到pod的端口,但是pod本身它自己是不知道端口的存在的。
因此,k8s的网络遵循以下原则:
- 一个节点的pod和其他节点的pod通信不需要通过做网络地址转换(NAT)
- 一个节点上所有的agent控制程序(如deamon和kubelet)可以和这个节点上的pod通信
- 节点主机网络中的Pod可以与其他所有节点上的所有Pod通信,而无需NAT
把上面这个pod替换成容器也是成立的,因为pod里面的容器和pod共享网络。
基本上的原则就是,k8s的里面的pod可以自由的和集群里面的任何其他pod通信(即使他们是部署在不同的宿主机),而且pod直接的通信是直接使用pod自己的ip来通信,他们不知道宿主机的ip,所以,对于pod之间来说,宿主机的网络信息是透明的,好像不存在一样。
然后,定了这几个原则之后,具体的实现k8s的这个网络模型有好多种实现,我们这里介绍的是Flannel,是其中最简单的一种实现。
Flannel实现pod之间的通信,是通过一种覆盖网络