【Docker】利用ambassador實現(xiàn)container跨主機連接
針對于同一個主機上的兩個container,我們可以使用docker的link機制來它們之間的連接。
然而,針對于不同主機上的兩個container,docker目前并沒有提供直接有效的方法來實現(xiàn)它們之間的連接,必須借助其它工具來實現(xiàn)。docker主頁的文章Link via an Ambassador Container介紹了一種方法,通過ambassador pattern來實現(xiàn)container跨主機連接,這里對這種方法做一下解釋。
主機VM1上有裝有Redis Server的container,主機VM2上有裝有Redis Client的container,為了實現(xiàn)Redis Client和Redis Server之間跨主機的連接,需要借助Ambassador容器,這里VM1上有一個Ambassador容器Ambassador1,VM2上有一個Ambassador容器Ambassador2。
這個方法是如何工作的呢?我們看一下下面的流程:
Ambassador1容器通過link方式確定Redis Server容器的ip地址和開放的6379端口,然后利用socat將容器內(nèi)部的6379端口收到的信息重定向到RedisServer容器的6379端口;
VM1將自己的6379端口綁定到Ambassador1容器的6379端口;
Ambassador2通過傳入環(huán)境變量的方式確定VM1的ip地址和6379端口,然后利用socat將容器內(nèi)部的6379端口收到的信息重定向到VM1的6379端口;
Redis Client容器通過link方式確定Ambassador2容器的ip地址和開放的6379端口,然后用redis-cli直接連接,連接請求將經(jīng)過Ambassador2、Ambassador1,***發(fā)送到Redis Server的6379端口。
啟動這4個container的命令如下:
啟動Redis Server:
- sudo docker run -d --name redis redis
啟動Ambassador1:
- sudo docker run -d --link redis:redis --name ambassador1 -p 6379:6379 ambassador
啟動Ambassador2:(其中x.x.x.x表示VM1的ip地址)
- sudo docker run -d --name ambassador2 --expose 6379 -e REDIS_PORT_6379_TCP=tcp://x.x.x.x:6379 ambassador
啟動Redis Client:
- sudo docker run -i -t --rm --link ambassador2:redis redis-cli
而Ambassador容器是如何利用linux端口映射socat來實現(xiàn)跨主機的通訊呢?
在svendowideit/Ambassador的Dockerfile里面,有一行關(guān)鍵的代碼:
- CMD env | grep _TCP= | sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' | sh && top
這行代碼的用法是在環(huán)境變量中找到包含"_TCP"的行,然后將從滿足正則表達式".*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)"的環(huán)境變量中提取ip和端口號,并執(zhí)行"socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&",其中/1表示環(huán)境變量名中指示端口號,/2表示ip地址,/3表示端口號。這個環(huán)境變量之所以這么命名,是由于docker link的機制是將被link的container的ip、端口、協(xié)議等信息以環(huán)境變量的形式放到link中去。
以Ambassador1為例,我們在啟動Ambassador1以后,可以查看里面的環(huán)境變量:
這里REDIS_PORT_6379_TCP=tcp://172.17.0.2:6379就是用于提取信息的環(huán)境變量,其中REDIS為Redis Server的在Ambassador1中的別名,是我們在link的時候制定的;6379為Redis Server開放的6379端口,用于提供Redis服務(wù);172.17.0.2為Redis Server的ip地址。如此,Ambassador1就能知道Redis Server服務(wù)的ip和端口,就能通過socat將redis訪問請求轉(zhuǎn)發(fā)給Redis Server。同理,我們就可以建立Redis Client——Ambassador2——Ambassador1——Redis Server的連接。
這種方式有一個缺點,就是在Ambassador2和Ambassador1建立連接的時候,Ambassador2必須要知道Ambassador1所在主機VM1的ip地址,從而硬編碼設(shè)置環(huán)境變量REDIS_PORT_6379_TCP,這樣靈活性就比較差,并且當(dāng)我們不知道VM1的ip地址時,這種方法是無法使用的。
原文出自:http://blog.csdn.net/sunset108/article/details/40856957