1. 程式人生 > >Docker跨伺服器通訊Overlay解決方案(上) Consul單例項

Docker跨伺服器通訊Overlay解決方案(上) Consul單例項

場景

公司微服務快上線了,微服務都是用Docker容器進行部署的,在同一臺主機下,把服務都部署上,註冊到Nacos的IP與PORT都是內網的IP與Dockerfile中定義的埠號,看起來好像也沒什麼問題,通過閘道器去呼叫也是可以調通的,請注意這有一個大前提:

必須把所有服務容器部署在同一臺主機上時才可以!

當服務例項沒有部署在同一主機上,比如閘道器服務在A伺服器,服務a在B伺服器上,同樣註冊到Nacos (或其它註冊中心) ,此時上報上來的都是內網的IP,那麼當外部有請求進來的時候,閘道器通過Nacos的服務列表,找到了對應的服務a的內網IP,一呼叫發現呼叫不通

ps:內網怎麼會通……

任務

微服務容器可以不在同一臺伺服器上,互相呼叫

想法

  1. 既然上報的是內網的IP,我直接讓他上報宿主機的IP和埠唄
  2. 使用Docker的host網路模式
  3. 修改部署指令碼,通過shell部署容器時,獲取宿主機IP與設定的對映埠號
  4. 讓Docker的網路互通

分析

以下分別按上邊的“想法”部分來進行說明下問題

  1. 翻遍官方文件與Github,得出的方案又有兩個:
    • 固定IP埠,把宿主機IP與埠寫死在配置檔案中:看起來是解決了,但是問題是無法水平擴充套件了 ——勉強能用
    • 固定網絡卡,防止因多網絡卡環境上報錯誤IP埠:沒有用的,進入容器中ifconfig發現內部網絡卡只有兩個,分別是eth0lo,對應網絡卡的IP就是內網IP ——還是沒用
  2. 使用Docker的Host網路模式,你會發現IP這回上報的的確是宿主機IP,但是埠號不對啊……如果自己去通過shell使用Java引數傳入待對映的埠號的話,這種情況理論上是可行的,唯一缺點是docker ps
    再也直接看不到埠號了,需要額外去docker inspect ——可以用
  3. 對映埠號可以獲取,但是主機的網絡卡名稱不同,寫死後不靈活,如果有的是eth0,有的是ens33呢?還有更多不可測的情況! ——或許可用
  4. 通過一些成熟的Docker容器網路共享,但是會有一定的效能損耗 ——完全可用

概念與選型

最穩妥的辦法——使用Docker網路共享,在搜尋引擎的幫助下,我決定用Overlay的方式來實現效果

以下簡單說下Overlay:

容器在兩個跨主機進行通訊的時候,是使用overlay network這個網路模式進行通訊;如果使用host也可以實現跨主機進行通訊,直接使用這個物理的ip地址就可以進行通訊。overlay它會虛擬出一個網路比如10.0.2.3這個ip地址。在這個overlay網路模式裡面,有一個類似於服務閘道器的地址,然後把這個包轉發到物理伺服器這個地址,最終通過路由和交換,到達另一個伺服器的ip地址。

想要實現Overlay網路,需要引入一個K-V資料庫,來儲存網路狀態資訊,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支援的K-V資料庫

我們這裡使用 Consul,相比其它K-V資料庫,Consul提供的介面化方便管理,所以這裡使用Consul實現Overlay

通過讓每個伺服器的Docker daemon將自己的IP註冊到Consul中,來共享Docker內網,這裡共享的內網是Overlay網路模式的,也只有在註冊的Docker環境下使用同overlay網路的容器,才能互相通訊

ps: 建立完成後,不使用overlay網路的跨伺服器容器,不能ping通

小試身手

單節點的Consul實現Overlay網路,使用Docker映象

環境說明

伺服器OS 主機IP Docker版本 網絡卡名
Ubuntu Server 18.04 LTS 192.168.87.133 18.09.6 ens33
Ubuntu Server 18.04 LTS 192.168.87.139 18.09.7 ens33

待使用的Consul版本為1.5.2,看Docker Hub上提示漏洞目前最小的。

本測試環境適用於Systemd管理的Linux發行版

Consul沒有使用非官方的progrium/consul,主要是因為這個映象實在太老了,四年前的如果有漏洞也沒能及時修復,所以自己去<hub.docker.com>去趟了遍官方的坑!