Swarm初探

1 簡介

Swarm 是使用 SwarmKit 構建的 Docker 引擎內置(原生)的集羣管理和編排工具。其主要作用是把若干臺Docker主機抽象爲一個整體,並且通過一個入口統一管理這些Docker主機上的各種Docker資源。Swarm和Kubernetes比較類似,但是更加輕量,具有的功能也較kubernetes更少一些。

Docker v1.12 是一個非常重要的版本,Docker 重新實現了集羣的編排方式。在此之前,提供集羣功能的 Docker Swarm 是一個單獨的軟件,而且依賴外部數據庫(比如 Consul、etcd 或 Zookeeper)。從 v1.12 開始,Docker Swarm 的功能已經完全與 Docker Engine 集成,要管理集羣,只需要啓動 Swarm Mode。安裝好 Docker,Swarm 就已經在那裏了,服務發現也在那裏了(不需要安裝 Consul 等外部數據庫)。

2 架構分析

2.1 基本架構

基本架構
如上圖所示,Swarm Node表示加入Swarm集羣中的一個Docker Engine實例,基於該Docker Engine可以創建並管理多個Docker容器。其中,最開始創建Swarm集羣的時候,Swarm Manager便是集羣中的第一個Swarm Node。在所有的Node中,又根據其職能劃分爲Manager Node和Worker Node。

manager node

Manger 節點,顧名思義,是進行 Swarm 集羣的管理工作的,它的管理工作集中在如下部分,

  • 維護一個集羣的狀態
  • 對Services進行調度
  • 爲Swarm提供外部可調用的API接口

Manager 節點需要時刻維護和保存當前 Swarm 集羣中各個節點的一致性狀態,這裏主要是指各個 Tasks 的執行的狀態和其它節點的狀態;因爲 Swarm 集羣是一個典型的分佈式集羣,在保證一致性上,Manager 節點採用 Raft 協議來保證分佈式場景下的數據一致性;
通常爲了保證 Manager 節點的高可用,Docker 建議採用奇數個 Manager 節點,這樣的話,你可以在 Manager 失敗的時候不用關機維護,我們給出如下的建議:

  • 3 個 Manager 節點最多可以同時容忍 1 個 Manager 節點失效的情況下保證高可用;
  • 5 個 Manager 節點最多可以同時容忍 2 個 Manager 節點失效的情況下保證高可用;
  • N 個 Manager 節點最多可以同時容忍 (N−1)/2個 Manager 節點失效的情況下保證高可用;
  • Docker 建議最多最多的情況下,使用 7 個 Manager 節點就夠了,否則反而會降低集羣的性能了。
Worker Node

Worker Node接收由Manager Node調度並指派的Task,啓動一個Docker容器來運行指定的服務,並且Worker Node需要向Manager Node彙報被指派的Task的執行狀態。

更換角色

可以通過docker node promote/demote 來提升或者降級節點

2.2 設計架構

設計架構

跨主機容器通信

Docker Swarm 內置的跨主機容器通信方案是overlay網絡,這是一個基於vxlan協議的網絡實現。VxLAN 可將二層數據封裝到 UDP 進行傳輸,VxLAN 提供與 VLAN 相同的以太網二層服務,但是擁有更強的擴展性和靈活性。 overlay 通過虛擬出一個子網,讓處於不同主機的容器能透明地使用這個子網。所以跨主機的容器通信就變成了在同一個子網下的容器通信,看上去就像是同一主機下的bridge網絡通信。
爲支持容器跨主機通信,Docker 提供了 overlay driver,使用戶可以創建基於 VxLAN 的 overlay 網絡。其實,docker 會創建一個 bridge 網絡 “docker_gwbridge”,爲所有連接到 overlay 網絡的容器提供訪問外網的能力。`docker network inspect docker_gwbridge 查看網絡信息。
docker network ls
overlay網絡的具體實現:
docker 會爲每個 overlay 網絡創建一個獨立的 network namespace,其中會有一個 linux bridge br0,endpoint 還是由 veth pair 實現,一端連接到容器中(即 eth0),另一端連接到 namespace 的 br0 上。

br0 除了連接所有的 endpoint,還會連接一個 vxlan 設備,用於與其他 host 建立 vxlan tunnel。容器之間的數據就是通過這個 tunnel 通信的。邏輯網絡拓撲結構如圖所示:
在這裏插入圖片描述

服務發現

docker Swarm mode下會爲每個節點的docker engine內置一個DNS server,各個節點間的DNS server gossip協議互相交互信息。此處DNS server用於容器間的服務發現。swarm mode會爲每個 –net=自定義網絡的service分配一個DNS entry。目前必須是自定義網絡,比如overaly,自建bridge。(在engine DNS之上)

原理:
每個Docker容器都有一個resolv.conf,它將DNS查詢轉發到docker engine,該引擎充當DNS服務器。docker 引擎收到請求後就會在發出請求的容器所在的所有網絡中,檢查域名對應的是不是一個容器或者是服務,如果是,docker引擎就會從存儲的key-value建值對中查找這個容器名、任務名、或者服務名對應的IP地址,並把這個IP地址或者是服務的虛擬IP地址返回給發起請求的域名解析器。
由上可知,docker的服務發現的作用範圍是網絡級別,也就意味着只有在同一個網絡上的容器或任務才能利用內嵌的DNS服務來相互發現,不在同一個網絡裏面的服務是不能解析名稱的,另外,爲了安全和性能只有當一個節點上有容器或任務在某個網絡裏面時,這個節點纔會存儲那個網絡裏面的DNS記錄。
如果目的容器或服務和源容器不在同一個網絡裏面,Docker引擎會把這個DNS查詢轉發到配置的默認DNS服務 。
service-dns
在上面的例子中,總共有兩個服務myservice和client,其中myservice有兩個容器,這兩個服務在同一個網裏面。在client裏針對docker.com和myservice各執行了一個curl操作,下面時執行的流程:

  • 爲了client解析docker.com和myservice,DNS查詢進行初始化
  • 容器內建的解析器在127.0.0.11:53攔截到這個DNS查詢請求,並把請求轉發到docker引擎的DNS服務
  • myservice被解析成服務對應的虛擬IP(10.0.0.3),在接下來的內部負載均衡階段再被解析成一個具體任務的IP地址。如果是容器名稱這一步直接解析成容器對應的IP地址(10.0.0.4或者10.0.0.5)。
  • docker.com在mynet網絡上不能被解析成服務,所以這個請求被轉發到配置好的默認DNS服務器(8.8.8.8)上。

負載均衡

負載均衡分爲兩種:Swarm集羣內的service之間的相互訪問需要做負載均衡,稱爲內部負載均衡(Internal LB);從Swarm集羣外部訪問服務的公開端口,也需要做負載均衡,稱外部部負載均衡(Exteral LB or Ingress LB)。

  • internal LB
    內部負載均衡就是我們在上一段提到的服務發現,集羣內部通過DNS訪問service時,Swarm默認通過VIP(virtual IP)、iptables、IPVS轉發到某個容器。
    my-net
    當在docker swarm集羣模式下創建一個服務時,會自動在服務所屬的網絡上給服務額外的分配一個虛擬IP,當解析服務名字時就會返回這個虛擬IP。對虛擬IP的請求會通過overlay網絡自動的負載到這個服務所有的健康任務上。這個方式也避免了客戶端的負載均衡,因爲只有單獨的一個IP會返回到客戶端,docker會處理虛擬IP到具體任務的路由,並把請求平均的分配給所有的健康任務。
    mynet
  • Exteral LB(Ingress LB 或者 Swarm Mode Routing Mesh)
    看名字就知道,這個負載均衡方式和前面提到的Ingress網絡有關。Swarm網絡要提供對外訪問的服務就需要打開公開端口,並映射到宿主機。Ingress LB就是外部通過公開端口訪問集羣時做的負載均衡。

當創建或更新一個服務時,你可以利用–publish選項把一個服務暴露到外部,在docker swarm模式下發佈一個端口意味着在集羣中的所有節點都會監聽這個端口,這時當訪問一個監聽了端口但是並沒有對應服務運行在其上的節點會發生什麼呢? 接下來就該我們的路由網(routing mesh)出場了,路由網時docker1.12引入的一個新特性,它結合了IPVS和iptables創建了一個強大的集羣範圍的L4層負載均衡,它使所有節點接收服務暴露端口的請求成爲可能。當任意節點接收到針對某個服務暴露的TCP/UDP端口的請求時,這個節點會利用預先定義過的Ingress overlay網絡,把請求轉發給服務對應的虛擬IP。ingress網絡和其他的overlay網絡一樣,只是它的目的是爲了轉換來自客戶端到集羣的請求,它也是利用我們前一小節介紹過的基於VIP的負載均衡技術。

啓動服務後,你可以爲應用程序創建外部DNS記錄,並將其映射到任何或所有Docker swarm節點。你無需擔心你的容器具體運行在那個節點上,因爲有了路由網這個特性後,你的集羣看起來就像是單獨的一個節點一樣。
ingress
上面這個圖表明瞭路由網是怎麼工作的:

  • 服務(app)擁有兩份複製,並把端口映射到外部端口的8000
  • 路由網在集羣中的所有節點上都暴露出8000
  • 外部對服務app的請求可以是任意節點,在本例子中外部的負載均衡器將請求轉發到了沒有app服務的主機上
  • docker swarm的IPVS利用ingress overlay網路將請求重新轉發到運行着app服務的節點的容器中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章