1. 程式人生 > >Docker容器跨主機通訊之:直接路由方式

Docker容器跨主機通訊之:直接路由方式

Desktop

概述

就目前Docker自身預設的網路來說,單臺主機上的不同Docker容器可以藉助docker0網橋直接通訊,這沒毛病,而不同主機上的Docker容器之間只能通過在主機上用對映埠的方法來進行通訊,有時這種方式會很不方便,甚至達不到我們的要求,因此位於不同物理機上的Docker容器之間直接使用本身的IP地址進行通訊很有必要。再者說,如果將Docker容器起在不同的物理主機上,我們不可避免的會遭遇到Docker容器的跨主機通訊問題。本文就來嘗試一下。

注: 本文首發於 My 公眾號 CodeSheep ,可 長按掃描 下面的 小心心 來訂閱 ↓ ↓ ↓

CodeSheep · 程式羊

情景構造

如下圖所示,我們有兩個物理主機1和主機2,我們在各自宿主機上啟動一個centos容器,啟動成功之後,兩個容器分別執行在兩個宿主機之上,預設的IP地址分配如圖所示,這也是Docker自身預設的網路。

兩臺主機上的容器如何通訊?

此時兩臺主機上的Docker容器如何直接通過IP地址進行通訊?

一種直接想到的方案便是通過分別在各自主機中 新增路由 來實現兩個centos容器之間的直接通訊。我們來試試吧

方案原理分析

由於使用容器的IP進行路由,就需要避免不同主機上的容器使用了相同的IP,為此我們應該為不同的主機分配不同的子網來保證。於是我們構造一下兩個容器之間通訊的路由方案,如下圖所示。

容器間通訊

各項配置如下:

  • 主機1的IP地址為:192.168.145.128
  • 主機2的IP地址為:192.168.145.129
  • 為主機1上的Docker容器分配的子網:172.17.1.0/24
  • 為主機2上的Docker容器分配的子網:172.17.2.0/24

這樣配置之後,兩個主機上的Docker容器就肯定不會使用相同的IP地址從而避免了IP衝突。

我們接下來 定義兩條路由規則 即可:
- 所有目的地址為172.17.1.0/24的包都被轉發到主機1上
- 所有目的地址為172.17.2.0/24的包都被轉發到主機2上

綜上所述,資料包在兩個容器間的傳遞過程如下:

  • 從container1 發往 container2 的資料包,首先發往container1的“閘道器”docker0,然後通過查詢主機1的路由得知需要將資料包發給主機2,資料包到達主機2後再轉發給主機2的docker0,最後由其將資料包轉到container2中;反向原理相同,不再贅述。

我們心裡方案想的是這樣,接下來實踐一下看看是否可行。

實際試驗

  • 0x01. 分別對主機1和主機2上的docker0進行配置

編輯主機1上的 /etc/docker/daemon.json 檔案,新增內容:"bip" : "ip/netmask"

{ "bip", "172.17.1.252/24" }

編輯主機2上的 /etc/docker/daemon.json 檔案,新增內容:"bip" : "ip/netmask"

{ "bip", "172.17.2.252/24" }
  • 0x02. 重啟docker服務

主機1和主機2上均執行如下命令重啟docker服務以使修改後的docker0網段生效

systemctl restart docker
  • 0x03. 新增路由規則

主機1上新增路由規則如下:

route add -net 172.17.2.0 netmask 255.255.255.0 gw 192.168.145.129

主機2上新增路由規則如下:

route add -net 172.17.1.0 netmask 255.255.255.0 gw 192.168.145.128
  • 0x04. 配置iptables規則

主機1上新增如下規則:

iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.1.0/24 ! -d 172.17.0.0/16 -j MASQUERADE

主機2上新增如下規則:

iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.2.0/24 ! -d 172.17.0.0/16 -j MASQUERADE
  • 0x05. 啟動容器

主機1上啟動centos容器:

docker run -it --name container1 centos /bin/bash

主機2上啟動centos容器:

docker run -it --name container2 centos /bin/bash
  • 0x06. 容器間直接通訊

好了,現在兩容器可以互ping了

container1 ping container2

container2 ping container1

後記

本文探討了區域網中不同宿主機間Docker容器直接通訊的一種可能方案。當然現在實現跨主機容器間通訊的現成方案也很多,典型的比如flannel這種,我的 個人私有云 也用的是這種方案。

作者更多的SpringBt實踐文章在此:

如果有興趣,也可以抽點時間看看作者一些關於容器化、微服務化方面的文章:

長按掃描 下面的 小心心 來訂閱 CodeSheep,獲取更多 務實、能看懂、可復現的 原創文 ↓↓↓

CodeSheep · 程式羊