Flannel
Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的 不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。
Flannel聚焦于网络,而非网络策略。
工作原理
Flannel在每个主机上运行一个小的单一二进制代理,称为flanneld,并负责从更大的预配置地址空间中 为每个主机分配子网租约。 Flannel直接使用Kubernetes API或etcd来存储网络配置,分配的子网和 任何辅助数据(例如主机的公共IP)。 使用多种后端机制之一转发数据包,包括VXLAN和各种云集成。
在默认的Docker配置中,每个Node的Docker服务会分别负责所在节点容器的IP分配。Node内部的容器 之间可以相互访问,但是跨主机(Node)网络相互间是不能通信。Flannel设计目的就是为集群中所有节点 重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得”同属一个内网”且”不重复的”IP地址, 并让属于不同节点上的容器能够直接通过内网IP通信。
Flannel 使用etcd存储配置数据和子网分配信息。flannel 启动之后,后台进程首先检索配置和正在 使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。etcd也存储这个每个主机对应的ip。 flannel 使用etcd的watch机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据 它来维护一个路由表。为了提高性能,flannel优化了Universal TAP/TUN设备,对TUN和UDP之间的ip 分片做了代理。
报文传输路径
数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel.1虚拟网卡。
Flannel通过Etcd服务维护了一张节点间的路由表,该张表里保存了各个节点主机的子网网段信息。
源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务, 数据到达以后被解包,然后进入目的节点的flannel.1虚拟网卡,再然后被转发到目的主机的docker0虚拟网卡, 最后就像本机容器通信一样的由docker0路由到目标容器。
在最外层报文,是有A主机到B主机, 然后再将报文解封装到目标的虚拟机中。
编译及安装
sudo yum install kernel-headers golang gcc glibc-static
下载代码 :
git clone https://github.com/coreos/flannel.git
编译 :
CGO_ENABLED=1 make dist/flanneld
后端支持
推荐使用内核VXLAN封装数据包。还支持host-gw/UDP等等。
使用host-gw通过远程计算机IP创建到子网的IP路由。 host-gw需要运行flannel的主机之间具有 直接的layer2连接。因此在云上不能使用。
host-gw具有良好的性能,几乎没有依赖关系,并且易于设置。
运行
首先启动etcd, 然后进行基本设置
$ etcd &
或
$ systemctl start etcd
然后在etcd中添加flannel配置
$ etcdctl set /coreos.com/network/config '{ "Network": "10.5.0.0/16", "Backend": {"Type": "vxlan"}}'
启动flanneld
[zhang@localhost flannel]$ sudo ./dist/flanneld [sudo] password for zhang: I0918 01:50:49.978004 7651 main.go:518] Determining IP address of default interface I0918 01:50:49.980126 7651 main.go:531] Using interface with name enp0s3 and address 10.0.2.15 I0918 01:50:49.980163 7651 main.go:548] Defaulting external address to interface address (10.0.2.15) I0918 01:50:49.980453 7651 main.go:246] Created subnet manager: Etcd Local Manager with Previous Subnet: 10.5.58.0/24 I0918 01:50:49.980471 7651 main.go:249] Installing signal handlers I0918 01:50:49.983762 7651 main.go:390] Found network config - Backend type: vxlan I0918 01:50:49.983834 7651 vxlan.go:121] VXLAN config: VNI=1 Port=0 GBP=false Learning=false DirectRouting=false I0918 01:50:49.988488 7651 local_manager.go:147] Found lease (10.5.58.0/24) for current IP (10.0.2.15), reusing I0918 01:50:49.992472 7651 main.go:313] Changing default FORWARD chain policy to ACCEPT I0918 01:50:49.992804 7651 main.go:321] Wrote subnet file to /run/flannel/subnet.env I0918 01:50:49.992829 7651 main.go:325] Running backend. I0918 01:50:50.002762 7651 vxlan_network.go:60] watching for new subnet leases I0918 01:50:50.003475 7651 main.go:433] Waiting for 22h59m59.985730351s to renew lease
进程启动成功后, 将创建VXLAN tunnel设备, 我这里设备名称为flannel.1, 可以查看配置
- $ cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.5.0.0/16 FLANNEL_SUBNET=10.5.58.1/24 FLANNEL_MTU=1450 FLANNEL_IPMASQ=false
可以通过”ip -d addr”查看flannel.1网卡信息, 选项”-d”表示输出详细信息
[root@zhang1 ckd]# ip -d addr show flannel.1
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether 2e:89:bf:b4:cd:aa brd ff:ff:ff:ff:ff:ff promiscuity 0
vxlan id 1 local 192.168.101.180 dev enp0s8 srcport 0 0 dstport 8472 nolearning ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 10.244.0.0/32 brd 10.244.0.0 scope global flannel.1
valid_lft forever preferred_lft forever
inet6 fe80::2c89:bfff:feb4:cdaa/64 scope link
valid_lft forever preferred_lft forever
从以上输出可以看到,flannel.1的local IP为192.168.101.180,目的端口为8472。MTU值为 1450, 比通常网卡的mtu 1500要小。 vxlan网络IP为10.244.0.0/32。
通过k8s安装
flannel也可以运行在容器中,它的网络模式为host模式,即hostNetwork为true.
flannel自己的控制器如果作为pod来部署的话是一个demonset,一个节点上只运行一个pod副本,相当于模拟运行了系统级的守护进程。 并且这个pod副本和宿主机共享网络名称空间。
创建命令为
kubectl apply -f kube-flannel.yml
kube-flannel.yml在代码库中有提供,地址为: https://github.com/coreos/flannel.git仓库下Documentation/kube-flannel.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
诊断
kubectl get po –namespace kube-system -l app=flannel
kubectl logs –namespace kube-system <POD_ID> -c kube-flannel
问题,没有默认路由错误
输出以下错误
[zhang@localhost flannel]$ sudo ./dist/flanneld
I0920 21:47:11.200976 2224 main.go:518] Determining IP address of default interface
E0920 21:47:11.201471 2224 main.go:204] Failed to find any valid interface to use: failed to get default interface: Unable to find default route
解决方法:增加默认路由, 我这里有NAT网卡可以出去,因此通过dhcp分配ip及默认路由即可。
$ sudo dhclient enp0s3
参考资料
https://github.com/coreos/flannel/blob/master/Documentation/running.md
https://github.com/coreos/flannel/blob/master/Documentation/kubernetes.md