0.前言
在k8s集群中,每一个pod都有一个独立的ip地址,并且每个pod都处于一个扁平的网络中,相互之间可以通过网络访问。k8s的网络规范采用的是CNI容器网络规范,该规范规定了容器runtime和网络插件之间的简单契约,这个契约通过json语法定义了CNI插件所需要提供的输入和输出。具体表现为容器runtime首先需要分配一个网络命名空间以及一个容器ID,然后连同一些CNI配置参数传给网络驱动,接着网络驱动会将该容器连接到网络并将分配的IP地址以JSON的格式返回给容器runtime。这种官方的说法确实比较难以理解,因为之前部署k8s集群的时候,采用的是calico的网络方案,所以今天就借着一些例子来看下calico网络方案是如何实现pod网络互联的。
1.Calico概述
Calico 是一种容器之间互通的网络方案,我们知道在k8s集群中,pod之间既需要隔离又需要网络互通,Calico 不使用隧道或 NAT 来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过 host 上路由配置完成跨 Host 转发。
Calico如此设计是具有以下优势的:
(1)更好的利用资源;
(2)具有可扩展性;
(3)极强的可用性。
Calico的主要组件有:
(1)Felix:一个守护程序,Calico代理agent,它在每个提供endpoints资源的计算机上运行;
(2)Etcd:分布式键值存储,用来保证Calico中网络元数据的一致性;
(3)BIRD:集中式的路由分发。
2.Calico原理
Calico把每个操作系统的协议栈认为是一个路由器,然后把所有的容器认为是连在这个路由器上的网络终端,在路由器之间跑标准的路由协议——BGP的协议,然后让它们自己去学习这个网络拓扑该如何转发。
所以Calico方案其实是一个纯三层的方案,也就是说让每台机器的协议栈的三层去确保两个容器,跨主机容器之间的三层连通性。
也由于Calico是一种纯三层的实现,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率可能是所有方案中最高的,因为它的包直接走原生TCP/IP的协议栈,它的隔离也因为这个栈而变得好做。
3.calico网络实现方式
由于我们之前部署calico的时候采用的是IPIP的方式,所以本次主要讲解IPIP方式的实现。
(1)查看路由表
route -n
(2)路由表中Flags标志含义
U: up表示当前为启动状态
H: host表示该路由为一个主机,多为达到数据包的路由
G: Gateway 表示该路由是一个网关,如果没有说明目的地是直连的
D: Dynamicaly 表示该路由是重定向报文修改
M: 表示该路由已被重定向报文修改
(3)IPIP详解
从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel。IPIP是一种将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式。启用IPIP模式时,Calico将在各Node上创建一个名为”tunl0″的虚拟网络接口。
我们来借着案例看一下:
kubectl get pod -o wide |grep busybox
之前我们在k8s集群部署了两个busybox,分别运行在k8s-node1和k8s-node2上。 我们进入k8s-node1上的busybox里,然后ping一下k8s-node2上的busybox。
kubectl exec -it busybox1 -- /bin/sh
ping 172.30.169.129
可以看到网络是通的,之后再看看下ping包的旅程。
kubectl exec -it busybox1 -- /bin/sh
route -n
根据路由信息,当ping 172.30.169.129的时候,会匹配到第一条,也即去往任何网段的数据包都发往网关169.254.1.1,然后从eth0网卡发送出去。
我们再看下k8s-node1的路由信息:
route -n
当ping包来到k8s-node1节点上时,会匹配到路由tunl0(红框中的),该路由的含义是:去往172.30.169.128/24网段的数据包会发往网关192.168.159.166,因为busybox1在k8s-node2(192.168.159.166)上,所以ping包会发往k8s-node2。
再来看下k8s-node2的路由信息:
route -n
当ping包来到k8s-node2的时候,会匹配到上图中的规则(红框中的),该条规则表示 172.30.169.129是本机直连设备,数据包发往设备cali12d4a061371,这个设备是创建busybox1的时候calico给busybox1创建的一个veth pair设备,veth pair的另一端就是pod2网卡,也就是说发送到cali12d4a061371的数据就是发送到busybox pod的网卡,也就是ping包的目的地。
4.总结
上面讲解了在calico网络模式下,一个网络包从一个pod到另一个pod的过程,如果单看理论,确实比较复杂,但是结合案例一起看的话,应该还是可以理解的,当大家在日常工作中遇到k8s集群网络问题,可以按照以上的方式排查,查看虚拟网络设备和路由,再结合装包来看就可以很快找到问题了。