天天看點

Flannel介紹

Flannel介紹

Flannel是 CoreOS 團隊針對Kubernetes設計的一個網絡規劃服務,簡單來說,它的功能是讓叢集中的不同節點主機建立的 Docker 容器都具有全叢集唯一的虛拟IP位址。 

在Kubernetes的網絡模型中,假設了每個實體節點應該具備一段“屬于同一個内網IP段内”的“專用的子網IP”。例如: 

節點A:10.0.1.0/24
節點B:10.0.2.0/24
節點C:10.0.3.0/24
      

但在預設的 Docker 配置中,每個節點上的 Docker 服務會分别負責所在節點容器的IP配置設定。這樣導緻的一個問題是,不同節點上容器可能獲得相同的内外IP位址。并使這些容器之間能夠之間通過IP位址互相找到,也就是互相ping通。 

Flannel的設計目的就是為叢集中的所有節點重新規劃IP位址的使用規則,進而使得不同節點上的容器能夠獲得“同屬一個内網”且”不重複的”IP位址,并讓屬于不同節點上的容器能夠直接通過内網IP通信。 

2Flannel的工作原理

Flannel實質上是一種“覆寫網絡(overlay network)”,也就是将 TCP 資料包 裝在另一種網絡包裡面進行路由轉發和通信,目前已經支援 UDP 、VxLAN、AWS VPC和GCE路由等資料轉發方式。 

預設的節點間資料通信方式是 UDP 轉發,在Flannel的 GitHub 頁面有如下的一張原理圖: 

Flannel介紹

這張圖的 資訊量 很全,下面簡單的解讀一下。 

資料從源容器中發出後,經由所在主機的docker0虛拟網卡轉發到flannel0虛拟網卡,這是個 P2P 的虛拟網卡,flanneld服務監聽在網卡的另外一端。 

Flannel通過 Etcd 服務維護了一張節點間的 路由表 ,在稍後的配置部分我們會介紹其中的内容。 

源主機的flanneld服務将原本的資料内容 UDP 封裝後根據自己的 路由表 投遞給目的節點的flanneld服務,資料到達以後被解包,然後直 接進入目的節點的flannel0虛拟網卡,然後被轉發到目的主機的docker0虛拟網卡,最後就像本機容器通信一下的有docker0路由到達目标容器。 

這樣整個 資料包 的傳遞就完成了,這裡需要解釋三個問題。 

第一個問題,UDP封裝是怎麼一回事?  

我們來看下面這個圖,這是在其中一個通信節點上抓取到的ping指令通信 資料包 。可以看到在 UDP 的資料内容部分其實是另一個 ICMP (也就是ping指令)的 資料包 。 

Flannel介紹

原始資料是在起始節點的Flannel服務上進行 UDP 封裝的,投遞到目的節點後就被另一端的Flannel服務還原成了原始的 資料包 ,兩邊的 Docker 服務都感覺不到這個過程的存在。 

第二個問題,為什麼每個節點上的Docker會使用不同的IP位址段?  

這個事情看起來很詭異,但真相十分簡單。其實隻是單純的因為Flannel通過 Etcd 配置設定了每個節點可用的IP位址段後,偷偷的修改了 Docker 的啟動參數,見下圖。 

Flannel介紹

這個是在運作了Flannel服務的節點上檢視到的 Docker 服務程序運作參數。 

注意其中的“--bip=172.17.18.1/24”這個參數,它限制了所在節點容器獲得的IP範圍。 

這個IP範圍是由Flannel自動配置設定的,由Flannel通過儲存在 Etcd 服務中的記錄確定它們不會重複。 

第三個問題,為什麼在發送節點上的資料會從docker0路由到flannel0虛拟網卡,在目的節點會從flannel0路由到docker0虛拟網卡?  

我們來看一眼安裝了Flannel的節點上的 路由表 。下面是資料發送節點的 路由表 : 

Flannel介紹

這個是資料接收節點的 路由表 : 

Flannel介紹

例如現在有一個 資料包 要從IP為172.17.18.2的容器發到IP為172.17.46.2的容器。根據資料發送節點的 路由表 ,它隻與 172.17.0.0/16比對這條記錄比對,是以資料從docker0出來以後就被投遞到了flannel0。同理在目标節點,由于投遞的位址是一個容 器,是以目的位址一定會落在docker0對于的172.17.46.0/24這個記錄上,自然的被投遞到了docker0網卡。 

回到頂部

3Flannel的安裝和配置

Flannel是Golang編寫的程式,是以的安裝十分簡單。 

從  https :// github .com/ coreos /flannel/releases和  https :// github .com/ coreos / etcd /releases分别下載下傳Flannel和 Etcd 的最新版本 二進制 包。 

解壓後将Flannel的 二進制 檔案“flanneld”和腳本檔案“mk- docker -opts.sh”、以及 Etcd 的 二進制 檔案“ etcd ”和“etcdctl”放到系統的PATH目錄下面安裝就算完成了。 

配置部分要複雜一些。 

首先啟動 Etcd ,參考  https :// github .com/ coreos / etcd  ... overy。 

通路這個位址:  https ://discovery. etcd .io/new?size=3 獲得一個“Discovery位址” 

在每個節點上運作以下啟動指令: 

etcd  -initial-advertise-peer-urls  http ://<目前節點IP>:2380 -listen-peer-urls  http ://<目前節點IP>:2380 -listen-client-urls http ://<目前節點IP>:2379, http ://<目前節點IP>:2379 -advertise-client-urls  http ://<目前節點IP>:2379 -discovery <剛剛獲得的Discovery位址> & 

啟動完 Etcd 以後,就可以配置Flannel了。 

Flannel的配置資訊全部在 Etcd 裡面記錄,往 Etcd 裡面寫入下面這個最簡單的配置,隻指定Flannel能用來配置設定給每個 Docker 節點的拟IP位址段: 

etcdctl set /coreos.com/network/config '{ "Network": "172.17.0.0/16" }'      

然後在每個節點分别啟動Flannel: 

flanneld &      

最後需要給 Docker 動一點手腳,修改它的啟動參數和docker0位址。 

在每個節點上執行: 

sudo mk-docker-opts.sh -i
source /run/flannel/subnet.env
sudo rm /var/run/docker.pid
sudo ifconfig docker0 ${FLANNEL_SUBNET} 
      

重新開機動一次 Docker ,這樣配置就完成了。 

現在在兩個節點分别啟動一個 Docker 容器,它們之間已經通過IP位址直接互相ping通了。 

到此,整個Flannel叢集也就正常運作了。 

最後,前面反複提到過Flannel有一個儲存在 Etcd 的 路由表 ,可以在 Etcd 資料中找到這些路由記錄,如下圖。 

Flannel介紹

Q&A

問:資料從源容器中發出後,經由所在主機的docker0虛拟網卡轉發到flannel0虛拟網卡,這種P2P實際生産中是否存在丢包,或者此機制有高可用保障麼?  

答:隻是本機的 P2P 網卡,沒有經過外部網絡,應該還比較穩定。但我這裡沒有具體資料。 

問:UDP資料封裝,轉發的形式也是UDP麼?我們一般知道UDP發送資料是無狀态的,可靠麼?  

答:轉發的是 UDP , 高并發 資料流 時候也許會有問題,我這裡同樣沒有資料。 

問:實際上,kubernates是淡化了容器ip,外圍使用者隻需關注所調用的服務,并不關心具體的ip,這裡fannel将IP分開且唯一,這樣做有什麼好處?有實際應用的業務場景麼?  

答: IP唯一是Kubernetes能夠組網的條件之一,不把網絡拉通後面的事情都不好整。 

問:Flannel通過Etcd配置設定了每個節點可用的IP位址段後,偷偷的修改了Docker的啟動參數:那麼如果增加節點,或删除節點,這些位址段(ETCD上)會動态變化麼?如果不是動态變化,會造成IP位址的浪費麼?  

答會造成一些浪費,一般使用10.x.x.x的IP段。 

問:sudo mk-docker-opts.sh -i 這個指令具體幹什麼了?非coreos上使用flannel有什麼不同?  

答:生成了一個 Docker 啟動的 環境變量 檔案,裡面給 Docker 增加了啟動參數。 

沒有什麼不同,隻是 CoreOS 內建了Flannel,在 CoreOS 上面啟動Flannel隻是一行指令:systemctl start flanneld。 

問:容器IP都是固定的嗎?外網與實體主機能ping通,也能ping通所有Docker叢集的容器IP?  

答:不是固定的,IP配置設定還是 Docker 在做,Flannel隻是配置設定了子網。 

問:Flannel的能否實作VPN?你們有沒有研究過?  

答: 應該不能,它要求這些容器本來就在一個内網裡面。 

問:Flannl是誰開發的?全是對k8s的二次開發嗎?  

答:  CoreOS 公司,不是k8s的二次開發,獨立的開源項目,給k8s提供基礎網絡環境。 

問:Flannel支援非封包的純轉發嗎?這樣性能就不會有損失了?  

答:非封裝怎樣路由呢?發出來的 TCP 包本身并沒有在網絡間路由的資訊,别忘了,兩個Flannel不是直連的,隔着普通的 區域網路 絡。 

問: Flanel現在到哪個版本了,後續版本有什麼側重點?性能優化,還是功能擴充?  

答:還沒到1.0,在 GitHub 上面有他們的發展計劃,性能是很大的一部分。 

問: 就是在CoreOS中,客戶還需要安裝Flannel嗎?  

答:不需要,在啟動的Cloudinit配置裡面給 Etcd 寫入Flannel配置,然後加上flanneld.service command: start 就可以了,啟動完直接可用,文檔連接配接我不找了,有這段配置,現成的。 

問: 可不可以直接用指令指定每個主機的ip範圍,然後做gre隧道實作節點之間的通信?這樣也可以實作不同主機上的容器ip不同且可以互相通信吧?  

答:還不支援指定哪個節點用那段IP,不過貌似可以在 Etcd 手改。 

問: Flannel隻是負責通信服務,那是不是還要安裝k8s?  

答:是的,k8s是單獨的。 

問:現在Docker的網絡元件還有什麼可以選擇或者推薦的?  

答:Overlay網絡的常用就是Flannel和Weave,其他OVS之類的另說了。