kubernetes集群网络的路由和交换技术

Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡

十余年的涵江网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。营销型网站建设的优势是能够根据用户设备显示端的尺寸不同,自动调整涵江建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“涵江网站设计”,“涵江网站推广”以来,每个客户项目都认真落实执行。

在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。

kubernetes网络需要解决下面4个问题:

集群内
同一个Pod中的container之间的通信
Pod和Pod之间的通信
Pod和Service之间的通信
集群外
外部应用与Service之间的通信

1、公司网络架构

kubernetes集群网络的路由和交换技术
先看一下这个架构图,最下面的是我们的服务器,就是我们维护的服务器,要想接入到网络中,它要经过上面链路经过的转发,像服务器,办公电脑都是连接的交换机,交换机是一个端口比较多的,然后它处于接入层,然后再往上就是核心的交换机,就是三层的,并且是一些网络策略,再往上我们需要将我们核心交换机的网络中的数据转发到互联网,它就要通过路由器转发出去到互联网,然后到互联网就可以访问一些网站,百度,谷歌等,然后其他层面访问百度服务器,实际互联网访问百度服务器,也是通过各个设备,交换机,路由等进行转发,到达百度,通过这种形式呢,将一些小的独立的网络与其他网络连在一块,形成一个庞大的整体,这就是互联网。

大部分分成了以下几层:
路由器:网络出口
核心层:主要完成数据高效转发、链路备份等,它是路由器下面核心的入口,下面所有的交换机和服务器最上面的入口,这一层主要是保证高效的转发下面的数据,但在这一层有时候还会独立的剥离出一层,也就是在二层交换机上面添加一个汇聚层,汇聚层一般都是完成一些网络策略,数据包从互联网来了,然后在三层做一些管控,下面的数据包出现一些,怎么管控,下面可能会划分很多的vlan,很多虚拟的局域网,一般大型公司都是通过使用三层交换,来划分多个vlan来实现不能策略的管控,比如说办公网络是不通的,要是想通的话,需要申请ecl,公司与机房的网络也是不通的,这是默认不让通,也是为了安全着想,然后就是公司与测试机房也是不通的,要是想通也是需要申请ecl,所以这些都是在核心层,汇聚层去管控的,然后在下面接入交换机,这个跟机房的都是一样的

大部分就是分成三层:接入层--->核心层/汇聚层--->网络出口
汇聚层:网络策略、安全、工作站交换机的接入、VLAN之间通信等功能
接入层:工作站的接入
下面我们研究的事是也就是接入层当我们的服务器、pc电脑,如果想到达互联网它的数据包怎么途径的去转发的?
我们还要知道别人访问我们的服务器,这个数据是怎么来的,还要了解不同区域的局域网之间通信是怎么个流程?
如果在同一个vlan里面,也就是同一个局域网通信它们又是一个怎么样的通信?

了解这么多问题,那么就要去了解这些网络设备,第一个就是交换机(switch),第二个就是路由器(router)
在我们学习k8s中,像里面的网络虽然是看不见摸不着的网络设备,但是它背后的工作都是这些组成的,只不过这些路由器交换机你是看不到的,你看到的都是服务器上的一些操作,但是背后是怎么出去的,需要我们掌握。

2、交换技术
有想过局域网内主机怎么通信的?主机访问外网又是怎么通信的?
想要搞懂这些问题得从交换机、路由器讲起。
kubernetes集群网络的路由和交换技术
这个是一个华为h4c的交换机,这个是24口的,也有48口的,所以它的口要相比路由器多很多很多,它主要是为了接入更多的工作站,因为工作站就有很多的pc电脑了,服务器,所以多很多,所以它面向的对象就是一些实际的计算机,它涉及的口业比较多,而路由器它本身的上下级关系设备比较少,一般也就4-5个,这个交换机做的用的就是这个交换技术,我们要了解这个交换技术怎么去工作的,通过局域网内主机怎么通信的?主机访问外网又是怎么通信的?进行出发,去理解这个交换技术怎么去工作的

交换机工作在OSI参考模型的第二层,即数据链路层。交换机拥有一条高带宽的背部总线交换矩阵,在同一时间可进行多个端口对之间的数据传输。

而交换机又在工作上分为2层和3层,这个也是指的是OSI中的2层和3层(3层传输层,2层数据链路层)
交换技术分为2层和3层:
2层:主要用于小型局域网,仅支持在数据链路层转发数据,对工作站接入,这个也就是基于MAC地址的转发,
3层:三层交换技术诞生,最初是为了解决广播域的问题,多年发展,三层交换机书已经成为构建中大型网络的主要力量,这个也就是基于路由器的功能,基于IP,数据包进行去转发,主要也是解决一个广播域的问题。

例如有一台交换机,下面分别有两台pc,分别为主机a,和主机b,现在是主机a去访问主机b怎么去通信?
这就不得去了解交换机怎么去工作的,因为本身我们的两台pc是物理隔离的,上面有交换机进行连接,它们实现的通信那么就要去理解交换机的工作原理。
下面简单总结了OSI模型对应的功能

应用层:(各种应用程序协议,如http、ftp、pop3、smtp等)
传输层:TCP/UDP (接收上一层的数据,在必要的时候把数据进行分割,并将这些数据交给网络层,且保证这些数据段有效到达对端)
网络层:IP地址 (控制子网的运行,如逻辑编址、分组传输、路由选择) 对应设备路由器
数据链路层:MAC地址(物理寻址,也就是机器上在出厂商留下的编码,也就是网卡,也是网络中唯一的标识,同时将原始比特流转变为逻辑的传输线路)对应设备交换机
物理层:比特流(机械、电子、定时接口通信信道上的原始比特流传输)

其实在交换机中它是根据二层的MAC地址进行转发的,mac地址也就是每个电脑上的网卡,这个网卡是有一个物理地址的,也是唯一的,也就是厂商出的时候,帮你带出去的,而交换机就是基于这个mac地址进行转发通信的,如果主机a发送一个文件到主机b,要发给谁那么就要涉及到一个ip地址,也就是相当于一个门牌号,通过这个标识可以找到你,所以必须要知道这个ip是谁,但交换机不会考虑这个ip是谁,因为它设计原理就是基于Mac地址进行寻址的,所以主机a发送这个数据包时,必须知道目标主机的mac地址,才能封装一个二层的,这个包称为帧,那怎么去找的这个ip呢,本身这个mac地址就是唯一的,而它的IP是同一个网段,如果不是一个网段也不能之间通信了,虽然知道了对方的ip地址,但是交换机的工作设计是通过对方的mac地址进行转发的,因为它工作是在二层,所以这里还依赖了一个ARP的协议,这个ARP是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源,完成存档之后,下次就能直接请求并转发数据包了,那么这就组成了四元组,首先源IP,源mac,目的ip,目的mac,也就是一个二层的包,这样就完成一个数据的传输。

这期间就会涉及到一个广播域的问题,在公司中有一个大的网络,而在这个网络中会划分为很多的虚拟网,比如交换机下面接了20多台主机,如果发的这个广播包,要被其他的拦截了,或者有一些主机就喜欢发广播包,比如没有这个目的地址,比如没有这个1.30这个主机,那么这个交换机找不到一直就广播,那么就会产生大量的流量丢失,网络延迟,网络瘫痪等等,那么为了解决这个问题,可能上百的主机划分为小的局域网,如果广播域不划分的话,那么这个广播域遇到一个找不到的目的mac就会产生一些不好的因素,如果换成小的局域网的话,只会影响小部分,也就是vlan,一个vlan就是一个广播域,一个路由器下的一个端口就是一个广播域,vlan的作用就是将物理环境逻辑上划分为不同的局域网,而vlan就是隔离这个广播域的,路由器也能隔离广播域,所以路由器下面就是一个广播域,如果某个vlan中出现广播风暴或者arp(arp实际就是通过伪造IP地址和MAC地址进行欺骗。使以太网数据包的源地址、目标地址和ARP数通信量导致网络中断或中间人。ARP主要存在于局域网中。若其中一台计算机感染ARP病毒。就会试图通过ARP欺骗截获局域网内其他计算机的信息,造成局域网内的计算机通信故障。)就会影响这个vlan这个广播域中的主机,这也是大型公司网络架构为什么划分vlan的原因。

广播域
交换机在转发数据时会先进行广播,这个广播可以发送的区域就是一个广播域。交换机之间对广播帧是透明的,所以交换机之间组成的网络是一个广播域。
路由器的一个接口下的网络是一个广播域,所以路由器可以隔离广播域。
ARP(地址解析协议,在IPV6中用NDP替代)
发送这个广播帧是由ARP协议实现,ARP是通过IP地址获取物理地址的一个TCP/IP协议,主要负责将某个IP地址解析成对应的MAC地址。
三层交换机
前面讲的二层交换机只工作在数据链路层,路由器则工作在网络层。而功能强大的三层交换机可同时工作在数据链路层和网络层,并根据 MAC地址或IP地址转发数据包,而三层的交换机又支持路由器的功能,路由器是工作在网络层,而三层交换机又集成了二层和三层,所以叫做三层交换机,当我们把二层交换机换成3层的之后,就能实现不同vlan之间的通信了,不同vlan也就是隔离的局域网,然后使用二层的话是过不去的,因为这个不在同一个网段了,这个广播包也散不到这一块了,那只有走路由表的形式转发出去,但是三层的交换机不能替代路由的功能,因为三层交换机设计之初就是来解决不同vlan不能局域网之间的广播域的问题,经过多年的时间,三层也不仅仅只做这一块,还会做一些网络策略之类的,安全之类的,比较成熟了。
网桥
网桥(Bridge)是早期的两端口二层网络设备,用来连接不同网段。网桥的两个端口分别有一条独立的交换信道,不是共享一条背板总线,可隔离冲突域。网桥比集线器(Hub)性能更好,集线器上各端口都是共享同一条背板总线的。后来,网桥被具有更多端口、同时也可隔离冲突域的交换机(Switch)所取代。
VLAN(Virtual Local Area Network):虚拟局域网
VLAN是一种将局域网设备从逻辑上划分成一个个网段。
一个VLAN就是一个广播域,VLAN之间的通信是通过第3层的路由器来完成的。VLAN应用非常广泛,基本上大部分网络项目都会划分vlan。
VLAN的主要好处:
分割广播域,减少广播风暴影响范围。
提高网络安全性,根据不同的部门、用途、应用划分不同网段

其实刚才说道arp缓存表,广播的时候,会收到一份目的的mac地址表,然后缓存再留一份,其实这个是通过命令行也能看到的
用arp -a 就能看到,而缓存表也是为了,下次再去发送数据包的时候,不用再去广播目的mac来,它会先从自己的缓存表去找有没有对应的目的mac表,有的话就直接转发数据包,但是这个表也有保留时间,如果这个表不活跃了也就没了。
在k8s中一台中容器是怎么通信的,就是通过ARP协议,跟交换机原理一样,因为它有网桥也就是一个交换机的角色进行来实现的,ARP协议在网桥中都是支持的
3、路由技术
kubernetes集群网络的路由和交换技术
这个也是一个h4c的路由器,里面才6个口,但是这个口一般分为2个角色,当然除了一个console管理口,一个是LAN口一个是WAN口,
路由器主要分为两个端口类型:LAN口和WAN口
WAN口:配置公网IP,接入到互联网,转发来自LAN口的IP数据包。
LAN口:配置内网IP(网关),连接内部交换机,对接的是工作机,工作站。
那么这里又出现了一个公网IP和内网IP,wan口肯定需要配置一个公网ip的,它好让下面的机器出去能够访问外网,那么本身互联网就一个内网的IP怎么才能连接到互联网呢,那么就是需要一个互联网上互相信任的公网ip ,公网就是互联网可见的,其他人都可以随意的访问这个IP,那么内网IP呢,只有内部局域网之间访问,就像机房的服务器一样,有两个网卡,一个是内网一个是公网,外网IP是配置的公网,内网是配置的内网IP,出外网肯定需要走公网网卡。
路由器是连接两个或多个网络的硬件设备,将从端口上接收的数据包,根据数据包的目的地址智能转发出去。
路由器的功能
路由
转发
隔离子网
隔离广播域
路由器是互联网的枢纽,是连接互联网中各个局域网、广域网的设备,相比交换机来说,路由器的数据转发很复杂,它会根据目的地址给出一条最优的路径。那么路径信息的来源有两种:动态路由和静态路由。
就是说公司的网络怎么到互联网呢,就是说互联网的用户怎么访问我们的服务呢,都是通过路由器转发,而交换机只做局域网之间数据包的转发,也就是能在二层通过MAC地址,能发广播包的环境下才可以转发这个数据包,但是路由器的转发比较复杂,它去转发它会考虑哪个路径比较好,最优的路径,走最近的路,也就是路由器会做这么一个事,而这个路径分为两个一个为静态一个为动态。

静态路由:指人工手动指定到目标主机的地址然后记录在路由表中,如果其中某个节点不可用则需要重新指定,手动的可能就像在你的linux服务器上或者路由器上手动去添加路由表,这个路由我应该转发给谁,下一跳是谁,当下一跳不能用了,那么这个数据包在这个路由器就不能用了,下一跳转发不过去就丢弃了,数据包过不去,访问自然就是不可达网络。
动态路由:则是路由器根据动态路由协议自动计算出路径永久可用,能实时地适应网络结构的变化。
常用的动态路由协议:
RIP( Routing Information Protocol ,路由信息协议)
OSPF(Open Shortest Path First,开放式最短路径优先)
BGP(Border Gateway Protocol,边界网关协议)

4、OSI七层模型
OSI(Open System Interconnection)是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。
kubernetes集群网络的路由和交换技术

我们经常说的七层和四层的转发其实就是基于OSI七层模型的体系
从主机a到主机b,经历了哪些阶段经过的处理,这个的话,一般就是通过下面这种方式从主机a的数据到主机b的数据,先进行封装对这个数据包进行封装,到4层之后就是一个传输层,也就是TCP/UDP的协议,为两个端系统的会话层之间,提供建立、维护和取消传输连接的功能,负责端到端的可靠数据传输,在这一层,信息传送的协议数据单元称为段或报文,然后到达网络层,主要定义了能够标识所有结点的逻辑地址,还定义了路由实现的方式和学习的方式,根据ip的地址的标识进行,一般使用的都是市面的路由器来完成,然后到数据链路层,到达交换机,也就是物理地址,通过ARP协议地址解析协议,解析目的mac和源mac地址,加入缓存中,以便下次使用然后到物理层将数据包转化为计算机可以识别的比特序列,然后一层一层的返回拆开返回到目标主机
kubernetes集群网络的路由和交换技术
5、TCP/UDP协议
TCP(Transmission Control Protocol,传输控制协议),面向连接协议,双方先建立可靠的连接,再发送数据。tcp主要适用于传输数据量大,可靠性要求高的应用场景,它设计数据包如果超过了mpu,最大传输单元,最大是1500字节,如果数据包超出了1500字节就进行分组,就是在三层这里进行分组,分成很多的小块进行发布,并且这个组会打成一个序号,这个序号就能保证发送的数据,是不是连续或者损坏,然后重传,tcp保证来保证数据包的可靠性
UDP(User Data Protocol,用户数据报协议),面向非连接协议,不与对方建立连接,直接将数据包发送给对方。适用于一次只传输少量的数据,可靠性要求低的应用场景。相对TCP传输速度快。这个udp没有三次握手就直接进行发送数据包,但是发包呢,但不能确定你这个包能不能准确接收到,因为没有ack来返回序列号来确定,这个序列号为1了,我收到这个包,序列号为2了我收到这个包,如果发送一个3没有收到这个包就会跟你重传,它设计的也比较简单,你给我个端口,我就能给你发这个包,不管你收没收到,不会响应,而且超出最大的传输单元之后,也会进行分组,但是不能保证分组的数据包的可靠性,其中有一个包丢了,其它的包就不能做整合了,因为这个数据包跟你分开之后,少了一块,那么这个数据包就是一个损坏的状态,对方就收不到了,因为这个数据包丢弃了。

4.2 Kubernetes网络模型

像flannel和calico网络插件都有一定的要求,怎么接入到k8s里面必须满足这些要求,也就是都满足这些要求才能被第三方网络插件支持
Kubernetes 要求所有的网络插件实现必须满足如下要求:
一个Pod一个IP。  这个是必须的,一个pod可以与节点上的所有pod可以通信,就是直接可以访问的,不需要nginx代理
所有的 Pod 可以与任何其他 Pod 直接通信,无需使用 NAT 映射。 k8s的所有节点都可以访问这个pod,这个首先是在苏主机出发可以访问到所有的pod
所有节点可以与所有 Pod 直接通信,无需使用 NAT 映射
Pod 内部获取到的 IP 地址与其他 Pod 或节点与其通信时的 IP 地址是同一个。
在同一个节点docker的网络是什么样的?要了解pod在同一个节点与同一个节点的通信,可以先从docker的网络模型先去理解,这个跟pod与pod的相通信是一样的。
1、Docker容器网络模型
先看下Linux网络名词:
也就是安装好一个linux主机之后,会创建一个网络命名空间也就是所有的进程都在这个网络命名空间里面,所以都可以在这个linux中访问这个网络,但是这个docker利用这个大的网络命名空间进行了隔离,也就是一个容器也就是一个网络命名空间,所以在宿主上看不到也访问不到某个容器的网络的,是看不到的,而容器之间也看不到对方的网络的,所以容器使用的namespace给容器做的网络的隔离,然后容器还有个问题
也就是容器已经都有自己的命名空间了,容器与宿主机也是隔离的,我的数据包是怎么出去的,所以这里就用到了这个设备对veth
网络的命名空间:Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信;Docker利用这一特性,实现不同容器间的网络隔离。
Veth设备对:Veth设备对的引入是为了实现在不同网络命名空间的通信。这个设备对相当于一个网线一样,容器的网络命名空间与宿主机上的命名空间,宿主机的命名空间为root,现在想让containers的命名空间与宿主机的命名空间进行通信的话,所以会用到这个veth的这个设备对,这个网线,让容器的命名空间接入到宿主机的命名空间中,当在k8s中起个pod时,当使用docker起个容器时,用ifconfig会看到很多veth的很多设备,其实这就是另一端,可以说是水晶头的另一头,容器本身就有一个自己虚拟的网络,它想出去只有借助宿主机的网络出去,因为本身就是在宿主机上的一个藏着的网络,它要想出去还得通过宿主机,所以它有这个设备对就能完成数据的转发。
Iptables/Netfilter:Docker使用Netfilter实现容器网络转发。要是docker要想上网,虽然有了容器与宿主机网络命名空间的这么一个数据包过来,但是它怎么通过宿主机的网络访问到外部的网络呢,所以它用到了netfilter,它的linux的一个IP包的过滤机制,然后来实现容器之间的网络的转发,容器到达宿主机,而veth这个口实际是接入了网桥中,然后可以这么想象,每个容器就是一个电脑,交换机就是一个网桥,可以通过命令看到另一端,能看一下这个网桥加入了哪些网线,这个交换机下面有哪些主机,通过这个命令可以看出跟交换机的原理差不多,通过arp协议获取mac地址,也就是封装二层数据包这个帧包,然后之间在二层进行转发的,但是它要访问外网又需要iptables的snat dnat,根据原地址目标地址转发外网

[root@k8s-node1 ~]# yum -y install bridge-utils
[root@k8s-node1 ~]# brctl show cni0
bridge name bridge id       STP enabled interfaces
cni0        8000.e27423da0b65   no      vethbf3ee8ae
                            vethf4889480

网桥:网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。这个可以通过ifconfig可以看到docker0的网桥,这个网桥是docker创建容器也就是让它加入到这个交换机里面实现相互的访问了。
路由:Linux系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里。这个呢会遇到也就是用到第三方插件的时候,会出现很多的路由表来实现容器之间的通信

Docker容器网络示意图如下:
kubernetes集群网络的路由和交换技术
这个就是容器网络的示意图,每个容器都有一个veth的设备对,也就是部署一个pod后会出现这个一个设备对来连接宿主机的命名空间,这个对一头是网线一头是网桥,也就是eth0(docker0),如果他们通信的话,直接走二层广播包协议封包就能实现网络的转发了,它想出去就通过iptables的nat,来借助宿主机的网络访问外网
2、Pod 网络
问题:Pod是K8S最小调度单元,一个Pod由一个容器或多个容器组成,当多个容器时,怎么都用这一个Pod IP?
就是我这个pod中不管有多少个容器只能用这一个ip通信,这也是它设计pod的意义
实现:k8s会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了。即网络设备、IP地址、Mac地址等。这就是解决网络共享的一种解法。在Pod的IP地址就是infra container的IP地址。

这个infra每个容器启动的时候都会帮你拉一个infra的小容器可以在kubelet,conf配置文件可以看到,这个容器也比较简单使用go启动这么一个容器,来保持一个持久运行的状态,创建的时候本身都带一个自身的网络命名空间,这个里面不跑任何的程序,但是它主要来维护网络的命名空间,业务容器实际就是链接到这个网络命名空间的,而这个命名空间对与用户是不可见的,比如我们跑的微服务,使用sidecar模式跑了多个容器,那么看到的只用到一个podIP,那么创建的业务容器会链接到这个infra中,比如再创建一个sidecar容器,它都会链接到这里面,这个IP也都给pause,它有独立的网络命名空间,然后kubelet帮它分了一个ip ,也就是get pod -o wide看到的ip ,这个IP全网都是唯一的,所以就可以访问这个IP,就能访问到业务暴露的端口,所以通过这种机制将pod的网络共享
kubernetes集群网络的路由和交换技术
k8s的pod和容器,pod是一个或者多个容器组成的,但是它的网络命名空间也是一个,只不过它为了亲密性的应用,增加了一个pod的概念,而docker容器一个容器一个网络命名空间,他们其实也不多,都是两个独立的命名空间,跟上面图一样了,宿主机一个网络命名空间,然后pod1一个网络命名空间,pod2一个网络命名空间,它两个进行通信,和两个container进行通信其实都是一样的,因为都是两个network,namespace的通信,都是通过veth进行转发过来,交换机从二层转发过来,访问也是一样的。

在 Kubernetes 中,每一个 Pod 都有一个真实的 IP 地址,并且每一个 Pod 都可以使用此 IP 地址与 其他 Pod 通信。
Pod之间通信会有两种情况:
两个Pod在同一个Node上,也就是两个服务两个副本的话,都分布在node1上面
两个Pod在不同Node上,也就是两个服务两个副本的话,都分布在node1和node2上面
这两种情况的数据通信的流程都是不一样的

先看下第一种情况:两个Pod在同一个Node上
同节点Pod之间通信道理与Docker网络一样的,如下图:
kubernetes集群网络的路由和交换技术
对 Pod1 来说,eth0 通过虚拟以太网设备(veth0)连接到 root namespace;
网桥 cbr0 中为 veth0 配置了一个网段。一旦数据包到达网桥,网桥使用ARP 协议解析出其正确的目标网段 veth2;
网桥 cbr0 将数据包发送到 veth2;
数据包到达 veth2 时,被直接转发到 Pod2 的 network namespace 中的 eth0 网络设备。

再看下第二种情况:两个Pod在不同Node上
还有就是两个pod在不同节点,上面那张图,当pod1出这个这个数据包时,因为两个pod是在不同node上了,两个不同的node相当于两个不同的机器,如果在任何没有处理的情况下,这个数据包肯定是出不去的,因为访问的地址是node2上的地址,所以想想怎么将这个数据包送出去,所以能送出去就需要第三的网络组件来实现了,说白了第三方的网络插件,主要来实现的跨节点网络之间的通信,而不是本地容器节点的通信,因为这个有了,所以不需要它来实现,它主要实现的是怎么将原始的数据源的数据包发送到目的的eth0口上。

K8S网络模型要求Pod IP在整个网络中都可访问,这种需求是由第三方网络组件实现。

所以两个容器进行跨节点的通信,它是由第三方组件进行转发的,中间的云就是第三方组件,不管是由路由方案还是隧道方案也好,要把node1的包发到指定的目的节点的node上。

kubernetes集群网络的路由和交换技术
3、CNI(容器网络接口)

在k8s中cni是现在k8s容器网络接口的规范,本身docker中有个cnm,也是一个网络标准的,但是那种不太适应与集群的这种形式,后来结果一些大型的公司做了这么一个cni的网络接口的标准
CNI(Container Network Interface,容器网络接口):是一个容器网络规范,Kubernetes网络采用的就是这个CNI规范
CNI实现依赖两种插件,一种CNI Plugin是负责容器连接到主机,并且能为他分配IP,另一种就是能为它这些容器管理IP,就像说两个pod能不能设置一个IP,所以这个是不行的,都收到这个数据包,谁来响应呀,所以是由IPAM负责配置容器网络命名空间的网络,来保证每个pod分配一个唯一的IP

CNI插件默认路径:

ls /opt/cni/bin/

这个目录就是为容器来分配IP的,当kubelet启动一个pod时,然后来调用这个配置文件来配置网络

这里面的二进制文件都是这个地址来提供的,可以把里面的包下载下来,在release里面可以下载打好的包,这个插件就是来满足各种第三方网络组件的支持
地址:https://github.com/containernetworking/cni
当你在宿主机上部署Flanneld后,flanneld 启动后会在每台宿主机上生成它对应的CNI 配置文件(它其实是一个 ConfigMap),从而告诉Kubernetes,这个集群要使用 Flannel 作为容器网络方案。

CNI配置文件路径:
容器网络的管理也是有配置文件的,这里面配置就是某一个第三方组件,所管理的配置信息,一些属性信息
cat /etc/cni/net.d/10-flannel.conflist

当 kubelet 组件需要创建 Pod 的时候,先调用dockershim它先创建一个 Infra 容器。然后调用 CNI 插件为 Infra 容器配置网络。
这两个路径在kubelet启动参数中定义:

 --network-plugin=cni \   指定cni网络
 --cni-conf-dir=/etc/cni/net.d \  指定cni配置文件的位置
 --cni-bin-dir=/opt/cni/bin  指定cni二进制文件的位置

小结,其实cni存在的意义就在于,让第三方网络组件能够更顺利的连接k8s,因为pod由kubelet去创建的,它创建pod的网络也是kubelet帮它去分配的,那kubelet这么去创建的容器呢?kubelet来调用docker的API去实现的,也就是使用dockershim来创建容器,并且也会调用这个二进制文件,然后为这个容器分配这个网络,比如分配一个目的ip,有cni就是为了网络规范,k8s这块不能都满足所有的需求,所以它制定了一个规范,只要安装它的规范来就能接入到k8s的网络中来,第二个它能结藕组件,也就是都能接入想用的组件都可以,只要满足这个需求,所以的组件都能接入进来。

问题总结:
1、一个局域网内主机A和主机B之间通信数据包传输流程
也就是在一个vlan里面通信的流程,首先要检查自己的ARP缓存表有没有MAC地址,二层的传输是基于Mac地址的,不会考虑哪个IP是多少,在一个局域网进行通信首先判断发送到的目的地址。
C类网段:192.168.30.0/24首先判断源ip和目的ip,都是不是在一个网段里面,这是一个前提在一个局域网进行通信,也就是原地址发送到主机b这台,首先要做一个数据包的封装,因为是在二层,首先要获取目的的mac地址
1)在本机查找ARP缓存表有没有二层数据包这个帧所需的mac地址,如果没有就会发送ARP广播包,这么这个主机肯定能收到,这个是有根网线进行来连接的,那么交换机收到这个广播包,会询问目的主机的mac地址是多少那么形成这个四元组:源IP,源mac,目的IP,目的mac,如果交换机没有这个目的的mac那么就会发送这个局域网内所有主机,因为这个有这个目的ip了,所以目的IP它会响应我的mac地址是多少多少,那么如果不是,它就会将这个包给丢弃了,那么响应之后b会发给交换机,交换机再发送给主机a,然后进行封包,主机a就能发送给主机b,那么这就是一个2层局域网之间的通信原理。

中间会有一个ARP缓存表,这个表都会在主机a,主机b,交换机去记录经过二层传输的源IP和目的IP对应的mac地址,以便下次再传输时,直接使用现有的进行去封装

那么如果这个局域网的交换机去发送广播包,不同网段下的主机会不会收到,如果没有三层交换机是收不到的,如果使用的三层交换机也就是核心交换机,它可以处理2层的ARP,那么不同网段的交换机也能收到,如果是路由器的话,那自然收不到了,因为路由器下面每一个端口,都有一个vlan,路由器隔离了这个广播包,那么如果它是一个三层的核心交换机,它能处理二层的还能处理三层的,那么它是可以收到的。

2、主机A和主机B不在一个局域网之间通信数据包传输流程

vlan1 192.168.36.0/24
vlan2 192.168.35.0/24

他们是不在一个子网中,那么这两个进行去通信,需要经过路由器了,因为它超过了二层数据包转发的范围了,那这种情况下进行通信首先也是判断目标IP是不是在一个子网里面,如果在一个子网里面那么它会发送到自己的默认网关,可以通过ip route可以看到

[root@k8s-node2 ~]# ip route 
default via 10.4.7.1 dev eth0 proto static metric 100 
10.4.7.0/24 dev eth0 proto kernel scope link src 10.4.7.21 metric 100 
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1 
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink 
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 

因为目标ip已经不在一个子网中了,去arp广播,自然没办法响应,还是丢弃的,还是没人响应,就会走默认的网关,10.4.7.1也就是下一跳地址,然后这个数据包就会转发到这个网关上,然后网关要查看本机的路由表,一般路由表就会记录一些目的地址还有下一跳地址,然后从哪个路由表去出

路由表:
目的地址。比如192.168.35.0/24,网关  接口,因为下面的信息都知道,所以就没有下一跳了
也就是数据包从vlan1进入二层,再进入核心交换机这里有两个口,a口还有b口,a口就是默认的网关,然后查询路由表这个网段的是从b口出,然后到达交换机到2层,然后到目的的vlan上,这个期间二层也会记录mac地址。


新闻标题:kubernetes集群网络的路由和交换技术
链接地址:http://scyanting.com/article/ihcdgh.html