曾记得有一位哲人说过:“在云计算当中,计算最基础,存储最重要,网络最复杂”,而PaaS云平台Kubernetes的出现也使得网络的应用场景变得更加复杂多变。本文试图从Kubernetes当中容器跨节点网络通信方案Flannel的实际应用场景出发,带领读者梳理Kubernetes当中容器跨节点网络通信的实现过程以及背后的实现原理。
| Kubernetes网络模型
通过上一篇文章《深入浅出Kubernetes网络:容器网络初探》我们知道了Docker通过VEth虚拟网络设备以及Linux bridge实现了同一台主机上的容器网络通信,再通过iptables进行NAT实现了容器和外部网络的通信。
这对于简单部署的应用已经能够满足网络通信的需求了,但是Kubernetes作为一个容器编排平台,要处理的是生产环境当中高并发大规模的弹性扩展问题,首先要解决的就是整个集群当中所有节点上的容器网络通信问题。
为了解决Kubernetes当中网络通信的问题,Kubernetes作为一个容器编排平台提出了Kubernetes网络模型,但是并没有自己去实现,具体网络通信方案通过网络插件来实现。
其实Kubernetes网络模型当中总共只作了三点要求:
-
运行在一个节点当中的Pod能在不经过NAT的情况下跟集群中所有的Pod进行通信
-
节点当中的客户端(system daemon、kubelet)能跟该节点当中的所有Pod进行通信
-
以host network模式运行在一个节点上的Pod能跟集群中所有的Pod进行通信
从Kubernetes的网络模型我们可以看出来,在Kubernetes当中希望做到的是每一个Pod都有一个在集群当中独一无二的IP,并且可以通过这个IP直接跟集群当中的其他Pod以及节点自身的网络进行通信,一句话概括就是Kubernetes当中希望网络是扁平化的。
针对Kubernetes网络模型也涌现出了许多的实现方案,例如Calico、Flannel、Weave等等,虽然实现原理各有千秋,但都围绕着同一个问题即如何实现Kubernetes当中的扁平网络进行展开。Kubernetes只需要负责编排调度相关的事情,修桥铺路的事情交给相应的网络插件即可。
| Flannel简介
Flannel项目为CoreOS团队对Kubernetes网络设计实现的一种三层网络通信方案,安装部署方式可以参考官方示例文档:https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml,故关于Flannel的安装部署部分这里暂时不进行赘述,有兴趣的同学可以参考官方文档进行部署测试。
为了便于理解和说明,以下内容将用一个1(master)+2(work node)的Kubernetes集群进行举例说明。
在安装部署完成之后应该能看到在各个节点上通过DaemonSet的方式运行了一个Flannel的Pod。
[root@10-10-88-192 ~]# kubectl get daemonset -n kube-system -l app=flannel
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-flannel-ds 3 3 3 3 3 beta.kubernetes.io/arch=amd64 135d
[root@10-10-88-192 ~]#
[root@10-10-88-192 ~]#
[root@10-10-88-192 ~]# kubectl get pod -n kube-system -o wide -l app=flannel
NAME READY STATUS RESTARTS AGE IP NODE
kube-flannel-ds-npcxv 1/1 Running 0 2h 172.16.130.164 10-10-88-170
kube-flannel-ds-rv8wv 1/1 Running 0 2h 172.16.130.244 10-10-88-192
kube-flannel-ds-t5zlv 1/1 Running 0 2h 172.16.130.140 10-10-88-195
[root@10-10-88-192 ~]#
每一个Flannel的Pod当中都运行了一个flanneld进程,且flanneld的配置文件以ConfigMap的形式挂载到容器内的/etc/kube-flannel/目录供flanneld使用。
[root@10-10-88-192 ~]# kubectl get cm -n kube-system -l app=flannel
NAME DATA AGE
kube-flannel-cfg 2 137d
[root@10-10-88-192 ~]#
| Flannel Backend
Flannel通过在每一个节点上启动一个叫flanneld的进程,负责每一个节点上的子网划分,并将相关的配置信息如各个节点的子网网段、外部IP等保存到etcd当中,而具体的网络包转发交给具体的Backend来实现。
flanneld可以在启动的时候通过配置文件来指定不同的Backend来进行网络通信,目前比较成熟的Backend有VXLAN、host-gw以及UDP三种方式,也已经有诸如AWS,GCE and AliVPC这些还在实验阶段的Backend。VXLAN是目前官方最推崇的一种Backend实现方式,host-gw一般用于对网络性能要求比较高的场景,但需要基础架构本身的支持,UDP则一般用于Debug和一些比较老的不支持VXLAN的Linux内核。
这里只展开讲讲最成熟也是最通用的三种Backend网络通信实现流程:
-
UDP
-
VXLAN
-
host-gw
UDP
由于UDP模式相对容易理解,故这里先采用UDP这种Backend模式进行举例说明然后再对其他Backend模式进行展开讲解。
采用UDP模式时需要在flanneld的配置文件当中指定Backend type为UDP,可以通过直