flannel是CoreOS提供用于解決Dokcer集群跨主機通訊的覆蓋網(wǎng)絡工具招盲。它的主要思路是:預先留出一個網(wǎng)段聪蘸,每個主機使用其中一部分,然后每個容器被分配不同的ip控乾;讓所有的容器認為大家在同一個直連的網(wǎng)絡娜遵,底層通過UDP/VxLAN
等進行報文的封裝和轉發(fā)。
flannel項目地址:https://github.com/coreos/flannel
flannel架構介紹
flannel默認使用8285端口作為UDP
封裝報文的端口慨仿,VxLan使用8472端口纳胧。
那么一條網(wǎng)絡報文是怎么從一個容器發(fā)送到另外一個容器的呢跑慕?
容器直接使用目標容器的ip訪問摧找,默認通過容器內(nèi)部的eth0發(fā)送出去牢硅。
報文通過veth pair
被發(fā)送到vethXXX
减余。
vethXXX
是直接連接到虛擬交換機docker0
的,報文通過虛擬bridge docker0
發(fā)送出去位岔。
查找路由表抒抬,外部容器ip的報文都會轉發(fā)到flannel0
虛擬網(wǎng)卡,這是一個P2P
的虛擬網(wǎng)卡瞧剖,然后報文就被轉發(fā)到監(jiān)聽在另一端的flanneld
抓于。
flanneld
通過etcd
維護了各個節(jié)點之間的路由表浇借,把原來的報文UDP
封裝一層,通過配置的iface
發(fā)送出去巾遭。
報文通過主機之間的網(wǎng)絡找到目標主機。
報文繼續(xù)往上灼舍,到傳輸層涨薪,交給監(jiān)聽在8285端口的flanneld
程序處理。
數(shù)據(jù)被解包献丑,然后發(fā)送給flannel0
虛擬網(wǎng)卡侠姑。
查找路由表莽红,發(fā)現(xiàn)對應容器的報文要交給docker0
。
docker0
找到連到自己的容器,把報文發(fā)送過去圃酵。
flannel安裝配置
環(huán)境準備
一共三臺機器:一個etcd集群郭赐,三臺機器安裝flannel和Docker确沸。
節(jié)點名稱
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
關于etcd的安裝使用已經(jīng)在「etcd使用入門」和「通過靜態(tài)發(fā)現(xiàn)方式部署etcd集群」中做了比較詳細的講解菩彬,如果你還不會安裝etcd可先閱讀下這兩篇文章。這里就不再重復講解了骗灶。
安裝flannel
三個節(jié)點都需安裝配置flannel耙旦,這里以etcd1節(jié)點為例。
flannel和etcd一樣轻黑,直接從官方下載二進制執(zhí)行文件就可以用了琴昆。當然,你也可以自己編譯抖拦。
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
這兩個文件噩茄,其中flanneld
為主要的執(zhí)行文件复颈,sh腳本用于生成Docker啟動參數(shù)。
配置flannel
由于flannel
需要依賴etcd
來保證集群IP分配不沖突的問題凿菩,所以首先要在etcd
中設置 flannel
節(jié)點所使用的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預設的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比起預設的udp性能相對好一些肢执。
啟動flannel
命令行方式運行
1
$ /opt/flannel/flanneld --etcd-endpoints="http://etcd1.hi-linux.com:2379" --ip-masq=true >> /var/log/flanneld.log 2>&1 &
后臺服務方式運行
給flannel創(chuàng)建一個systemd服務译红,方便以后管理侦厚。創(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地址刨沦,請根據(jù)實際情況修改膘怕。
啟動flannel服務
1
$ systemctl start flanneld
flannel啟動過程解析
flannel服務需要先于Docker啟動。flannel服務啟動時主要做了以下幾步的工作:
從etcd中獲取network的配置信息来破。
劃分subnet忘古,并在etcd中進行注冊。
將子網(wǎng)信息記錄到/run/flannel/subnet.env
中送朱。
驗證flannel網(wǎng)絡
在etcd1節(jié)點上看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)絡情況:
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中存儲的地址一樣驶沼,這樣flannel網(wǎng)絡配置完成。
配置Docker
在各個節(jié)點安裝好以后最后要更改Docker
的啟動參數(shù)大年,使其能夠使用flannel
進行IP分配鹉戚,以及網(wǎng)絡通訊。
flannel
運行后會生成一個環(huán)境變量文件遏餐,包含了當前主機要使用flannel
通訊的相關參數(shù)赢底。
查看flannel分配的網(wǎng)絡參數(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運行參數(shù)
使用flannel提供的腳本將subnet.env轉寫成Docker啟動參數(shù)幸冻,創(chuà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啟動參數(shù)
修改docker的啟動參數(shù)庞溜,并使其啟動后使用由flannel生成的配置參數(shù)碑定,修改如下:
1
2
3
4
5
6
編輯 systemd service 配置文件
$ vim /lib/systemd/system/docker.service
在啟動時增加flannel提供的啟動參數(shù)
ExecStart=/usr/bin/dockerd $DOCKER_OPTS
指定這些啟動參數(shù)所在的文件位置(這個配置是新增的,同樣放在Service標簽下)
EnvironmentFile=/run/docker_opts.env
然后重新加載systemd配置漫试,并重啟Docker
即可
1
2
$ systemctl daemon-reload
$ systemctl restart docker
此時可以看到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é)點etcd1的flannel安裝配置完成了普泡,其它兩節(jié)點按以上方法配置完成就行了。
測試flannel
三臺機器都配置好了之后叮趴,我們在三臺機器上分別開啟一個docker容器权烧,測試它們的網(wǎng)絡是否可相互聯(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
從不同宿主機容器到三臺宿主機
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
從容器到到跨宿主機容器
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
測試容器到到跨宿主機容器遇到一個坑,開始怎么都不通宫静,后找到原因是宿主機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