Docker學習筆記 — Coreos/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通信。

Flannel的工作原理


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

默認的節點間數據通信方式是UDP轉發,在Flannel的GitHub頁面有如下的一張原理圖:

這裏寫圖片描述

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

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

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

源主機的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/releaseshttps://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數據中找到這些路由記錄,如下圖。

這裏寫圖片描述



轉載自:DockOne技術分享(十八):一篇文章帶你瞭解Flannel

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章