利用OpenVSwitch構建多主機Docker網路

linux.cn發表於2015-03-31

當你在一臺主機上成功執行Docker容器後,信心滿滿地打算將其擴充套件到多臺主機時,卻發現前面的嘗試只相當於寫了個Hello World的入門程式,多主機的網路設定成了下一道門檻。在你嘗試各種方案時不妨先看看本文,或許就會豁然開朗,發現原來也不復雜。嗯,是的,本文用到了 OpenVSwitch。

執行Docker已經不是什麼新鮮事,網上有很多入門教程來幫助你在一臺主機上執行容器。這臺主機可以是Linux伺服器,也可以是Mac(藉助類似boot2docker的專案)。

在多臺主機上執行卻是另外一回事……

可選方案:

  • 分別在每臺主機上執行Docker,在公網或內網網路卡上暴露埠以便容器間相互通訊。這可能比較麻煩,而且會引發安全問題。
  • 執行類似Weave的中間層方案來完全地抽象網路。這個專案前景不錯,不過還太年輕,尚未與compose(之前的fig)或maestro-ng這類編排工具整合。
  • 執行類似Deis或Flynn的Docker多主機一站式方案。這可能不在你的考慮範圍內。
  • 在主機間的網狀網路中建立一個共享網橋,讓Docker服務在那執行容器。這聽起來有點複雜,不過……本文中我們將看到這可以非常容易地完成!

利用OpenVSwitch構建多主機Docker網路

概述

基本上,我們將執行以下步驟:

  • 在每臺伺服器上安裝Docker;
  • 在每臺伺服器上安裝OpenVSwitch;
  • 自定義網路設定用以自動在主機間建立網橋/隧道(在每臺伺服器的/etc/network/interfaces裡);
  • 自定義每個Docker服務配置,只處理docker0 IP範圍的一小部分,防止新容器的IP地址發生重疊。

就是這樣。重啟服務或重啟伺服器後,你將獲得一個具備連線冗餘(link redundancy)的全網狀網路,Docker服務可以在專用的IP範圍(不會重疊)上執行容器,並且不需要在公網或內網網路卡上暴露所有埠就能互聯。很棒,對麼?

技術

簡單列一下我們用到的技術:

  • Docker:嗯……這是篇關於Docker與網路的文章,所以……
  • OpenVSwitch:非常棒的虛擬網路交換機專案,伸縮性非常好,根據本指南,你可以執行“任意”規模的網路。

我們將假定伺服器執行的是Ubuntu Server 14.04.02 LTS x64,對於其它系統,你可能需要修改下面提供的各項配置。

安裝

Docker

無需多言,遵循官網提供的指南就行。稍後我們將深入其配置,以便執行於伺服器上的不同Docker服務可相互協作。

OpenVSwitch

糟糕的是,預設倉庫裡OpenVSwitch安裝包不可用(或過期了),我們需要自己構建.deb檔案(一次),然後分發給不同主機。為了保持生產機的整潔,可另外找臺小主機來安裝開發包,並構建安裝包。

OpenVSwitch GitHub上有詳細的構建手冊。

執行下列命令來構建安裝包(新版請按要求修改):

#獲取最新存檔
wget http://openvswitch.org/releases/openvswitch-2.3.1.tar.gz
tar xzvf openvswitch-2.3.1.tar.gz
cd openvswitch-2.3.1

#安裝依賴
sudo apt-get install -y build-essential fakeroot debhelper /
                    autoconf automake bzip2 libssl-dev /
                    openssl graphviz python-all procps /
                    python-qt4 python-zopeinterface /
                    python-twisted-conch libtool

# 構建(不使用並行檢查)
DEB_BUILD_OPTIONS='parallel=8 nocheck' fakeroot debian/rules binary

# 得到最新deb檔案並複製到某處
cd ..
ls -al *deb

現在你有了新的.deb安裝包,接下來將其推送並安裝到所有主機上。

# 複製包到各主機並ssh登入
scp -r *deb user@remote_host:~/.
ssh user@remote_host

# 安裝一些依賴(後面需要)並安裝包
sudo apt-get install -y bridge-utils
sudo dpkg -i openvswitch-common_2.3.1-1_amd64.deb /
         openvswitch-switch_2.3.1-1_amd64.deb

配置

網路

你可以使用OpenVSwitch提供的不同命令列工具來構建網狀網路(比如ovs-vsctl),不過Ubuntu提供了一個輔助工具讓你可以通過/etc/network/interfaces檔案定義網路。

假定三臺主機:1.1.1.1、2.2.2.2和3.3.3.3,可以通過上述IP相互ping通,它們是在公網或內網上並不重要。host1的/etc/network/interfaces大概如下。

...
# eth0、eth1和lo配置
...

# auto:為了有效地在主機啟動時啟動它
# br0=br0:防止在`ifquery --list`時被找到
auto br0=br0
allow-ovs br0
iface br0 inet manual
ovs_type OVSBridge
ovs_ports gre1 gre2
ovs_extra set bridge ${IFACE} stp_enable=true
mtu 1462

# 沒有auto,這是ovs的一個額外配置
# 兩臺主機的gre名字必須相符
allow-br0 gre1
iface gre1 inet manual
ovs_type OVSPort
ovs_bridge br0
ovs_extra set interface ${IFACE} type=gre options:remote_ip=2.2.2.2

allow-br0 gre2
iface gre2 inet manual
ovs_type OVSPort
ovs_bridge br0
ovs_extra set interface ${IFACE} type=gre options:remote_ip=3.3.3.3

# auto:啟動時建立
# 定義docker要使用的docker0,並(在可用時)連線到到OpenVSwitch建立的br0網橋上
# 每臺主機需要使用不同的IP地址(不要相互衝突!)
auto docker0=docker0
iface docker0 inet static
address 172.17.42.1
network 172.17.0.0
netmask 255.255.0.0
bridge_ports br0
mtu 1462

在其它主機上要對這個配置上做些調整:remote_ip的IP地址要相互配對。

利用OpenVSwitch構建多主機Docker網路

幾點說明:

  • 生成樹協議(Spanning Tree Protocol):如果應用該配置,將在3臺伺服器中建立一個網路迴路,這可不行。給br0網橋新增stp_enable=true將確保一些gre隧道被切斷。同時確保網狀網路的冗餘,允許網路在其中一臺主機下線時恢復。
  • MTU:這是一項關鍵設定!沒有這項,你可能獲得一些意外“驚喜”:網路看起來工作正常(比如可以ping),但無法支援大資料包(比如BW測試中的iperf、大資料量請求或簡單的檔案複製)。注意,GRE隧道需要封裝多種協議:
    • 乙太網:14位元組——我們說的是網橋間的第2層;
    • IPv4:20位元組——容器/主機間通訊;
    • GRE:4位元組——因為,嗯,這是個GRE隧道;
    • 也就是物理網路卡MTU減去38位元組,結果是1462(基於常規的1500 MTU網路卡)。
  • 在auto定義中使用“=”:對於具有固定IP的伺服器這不是必需的,但有些雲服務商(這裡就不說是誰了……Digital Ocean(譯者:軟廣再次亂入))使用了一個依靠ifquery –list –allow auto的init服務(/etc/init/cloud-init-container.conf)。不加上“=”號將包含OpenVSwitch網路卡,並延遲整個啟動過程直到init指令碼失敗並超時。
  • docker0網橋:每臺伺服器都需要自己的IP地址(比如172.17.42.1、172.17.42.2)。由於docker0網橋處在br0網橋之上,它們將(也應該!)可以相互連線。想象一下,要解決IP衝突會有多亂……這也是為什麼我們要在啟動時定義它,而不依賴docker服務來為我們建立這個網橋。
  • GRE隧道:你可以從gre0(而不是gre1)開始,它能完美工作。但由於某種原因,在輸入ifconfig時你可以看到gre0,卻看不到其他隧道。這可能是gre0作為虛擬網路卡的一個副作用。從gre1開始將讓所有的gre隧道對ifconfig“隱身”(好過於只能看見一個)。彆著急,你還是可以使用ovs-vsctl命令顯示隧道/網橋。
  • 3臺以上主機:你可以遵循相同的邏輯,並且:
    • 新增額外的隧道(iface greX)來連線新主機。
    • 在br0網橋定義中更新ovs_ports以包含interfaces檔案中定義的所有gre隧道。
    • 聰明點……不要將每臺伺服器跟其他主機一一連結……STP收斂(convergence)將需要更長的時間,並且無法提供任何除了多重額外鏈路冗餘之外的有用價值。

如果現在重啟伺服器,你將擁有一個具備冗餘的網狀網路,你可以執行以下命令來測試:

  • 從host1上ping 172.17.42.2或其他IP;
  • 在主機上執行iperf,通過ifconfig檢視使用中的連結;
  • 在ping第三臺主機時停止“中間”那臺,檢視網路收斂(通過STP)時ping中斷了幾秒鐘。

利用OpenVSwitch構建多主機Docker網路

Docker

我們現在有了一個完善的網路,每個Docker服務都可以將它們的容器掛接到docker0網橋上。讓Docker自動完成這步不是很棒麼?答案在於Docker有能力分配一個最小的IP地址池!

對於該示例,我們假定:

  • 每臺主機(1.1.1.1、2.2.2.2、3.3.3.3)掛接到前面建立的docker0網橋上,其各自的IP地址是172.17.42.1、172.17.42.2、172.17.42.3;
  • 給docker0網路卡指定了一個/16的IP範圍;
  • 給每臺主機指定了一小塊docker0的IP範圍,以/18 fixed-cidr的形式儲存在它們的docker服務配置中。分別是172.17.64.0/18、172.17.128.0/18、172.17.192.0/18。

如果你的主機多於3臺,你需要細分一個每個範圍,或根據組織需要對整個網路拓撲結構進行重新考慮。

利用OpenVSwitch構建多主機Docker網路

host1的配置檔案(/etc/default/docker)是這樣的:

BRIDGE=docker0
CIDR=172.17.64.0/18

wait_ip() {
address=$(ip add show $BRIDGE | grep 'inet ' | awk '{print $2}')
[ -z "$address" ] && sleep $1 || :
}

wait_ip 5
wait_ip 15

DOCKER_OPTS="
-H unix:///var/run/docker.sock
-H tcp://0.0.0.0:2375
--fixed-cidr=$CIDR
--bridge $BRIDGE
--mtu 1462
"

你可以根據需要修改DOCKER_OPTS配置,新增映象、不安全的registry、DNS等等。

說明:

  • wait_ip:由於docker0網橋最後被建立,獲取IP地址可能需要花點時間。使用wait_ip“功能”,你可以在返回docker init指令碼前安全地等待幾秒鐘。該配置檔案是被真正的init指令碼(/etc/init/docker.conf)所引用。
  • mtu:與前面相同原因,只是一個預防措施,用於確保每個網路卡被建立時會被指定正確的MTU。
  • -H tcp://……:如果你不想通過0.0.0.0將其“公開”(或繫結到伺服器“真實”網路卡之一),你也可以將它安全地繫結到……該主機的docker0 IP地址(比如172.17.42.2)!這樣,你可以從任何一臺主機訪問到私有網狀網路裡的任何一個docker服務。

結語

重啟一下(至少保證啟動時所有東西都會自動上線)。

你可以試試以下命令看看一切是否正常。

# 訪問host1
ssh user@host1

# 執行一個新容器
docker run -ti ubuntu bash

# 檢查IP(在容器內執行)
ip add | grep eth0

#
# 在其他視窗中
#
# 訪問另一臺主機(host2或3)
ssh user@host2

# 執行一個新容器
docker run -ti ubuntu bash

# Ping其他的容器!
ping $IP

這不是一份指導如何在多主機上設定Docker的權威指南,歡迎大家提出批評(譯者注:譯稿也一樣,請大家多多指正)。很多想法是在整體安裝時產生的,本文儘可能詳細地說明了為何選擇這個或那個選項。

如果將分級網橋、VLAN等包括進來,事情將更復雜,不過那超出了本文的範圍。;)

顯然,更完整的網路是有需求的,而且看起來這個已經在開發中。

參考內容

  • https://goldmann.pl/blog/2014/ … osts/
  • http://networkstatic.net/open- … tion/
  • http://networkstatic.net/confi … itch/
  • http://fbevmware.blogspot.com. … .html
  • http://openvswitch.org/support … .html
  • https://access.redhat.com/docu … .html
  • https://communities.vmware.com … ation
  • http://www.microhowto.info/tro … .html
  • http://blog.scottlowe.org/2013 … itch/
  • http://blog.scottlowe.org/2013 … itch/
  • https://github.com/openvswitch … an.md
  • http://baturin.org/tools/encapcalc/

如果你讀完本文了,恭喜!

相關文章