weave 是 Weaveworks 開發的容器網絡解決方案。weave 創建的虛擬網絡可以將部署在多個主機上的容器連接起來。對容器來說,weave 就像一個巨大的以太網交換機,所有容器都被接入這個交換機,容器可以直接通信,無需 NAT 和端口映射。除此之外,weave 的 DNS 模塊使容器可以通過 hostname 訪問。https://www.weave.works/docs/cloud/latest/install/installing-agents/#weave-cloud
介紹
Weave在Docker主機之間實現Overlay網絡,使用業界標準VXLAN封裝,基於UDP傳輸,也可以加密傳輸。 Weave Net創建一個連接多個Docker主機的虛擬網絡,類似於一個以太網交換機,所有的容器都連接到這上面,互相通信。 Weave Net由多個peer組成,Weave路由器運行不同Docker主機上,是一個用戶空間的進程;每個peer都有一個名稱,重啓保持不變。它們通過TCP連接彼此,建立後交換拓撲信息。 Weave Net可以在具有編號拓撲的部分連接的網絡中路由數據包。
特點
# IP地址管理(IPAM)
Weave自動爲容器分配唯一的IP地址。可通過weave ps查看
# 命名和發現
命名的容器自動會註冊到Weave DNS中,並可以通過容器名稱訪問。
注:weave自己維護了一個微型的dns服務器。可以實現主機名通信。
# 負載均衡
允許註冊多個相同名稱的容器,Weave DNS隨機爲每個請求返回地址,提供基本的負載均衡功能。
注:如果訪問容器名相同,則會自動輪詢訪問該容器,實現負載均衡。
# 手動指定IP地址
docker run –it –e WEAVE_CIDR=10.32.0.100/24 busybox
# 動態拓撲
可以在不停止或重新配置剩餘Docker主機的情況下添加主機到Weave網絡中或從Weave網絡中刪除
# 容錯
weave peer不斷交換拓撲信息,監視和建立與其他peer的網絡連接。如果有主機或網絡出現故障,Weave會繞過這個主機,保證兩邊容器可以繼續通信,當恢復時,恢復完全連接
Docker Weave 工作原理
網卡設備
Container eth0: eth0是容器主機的默認網絡,主要提供容器訪問外網所提供的服務,走的默認docker網絡架構,只不過他創建了docker_gwbridge這個網橋。
docker_gwbridge: docker_gwbridge是容器所創建的網橋它替代了docker0的服務。
Contailner ethwe: 它是veth pair虛擬設備對,與其他容器通信的網絡虛擬網卡。
vethwe-bridge: 是ethwe設備對創建的weave網橋。網橋內分配的具體的IP與網關。
weave: weave網橋,通過route路由表找到目標,通過端口將數據包轉發到對端端口節點。
eth0: 真機網卡與外界網卡連接得真機網卡,它用來轉發,容器VXLAN與NAT兩種網卡類型的數據包到指定的對端節點。
注:weave會將相鄰的節點互相學習,通過route路由表進行相互通信,並通過單獨的端口發送數據。類似於靜態路由。
Contailner ethwe 發送數據包到對端容器通信
1、ethwe 會將數據包發送給vethwe-bridge網橋。
2、vethwe-bridge接收到數據包後由weave去處理這個數據,通過UDP6783數據端口依照weave的路由錶轉發到下一路由節點。
3、如果該節點就是目的地,本地weave會把信息轉發到內核的TCP協議站,再轉發到目的節點。
實驗環境描述
weave 不依賴分佈式數據庫(例如 etcd 和 consul)交換網絡信息,每個主機上只需運行 weave 組件就能建立起跨主機容器網絡。我們會在 host1 和 host2 上部署 weave 並實踐 weave 的各項特性
Weave不需要集中式的key-value存儲,所以安裝和運行都很簡單。直接把Weave二進制文件下載到系統中就可以了
192.168.1.122 | 部署docker weave 主機名:host1 |
192.168.1.123 | 部署docker weave 主機名:host2 |
1、設置主機名及綁定hosts
[root@host1 ~]# hostnamectl --static set-hostname host1
2、關閉防火牆
[root@host1 ~]# systemctl disable firewalld.service
[root@host1 ~]# systemctl stop firewalld.service
3、安裝docker
[root@host1 ~]# yum install -y docker
[root@host1 ~]# systemctl daemon-reload && systemctl start docker #啓動docker
[root@host1 ~]# chkconfig docker on #加入開機啓動
4、下載weave 到/usr/local/bin/weave
[root@host1 ~]# curl -L git.io/weave -o /usr/local/bin/weave
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
100 595 100 595 0 0 217 0 0:00:02 0:00:02 --:--:-- 581k
100 52227 100 52227 0 0 13476 0 0:00:03 0:00:03 --:--:-- 112k
5、賦予權限/usr/local/bin/weave
[root@host1 ~]# chmod a+x /usr/local/bin/weave
6、啓動weave
###host1上啓動wave,wave組建以容器方式運行
[root@host1 ~]# weave launch
2.6.2: Pulling from weaveworks/weave
Digest: sha256:6f6839774ca225076116790145a415fa99706133310bcf7a56ce29fd89c245d3
Status: Downloaded newer image for weaveworks/weave:2.6.2
docker.io/weaveworks/weave:2.6.2
latest: Pulling from weaveworks/weavedb
72bf8a6af285: Pull complete
Digest: sha256:7badb003b9c0bf5c51bf801be2a4d5d371f0738818f9cbe60a508f54fd07de9a
Status: Downloaded newer image for weaveworks/weavedb:latest
docker.io/weaveworks/weavedb:latest
Unable to find image 'weaveworks/weaveexec:2.6.2' locally
2.6.2: Pulling from weaveworks/weaveexec
Digest: sha256:a28b3c098a049d923fb08231a1bba22e6d57c83710257e41220c28ffccb2d66c
Status: Downloaded newer image for weaveworks/weaveexec:2.6.2
217ed2e604a7e2c5f9ab5d2557c088ccb0b41d23df6373152cd1ce5eb047
7、weave組建以容器方式運行
[root@host1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bbox1
217ed2e604a7 weaveworks/weave:2.6.2 "/home/weave/weaver …" 12 hours ago Up 12 hours weave
[root@host1 ~]#
8、weave 會創建一個新的 Docker 網絡 weave
:
[root@host1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3be562ae8342 bridge bridge local
8a47585430f3 host host local
14925807ce29 none null local
5d669a4aaa5e weave weavemesh local #weave網絡
[root@host1 ~]#
9、查看weave網絡地址段
driver 爲 weavemesh
,IP 範圍 10.32.0.0/12
。
[root@host1 ~]# docker network inspect 5d669a4aaa5e
[
{
"Name": "weave",
"Id": "5d669a4aaa5e80345d2b341aa436bc777b80ad5b292bef107fe378292b361407",
"Created": "2020-03-12T18:54:23.262355683-04:00",
"Scope": "local",
"Driver": "weavemesh",
"EnableIPv6": false,
"IPAM": {
"Driver": "weavemesh",
"Options": null,
"Config": [
{
"Subnet": "10.32.0.0/12" #weave地址段
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"works.weave.multicast": "true"
},
"Labels": {}
}
]
[root@host1 ~]#
10 在host1上運行容器
[root@host1 ~]# weave env
export DOCKER_HOST=unix:///var/run/weave/weave.sock
#將命令發給weave proxy,如果不需要了執行:# eval $(weave env --restore)
[root@host1 ~]# eval $(weave env)
[root@host1 ~]# docker run -itd --name bbox1 busybox
d0a4d7c482ed69ee920f97cd809e978e3813d2e5f76c3c3e343361f7f9840c89
[root@host1 ~]#
首先執行 eval $(weave env)
很重要,其作用是將後續的 docker 命令發給 weave proxy 處理。如果要恢復之前的環境,可執行 eval $(weave env --restore)
。
11、容器網絡分析
查看host1上容器bbox1的ip
查看一下當前容器 bbox1 的網絡配置:
[root@host1 ~]# docker exec -it bbox1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 #默認連接docker0的bridge網絡
valid_lft forever preferred_lft forever
26: ethwe@if27: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1376 qdisc noqueue
link/ether ee:96:74:3b:d3:00 brd ff:ff:ff:ff:ff:ff
inet 10.32.0.1/12 brd 10.47.255.255 scope global ethwe #連接到主機的weave網絡接口
valid_lft forever preferred_lft forever
[root@host1 ~]#
bbox1 有兩個網絡接口 eth0 和 ethwe,其中 eth0 連接的是默認 bridge 網絡,即網橋 docker0。
現在我們重點分析 ethwe。從命名和分配的 IP 10.32.0.1/12 可以猜測 ethwe 與 weave 相關,ethwe@if27
告訴我們與 ethwe 對應的是編號 27 的 interface。從 host1 的 ip link
命令輸出中找到該 interface:
[root@host1 ~]# ip link show
.........
27: vethwepl8618@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue master weave state UP mode DEFAULT group default
link/ether a6:39:fa:a4:a4:74 brd ff:ff:ff:ff:ff:ff link-netnsid 2 #這個接口是與容器相連的接口
[root@host1 ~]#
vethwepl8618@if26
與 ethwe
是一對 veth pair,而且 vethwepl8618 掛在 host1 的 Linux bridge weave
上。
[root@host1 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024286810522 no veth24ed3f2
weave 8000.0e8e2735b12c no vethwe-bridge
vethwepl8618
除了 ethwepl8618 ,weave 上還掛了一個 vethwe-bridge
,這是什麼?讓我們更深入的分析一下,查看 ip -d link
輸出:
這裏出現了多個新 interface:
① vethwe-bridge 與 vethwe-datapath 是 veth pair。
② vethwe-datapath 的父設備(master)是 datapath。
③ datapath 是一個 openvswitch。
④ vxlan-6784 是 vxlan interface,其 master 也是 datapath,weave 主機間是通過 VxLAN 通信的。
weave 網絡包含兩個虛擬交換機:Linux bridge weave
和 Open vSwitch datapath
,veth pair vethwe-bridge
和 vethwe-datapath
將二者連接在一起。weave
和 datapath
分工不同,weave
負責將容器接入 weave 網絡,datapath
負責在主機間 VxLAN 隧道中並收發數據。
host1上運行第二個容器 在bbox1 ping bbox2 支持dns name
[root@host1 ~]# docker run --name bbox2 -itd busybox
61d93aa29198d445ac454ef02487f703febb7644079943a909ebac577b0cb591
[root@host1 ~]# docker exec -it bbox1 ping -c 4 bbox2
PING bbox2 (10.32.0.2): 56 data bytes
64 bytes from 10.32.0.2: seq=0 ttl=64 time=0.244 ms
64 bytes from 10.32.0.2: seq=1 ttl=64 time=0.084 ms
^C
--- bbox2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.084/0.164/0.244 ms
當前 host1 網絡結構爲:
Weave 跨主機的連通和隔離特性
host2安裝weave
1、設置主機名及綁定hosts
[root@host2 ~]# hostnamectl --static set-hostname host2
2、關閉防火牆
[root@host2 ~]# systemctl disable firewalld.service
[root@host2 ~]# systemctl stop firewalld.service
3、安裝docker
[root@host2 ~]# yum install -y docker
[root@host2 ~]# systemctl daemon-reload && systemctl start docker #啓動docker
[root@host2 ~]# chkconfig docker on #加入開機啓動
4、下載weave 到/usr/local/bin/weave
[root@host1 ~]# curl -L git.io/weave -o /usr/local/bin/weave
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
100 595 100 595 0 0 217 0 0:00:02 0:00:02 --:--:-- 581k
100 52227 100 52227 0 0 13476 0 0:00:03 0:00:03 --:--:-- 112k
5、賦予權限/usr/local/bin/weave
[root@host2 ~]# chmod a+x /usr/local/bin/weave
6、啓動weave
###host2上啓動wave,啓動weave指向host1的weave:wave組建以容器方式運行
這裏必須指定 host1 的 IP 192.168.1.122
,這樣 host1 和 host2 才能加入到同一個 weave 網絡。
[root@host2 ~]# weave launch 192.168.1.122
2.6.2: Pulling from weaveworks/weave
Digest: sha256:6f6839774ca225076116790145a415fa99706133310bcf7a56ce29fd89c245d3
Status: Downloaded newer image for weaveworks/weave:2.6.2
docker.io/weaveworks/weave:2.6.2
latest: Pulling from weaveworks/weavedb
72bf8a6af285: Pull complete
Digest: sha256:7badb003b9c0bf5c51bf801be2a4d5d371f0738818f9cbe60a508f54fd07de9a
Status: Downloaded newer image for weaveworks/weavedb:latest
docker.io/weaveworks/weavedb:latest
Unable to find image 'weaveworks/weaveexec:2.6.2' locally
2.6.2: Pulling from weaveworks/weaveexec
Digest: sha256:a28b3c098a049d923fb08231a1bba22e6d57c83710257e41220c28ffccb2d66c
Status: Downloaded newer image for weaveworks/weaveexec:2.6.2
a85d5a20516466b6e2c5f9ab5d2557c088ccb0b41d23df6373152cd1ce5eb047
[root@host2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a85d5a205164 weaveworks/weave:2.6.2 "/home/weave/weaver …" 13 seconds ago Up 13 seconds weave
[root@host2 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
22c93b1df59e bridge bridge local
e75a72e83f90 host host local
ac72879f7ab4 none null local
0fdf77b12596 weave weavemesh local
在host2上運行容器 bbox3:
[root@host2 ~]# eval $(weave env)
[root@host2 ~]# docker run --name bbox3 -itd busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
0669b0daf1fb: Pull complete
Digest: sha256:b26cd013274a657b86e706210ddd5cc1f82f50155791199d29b9e86e935ce135
Status: Downloaded newer image for busybox:latest
0a0a544571db1c036f83cb46f42a09e5643a35ad4d5f4ac70a6d30a551045fce
[root@host2 ~]# docker exec bbox3 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
14: ethwe@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1376 qdisc noqueue
link/ether 46:eb:01:77:ba:1d brd ff:ff:ff:ff:ff:ff
inet 10.44.0.0/12 brd 10.47.255.255 scope global ethwe
valid_lft forever preferred_lft forever
weave 網絡連通性
bbox3 能夠直接 ping bbox1 和 bbox2。
bbox1、bbox2 和 bbox3 的 IP 分別爲 10.32.0.1/12、10.32.0.2/12 和 10.44.0.0/12,注意掩碼爲 12 位,實際上這三個 IP 位於同一個 subnet 10.32.0.0/12。通過 host1 和 host2 之間的 VxLAN 隧道,三個容器邏輯上是在同一個 LAN 中的,當然能直接通信了。bbox3 ping bbox1 的數據流向如下圖所示:
① 數據包目的地址爲 10.32.0.1,根據 bbox3 的路由表,數據從 ethwe 發送出去。
② host2 weave 查詢到目的地主機,將數據通過 VxLAN 發送給 host1。
③ host1 weave 接受到數據,根據目的 IP 將數據轉發給 bbox1。
weave 網絡隔離
默認配置下,weave 使用一個大 subnet(例如 10.32.0.0/12),所有主機的容器都從這個地址空間中分配 IP,因爲同屬一個 subnet,容器可以直接通信。如果要實現網絡隔離,可以通過環境變量 WEAVE_CIDR
爲容器分配不同 subnet 的 IP,舉例如下:
[root@host1 ~]# docker run -e WEAVE_CIDR=net:10.32.2.0/24 -itd --name bbox4 busybox
ec3f37554696cf51b88740e11942f3f86a0244adea52f1b8438ed7c5eade85f0
[root@host1 ~]# docker exec bbox4 ip r
default via 172.17.0.1 dev eth0
10.32.2.0/24 dev ethwe scope link src 10.32.2.1
172.17.0.0/16 dev eth0 scope link src 172.17.0.4
224.0.0.0/4 dev ethwe scope link
[root@host1 ~]# docker exec bbox4 ping -c 4 bbox1
PING bbox1 (10.32.0.1): 56 data bytes
--- bbox1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
[root@host1 ~]#
WEAVE_CIDR=net:10.32.2.0/24
的作用是使容器分配到 IP 10.32.2.2
。由於 10.32.0.0/12 與 10.32.2.0/24 位於不同的 subnet,所以無法 ping 到 bbox1。
除了 subnet,我們還可以直接爲容器分配特定的 IP:
[root@host1 ~]# docker run -e WEAVE_CIDR=ip:10.32.6.6/24 -itd --name bbox5 busybox
036e2885c5eeedd202b2b023035f3cc4d5ebbb1c0a5d42d80361ff7468eeb59f
[root@host1 ~]# docker exec bbox5 ip r
default via 172.17.0.1 dev eth0
10.32.6.0/24 dev ethwe scope link src 10.32.6.6
172.17.0.0/16 dev eth0 scope link src 172.17.0.5
224.0.0.0/4 dev ethwe scope link
[root@host1 ~]# docker exec bbox5 ping -c 4 bbox1
PING bbox1 (10.32.0.1): 56 data bytes
--- bbox1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
[root@host1 ~]#
10.32.0.0/12 與 10.32.6.6/24 位於不同的 subnet,所以無法 ping 到 bbox1
Weave 與外網通信
-
首先將主機加入到 weave 網絡。
-
然後把主機當作訪問 weave 網絡的網關。
要將主機加入到 weave,執行 weave expose
[root@host1 ~]# weave expose
10.32.0.3
[root@host1 ~]#
這個 IP 10.32.0.3
會被配置到 host1 的 weave 網橋上
[root@host1 ~]# ip a show weave
6: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP group default qlen 1000
link/ether 0e:8e:27:35:b1:2c brd ff:ff:ff:ff:ff:ff
inet 10.32.0.3/12 brd 10.47.255.255 scope global weave
valid_lft forever preferred_lft forever
inet6 fe80::c8e:27ff:fe35:b12c/64 scope link
valid_lft forever preferred_lft forever
[root@host1 ~]#
weave 網橋位於 root namespace,它負責將容器接入 weave 網絡。給 weave 配置同一 subnet 的 IP 其本質就是將 host1 接入 weave 網絡。 host1 現在已經可以直接與同一 weave 網絡中的容器通信了,無論容器是否位於 host1。
在 host1 中 ping 同一主機的 bbox1(10.32.0.1):
ping host2 上的 bbox3(10.44.0.0):
接下來要讓其他非 weave 主機訪問到 bbox1 和 bbox3,只需將網關指向 host1。例如在 192.168.1.101 上添加如下路由:
例如一臺新的機器上添加 ip route add 10.32.0.0/12 via 192.168.1.104
通過上面的配置我們實現了外網到 weave 這個方向的通信,反方向呢?
其實答案很簡單:因爲容器本身就掛在默認的 bridge 網絡上,docker0 已經實現了 NAT,所以容器無需額外配置就能訪問外網。
IPAM
10.32.0.0/12 是 weave 網絡使用的默認 subnet,如果此地址空間與現有 IP 衝突,可以通過 --ipalloc-range
分配特定的 subnet。
weave launch --ipalloc-range 10.2.0.0/16
不過請確保所有 host 都使用相同的 subnet。
weave --help #查看幫助
weave ps #查看weave路由狀態:weave ps
weave connect OTHER_HOST #可以把一臺主機連接到weave網絡
weave attach #動態添加網絡對於不是通過weave啓動的容器,可以通過weave attach 10.0.1.1/24 $ContainerId來添加網絡(weave detach刪除網絡)
weave expose #不使用docker的原生網絡容器和宿主機之間是無法互通的 , weave expose ip/24這個命令會把宿主機加入到weave 網絡中, 宿主機就可以和容器之間自由通信了
weave launch -password #安全性:可以通過weave launch -password wEaVe設置一個密碼用於weave peers之間加密通信
例如 weave ps
[root@host1 ~]# weave ps
weave:expose 0e:8e:27:35:b1:2c 10.32.0.3/12
036e2885c5ee 5a:e8:2a:bb:b8:b0 10.32.6.6/24
ec3f37554696 e2:7b:d0:be:ef:dd 10.32.2.1/24
0e626d17939b 72:1e:81:47:20:b0 10.32.0.2/12
1ccdad419a19 72:d6:1d:15:3b:99 10.32.0.1/12
1.eval $(weave env) 將docker命令代理給weave 執行,(如果先執行這個, docker命令啓動的容器就會被自動加入weave網絡,並自動分配IP)
2.docker run -d --rm nginx (正常啓動容器)
如果沒有執行步驟一直接啓動的docker容器是不能自動加入到weave網絡中的, 可以使用下列命令添加到weave網絡
- weave attach IP/24 ContainerId #將容器加入到weave網絡並分配指定IP(24爲網絡地址範圍,決定了該網絡中最多可以有多少臺計算機)
- weave attach ContainerId IP #將容器加入到weave網絡並自動分配IP