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

場景

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

必須把全部服務容器部署在同一臺主機上時才能夠!node

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

ps:內網怎麼會通……github

任務

微服務容器能夠不在同一臺服務器上,互相調用docker

想法

  1. 既然上報的是內網的IP,我直接讓他上報宿主機的IP和端口唄
  2. 使用Docker的host網絡模式
  3. 修改部署腳本,經過shell部署容器時,獲取宿主機IP與設置的映射端口號
  4. 讓Docker的網絡互通

分析

如下分別按上邊的「想法」部分來進行說明下問題shell

  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:json

容器在兩個跨主機進行通訊的時候,是使用overlay network這個網絡模式進行通訊;若是使用host也能夠實現跨主機進行通訊,直接使用這個物理的ip地址就能夠進行通訊。overlay它會虛擬出一個網絡好比10.0.2.3這個ip地址。在這個overlay網絡模式裏面,有一個相似於服務網關的地址,而後把這個包轉發到物理服務器這個地址,最終經過路由和交換,到達另外一個服務器的ip地址。vim

想要實現Overlay網絡,須要引入一個K-V數據庫,來保存網絡狀態信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的K-V數據庫centos

咱們這裏使用 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>去趟了遍官方的坑!💔

注意事項

每臺運行docker的主機都不能同hostname,可使用

$ sudo hostnamectl set-hostname your-new-hostname

同hostname會致使同名的主機docker沒法互相通訊

動手作

準備Consul使用鏡像在133服務器上啓動,因此能夠先配置下Docker daemon的啓動參數指向133服務器

  • 分別修改13三、139兩臺服務器的docker.service
$ ifconfig
#已經去除干擾網卡,記錄網卡名爲ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.87.133  netmask 255.255.255.0  broadcast 192.168.87.255
        inet6 fe80::20c:29ff:fe02:e00a  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:02:e0:0a  txqueuelen 1000  (Ethernet)
        RX packets 156739  bytes 233182466 (233.1 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 45173  bytes 2809606 (2.8 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

$ vim /etc/docker/daemon.json

保存退出.

cluster-store:配置的Consul的leader地址,單體直接寫,其它軟件注意協議

cluster-advertise: 指定監聽的網卡和端口,也能夠指定接收訂閱消息的IP:PORT

還有一種是直接修改docker.service的,參考以下:

$ cd /etc/systemd/system/multi-user.target.wants
$ sudo vim docker.service

找到ExecStart= 字眼,在此行末尾添加以下代碼

--cluster-store=consul://192.168.87.133:8500 --cluster-advertise=ens33:2375

效果以下:

操做效果與以上方法保持一致

接着執行命令,重啓docker服務,另外一臺服務器操做方式相同,注意網卡名稱

$ sudo systemctl daemon-reload && sudo systemctl restart docker
  • 在133服務器啓動Consul服務
docker run -d --network host -h consul --name=consul --restart=always -e CONSUL_BIND_INTERFACE=ens33 consul:1.5.2

用主機模式的緣由是防止有些端口沒有映射出來,還有就是想讓Consul識別外部網卡的方式只能host模式,下面給個非host的方式

$ docker run -di  -h consul -p 8500:8500 --name=consul consul:1.5.2
  • 建立Docker overlay共享網絡
$ docker network create -d overlay my_overlay

這裏與普通建立網絡不一樣在於指定了overlay模式的網絡,-d也能夠寫爲--driver

  • 訪問Consul的頁面,如個人是192.168.87.133:8500

咱們的配置在Key/Value處,

點擊docker -> nodes

出現上邊的兩個節點,分別是兩個docker daemon (守護進程) 註冊的值

測試

新建兩個centos的容器分別在兩臺服務器上,使用overlay 咱們剛纔建立的網絡

133服務器

$ docker run -di --network my_overlay --name mycentos1 centos:7

139服務器

$ docker run -di --network my_overlay --name mycentos2 centos:7

--net全拼爲--network--開頭的可不加=

查看133服務器mycentos1容器的IP

$ docker inspect -f "{{ .NetworkSettings.Networks.my_overlay.IPAddress}}" mycentos1
10.0.1.2

查看139服務器mycentos2容器的IP

$ docker inspect -f "{{ .NetworkSettings.Networks.my_overlay.IPAddress}}" mycentos2
10.0.1.3

分別從133服務器ping 139服務器的mycentos2的內網IP

反過來ping也是同樣的,可是並非讓咱們經過外部去訪問的,經過同一overlay網絡的容器就能夠,不信咱們做以下嘗試

133服務器

$ docker exec -it mycentos1 bash
# ping 10.0.1.3

訪問得通,沒有丟包,反過來也是同樣的,篇幅有限就不試驗了

這起碼說明,如今的服務的確已經網絡互通了,下篇文章咱們來搞下生產用的集羣方式

引文

本文系Hellxz學習與實踐文章,禁止布布扣、碼迷等第三方爬蟲網站爬取

相關文章
相關標籤/搜索