flannel原理簡(jiǎn)析及安裝

flannel是CoreOS提供用于解決Dokcer集群跨主機(jī)通訊的覆蓋網(wǎng)絡(luò)工具。它的主要思路是:預(yù)先留出一個(gè)網(wǎng)段,每個(gè)主機(jī)使用其中一部分,然后每個(gè)容器被分配不同的ip;讓所有的容器認(rèn)為大家在同一個(gè)直連的網(wǎng)絡(luò),底層通過UDP/VxLAN
等進(jìn)行報(bào)文的封裝和轉(zhuǎn)發(fā)。
flannel項(xiàng)目地址:https://github.com/coreos/flannel
flannel架構(gòu)介紹
flannel默認(rèn)使用8285端口作為UDP
封裝報(bào)文的端口,VxLan使用8472端口。


那么一條網(wǎng)絡(luò)報(bào)文是怎么從一個(gè)容器發(fā)送到另外一個(gè)容器的呢?
容器直接使用目標(biāo)容器的ip訪問,默認(rèn)通過容器內(nèi)部的eth0發(fā)送出去。
報(bào)文通過veth pair
被發(fā)送到vethXXX
。
vethXXX
是直接連接到虛擬交換機(jī)docker0
的,報(bào)文通過虛擬bridge docker0
發(fā)送出去。
查找路由表,外部容器ip的報(bào)文都會(huì)轉(zhuǎn)發(fā)到flannel0
虛擬網(wǎng)卡,這是一個(gè)P2P
的虛擬網(wǎng)卡,然后報(bào)文就被轉(zhuǎn)發(fā)到監(jiān)聽在另一端的flanneld
。
flanneld
通過etcd
維護(hù)了各個(gè)節(jié)點(diǎn)之間的路由表,把原來(lái)的報(bào)文UDP
封裝一層,通過配置的iface
發(fā)送出去。
報(bào)文通過主機(jī)之間的網(wǎng)絡(luò)找到目標(biāo)主機(jī)。
報(bào)文繼續(xù)往上,到傳輸層,交給監(jiān)聽在8285端口的flanneld
程序處理。
數(shù)據(jù)被解包,然后發(fā)送給flannel0
虛擬網(wǎng)卡。
查找路由表,發(fā)現(xiàn)對(duì)應(yīng)容器的報(bào)文要交給docker0
。
docker0
找到連到自己的容器,把報(bào)文發(fā)送過去。

flannel安裝配置
環(huán)境準(zhǔn)備
一共三臺(tái)機(jī)器:一個(gè)etcd集群,三臺(tái)機(jī)器安裝flannel和Docker。
節(jié)點(diǎn)名稱
IP地址
軟件環(huán)境

etcd1
192.168.2.210
etcd、flannel、docker

etcd2
192.168.2.211
etcd、flannel、docker

etcd3
192.168.2.212
etcd、flannel、docker

安裝etcd
關(guān)于etcd的安裝使用已經(jīng)在「etcd使用入門」和「通過靜態(tài)發(fā)現(xiàn)方式部署etcd集群」中做了比較詳細(xì)的講解,如果你還不會(huì)安裝etcd可先閱讀下這兩篇文章。這里就不再重復(fù)講解了。
安裝flannel
三個(gè)節(jié)點(diǎn)都需安裝配置flannel,這里以etcd1節(jié)點(diǎn)為例。
flannel和etcd一樣,直接從官方下載二進(jìn)制執(zhí)行文件就可以用了。當(dāng)然,你也可以自己編譯。
1
2
3

$ curl -L https://github.com/coreos/flannel/releases/download/v0.7.0/flannel-v0.7.0-linux-amd64.tar.gz -o flannel.tar.gz
$ mkdir -p /opt/flannel
$ tar xzf flannel.tar.gz -C /opt/flannel

解壓后主要有flanneld
、mk-docker-opts.sh
這兩個(gè)文件,其中flanneld
為主要的執(zhí)行文件,sh腳本用于生成Docker啟動(dòng)參數(shù)。
配置flannel
由于flannel
需要依賴etcd
來(lái)保證集群IP分配不沖突的問題,所以首先要在etcd
中設(shè)置 flannel
節(jié)點(diǎn)所使用的IP段。
1
2
3
4

$ etcdctl --endpoints "http://etcd1.hi-linux.com:2379"
set /coreos.com/network/config '{"NetWork":"10.0.0.0/16", "SubnetMin": "10.0.1.0", "SubnetMax": "10.0.20.0"}'

{"NetWork":"10.0.0.0/16", "SubnetMin": "10.0.1.0", "SubnetMax": "10.0.20.0"}

flannel預(yù)設(shè)的backend type
是udp,如果想要使用vxlan
作為backend
,可以加上backend
參數(shù):
1
2

$ etcdctl --endpoints "http://etcd1.hi-linux.com:2379"
set /coreos.com/network/config '{"NetWork":"10.0.0.0/16", "Backend": {"Type": "vxlan"}}'

flannel backend為vxlan比起預(yù)設(shè)的udp性能相對(duì)好一些。

啟動(dòng)flannel
命令行方式運(yùn)行

1

$ /opt/flannel/flanneld --etcd-endpoints="http://etcd1.hi-linux.com:2379" --ip-masq=true >> /var/log/flanneld.log 2>&1 &

后臺(tái)服務(wù)方式運(yùn)行

給flannel創(chuàng)建一個(gè)systemd服務(wù),方便以后管理。創(chuàng)建flannel配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

$ cat <<EOF | sudo tee /etc/systemd/system/flanneld.service
[Unit]
Description=Flanneld
Documentation=https://github.com/coreos/flannel
After=network.target
Before=docker.service

[Service]
User=root
ExecStart=/opt/flannel/flanneld
--etcd-endpoints="http://etcd1.hi-linux.com:2379,http://etcd2.hi-linux.com:2379,http://etcd3.hi-linux.com:2379"
--iface=192.168.2.210
--ip-masq
Restart=on-failure
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

注意:--iface
參數(shù)為要綁定的網(wǎng)卡的IP地址,請(qǐng)根據(jù)實(shí)際情況修改。

啟動(dòng)flannel服務(wù)
1

$ systemctl start flanneld

flannel啟動(dòng)過程解析
flannel服務(wù)需要先于Docker啟動(dòng)。flannel服務(wù)啟動(dòng)時(shí)主要做了以下幾步的工作:
從etcd中獲取network的配置信息。
劃分subnet,并在etcd中進(jìn)行注冊(cè)。
將子網(wǎng)信息記錄到/run/flannel/subnet.env
中。

驗(yàn)證flannel網(wǎng)絡(luò)
在etcd1節(jié)點(diǎn)上看etcd中的內(nèi)容
1
2
3

$ etcdctl --endpoints "http://etcd1.hi-linux.com:2379" ls /coreos.com/network/subnets

/coreos.com/network/subnets/10.0.2.0-24

查看flannel0的網(wǎng)絡(luò)情況:
1
2
3
4
5
6
7
8

$ ifconfig flannel0
flannel0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.0.2.0 P-t-P:10.0.2.0 Mask:255.255.0.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1472 Metric:1
RX packets:85 errors:0 dropped:0 overruns:0 frame:0
TX packets:75 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:7140 (7.1 KB) TX bytes:6300 (6.3 KB)

可以看到flannel0網(wǎng)卡的地址和etcd中存儲(chǔ)的地址一樣,這樣flannel網(wǎng)絡(luò)配置完成。
配置Docker
在各個(gè)節(jié)點(diǎn)安裝好以后最后要更改Docker
的啟動(dòng)參數(shù),使其能夠使用flannel
進(jìn)行IP分配,以及網(wǎng)絡(luò)通訊。
flannel
運(yùn)行后會(huì)生成一個(gè)環(huán)境變量文件,包含了當(dāng)前主機(jī)要使用flannel
通訊的相關(guān)參數(shù)。
查看flannel分配的網(wǎng)絡(luò)參數(shù)

1
2
3
4
5
6

$ cat /run/flannel/subnet.env

FLANNEL_NETWORK=10.0.0.0/16
FLANNEL_SUBNET=10.0.2.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=true

創(chuàng)建Docker運(yùn)行參數(shù)

使用flannel提供的腳本將subnet.env轉(zhuǎn)寫成Docker啟動(dòng)參數(shù),創(chuàng)建好的啟動(dòng)參數(shù)位于/run/docker_opts.env
文件中。
1
2
3
4

$ /opt/flannel/mk-docker-opts.sh -d /run/docker_opts.env -c

$ cat /run/docker_opts.env
DOCKER_OPTS=" --bip=10.0.2.1/24 --ip-masq=false --mtu=1472"

修改Docker啟動(dòng)參數(shù)

修改docker的啟動(dòng)參數(shù),并使其啟動(dòng)后使用由flannel生成的配置參數(shù),修改如下:
1
2
3
4
5
6

編輯 systemd service 配置文件

$ vim /lib/systemd/system/docker.service

在啟動(dòng)時(shí)增加flannel提供的啟動(dòng)參數(shù)

ExecStart=/usr/bin/dockerd $DOCKER_OPTS

指定這些啟動(dòng)參數(shù)所在的文件位置(這個(gè)配置是新增的,同樣放在Service標(biāo)簽下)

EnvironmentFile=/run/docker_opts.env

然后重新加載systemd配置,并重啟Docker
即可
1
2

$ systemctl daemon-reload
$ systemctl restart docker

此時(shí)可以看到docker0
的網(wǎng)卡ip地址已經(jīng)處于flannel
網(wǎng)卡網(wǎng)段之內(nèi)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

$ ifconfig flannel0
flannel0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.0.2.0 P-t-P:10.0.2.0 Mask:255.255.0.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1472 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

$ ifconfig docker0
docker0 Link encap:Ethernet HWaddr 02:42:cf:87:3c:f7
inet addr:10.0.2.1 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

到此節(jié)點(diǎn)etcd1的flannel安裝配置完成了,其它兩節(jié)點(diǎn)按以上方法配置完成就行了。
測(cè)試flannel
三臺(tái)機(jī)器都配置好了之后,我們?cè)谌_(tái)機(jī)器上分別開啟一個(gè)docker容器,測(cè)試它們的網(wǎng)絡(luò)是否可相互聯(lián)通的。
etcd1
1
2
3
4
5

$ docker run -it busybox sh

查看容器IP

$ cat /etc/hosts
10.0.2.2 9de86bfde6cc

etcd2
1
2
3
4
5

$ docker run -it busybox sh

查看容器IP

$ cat /etc/hosts
10.0.5.2 9ddd4a4e455b

etcd3
1
2
3
4
5

$ docker run -it busybox sh

查看容器IP

$ cat /etc/hosts
10.0.6.2 cbb0d891f353

從不同宿主機(jī)容器到三臺(tái)宿主機(jī)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

/ # ping -c3 192.168.2.210
PING 192.168.2.210 (192.168.2.210): 56 data bytes
64 bytes from 192.168.2.210: seq=0 ttl=64 time=0.089 ms
64 bytes from 192.168.2.210: seq=1 ttl=64 time=0.065 ms

/ # ping -c5 192.168.2.211
PING 192.168.2.211 (192.168.2.211): 56 data bytes
64 bytes from 192.168.2.211: seq=0 ttl=63 time=1.712 ms
64 bytes from 192.168.2.211: seq=1 ttl=63 time=0.356 ms
64 bytes from 192.168.2.211: seq=2 ttl=63 time=2.201 ms

/ # ping -c3 192.168.2.212
PING 192.168.2.212 (192.168.2.212): 56 data bytes
64 bytes from 192.168.2.212: seq=0 ttl=63 time=0.467 ms
64 bytes from 192.168.2.212: seq=1 ttl=63 time=0.477 ms
64 bytes from 192.168.2.212: seq=2 ttl=63 time=0.532 ms

從容器到到跨宿主機(jī)容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

/ # ping -c3 10.0.5.2
PING 10.0.5.2 (10.0.5.2): 56 data bytes
64 bytes from 10.0.5.2: seq=0 ttl=60 time=0.692 ms
64 bytes from 10.0.5.2: seq=1 ttl=60 time=0.565 ms
64 bytes from 10.0.5.2: seq=2 ttl=60 time=1.135 ms

/ # ping -c3 10.0.6.2
PING 10.0.6.2 (10.0.6.2): 56 data bytes
64 bytes from 10.0.6.2: seq=0 ttl=60 time=0.678 ms
64 bytes from 10.0.6.2: seq=1 ttl=60 time=0.907 ms
64 bytes from 10.0.6.2: seq=2 ttl=60 time=1.272 ms

/ # ping -c3 10.0.2.2
PING 10.0.2.2 (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: seq=0 ttl=60 time=0.644 ms
64 bytes from 10.0.2.2: seq=1 ttl=60 time=0.915 ms
64 bytes from 10.0.2.2: seq=2 ttl=60 time=1.032 ms

測(cè)試容器到到跨宿主機(jī)容器遇到一個(gè)坑,開始怎么都不通,后找到原因是宿主機(jī)iptables
給阻擋掉了。附:Ubuntu一鍵清除iptables規(guī)則腳本
1
2
3
4
5
6
7
8
9
10

$ cat clear_iptables_rule.sh

!/bin/bash

iptables -F
iptables -X
iptables -Z
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

參考文檔
http://www.google.comhttp://t.cn/RcnGQ02http://t.cn/RXVHGpIhttp://t.cn/RXfavPGhttp://t.cn/RXfEThAhttp://t.cn/RXfEmS8http://t.cn/R5Xgfnx

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容