你也許已經知道了,Docker 容器技術是現有的成熟虛擬化技術的一個替代方案。它被企業應用在越來越多的領域中,比如快速部署環境、簡化基礎設施的配置流程、多客戶環境間的互相隔離等等。當你開始在真實的生產環境使用 Docker 容器去部署應用沙箱時,你可能需要用到多個容器部署一套復雜的多層應用系統,其中每個容器負責一個特定的功能(例如負載均衡、LAMP 棧、數據庫、UI 等)。
那么問題來了:有多臺宿主機,我們事先不知道會在哪臺宿主機上創建容器,如果保證在這些宿主機上創建的容器們可以互相聯網?
聯網技術哪家強?開源方案找 weave。這個工具可以為你省下不少煩惱。聽我的準沒錯,誰用誰知道。
于是本教程的主題就變成了“如何使用 weave 在不同主機上的 Docker 容器之間設置網絡”。
Weave 是如何工作的

讓我們先來看看 weave 怎么工作:先創建一個由多個 peer 組成的對等網絡,每個 peer 是一個虛擬路由器容器,叫做“weave 路由器”,它們分布在不同的宿主機上。這個對等網絡的每個 peer 之間會維持一個 TCP 鏈接,用于互相交換拓撲信息,它們也會建立 UDP 鏈接用于容器間通信。一個 weave 路由器通過橋接技術連接到本宿主機上的其他容器。當處于不同宿主機上的兩個容器想要通信,一臺宿主機上的 weave 路由器通過網橋截獲數據包,使用 UDP 協議封裝后發給另一臺宿主機上的 weave 路由器。
每個 weave 路由器會刷新整個對等網絡的拓撲信息,可以稱作容器的 MAC 地址(如同交換機的 MAC 地址學習一樣獲取其他容器的 MAC 地址),因此它可以決定數據包的下一跳是往哪個容器的。weave 能讓兩個處于不同宿主機的容器進行通信,只要這兩臺宿主機在 weave 拓撲結構內連到同一個 weave 路由器。另外,weave 路由器還能使用公鑰加密技術將 TCP 和 UDP 數據包進行加密。
準備工作
在使用 weave 之前,你需要在所有宿主機上安裝 Docker 環境,參考這些教程,在 Ubuntu 或 CentOS/Fedora 發行版中安裝 Docker。
Docker 環境部署完成后,使用下面的命令安裝 weave:
$ wget https://github.com/zettio/weave/releases/download/latest_release/weave
$ chmod a+x weave
$ sudo cp weave /usr/local/bin
注意你的 PATH 環境變量要包含 /usr/local/bin 這個路徑,請在 /etc/profile 文件中加入一行(LCTT 譯注:要使環境變量生效,你需要執行這個命令: source /etc/profile):
export PATH="$PATH:/usr/local/bin"
在每臺宿主機上重復上面的操作。
Weave 在 TCP 和 UDP 上都使用 6783 端口,如果你的系統開啟了防火墻,請確保這兩個端口不會被防火墻擋住。
在每臺宿主機上啟動 Weave 路由器
當你想要讓處于在不同宿主機上的容器能夠互相通信,第一步要做的就是在每臺宿主機上啟動 weave 路由器。
第一臺宿主機,運行下面的命令,就會創建并開啟一個 weave 路由器容器(LCTT 譯注:前面說過了,weave 路由器也是一個容器):
$ sudo weave launch
第一次運行這個命令的時候,它會下載一個 weave 鏡像,這會花一些時間。下載完成后就會自動運行這個鏡像。成功啟動后,終端會輸出這個 weave 路由器的 ID 號。
下面的命令用于查看路由器狀態:
$ sudo weave status

第一個 weave 路由器就緒了,目前為止整個 peer 對等網絡中只有一個 peer 成員。
你也可以使用 docker 的命令來查看 weave 路由器的狀態:
$ docker ps
第二臺宿主機部署步驟稍微有點不同,我們需要為這臺宿主機的 weave 路由器指定第一臺宿主機的 IP 地址,命令如下:
$ sudo weave launch first-host-IP-address>
當你查看路由器狀態,你會看到兩個 peer 成員:當前宿主機和第一個宿主機。

當你開啟更多路由器,這個 peer 成員列表會更長。當你新開一個路由器時,要指定前一個宿主機的 IP 地址,請注意不是第一個宿主機的 IP 地址(LCTT 譯注:鏈狀結構)。
現在你已經有了一個 weave 網絡了,它由位于不同宿主機的 weave 路由器組成。
把不同宿主機上的容器互聯起來
接下來要做的就是在不同宿主機上開啟 Docker 容器,并使用虛擬網絡將它們互聯起來。
假設我們創建一個私有網絡 10.0.0.0/24 來互聯 Docker 容器,并為這些容器隨機分配 IP 地址。
如果你想新建一個能加入 weave 網絡的容器,你就需要使用 weave 命令來創建,而不是 docker 命令。原因是 weave 命令內部會調用 docker 命令來新建容器然后為它設置網絡。
下面的命令是在宿主機 hostA 上建立一個 Ubuntu 容器,然后將它放到 10.0.0.0/24 網絡中,分配的 IP 地址為 10.0.0.1:
hostA:~$ sudo weave run 10.0.0.1/24 -t -i ubuntu
成功運行后,終端會顯示出容器的 ID 號。你可以使用這個 ID 來訪問這個容器:
hostA:~$ docker attach container-id>
在宿主機 hostB 上,也創建一個 Ubuntu 容器,IP 地址為 10.0.0.2:
hostB:~$ sudo weave run 10.0.0.2/24 -t -i ubuntu
訪問下這個容器的控制臺:
hostB:~$ docker attach container-id>
這兩個容器能夠互相 ping 通,你可以通過容器的控制臺檢查一下。

如果你檢查一下每個容器的網絡配置,你會發現有一塊名為“ethwe”的網卡,你分配給容器的 IP 地址出現在它們那里(比如這里分別是 10.0.0.1 和 10.0.0.2)。

Weave 的其他高級用法
weave 提供了一些非常巧妙的特性,我在這里作下簡單的介紹。
應用分離
使用 weave,你可以創建多個虛擬網絡,并為每個網絡設置不同的應用。比如你可以為一群容器創建 10.0.0.0/24 網絡,為另一群容器創建 10.10.0.0/24 網絡,weave 會自動幫你維護這些網絡,并將這兩個網絡互相隔離。另外,你可以靈活地將一個容器從一個網絡移到另一個網絡而不需要重啟容器。舉個例子:
首先開啟一個容器,運行在 10.0.0.0/24 網絡上:
$ sudo weave run 10.0.0.2/24 -t -i ubuntu
然后讓它脫離這個網絡:
$ sudo weave detach 10.0.0.2/24 container-id>
最后將它加入到 10.10.0.0/24 網絡中:
$ sudo weave attach 10.10.0.2/24 container-id>
現在這個容器可以與 10.10.0.0/24 網絡上的其它容器進行通信了。這在當你創建一個容器而網絡信息還不確定時就很有幫助了。
將 weave 網絡與宿主機網絡整合起來
有時候你想讓虛擬網絡中的容器能訪問物理主機的網絡?;蛘呦喾?,宿主機需要訪問容器。為滿足這個功能,weave 允許虛擬網絡與宿主機網絡整合。
舉個例子,在宿主機 hostA 上一個容器運行在 10.0.0.0/24 中,運行使用下面的命令:
hostA:~$ sudo weave expose 10.0.0.100/24
這個命令把 IP 地址 10.0.0.100 分配給宿主機 hostA,這樣一來宿主機 hostA 也連到了 10.0.0.0/24 網絡上了。顯然,你在為宿主機選擇 IP 地址的時候,需要選一個沒有被其他容器使用的地址。
現在 hostA 就可以訪問 10.0.0.0/24 上的所有容器了,不管這些容器是否位于 hostA 上。好巧妙的設定啊,32 個贊!
總結
如你所見,weave 是一個很有用的 docker 網絡配置工具。這個教程只是它強悍功能的冰山一角。如果你想進一步玩玩,你可以試試它的以下功能:多跳路由功能,這個在 multi-cloud 環境(LCTT 譯注:多云,企業使用多個不同的云服務提供商的產品,比如 IaaS 和 SaaS,來承載不同的業務)下還是很有用的;動態重路由功能是一個很巧妙的容錯技術;或者它的分布式 DNS 服務,它允許你為你的容器命名。