利用OpenVSwitch構建多主機Docker網絡

jopen 9年前發布 | 75K 次閱讀 Docker

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

運行Docker已經不是什么新鮮事,網上有很多入門教程來幫助你在一臺主機上運行容器。這臺主機可以是Linux服務器,也可以是Mac(借助類似 boot2docker的項目)。

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

可選方案:

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

    利用OpenVSwitch構建多主機Docker網絡

    概述

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

    • 在每臺服務器上安裝Docker;
    • 在每臺服務器上安裝OpenVSwitch;
    • 自定義網絡設置用以自動在主機間創建網橋/隧道(在每臺服務器的/etc/network/interfaces里);
    • 自定義每個Docker服務配置,只處理docker0IP范圍的一小部分,防止新容器的IP地址發生重疊。
    • </ul>
      就是這樣。重啟服務或重啟服務器后,你將獲得一個具備連接冗余(link redundancy)的全網狀網絡,Docker服務可以在專用的IP范圍(不會重疊)上運行容器,并且不需要在公網或內網網卡上暴露所有端口就能互聯。很棒,對么?

      技術

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

      • Docker:嗯……這是篇關于Docker與網絡的文章,所以……
      • OpenVSwitch:非常棒的虛擬網絡交換機項目,伸縮性非常好,根據本指南,你可以運行“任意”規模的網絡。
      • </ul>
        我們將假定服務器運行的是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</pre>
        現在你有了新的.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</pre>

        配置

        網絡

        你可以使用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&nbsp;--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</pre>
        在其它主機上要對這個配置上做些調整: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網卡)。
          • </ul> </li>

          • 在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)將需要更長的時間,并且無法提供任何除了多重額外鏈路冗余之外的有用價值。
            • </ul> </li> </ul>
              如果現在重啟服務器,你將擁有一個具備冗余的網狀網絡,你可以運行以下命令來測試:

              • 從host1上ping 172.17.42.2或其他IP;
              • 在主機上運行iperf,通過ifconfig查看使用中的鏈接;
              • 在ping第三臺主機時停止“中間”那臺,查看網絡收斂(通過STP)時ping中斷了幾秒鐘。
              • </ul>

                利用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范圍,以/18fixed-cidr的形式保存在它們的docker服務配置中。分別是172.17.64.0/18、172.17.128.0/18、172.17.192.0/18。
                • </ul>
                  如果你的主機多于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 "</pre>
                  你可以根據需要修改DOCKER_OPTS配置,添加鏡像、不安全的registry、DNS等等。

                  說明:

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!