(轉) Docker - Docker1.12服務發現,負載均衡和Routing Mesh

 

看到一篇介紹 Docker swarm以及如何編排的好文章,挪放到這裏,本身學習的同時也分享出來。
html

 

原文連接: http://wwwbuild.net/dockerone/414200.htmlnode

-----

Docker社區目前最熱的話題莫過於Docker 1.12的發佈, 明顯的感受就是你們都在討論Docker 1.12的新功能,各類關於1.12的使用手冊,文章,深度教程層出不窮, 一句話總結來講, 不知道Docker 1.12都很差意思跟人打招呼了。程序員

我的理解Docker 1.12最大的功能莫過於SwarmKit的引入,這應該算是Docker發展里程碑式的一個Release(上一個里程碑應該是runC和Containerd的剝離,標誌着Docker公司本身孤獨地玩到容器標準化概念引入),自此不再要說Docker是主機容器管理了, Docker已經可以管理一羣主機上的容器了。概念上Docker引入了node、service、task甚至更高於service一層的stack, 自此你們會發現容器和網絡已經不是Docker的first-class概念, 取而代之的是service、 stack和跨主機網絡。Docker SwarmKit的引入給容器編排投入了一顆重磅炸彈, 給個人感受是原來容器編排還能夠這麼玩,終於不要某某sos和某8s的全家桶了, 在容器編排的遠古時代(其實也不遠,就是觀念陳舊)不裝個五六七八個組件都很差意思跟人說是編排, 真的有這個必要麼? 固然了, Docker Swarm主要功能仍是是借鑑了「遠古時代」的幾款產品, 吸取了前人的優秀經驗。 讓我列幾個牛哄哄的功能給你們吧:docker

  1. 內置Raft, 媽媽不再用擔憂我還要依賴Zookeeper、Etcd、Consul了, 光部署這些東西就浪費我一成天外加三臺機器。ubuntu

  2. 不區分管理節點和Worker節點,想讓誰上就讓誰上, 猜測是參考了人家Nomad吧, 關鍵還能運行時Promote、Demote, 太方便了。緩存

  3. Service,Stack外加DAB, 用過都說好, 方便。網絡

  4. Rolling Update, Scale一個Service,灰度發佈分分鐘搞定(雖然有點雞肋),這個不用說也是借鑑了Kubernetes。負載均衡

一張圖展現一下Docker1.12的和老版本的功能對比。curl

固然當前Docker 1.12的功能還很初級,尚未據說過有人大規模生產級的應用(聽說能管理2000個節點,10W個容器),不過看的出來SwarmKit team新功能推出的速度仍是至關快的。 我的很看好這一趨勢。工具

下面分享一下Docker的一個服務是如何被外部訪問的。

在沒有Docker的時代咱們更喜歡的兩種辦法來部署一個服務 1, 單個機器上的單個進程,綁定到固定IP上的固定端口, 這種方式的優勢是簡單明瞭,程序員同窗們須要作的事情最大化的優化單個進程的處理能力, 保障這個進程不會由於各類問題退出, 由於一旦退出就沒得玩了。 2, 單個機器上的多個進程綁定到固定端口, 前面放一個代理工具。

容器化後你們發現之前的作法或多或少須要作些調整, 第一,因爲主機概念被弱化,集羣概念被突出, 應用程序再也不依賴某個主機或者某個端口; 第二, 容器生命週期不固定, 容器能夠隨時被啓動被中止, 容器的數量可多可少(這就是咱們常說的彈性)。因爲上面提到的兩個容器化的特性,一些新的問題被引入,聰明的工程師們想到了一些解決辦法來應對這些問題, 第一個解決辦法就是咱們要談到的服務發現,針對的問題是服務對外地址不定和服務隨時被啓動中止。 服務被發現之後要解決是如何把任務按照必定規則負載到容器中, 這就是第二個咱們要談的負載均衡。 負載均衡解決了單一入口負載到多個容器上問題, 可是因爲容器調度以後可能落到多個機器上, 假如某些主機上面沒有工做的容器,而對外服務時候又但願服務能夠被訪問, Routing Mesh概念引入是解決多個入口點負載到單個容器的問題。

服務發現

單純的服務發現很好實現, 無非就是監測Container的啓動、中止, 根據這些變更記錄下服務到底能夠經過哪些IP+端口能夠被訪問, 理論上實現一個初級的可用的服務發現不會超過十行代碼。成熟的服務發現還須要額外的工做好比健康檢查, 注意到咱們以前是假設了容器啓動就能夠對外服務, 實際中狀況可能遠非如此, 一個應用啓動以後可能要準備環境, 加載數據以後才能夠對外服務,健康檢查是保證服務可用以後再對外服務。 另一個成熟的服務發現必備條件是高可用, 明眼人可能已經發現以前的簡單版本不具有高可用和狀態一致性, 這也是爲何Docker引入了Raft協議。

負載均衡

傳統理解的負載均衡根據協議不一樣能夠分爲7層的和4層的, 7層負載均衡特色是能夠支持很複雜的用戶規則,好比HTTP header、Cookie等應用邏輯, 而4層只能支持到IP地址負載不一樣服務。

Docker1.12的服務發現和負載均衡是結合到一塊兒的, 實現辦法有兩種,DNS輪詢和IPVS。 理解這兩種策略以前須要知道的一個前提是Docker爲每一個服務都分配了一個虛擬IP, 這個IP對應的不是具體的一個Task或者一個具體的Container,而是專門爲一個服務保留。

下面咱們舉例子分別說明一下兩種負載均衡實現:

首先準備一下環境。

第一步以下圖所示用Go寫一段小代碼, 編譯成二進制放在一個ubuntu基礎鏡像裏, 同時個人ubuntu裏面安裝了一些基礎的網絡工具, 好比dig、curl、 ping等, 保存成鏡像ubuntu-base。


第二步, 根據Docker官方安裝文檔 咱們在虛擬機環境裏啓動兩個虛擬機, 構造一個Docker Swarm集羣。

第三步, 建立一個Overlay網絡, 取名overlay-test。

下面咱們試一下DNS輪訓模式的服務發現和負載均衡, 設置一個服務使用DNS輪詢仍是VIP, 只要設置好endpoint-mode這個參數就好, 以下圖所示:

使用下面命令啓動咱們的服務:

docker service create –network overlay-test –name demo –replicas=4 –endpoint-mode=dnsrr ubuntu-base

—network overlay-test是指定使用剛剛建立的Overlay網絡, –replicas=4 指定task數量, –endpoint-mode=dnsrr使用dnsrr方式作負載均衡。

啓動成功後以下圖所示:

當前機器上運行docker ps會發現有隻有兩個容器生成, 緣由是另外兩個task被調度到另一臺主機上。

下一步咱們考慮進入容器中看一下虛擬出來的網絡狀況。

咱們以前明明指定了使用overlay-test網絡, 按理應該只有兩塊網卡, 實際上Docker卻爲咱們生成了4塊, 多出來的兩塊是Docker爲容器作的手腳, 讓我來一一講解爲何會有4塊網卡的出現。

  1. lo網卡不用多說, 是本地網卡, 也叫回環網卡;

  2. eth2屬於以前建立的overlay-test網絡;

  3. eth1和docker_gwbridge網橋構成的網絡可使容器內的服務能夠在主機上訪問, 主機上telnet 172.18.0.4能夠訪問到咱們的服務,以下圖:

  4. eth0是ingress網絡中的一塊網卡, 是爲了Routing Mesh而設,稍後咱們會詳細說明。

繼續回到容器裏面看咱們查看一下服務狀況, 執行命令:


你們會發現經過服務名或者容器ID都能找到IP地址, 區別是服務名發現了本機上全部提供服務的容器IP, 至此同時實現了服務發現和內部負載均衡。

以上就是經過DNS輪詢實現的服務發現和負載均衡, 這樣的負載均衡是有一些缺點的, 好比:

  1. 一些應用可能緩存DNS請求, 致使容器變化以後DNS不能實時更新;

  2. DNS生效時間也致使不能實時反映服務變化狀況;

  3. 因爲以上緣由致使的負載均衡不夠準確。

下面我來演示一下VIP和IPVS模式的服務發現和負載均衡。 VIP和IPVS原理上比較容易理解, 就是Docker爲每一個服務分配了一個VIP, DNS解析服務名稱或者自定義的別名到這個VIP上。

因爲VIP自己沒有容器提供服務,Docker把到VIP的請求經過IPVS技術負載到後面的容器上。

Docker發佈一個服務時候默認會選擇VIP模式, 下面咱們用一樣的鏡像演示一下。

docker service create –network overlay-test –name demo –replicas=4 –endpoint-mode=vip —publish 8080:8080 ubuntu-base

啓動服務以後咱們inspect一下, 會發現Virtual IPs有兩個入口, 期中10.0.0.2就是overlay-test網絡下面的一個Endpoint, 這個Endpoint是服務而非容器的。

咱們進入容器中執行dig命令會發現:

此時DNS解析出來的是一個虛擬地址, 虛擬地址經過IPVS和一系列的iptables規則動態轉發到容器中。 這樣的負載均衡屏蔽了DNS輪詢的時效性問題,同時能夠支持UDP等協議, 性能也很是好。 缺點是不能作好比回話保持, 基於URL等應用層協議的規則的轉發。

下面聊聊Routing Mesh, Routing Mesh的目的是每一個主機上都爲服務預留端口, 保證每臺機器上均可以訪問到服務。實現的辦法就是Ingress網絡, 以前咱們提到容器中會多出一塊網絡,咱們Inspect ingress網絡,同時會發現網絡對應的容器上多出一個容器 ingress-sbox

一個請求到主機端口8080以後, 數據包的流向以下所示:

主機端口8080 => Ingress-sbox-VIP:8080 => 容器Ingress-sbox => IPVS分發到containers。

你們能夠看到訪問主機以後數據包流到了一個特殊的Sandbox容器裏, 這個容器和咱們的容器共享一個Ingress網絡,經過Iptables和IPVS等重定向到了最終容器之上。 達到了服務在任何一臺主機的8080端口均可達的目的。

已上就是我理解的Docker SwarmKit的幾種功能, 一些新的網絡技術你們也在討論,好比Macvlan和Ipvlan等, 經過這些技術Docker的應用場景愈來愈豐富, 愈來愈成熟, 讓咱們拭目以待。

 

國內首個基於Docker SwarmKit的容器管理面板——數人云Crane初版最新出爐,歡迎點擊「閱讀原文」申請體驗,點贊or吐槽均可以。

相關文章
相關標籤/搜索