Flannel簡介
Flannel是為Kubernetes設(shè)計的一個基于CNI的網(wǎng)絡(luò)插件,其目的是讓集群中創(chuàng)建的所有容器都具有唯一的IP地址。一般情況下,每個節(jié)點中的Docker管理進程會負(fù)責(zé)其所在節(jié)點容器的IP分配,這樣節(jié)點內(nèi)部的容器可以互相訪問,但是不同節(jié)點之間的容器無法通信。
Flannel的出現(xiàn)就是解決了上述不同節(jié)點間容器無法通信的問題,通過為集群中所有節(jié)點重新規(guī)劃IP地址及其使用規(guī)則,從而使得不同節(jié)點上的容器都能夠獲取同一個內(nèi)網(wǎng)且不重復(fù)的IP地址,并讓不同節(jié)點上的容器直接通過內(nèi)網(wǎng)IP通信。
Flannel架構(gòu)原理
Flannel會在每一個節(jié)點上運行名為flanneld代理,其負(fù)責(zé)為該節(jié)點預(yù)先分配一個子網(wǎng),并為Pod分配IP地址。Flannel使用Kubernetes或etcd來存儲網(wǎng)絡(luò)配置、分配的子網(wǎng)和主機公共IP等信息。數(shù)據(jù)包則通過VXLAN、UDP或host-gw這些類型的后端機制進行轉(zhuǎn)發(fā)。

Flannel 服務(wù)啟動后,首先讀取配置信息及其子網(wǎng)列表,再選擇一個可用的子網(wǎng)去注冊。Flannel 使用etcd存儲配置信息及子網(wǎng)分配內(nèi)容,同時也存儲了每個節(jié)點的ip地址。借助于etcd的watch機制監(jiān)控子網(wǎng)配置信息所有的變化,并且根據(jù)它來維護一個路由表。
一條報文從一個容器發(fā)送到另外一個容器需要經(jīng)歷如下的過程:
- 報文直接使用目標(biāo)容器的ip訪問,默認(rèn)通過容器內(nèi)部的eth0發(fā)送出去;
- 報文通過veth pair 被發(fā)送到 vethxxx;
- vethxxx再連接到虛擬交換機Docker0,報文通過虛擬網(wǎng)橋Docker0發(fā)送出去;
- 查找路由表,外部容器ip的報文都會轉(zhuǎn)到flannel0虛擬網(wǎng)卡,這是一個P2P的虛擬網(wǎng)卡,然后報文就被轉(zhuǎn)到監(jiān)聽在另一端的flanneld;
- Flannel通過Etcd服務(wù)維護了一張各節(jié)點間的路由表,這里保存了各個節(jié)點主機的子網(wǎng)網(wǎng)段信息。把原來的報文UDP封裝一層,通過配置的iface發(fā)送出去;
- 報文通過節(jié)點之間的網(wǎng)絡(luò)找到目標(biāo)節(jié)點;
- 報文繼續(xù)往上送,到達(dá)傳輸層,交給監(jiān)聽的8285端口的flanneld服務(wù)處理;
- 數(shù)據(jù)被解包,然后直接發(fā)送給flannel0虛擬網(wǎng)卡;
- 查找路由表, 發(fā)現(xiàn)對應(yīng)容器的報文并交給Docker0;
- Docker0找到對應(yīng)的容器并發(fā)送報文過去。
Fannel實戰(zhàn)
Flannel支持多種后端
VxLan
host gw:Host Gateway
通過ifconfig可以看到flannel.1:ip地址是10.244.0.0,用來封裝隧道協(xié)議報文的。mtu 1450,疊加隧道封裝會有額外開銷。
另外還有個cni的接口:ip地址是10.244.0.1

- VxLan
-
VxLan
擴展的四層隧道協(xié)議,通過二層幀進行傳送;先封裝vxlan首部,再封裝udp首部,再之外是ip首部,最外是以太網(wǎng)首部。這些額外的開銷會導(dǎo)致性能比較低,但是能管理獨立的網(wǎng)絡(luò)。
VxLan - Directrouting
源容器和目標(biāo)容器都在同一個節(jié)點,不用隧道。
-
host gw
Host Gateway,容器將報文發(fā)給虛擬接口,虛擬接口查詢本機路由表,通過宿主機網(wǎng)關(guān)發(fā)送出去。
這種方式性能也不錯,跟Calico沒啥大的差別,但是有個缺陷就是各個節(jié)點的網(wǎng)絡(luò)需要在同一個三層網(wǎng)絡(luò)中。
host gw - UDP
普通的udp方式轉(zhuǎn)發(fā),性能更差
安裝及配置
1.只用到amd64,3個副本的daemonset在三個不同的節(jié)點上

2.配置文件
Flannel的配置參數(shù):
Network: flannel使用的CIDR格式的網(wǎng)絡(luò)地址,用于為Pod配置網(wǎng)絡(luò)功能,這是全局的網(wǎng)絡(luò)地址,為每個節(jié)點配置一個子網(wǎng):
10.244.0.0/16 :最多只能是256個節(jié)點
master: 10.244.0.0/24
node01: 10.244.1.0/24
node02: 10.244.2.0/24
node03: 10.244.3.0/24
...
node255: 10.244.255.0/24

子網(wǎng)長度SubnetLen:把network切分子網(wǎng)供各個節(jié)點使用時,使用多長的掩碼進行切分,默認(rèn)為24;
最小SubnetMin:如10.244.0.0/24;
最大SubnetMax:如10.244.255.0/24;
Backend:vxlan, host-gw, udp
容器通信抓包:tcpdump -i cni0 -nn icmp/tcpdump -i flannel.1 -nn
報文從cni0進來,在flannel1封裝成vxlan報文,再通過物理網(wǎng)卡出去。

tcpdump -i ens32 -nn 172.20.0.66

配置flannel
cd manifest
mkdir flannel
cd flannel
vim net-con.json

kubectl edit configmap kube-flannel-cfg -n kube-system
在Backend的Type下加一個"Directrouting": true

ip route show //查看路由,發(fā)現(xiàn)沒有生效

查找原因

需要加個逗號,無語了......

只能下載執(zhí)行https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel.yml
先rm net-con.json,再修改下載的kube-flannel.yaml文件,把Directrouting加上。然后拆了重新裝,kubectl delete -f kube-flannel.yaml
kubectl apply -f kube-flannel.yaml
直接從一個容器ping另外一個后抓包,直接通過物理網(wǎng)卡通信,物理網(wǎng)卡橋接網(wǎng)絡(luò),性能比較好。

改成host-gw,支持directrouting,host-gw各個節(jié)點必須在同一個網(wǎng)段,跨網(wǎng)段是不行的。

路由的效果也是一樣的,也是vxlan的directrouting


