Docker學習總結之跨主機進行link


Docker學習總結之跨主機進行link

  Docker的功能非常強大,但要想駕馭好Docker卻不是一件很容易的事情。下面就介紹一種日常工作中會遇到的一個user case。比如現在有兩台host,分別標記為hostA和hostB。hostA用來運行oracle服務,hostB用來運行app服務。

  hostB中app產生的數據需要實時寫入hostA中的oracle數據庫。也就是hostB中的docker container需要link hostA中的docker container。

  為了解決這個問題,有兩個解決方案:

  方案一:

  將hostA中的oracle container對外expose 1521(我們假定此處對外expose 1521),然后在hostB中的app container中修改/etc/hosts文件,將hostA的IP添加到hosts文件中。

  Docker 部署圖如下:

  

  這種方案的優點就是可以根據實際情況自由配置,"自己的app掌控在自己手中"。

  但是缺點也很嚴重,首先每次run container時都需要修改hosts文件,而且每次host環境發生變化,都需要維護hosts文件,因此后續的維護成本很高。其次,如果遇到其他人開發的docker image,我們未必有權限來修改hosts文件。

  所以此方案也僅僅用作開發測試使用,不推薦正式采用。

  方案二:

  Docker官方提供了一種ambassador的agent方案。此方案借助一個名為svendowideit/ambassador的image,將不同host進行解耦合。

  Docker 部署圖如下:

  具體實施步驟如下:

  首先我們要在hostA和hostB之間pull svendowideit/ambassador。

1 docker pull svendowideit/ambassador

 

  根據部署圖可得知,是hostB要link hostA的container,因此我們需要先啟動hostA的container(此時可以理解hostA為server段,hostB為client段)。

docker run  -d  --name oracle tirtool/oracle11g:latest

  然后啟動hostA中的ambassador container。

docker run  -d --link oracle:oracle -p 1521:1521 --name ambassador svendowideit/ambassador:latest

  標紅的部分是需要重點注意的地方,這個命令也就是將hostA中的oracle container直接暴露在ambassador之中,這樣ambassador才能將訪問請求轉發到oracle container中。

  此刻,hostA中的事情都已經處理完了,我們開始處理hostB。

  與hostA的container啟動順序不用,我們需要先start hostB的ambassador。因為依據部署圖可知,hostB中是app container調用ambassador container,所以需要先保證ambassador已經啟動,才能啟動app container。

docker run -d --name ambassador-oracle --expose 1521 -e ORACLE_PORT_1521_TCP=tcp://<<hostA IP>>:1521 svendowideit/ambassador

  標紅的部分很重要,直接決定了hostB和hostA是否可以直接通訊。稍后,我們可以來解讀一下這部分參數。

  當hostB中的ambassador啟動成功后,我們開始啟動app container。

docker run --link ambassador-oracle:oracle  --name bw base/ubuntu:14.04

  大家注意到我們在app container中將ambassador-oracle alias為oracle,這樣在app container中的/etc/hosts文件中會出現一條記錄:

    10.1.0.3        oracle

  此刻app container中app產生數據后,如果調用oracle:1521,那么首先將請求發往hostB的ambassador的1521端口。hostB的ambassador會將數據轉發到hostA的1521端口。而此時hostA中的ambassador在listen 1521端口,接收到請求后會將數據轉發至hostA的oracle container中。oracle container處理完畢后將response返回值ambassador,ambassador再依次回傳。從而達到不同host中container相互訪問的目的。

  我們再看一下在hostB中執行 --expose 1521 -e ORACLE_PORT_1521_TCP=tcp://<<hostA IP>>:1521 時發生了什么事情。ambassador最重要的一項任務就是將hostB的1521端口同hostA的1521端口進行了端口映射。

  其實執行的是下面的命令:

  socat TCP4-LISTEN:1521,fork,reuseaddr TCP4:<hostA IP>:1521

  這條命令采取fork模式,將本機的1521的數據轉發到hostA的1521端口。而這條命令所需的參數來自於一個shell腳本:

  env | grep _TCP= | sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/'  | sh && top

  這條命令在env中找尋所有*_TCP的環境變量,我們在啟動時設定-e ORACLE_PORT_1521_TCP=tcp://<<hostA IP>>:1521 所以可以找到ORACLE_PORT_1521_TCP這條變量。找到后執行正則表達式"s/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/" 替換后的shell command就是socat TCP4-LISTEN:1521,fork,reuseaddr TCP4:<hostA IP>:1521。

  因此ambassador方案就是很巧妙的將不同host的port進行了橋接,而這些對docker使用者都是透明的。但這個方案也是有一些瑕疵的,就是如果新增container之后,需要重啟或者新增ambassador,所以如果一個ambassador同時對應多個container,那么在維護上面就會稍許麻煩些,但維護成本比方案一低了很多。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM