------------------------------------重要說明------------------------------------
本文內容都是參考Cloudman系列進行學習,是個人學習過程記錄,與原版不同!
原版請參考cloudman《每天5分鐘玩轉Docker容器技術》Cloudman博客如下:
http://blog.51cto.com/cloudman
------------------------------------重要說明------------------------------------
flannel 是 CoreOS 開發的容器網絡解決方案。flannel 爲每個 host 分配一個 subnet,容器從此 subnet 中分配 IP,這些 IP 可以在 host 間路由,容器間無需 NAT 和 port mapping 就可以跨主機通信。
每個 subnet 都是從一個更大的 IP 池中劃分的,flannel 會在每個主機上運行一個叫 flanneld 的 agent,其職責就是從池子中分配 subnet。爲了在各個主機間共享信息,flannel 用 etcd(與 consul 類似的 key-value 分佈式數據庫)存放網絡配置、已分配的 subnet、host 的 IP 等信息。
數據包如何在主機間轉發是由 backend 實現的。flannel 提供了多種 backend,最常用的有 vxlan 和 host-gw,我們將在本章討論這兩種 backend。其他 backend 請參考 https://github.com/coreos/flannel。
etcd 部署在 192.168.56.129【docker01】,docker02 和 docker03 上運行 flanneld,首先安裝配置 etcd。
a) 安裝配置 etcd
在 192.168.56.129 上運行如下腳本:
ETCD_VER=v2.3.7
DOWNLOAD_URL=https://github.com/coreos/etcd/releases/download
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
mkdir -p /tmp/test-etcd && tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/test-etcd --strip-components=1
cp /tmp/test-etcd/etcd* /usr/local/bin/
該腳本從 github 上下載 etcd 的可執行文件並保存到 /usr/local/bin/,啓動 etcd 並打開 2379 監聽端口。
etcd -listen-client-urls http://192.168.56.129:2379 -advertise-client-urls http://192.168.56.129:2379
該終端不要結束,新開一個終端
測試 etcd 是否可用:
可以正常在 etcd 中存取數據了。
當前網絡結構
b) 安裝配置 flannel
flannel 沒有現成的執行文件可用,必須自己 build,最可靠的方法是在 Docker 容器中 build。不過用於做 build 的 docker 鏡像託管在 gcr.io,國內可能無法直接訪問,爲方便大家,我把它 mirror 到了 docker hub,構建步驟如下:
1.下載並重命名 image
docker pull cloudman6/kube-cross:v1.6.2-2
docker tag cloudman6/kube-cross:v1.6.2-2 gcr.io/google_containers/kube-cross:v1.6.2-2
2.下載 flannel 源碼
git clone https://github.com/coreos/flannel.git
3.開始構建
cd flannel
make dist/flanneld-amd64
4.將 flanneld 執行文件拷貝到 host1 和 host2
scp dist/flanneld-amd64 192.168.56.130:/usr/local/bin/flanneld
scp dist/flanneld-amd64 192.168.56.128:/usr/local/bin/flanneld
c) 將 flannel 網絡的配置信息保存到 etcd
先將配置信息寫到文件 flannel-config.json 中:
cat >>flannel-config.json<<EOF
{
"Network": "10.2.0.0/16",
"SubnetLen": 24,
"Backend": {
"Type": "vxlan"
}
}
EOF
Network 定義該網絡的 IP 池爲 10.2.0.0/16。
SubnetLen 指定每個主機分配到的 subnet 大小爲 24 位,即10.2.X.0/24。
Backend 爲通信類型。 vxlan,即主機間通過 vxlan 通信,後面我們還會討論host-gw。
將配置存入 etcd
etcdctl --endpoints=192.168.56.129:2379 set /docker-test/network/config < flannel-config.json
/docker-test/network/config 是此 etcd 數據庫的 key,其 value 爲 flannel-config.json 的內容。
key 可以任意指定,這個 key 後面會作爲 flanneld 的一個啓動參數。執行 etcdctl get 確保設置成功。
d) 啓動 flannel
在 docker02 和 docker03 上執行如下命令,NOTE:Don’t close current terminal!
flanneld -etcd-endpoints=http://192.168.56.129:2379 -iface=ens33 -etcd-prefix=/docker-test/network
-etcd-endpoints 指定 etcd url。
-iface 指定主機間數據傳輸使用的 interface。
-etcd-prefix 指定 etcd 存放 flannel 網絡配置信息的 key。
① enp0s8 被選作與外部主機通信的 interface。
② 識別 flannel 網絡池 10.2.0.0/16。
③ 分配的 subnet 爲 10.2.40.0/24。
flanneld 啓動後,docker02 docker03 內部網絡會發生一些變化:
1.一個新的 interface flannel.1 被創建,而且配置上 subnet 的第一個 IP 10.2.3.0。
2.docker02 docker03 添加了一條路由:目的地址爲 flannel 網絡 10.2.0.0/16 的數據包都由 flannel.1 轉發
當前環境網絡拓撲如下:
e) 配置 Docker 連接 flannel
cat /run/flannel/subnet.env 中 FLANNEL_SUBNET 和FLANNEL_MTU
l docker02
l docker03
編輯 docker02 docker03的 Docker 配置文件 /etc/systemd/system/docker.service.d/10-machine.conf,設置 --bip 和 --mtu
l docker02
l docker03
重啓 Docker daemon
systemctl daemon-reload
systemctl restart docker.service
Docker --bip配置到 Linux bridge docker0 上,並添加 10.2.xx.0/24 的路由。
l docker02
l docker03
當前環境網絡拓撲如圖所示
可見:flannel 沒有創建新的 docker 網絡,而是直接使用默認的 bridge 網絡。同一主機的容器通過 docker0 連接,跨主機流量通過 flannel.1 轉發。
f) 將容器連接到 flannel 網絡
在 docker02 中運行容器 bbox1
在 docker03 中運行容器 bbox2
Docker02 和 docker03 的 IP 分別爲 10.2.3.2 和 10.2.98.2。
當前網絡拓撲
g) flannel 網絡連通性
測試 bbox1 和 bbxo2 的連通性
bbox1 能夠 ping 到位於不同 subnet 的 bbox2通過 traceroute 分析一下 bbox1 到 bbox2 的路徑。
1.bbox1 與 bbox2 不是一個 subnet數據包發送給默認網關 10.2.98.1 docker0。
2.根據 docker02的路由表下圖數據包會發給 flannel.1。
3.flannel.1 將數據包封裝成 VxLAN通過 ens33 發送給 docker03。
4.Docker03 收到包解封裝發現數據包目的地址爲 10.2.3.2根據路由表下圖將數據包發送給 flannel.1並通過 docker0 到達 bbox2。
另外flannel 是沒有 DNS 服務的容器無法通過 hostname 通信。
h) flannel 網絡隔離
flannel 爲每個主機分配了獨立的 subnet但 flannel.1 將這些 subnet 連接起來了相互之間可以路由。本質上flannel 將各主機上相互獨立的 docker0 容器網絡組成了一個互通的大網絡實現了容器跨主機通信。flannel 沒有提供隔離。
i) flannel 與外網連通性
因爲 flannel 網絡利用的是默認的 bridge 網絡所以容器與外網的連通方式與 bridge 網絡一樣即
1.容器通過 docker0 NAT 訪問外網
2.通過主機端口映射外網可以訪問容器
j) 如何使用 flannel host-gw backend
flannel 支持多種 backend,前面我們討論的是 vxlan,host-gw 是 flannel 的另一個 backend,本節會將前面的 vxlan backend 切換成 host-gw。
與 vxlan 不同,host-gw 不會封裝數據包,而是在主機的路由表中創建到其他主機 subnet 的路由條目,從而實現容器跨主機通信。要使用 host-gw 首先修改 flannel 的配置 flannel-config.json:
先將配置信息寫到文件 flannel-config.json 中:
cat >>flannel-config.json<<EOF
{
"Network": "10.2.0.0/16",
"SubnetLen": 24,
"Backend": {
"Type": "host-gw"
}
}
EOF
Type 用 host-gw 替換原先的 vxlan。更新 etcd 數據庫:
etcdctl --endpoints=192.168.56.129:2379 set /docker-test/network/config < flannel-config.json
Ctrl+C 掉之前 docker02 和 docker03 的 flanneld 進程並重啓。
flanneld -etcd-endpoints=http://192.168.56.129:2379 -iface=enp0s8 -etcd-prefix=/docker-test/network
l docker02
查看 docker02 的路由表,增加了一條到 10.2.98.0/24 的路由,網關爲 docker03 的 IP 192.168.56.128。
l docker03
查看 docker03 的路由表,增加了一條到 10.2.3.0/24 的路由,網關爲 docker02 的 IP 192.168.56.130。
從 /run/flannel/subnet.env 可以看到 host-gw 使用的 MTU 爲 1500
這與 vxlan MTU=1450 不同,所以應該修改 docker 啓動參數 --mtu=1500並重啓 docker daemon。
下面對 host-gw 和 vxlan 這兩種 backend 做個簡單比較。
1. host-gw 把每個主機都配置成網關,主機知道其他主機的 subnet 和轉發地址。vxlan 則在主機間建立隧道,不同主機的容器都在一個大的網段內(比如 10.2.0.0/16)。
2. 雖然 vxlan 與 host-gw 使用不同的機制建立主機之間連接,但對於容器則無需任何改變,bbox1 仍然可以與 bbox2 通信。
3. 由於 vxlan 需要對數據進行額外打包和拆包,性能會稍遜於 host-gw。
------------------------------------重要說明------------------------------------
本文內容都是參考Cloudman系列進行學習,是個人學習過程記錄,與原版不同!
原版請參考cloudman《每天5分鐘玩轉Docker容器技術》Cloudman博客如下:
http://blog.51cto.com/cloudman
------------------------------------重要說明------------------------------------
書籍:
1.《每天5分鐘玩轉Kubernetes》
https://item.jd.com/26225745440.html
2.《每天5分鐘玩轉Docker容器技術》
https://item.jd.com/16936307278.html
3.《每天5分鐘玩轉OpenStack》
https://item.jd.com/12086376.html