我要上頭條:Docker集群管理之Docker Swarm

前言:在Docker集群管理之Docker Machine和Docker集群管理之Docker Compose中,我們通過源碼分析了解了Docker Machine和Docker Compose的工作原理,本文將帶你了解Docker集群管理三劍客的Docker Swarm。本文為靈雀雲(www.alauda.cn)「我要上頭條」活動的投稿。‌‌

9月1日,杜航將在CSDN帶來線上課程「Docker集群管理三劍客」,報名地址:http://huiyi.csdn.net/activity/product/goods_list?project_id=2330。

在Docker項目的初期,Docker開發團隊著力於打造一個穩定的Docker容器運行環境以及構建一套Docker鏡像的標準,長久以來只能在單主機運行Docker容器便成為了其最大的局限性。Docker Swarm的出現宣告了Docker對於集群的支持,雖然還處於初級階段,功能和穩定性與其他集群管理工具也還有不小的差距,但其與Docker的原生集成使其有得天獨厚的優勢。

Advertisements

Docker Swarm是Docker原生的集群管理工具,它把多個Docker主機抽象成一個單一的虛擬主機。Docker Swarm支持標準的Docker API,所以任何可以與Docker Daemon通信的工具都可以使用Docker Swarm擴展到多個主機。特別值得關注的是對Docker命令行的支持,為使用者提供了從單一Docker主機到Docker集群的無縫切換。

安裝Docker Swarm

用戶可以通過下載Swarm鏡像的方式安裝Docker Swarm,這大大簡化了使用者編譯二進位文件所帶來的複雜度。

使用者也可以通過Docker Machine來構建由Swarm管理的Docker集群。Docker集群按角色可分為Master node和Slave node。 Master node負責管理所有slave nodes並根據策略將Docker容器調度到相應的slave node。Slave node為在Swarm master管理下的Docker主機,提供Docker容器的運行環境。Master node同時也可以是Slave node。

Advertisements

通過docker machine構建Swarm master node命令如下 – 我們會在接下來的篇幅里詳細講–swarm-discovery參數

Docker Machine在創建好Docker虛擬主機之後會運行swarm鏡像,啟動swarm manager容器

同時還會在master node上啟動一個worker容器,使本機既是master又是slave

通過Docker Machine創建Slave node命令如下:

至此一個簡單的swarm cluster已經裝好了,運行eval 「$(docker-machine env –swarm swarm-master)」設置docker client運行的環境變數,運行docker info可以看到Docker集群的信息。

運行docker run命令可以看到制定容器運行於Docker集群中的node-00上

Docker Swarm工作原理

Docker Swarm使用cli.go(https://github.com/codegangsta/cli)作為CLI的框架開發Swarm CLI,目前支持4個子命令:

  • Create – 向Docker Hub服務發現伺服器申請一個全球唯一的token標識此集群

  • List – 列舉當前集群的所有節點

  • Join – 加入一個集群

  • Manage – 管理一個集群

服務發現

Docker Swarm支持多種服務發現機制添加或刪除Slave節點,主要可分為靜態管理和動態管理兩種。

靜態管理包括靜態文件配置(file://)和靜態IP地址列表(nodes://)的方式。靜態文件的方式是將每一個節點的IP地址:埠寫到一個文件中,並將此配置文件以參數的形式傳給swarm manage容器。靜態IP地址列表的方式是將每一個節點的IP地址:埠以參數的形式傳給swarm manager容器(nodes://<node_ip1:port>,<node_ip2:port>)。

動態Slave節點的添加和刪除主要利用了服務發現工具,包括Docker Hub Hosted Discovery(token://), etcd(etcd://), consul(consul://)以及zookeeper(zk://),本文分析了Docker Hub Hosted Discovery以及etcd兩種服務發現解決方案。

Docker Hub Hosted Discovery

使用Docker Hub提供的服務發現工具首先需要創建一個唯一的token,swarm提供了create命令向discovery-stage.hub.docker.com發送一個POST請求,得到一個全球唯一的token用於表示本集群。

接下來將得到的token值設置為–swarm-discovery token://81fa078f8205ea14a0040caeb6c3616c參數傳遞給docker-machine。

節點上的slave容器會調用swarm join命令加入到一個集群當中。當使用Token作為發現服務的時候,slave node會定期(默認心跳時間為20s)向discovery-stage.hub.docker.com發送一個POST請求註冊本節點。其中Token值即為通過create從docker hub得到的唯一值, ttl表示經過節點保留的時間(默認為60s,即超過60s沒有心跳請求便刪除此節點)

Swarm manager容器會定期輪訓docker hub獲取當前節點列表, 並監控列表變化

使用etcd作為服務發現

使用etcd作為服務發現的時候不需要調用create命令生成token,將etcd的地址作為–swarm-discovery etcd://<etcd address:port>作為參數傳遞給docker-machine.

節點上的slave容器調用swarm join調用docker libkv中的etcd庫定期(心跳間隔默認20s)向指定的etcd伺服器註冊自己的信息key為/docker/swarm/nodes/<node_ip:port>,同樣設置本記錄超時時間(默認為60s)。

Swarm manage容器會監控目錄/docker/swarm/nodes,當其發生變化時會通過通道傳遞消息,將變化的節點加入集群或者從集群中刪除 。

Docker Swarm通過Join的方式動態的添加節點,通過節點信息在服務發現伺服器中的默認超時機制刪除出現故障的節點。Docker Swarm的manager容器定期從服務發現伺服器獲取當前可用的所有節點以供調度容器使用。

Swarm manager

Swarm manager以Docker容器的方式運行於Master node上,其監聽在埠3376並開啟tls證書認證,只有通過證書認證的客戶端才能訪問Swarm的API伺服器,此行為與Docker Machine一致。

Swarm manager的啟動過程如下(swarm docker容器內):

  1. 載入證書以供client與server之間做TLS通信使用

  2. 初始化容器狀態存儲倉庫 – 以文件的形式記錄運行在整個集群的容器信息,通過映射宿主機邏輯捲軸的方式確保數據持久化。

  3. 初始化服務發現類(token/kv/file/nodes)

  4. 初始化容器調度策略(strategies),目前Swarm支持三種策略,可以通–strategy配置:

    1. spread – 此策略首先排除剩餘CPU和內存不夠的節點,計算各節點可用CPU和內容資源進行排序,若多個節點可用CPU和內存數相等則將容器調度到當前運行容器數量最少的節點上,此策略旨在平衡各節點的壓力

    2. binpack – 此策略首先排除剩餘CPU和內存不夠的節點,計算各節點可用CPU和內容資源進行排序,若多個節點可用CPU和內存數相等則將容器調度到當前運行容器數量最多的節點上,此策略旨在充分利用所有資源,將資源預留給未來可能需求更大資源用量的容器

    3. random – 隨機分配到一個節點

  5. 初始化容器調度過濾器(filter),目前支持的過濾器主要包括以下幾種:

    1. 限制過濾器(constraint):限制過濾器是一個定義每個節點的key/value對,也可以認為是節點的標記。當創建容器的時候(docker run –lable xxx=xxx或docker run –e constraint:xxx=xxx),你可以選擇一些符合要求的節點子集部署容器。主要用例如將容器運行在支持指定硬體的節點上(storage=ssd),指定的區域(zone=china)或邏輯集群分組(env=production)

    2. 關聯過濾器(affinity):將容器運行在有關聯關係的節點上。關聯關係包括:關聯容器(-e affinity:container==<container name>),將容器運行於有關聯容器運行的節點;鏡像關聯(-e affinity:image==<image name>,將容器運行於存在某鏡像的節點;標記關聯(-e affinity:lable==<lable name>),將容器運於存在此標記的容器節點。

    3. 埠過濾器(port):將容器運行於此埠可用的節點,避免埠衝突導致的容器運行失敗

    4. 依賴過濾器(dependency):將容器運行於依賴的容器運行的節點。此依賴關係包括–link, –volume-from以及—net

    5. 健康過濾器(Health):避免容器運行於不健康的節點上

  6. 初始化集群類Cluster – 目前支持Swarm Cluster以及Mesos Cluster,本文分析的是Swarm Cluster。在此初始化過程中會并行執行對服務發現系統中節點列表的監控。當有新節點添加時Swarm manager會連接到新節點的Docker Daemon獲取當前節點的信息,如CPU,內存等(如下,紅色的為轉換成當前引擎類engine成員變數),同時還會獲取節點Docker的版本,並監控節點Docker引擎狀態變化。當需要刪除節點的時候,斷掉到節點Docker daemon的鏈接,停止接收Docker引擎狀態變化事件。{

    「ID」:」P5YI:5HCG:TC42:VL2U:N3CG:GJX7:IZLQ:G5XN:BV2C:AXJ7:JFST:A5DF」,

    「Containers」:2,

    「Images」:14,

    「Driver」:」aufs」,

    「DriverStatus」:[

    [

    「Root Dir」,

    「/mnt/sda1/var/lib/docker/aufs」

    ],

    [

    「Backing Filesystem」,

    「extfs」

    ],

    [

    「Dirs」,

    「18」

    ],

    [

    「Dirperm1 Supported」,

    「true」

    ]

    ],

    「MemoryLimit」:true,

    「SwapLimit」:true,

    「CpuCfsPeriod」:true,

    「CpuCfsQuota」:true,

    「IPv4Forwarding」:true,

    「Debug」:true,

    「NFd」:24,

    「OomKillDisable」:true,

    「NGoroutines」:38,

    「SystemTime」:」2015-08-19T03:11:05.708386976Z」,

    「ExecutionDriver」:」native-0.2″,

    「LoggingDriver」:」json-file」,

    「NEventsListener」:1,

    「KernelVersion」:」4.0.7-boot2docker」,

    「OperatingSystem」:」Boot2Docker 1.7.1 (TCL 6.3); master : c202798 – Wed Jul 15 00:16:02 UTC 2015″,

    「IndexServerAddress」:」https://index.docker.io/v1/」,

    「RegistryConfig」:{

    「InsecureRegistryCIDRs」:[

    「127.0.0.0/8″

    ],

    「IndexConfigs」:{

    「docker.io」:{

    「Name」:」docker.io」,

    「Mirrors」:null,

    「Secure」:true,

    「Official」:true

    }

    }

    },

    「InitSha1″:」」,

    「InitPath」:」/usr/local/bin/docker」,

    「NCPU」:1,

    「MemTotal」:1044643840,

    「DockerRootDir」:」/mnt/sda1/var/lib/docker」,

    「HttpProxy」:」」,

    「HttpsProxy」:」」,

    「NoProxy」:」」,

    「Name」:」swarm-node-00″,

    「Labels」:[

    「provider=virtualbox」

    ],

    「ExperimentalBuild」:false

    }

7.若當前是單master節點模式,則註冊API處理函數,此API伺服器主要處理來自Docker客戶端或其他工具的Docker標準API請求。若當前是多master節點確保高可用性的部署方式,則進行領導者選舉,當選的節點註冊API處理函數,備份的節點註冊備份API處理函數,此處區別是若請求發送到備份節點則轉發給領導者的master節點。

至此,Swarm manager便啟動成功,其動態添加可用節點刪除不可用節點,監聽來自Docker Client或其他工具的API請求轉發給相應的節點進行容器操作。

接下來我們看一下Swarm manager的API server。API Server監聽3376埠,處理標準的Docker API,支持Docker Client及其他工具啟動管理Docker容器。下面看兩個簡單的例子 :

docker build – 發送POST /build請求到Swarm API server

  1. 初始化Build參數,如Dockerfile,tag等

  2. 根據過濾器以及調度策略選擇一個節點

  3. 將POST /build請求轉發給選取節點的Docker Daemon

  4. 將返回值轉發給Docker Client

  5. 刷新選取節點的鏡像列表

至此,docker build命令就已完成。

docker run – 發送POST /containers/create請求到Swarm API server,創建成功得到container UUID后發送POST /containers/<uuid>/start請求啟動容器。

  1. 若含有–name參數則確保name在整個cluster唯一,否則返回啟動失敗

  2. 創建一個Swarm集群唯一標識,設置在容器標籤(label)中

  3. 根據過濾器以及調度策略選擇一個節點

  4. 在選定的節點創建Docker容器,若鏡像不存在在下載鏡像

  5. 若在選擇的節點因為找不到鏡像而創建失敗則加入鏡像關聯(image==~)再次選擇節點

  6. 若創建成功則將新創建的容器添加到狀態存儲倉庫

  7. 返回創建成功,docker client會發送start請求啟動容器

  8. API server找到創建此容器的節點,發送start API到節點的Docker Daemon完成容器啟動

通過這兩個例子,我們發現Swarm api server其實是一個代理,它通過自己的調度規則(調度策略以及調度過濾器)選擇合適的節點,將Docker API請求轉發給相應節點的Docker Daemon,將返回值做簡單處理之後返回給Docker Client實現對Docker容器的啟動,停止,刪除以及對鏡像的管理。

Swarm高可用

在整個Swarm集群中,Swarm manager負責整個集群並管理多個節點的資源調度。如果Swarm manager出現故障,則整個集群都會出現服務中斷的現象。Swarm支持master節點的高可用,當master節點出現故障時,可以將服務切換到另一個備用replica節點上,實現服務的高可用。

實現Swarm master的高可用,你需要自己搭建一套服務發現系統,如etcd,consul或zookeeper。目前docker-machine還不支持創建swarm replica伺服器,你需要手動啟動swarm容器。

本文的測試環境包括一台swarm-master(由docker-machine創建,沒有replica支持),一台swarm-replica(由docker-machine創建的slave node,手動啟動manage容器支持replica)和一台swarm-node-00(slave node)

從log中我們可以看到當前這台機器經過選舉成為集群主master(原master未支持replica,所以新創建的swarm-replica在選舉中得選)。

接下來我們進入到swarm-master中,停止原manager容器,手動啟動支持replica的manager容器

從log中我們可以看到當前這台機器在選舉中並未當選,成為備用master。

通過curl命令看一下etcd中鍵值/docker/swarm/leader也表明了192.168.99.104(swarm-replica為leader)

[root@registry swarm]# curl -k -X GET http://10.236.14.20:4001/v2/keys/docker/swarm/leader

{「action」:」get」,」node」:{「key」:」/docker/swarm/leader」,」value」:」192.168.99.104:3376″,」expiration」:」2015-08-19T07:24:16.252098457Z」,」ttl」:19,」modifiedIndex」:9200,」createdIndex」:8981}}

得到leadership的master主機會定期重置ttl佔有leadship,備用主機監控此鍵值變化並定期參與競選,若當選主機服務中斷,鍵值超時則備用主機被選中作為新的leader實現服務的高可用性。

到此為止,一套高可用的Docker Swarm集群的工作原理就分析完成了。從Swarm的Roadmap中可以看到接下來Swarm會繼續優化其調度系統,支持包括容器重新調度(應對Slave節點服務中斷,將運行在其上的容器調度到其他可用的節點上)以及全局部署(即在每個節點上部署選定容器,此應用場景包括在每個節點部署監控容器,log收集容器等)。Swarm還會在多個備選master節點中共享狀態信息,目前每台master節點保存的容器信息相對獨立,在master切換的時候會出現狀態不匹配的問題。目前Swarm API與Docker API的匹配度是75%,在接下來會盡量做到最大程度的匹配。Swarm會借鑒Docker libnetwork項目支持多主機間容器網路連通。Swarm還會與其他容器管理工具如Mesos以及Kubernetes集成去管理更大的集群。

Docker Swarm作為Docker在容器集群化道路上的嘗試已經初步取得的成果,但其目前還處於初級階段,不建議用於生產環境。隨著Swarm 項目的完善,在集群中部署Docker容器將會變得越來越簡單,使用者可以像在單一主機上運行Docker使用同樣的命令集,為Docker容器從單機化到集群化提供無縫遷移,真正解決了環境部署問題。

作者簡介:杜航,靈雀雲資深用戶,Websense雲基礎架構組開發經理,專註於Openstack和Docker。

轉載請註明來源。

Advertisements

你可能會喜歡