【編者的話】Flannel是 CoreOS 團隊針對 Kubernetes 設計的一個覆蓋網絡(Overlay Network)工具,其目的在於幫助每個使用 Kuberentes 的 CoreOS 主機擁有一個完整的子網。此次的分享內容將從Flannel的介紹、工做原理及安裝和配置三方面來介紹這個工具的使用方法。
第一部分:Flannel介紹
Flannel是CoreOS團隊針對Kubernetes設計的一個網絡規劃服務,簡單來講,它的功能是讓集羣中的不一樣節點主機建立的Docker容器都具備全集羣惟一的虛擬IP地址。git
在Kubernetes的網絡模型中,假設了每一個物理節點應該具有一段「屬於同一個內網IP段內」的「專用的子網IP」。例如:
節點A:10.0.1.0/24
節點B:10.0.2.0/24
節點C:10.0.3.0/24github
但在默認的Docker配置中,每一個節點上的Docker服務會分別負責所在節點容器的IP分配。這樣致使的一個問題是,不一樣節點上容器可能得到相同的內外IP地址。並使這些容器之間可以之間經過IP地址相互找到,也就是相互ping通。docker
Flannel的設計目的就是爲集羣中的全部節點從新規劃IP地址的使用規則,從而使得不一樣節點上的容器可以得到「同屬一個內網」且」不重複的」IP地址,並讓屬於不一樣節點上的容器可以直接經過內網IP通訊。
第二部分:Flannel的工做原理
Flannel實質上是一種「覆蓋網絡(overlay network)」,也就是將TCP數據包裝在另外一種網絡包裏面進行路由轉發和通訊,目前已經支持UDP、VxLAN、AWS VPC和GCE路由等數據轉發方式。性能優化
默認的節點間數據通訊方式是UDP轉發,在Flannel的GitHub頁面有以下的一張原理圖:
微信
這張圖的信息量很全,下面簡單的解讀一下。網絡
數據從源容器中發出後,經由所在主機的docker0虛擬網卡轉發到flannel0虛擬網卡,這是個P2P的虛擬網卡,flanneld服務監聽在網卡的另一端。併發
Flannel經過Etcd服務維護了一張節點間的路由表,在稍後的配置部分咱們會介紹其中的內容。ide
源主機的flanneld服務將本來的數據內容UDP封裝後根據本身的路由表投遞給目的節點的flanneld服務,數據到達之後被解包,而後直接進入目的節點的flannel0虛擬網卡,而後被轉發到目的主機的docker0虛擬網卡,最後就像本機容器通訊一下的有docker0路由到達目標容器。高併發
這樣整個數據包的傳遞就完成了,這裏須要解釋三個問題。工具
第一個問題,UDP封裝是怎麼一回事?
咱們來看下面這個圖,這是在其中一個通訊節點上抓取到的ping命令通訊數據包。能夠看到在UDP的數據內容部分實際上是另外一個ICMP(也就是ping命令)的數據包。
原始數據是在起始節點的Flannel服務上進行UDP封裝的,投遞到目的節點後就被另外一端的Flannel服務還原成了原始的數據包,兩邊的Docker服務都感受不到這個過程的存在。
第二個問題,爲何每一個節點上的Docker會使用不一樣的IP地址段?
這個事情看起來很詭異,但真相十分簡單。其實只是單純的由於Flannel經過Etcd分配了每一個節點可用的IP地址段後,偷偷的修改了Docker的啓動參數,見下圖。
這個是在運行了Flannel服務的節點上查看到的Docker服務進程運行參數。
注意其中的「--bip=172.17.18.1/24」這個參數,它限制了所在節點容器得到的IP範圍。
這個IP範圍是由Flannel自動分配的,由Flannel經過保存在Etcd服務中的記錄確保它們不會重複。
第三個問題,爲何在發送節點上的數據會從docker0路由到flannel0虛擬網卡,在目的節點會從flannel0路由到docker0虛擬網卡?
咱們來看一眼安裝了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網卡。
第三部分:Flannel的安裝和配置
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數據中找到這些路由記錄,以下圖。
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的可否實現×××?大家有沒有研究過?
答: 應該不能,它要求這些容器原本就在一個內網裏面。
問: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之類的另說了。
===========================以上內容根據2015年8月25日晚微信羣分享內容整理。分享人林帆,ThoughtWorks成都Cloud&DevOps諮詢師,目前主要研究內容是應用容器化和CoreOS系統相關領域。《CoreOS實踐指南》和《CoreOS那些事》系列文章做者。將在8月28日的容器技術大會上分享CoreOS的話題。DockOne每週都會組織定向的技術分享,歡迎感興趣的同窗加微信:liyingjiesx,進羣參與,您有想聽的話題能夠給咱們留言。