安裝docker跨主機網絡flannel


   

一、實驗環境

 

機器 操作系統 安裝服務
172.16.4.36 centos7

docker

etcd

flannel

 

172.16.4.37 centos7

docker

etcd

flanne

 

 

 

 

 

 

 

 

 

(以上環境中:docker已安裝好)

二、Flannel網絡原理

Flannel是CoreOS團隊針對Kubernetes設計的一個網絡規划服務,簡單來說,它的功能是讓集群中的不同節點主機創建的Docker容器都具有全集群唯一的虛擬IP地址。
但在默認的Docker配置中,每個節點上的Docker服務會分別負責所在節點容器的IP分配。這樣導致的一個問題是,不同節點上容器可能獲得相同的內外IP地址。並使
這些容器之間能夠之間通過IP地址相互找到,也就是相互ping通。
   
Flannel的設計目的就是為集群中的所有節點重新規划IP地址的使用規則,從而使得不同節點上的容器能夠獲得"同屬一個內網""不重復的"IP地址,並讓屬於不同節
點上的容器能夠直接通過內網IP通信。
   
Flannel實質上是一種"覆蓋網絡(overlay network)",即表示運行在一個網上的網(應用層網絡),並不依靠ip地址來傳遞消息,而是采用一種映射機制,把ip地址和
identifiers做映射來資源定位。也就是將TCP數據包裝在另一種網絡包里面進行路由轉發和通信,目前已經支持UDP、VxLAN、AWS VPC和GCE路由等數據轉發方式。
   
原理是每個主機配置一個ip段和子網個數。例如,可以配置一個覆蓋網絡使用 10.100.0.0/16段,每個主機/24個子網。比如主機a可以接受10.100.5.0/24,主機B可以
接受10.100.18.0/24的包。flannel使用etcd來維護分配的子網到實際的ip地址之間的映射。對於數據路徑,flannel 使用udp來封裝ip數據報,轉發到遠程主機。選擇
UDP作為轉發協議是因為他能穿透防火牆。例如,AWS Classic無法轉發IPoIP or GRE 網絡包,是因為它的安全組僅僅支持TCP/UDP/ICMP。
   
flannel 使用etcd存儲配置數據和子網分配信息。flannel 啟動之后,后台進程首先檢索配置和正在使用的子網列表,然后選擇一個可用的子網,然后嘗試去注冊它。
etcd也存儲這個每個主機對應的ip。flannel 使用etcd的watch機制監視/coreos.com/network/subnets下面所有元素的變化信息,並且根據它來維護一個路由表。為了
提高性能,flannel優化了Universal TAP/TUN設備,對TUN和UDP之間的ip分片做了代理。

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

  • 數據從源容器中發出后,經由所在主機的docker0虛擬網卡轉發到flannel0虛擬網卡,這是個P2P的虛擬網卡,flanneld服務監聽在網卡的另外一端。
  • Flannel通過Etcd服務維護了一張節點間的路由表,詳細記錄了各節點子網網段 。
  • 源主機的flanneld服務將原本的數據內容UDP封裝后根據自己的路由表投遞給目的節點的flanneld服務,數據到達以后被解包,然后直接進入目的節點的flannel0虛擬網卡,然后被轉發到目的主機的docker0虛擬網卡,最后就像本機容器通信一下的有docker0路由到達目標容器。
三、Flannel網絡部署實驗

1、安裝etcd

1)下載並解壓(在172.16.4.36和172.16.4.37上都執行以下命令)

wget https://github.com/etcd-io/etcd/releases/download/v3.3.10/etcd-v3.3.10-linux-amd64.tar.gz
tar -xf etcd-v3.3.10-linux-amd64.tar.gz
cd etcd-v3.3.10-linux-amd64
mv etcd* /usr/bin/

2)在172.16.4.36上新建:/usr/lib/systemd/system/etcd.service

[Unit]
Description=etcd
After=network.target

[Service]
Environment=ETCD_NAME=etcd-1
Environment=ETCD_DATA_DIR=/var/lib/etcd
Environment=ETCD_LISTEN_CLIENT_URLS=http://172.16.4.36:2379,http://127.0.0.1:2379
Environment=ETCD_LISTEN_PEER_URLS=http://172.16.4.36:2380
Environment=ETCD_ADVERTISE_CLIENT_URLS=http://172.16.4.36:2379,http://127.0.0.1:2379
Environment=ETCD_INITIAL_ADVERTISE_PEER_URLS=http://172.16.4.36:2380
Environment=ETCD_INITIAL_CLUSTER_STATE=new
Environment=ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-token
Environment=ETCD_INITIAL_CLUSTER=etcd-1=http://172.16.4.36:2380,etcd-2=http://172.16.4.37:2380
ExecStart=/usr/bin/etcd
[Install]
WantedBy=multi-user.target

3)在172.16.4.37上新建:/usr/lib/systemd/system/etcd.service

[Unit]
Description=etcd
After=network.target

[Service]
Environment=ETCD_NAME=etcd-2
Environment=ETCD_DATA_DIR=/var/lib/etcd
Environment=ETCD_LISTEN_CLIENT_URLS=http://172.16.4.37:2379,http://127.0.0.1:2379
Environment=ETCD_LISTEN_PEER_URLS=http://172.16.4.37:2380
Environment=ETCD_ADVERTISE_CLIENT_URLS=http://172.16.4.37:2379,http://127.0.0.1:2379
Environment=ETCD_INITIAL_ADVERTISE_PEER_URLS=http://172.16.4.37:2380
Environment=ETCD_INITIAL_CLUSTER_STATE=new
Environment=ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-token
Environment=ETCD_INITIAL_CLUSTER=etcd-1=http://172.16.4.36:2380,etcd-2=http://172.16.4.37:2380
ExecStart=/usr/bin/etcd
[Install]
WantedBy=multi-user.target
  • name:節點名稱 data-dir 指定節點的數據存儲目錄
  • listen-peer-urls: 監聽URL,用於與其他節點通訊
  • listen-client-urls: 對外提供服務的地址:比如 http://ip:2379,http://127.0.0.1:2379 ,客戶端會連接到這里和 etcd 交互
  • initial-advertise-peer-urls: 該節點同伴監聽地址,這個值會告訴集群中其他節點
  • initial-cluster 集群中所有節點的信息,格式為 node1=http://ip1:2380,node2=http://ip2:2380,… 。注意:這里的 node1 是節點的 --name 指定的名字;后面的 ip1:2380 是 --initial-advertise-peer-urls 指定的值
  • initial-cluster-state: 新建集群的時候,這個值為 new ;假如已經存在的集群,這個值為 existing
  • initial-cluster-token :創建集群的 token,這個值每個集群保持唯一。這樣的話,如果你要重新創建集群,即使配置和之前一樣,也會再次生成新的集群和節點 uuid;否則會導致多個集群之間的沖突,造成未知的錯誤
  • advertise-client-urls:對外公告的該節點客戶端監聽地址,這個值會告訴集群中其他節點
4)在172.16.4.36和172.16,4.37上新建:執行以下命令啟動服務
systemctl enable etcd
systemctl start etcd

測試etcd集群是否正常:

先在172.16.4.36上執行

etcdctl mkdir /boshen

先在172.16.4.37上執行

[root@ ~]# etcdctl ls
/boshen

從上面可以看出,36上創建的數據37上也能看到,表示etcd集群正常工作了

 

2、安裝flannel

1)下載並解壓(在172.16.4.36和172.16.4.37上都執行以下命令)

wget https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz
tar -xf flannel-v0.10.0-linux-amd64.tar.gz
cp flanneld /usr/bin/

2)定義flannel網絡ip池(只在一個節點上執行就行,比如在172.16.4.36上執行)

flannel-config.json 中,內容為:

{
  "Network": "10.3.0.0/16",
  "SubnetLen": 24,
  "Backend": {
    "Type": "vxlan"
  }
}
  1. Network 定義該網絡的 IP 池為 10.3.0.0/16
  2. SubnetLen 指定每個主機分配到的 subnet 大小為 24 位,即10.3.X.0/24
  3. Backend 為 vxlan,即主機間通過 vxlan 通信。

然后執行以下命令:

etcdctl set /docker-flannel/network/config < flannel-config.json

3)新建啟動文件: /usr/lib/systemd/system/flanneld.service(172.16.4.36和172.16.4.37)

[Unit]
Description=flannel
After=etcd.service network.target

[Service]
ExecStart=/usr/bin/flanneld --etcd-endpoints=http://172.16.4.36:2379,http://172.16.4.37:2379 -etcd-prefix=/docker-flannel/network  --iface=eth0
[Install]
WantedBy=multi-user.target
  • --etcd-endpoints 指定 etcd url。
  • --iface 指定主機間數據傳輸使用的 interface。
  • --etcd-prefix 指定 etcd 存放 flannel 網絡配置信息的 key。只能指到目錄級別,比如上面的key為:/docker-flannel/network/config ,只能指到/docker-flannel/network

4)啟動flanneld(172.16.4.36和172.16.4.37)

systemctl enable flanneld
systemctl start flanneld

查看狀態

systemctl status flanneld

172.16.4.36上自動分配的子網為:10.3.39.0/24

172.16.4.36上新建了一個interface:  flannel.1

172.16.4.36上添加了一條路由:目的地址為 flannel 網絡 10.3.59.0/24 的數據包都由 flannel.1 轉發

172.16.4.37上自動分配的子網為:10.3.59.0/24

172.16.4.37上也新建了一個interface:  flannel.1

172.16.4.36上添加了一條路由:目的地址為 flannel 網絡 10.3.39.0/24 的數據包都由 flannel.1 轉發

 

3、Docker中使用flannel

上面只是安裝了flannel網絡,還需要指定docker中默認的網絡為flannel,要不然容器仍然使用默認網絡(bridge)

1)編輯docker的配置文件:/usr/lib/systemd/system/docker.service

增加紫框部分:其中這兩個參數的值必須與 /run/flannel/subnet.env 中 FLANNEL_SUBNET 和FLANNEL_MTU 一致。

2)重啟docker服務

systemctl daemon-reload
systemctl restart docker

在172.16.4.36上,會將10.3.39.1配置到 Linux bridge docker0上,並添加了到10.3.39.0/24的一條路由

在172.16.4.37上,會將10.3.59.1配置到 Linux bridge docker0上,並添加了到10.3.59.0/24的一條路由

 3)測試flannel網絡的連通性

 在172.16.4.36上運行容器box1,容器內ip為10.3.39.2

docker run -itd --name=box1 busybox
docker exec box1 ip r

 在172.16.4.37上運行容器box2,容器內ip為10.3.59.2

docker run -itd --name=box2 busybox
docker exec box2 ip r

 

 在172.16.4.36上執行

可以發現,是可以ping通10.3.59.2,說明box1和box2是連通的,下面用traceroute分析下數據包流向:

  •  box1容器的數據包首先發給自己主機的docker0,因為docker0是box1容器內的默認網關
  • 在172.16.4.36上,根據下面的路由表,發送給docker0的數據包會發到10.3.39.0/24也就是會發給flannel.1,flannel.1 將數據包封裝成 VxLAN,通過 宿主機的eth0 發送給172.16.4.37

    

  • 在172.16.4.37上,收到box1發來的數據包,發現目的地址是10.3.59.2,根據宿主機的路由表,數據包發送給 flannel.1,並通過 docker0 到達 box2

     

 4)flannel網絡的隔離性

 flannel 為每個主機分配了獨立的 subnet,但 flannel.1 將這些 subnet 連接起來了,相互之間可以路由。本質上,flannel 將各主機上相互獨立的 docker0 容器網絡組成了一個互通的大網絡,實現了容器跨主機通信。flannel 沒有提供隔離。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM