【Docker】Docker三劍客實踐之部署集羣

做者:不洗碗工做室 - Marklux
出處:marklux.cn/blog/55
版權歸做者全部,轉載請註明出處node

前言

DOCKER技術在推出後掀起了一陣容器化技術的熱潮,容器化使得服務的部署變得極其簡易,這爲微服務和分佈式計算提供了很大的便利。web

爲了把容器化技術的優勢發揮到極致,docker公司前後推出了三大技術:docker-machine,docker-compose,docker-swarm,能夠說是幾乎實現了容器化技術中全部可能須要的底層技術手段。算法

在使用go語言實現了判題引擎並打包好docker鏡像後,就須要進行分佈式判題的編寫,此次就讓咱們手動實踐,嘗試使用docker的三大殺器來部署一個多機器構成的判題服務集羣。docker

三劍客簡介

docker-machine

docker技術是基於Linux內核的cgroup技術實現的,那麼問題來了,在非Linux平臺上是否就不能使用docker技術了呢?答案是能夠的,不過顯然須要藉助虛擬機去模擬出Linux環境來。安全

docker-machine就是docker公司官方提出的,用於在各類平臺上快速建立具備docker服務的虛擬機的技術,甚至能夠經過指定driver來定製虛擬機的實現原理(通常是virtualbox)。bash

docker-compose

docker鏡像在建立以後,每每須要本身手動pull來獲取鏡像,而後執行run命令來運行。當服務須要用到多種容器,容器之間又產生了各類依賴和鏈接的時候,部署一個服務的手動操做是使人感到十分厭煩的。服務器

dcoker-compose技術,就是經過一個.yml配置文件,將全部的容器的部署方法、文件映射、容器鏈接等等一系列的配置寫在一個配置文件裏,最後只須要執行docker-compose up命令就會像執行腳本同樣的去一個個安裝容器並自動部署他們,極大的便利了複雜服務的部署。網絡

docker-swarm

swarm是基於docker平臺實現的集羣技術,他能夠經過幾條簡單的指令快速的建立一個docker集羣,接着在集羣的共享網絡上部署應用,最終實現分佈式的服務。架構

相比起zookeeper等集羣管理框架來講,swarm顯得十分輕量,做爲一個工具,它把節點的加入、管理、發現等複雜的操做都濃縮爲幾句簡單的命令,而且具備自動發現節點和調度的算法,還支持自定製。雖然swarm技術如今還不是很是成熟,但其威力已經可見通常。負載均衡

淺談docker服務架構和遠程API

在正式使用docker技術部署集羣應用時,咱們應該先來了解一下docker工做的一些底層原理,和docker遠程調用的API,這樣才能大致瞭解集羣到底是如何運做的。

daemon

以前的docker入門文章中講過,docker的基礎服務,好比容器的建立、查看、中止、鏡像的管理,其實都是由docker的守護進程(daemon)來實現的。

每次執行的docker指令其實都是經過向daemon發送請求來實現的。

daemon的運做(通訊模式)主要有兩種,一種是經過unix套接字(默認,但只能在本地訪問到,比較安全),一種是經過監聽tcp協議地址和端口來實現(這個能夠實如今遠程調用到docker服務)。

遠程API

除了經過遠程tcp協議訪問遠程主機上的docker服務外,docker還提供了一套基於HTTP的API,可使用curl來實現操做遠程主機上的docker服務,這爲開發基於WEB的docker服務提供了便利。

遠程docker使用示例

最終實現集羣的時候實際是使用docker的遠程調用來將不一樣的docker主機鏈接成一個總體的(經過tcp協議)。

咱們不妨先來手動模擬嘗試一下docker服務的遠程調用吧。

首先須要在提供服務的主機上將docker的運行方式改成tcp,具體方法爲修改/etc/default/docker中的DOCKER_OPTS爲以下內容

-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock複製代碼

-H 後的參數是本身定義的要綁定的tcp地址和端口,成功綁定後重啓docker服務就能夠在該端口訪問到docker的daemon服務。

不幸的是:

  • 在OSX平臺上,並無找到docker的daemon配置文件
  • 在OSX平臺上,使用docker -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock -d這樣的命令來嘗試以tcp的方式啓動docker daemon也是失敗的,並無任何做用
  • 目前推測除了Linux平臺上,其餘平臺上的配置方法都不太同樣,可是在網絡上暫時沒有找到解決方案,因此後面的操做我只能經過在本地建立多個docker-machine的方式來模擬實現遠程調用。

假設咱們在192.168.1.123這臺主機上開啓了docker服務,監聽了2375端口,那麼咱們就能夠在同一網段的其餘主機上(好比192.168.1.233)經過docker -H tcp://192.168.1.123:2345 <command>的方式調用到該主機上的docker服務。

好比

docker -H tcp://192.168.1.123:2345 ps
docker -H tcp://192.168.1.123:2345 images
docker -H tcp://192.168.1.123:2345 run ...複製代碼

最終swarm構建集羣的時候,就是經過這樣的遠程服務調用來調度各個節點的。

集羣和分佈式運算

在正式開始實踐集羣以前,咱們有必要了解究竟什麼是集羣,什麼是分佈式計算。

首先,這二者有一個共同點,就是他們都是使用了多個服務節點的,通俗的說,就是要用到多臺服務器協同工做(不必定是實體,也多是虛擬機)。

而二者的區別在於:

  • 集羣是多臺機器執行同一個業務,每次根據調度算法尋找最合適的節點來執行該業務
  • 分佈式計算是將一個業務拆分紅多個獨立的部分,由多臺機器共同協做完成

集羣的優勢在於,當業務的須要的資源比較大時,能夠避免由一個服務器去獨自承擔壓力,並且即使有一個節點宕機了,業務仍然能夠繼續正常運行。這有點相似於負載均衡。

分佈式的優勢則是在計算上,能夠協同多臺機器發揮計算的威力,進行須要超高性能的運算。

構建集羣

說如今咱們正式開始構建集羣。

使用docker-machine建立節點

因爲實體機器的缺少以及在osx上沒法正常開啓tcp的docker服務,咱們基於docker-machine來建立多個虛擬機,做爲集羣中的節點。

執行下面的命令就能夠建立一個新的docker-machine虛擬機manager1

docker-machine create --driver virtualbox manager1複製代碼

在建立了虛擬機後,可使用docker-machine env manager1來查看虛擬機manager1的相關信息,包括IP地址等

如今咱們繼續執行命令建立worker1worker2兩個節點,使用docker-machine ls命令能夠查看到全部正在工做的虛擬機:

docker-machine ls
NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
manager1   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.06.1-ce   
worker1    -        virtualbox   Running   tcp://192.168.99.101:2376           v17.06.1-ce   
worker2    -        virtualbox   Running   tcp://192.168.99.102:2376           v17.06.1-ce複製代碼

建立docker machine後,能夠經過docker-machine ssh manager1 <command>的方式來訪問虛擬機,執行指令。

建立swarm集羣

初始化一個swarm集羣的命令爲:

docker swarm init --listen-addr <MANAGER-IP>:<PORT> --advertise-addr <IP>複製代碼

--listen-addr參數是管理者節點的docker服務所在的IP:PORT,也就是說,能夠經過這個組合訪問到該節點的docker服務。

--advertise-addr是廣播地址,也就是其餘節點加入該swarm集羣時,須要訪問的IP

如今咱們在manager1節點裏建立swarm網絡,執行

docker-machine ssh manager1 docker swarm init --listen-addr 192.168.99.100:2377 --advertise-addr 192.168.99.100複製代碼

返回響應:

Swarm initialized: current node (23lkbq7uovqsg550qfzup59t6) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
    192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.複製代碼

這樣便建立了一個swarm集羣,而且manager1節點目前是以管理者的身份加入在節點中的。

如今咱們把worker1worker2兩個節點加入到swarm集羣中去,分別在兩個節點的虛擬機中執行docker swarm join --token ..便可:

docker-machine ssh worker1 docker swarm join --token \
    SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
    192.168.99.100:2377
This node joined a swarm as a worker.複製代碼
docker-machine ssh worker2 docker swarm join --token \
    SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
    192.168.99.100:2377
This node joined a swarm as a worker.複製代碼

在任何一個節點上執行docker node ls均可以查看到當前整個集羣中的全部節點:

docker-machine ssh manager1 docker node ls
NAME     ACTIVE    DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
manager1   -       virtualbox   Running   tcp://192.168.99.100:2376           v1.12.3   
worker1    -       virtualbox   Running   tcp://192.168.99.101:2376           v1.12.3   
worker2    -       virtualbox   Running   tcp://192.168.99.102:2376           v1.12.3複製代碼

建立跨主機網絡

集羣創建完畢以後咱們要作的就是在集羣上部署咱們的服務。可是首先應該讓全部的節點處在一個共享的網絡中,這樣當咱們把服務部署在這個共享網絡中,就至關於部署在整個集羣中了。

使用docker network ls能夠查看到當前主機所參與的全部網絡:

docker-machine ssh manager1 docker network ls
NETWORK ID         NAME            DRIVER          SCOPE
764ff31881e5        bridge          bridge          local                  
fbd9a977aa03        host            host            local               
6p6xlousvsy2        ingress         overlay         swarm            
e81af24d643d        none            null            local複製代碼

其中SCOPE爲swarm,DRIVER爲overlay的即爲集羣節點中的共享網絡。集羣創建後會有一個默認的ingress共享網絡,如今咱們來再建立一個:

docker-machine ssh manager1 docker network create --driver overlay swarm_test複製代碼

在跨主機網絡上部署服務

在集羣上部署應用,就是在共享網絡上部署服務(service)

但首先要保證每一個節點上都已經有所需的鏡像和環境了,這點即可以經過將同一份docker-compose配置文件共享到每一個主機上,使用docker-compose在每一個節點上下載鏡像和搭建環境的工做。

因爲judge_server的服務架構很簡單,就一個鏡像,因此我在這裏直接在每臺主機上把它pull下來就行了:

docker-machine ssh manager1 docker pull registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0
docker-machine ssh worker1 docker pull registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0
docker-machine ssh worker2 docker pull registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0複製代碼

接下來即是重頭戲,咱們使用manager1節點,在共享網絡上啓動咱們的服務

docker service create --replicas 3 --name judge_swarm -p 8090:8090 --network=swarm_test registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0複製代碼

這個命令看起來是否是很像docker run?沒錯,swarm最終的目的就是把操做集羣變得像操做單一的docker服務端同樣簡單!

--replicas 用於指定服務須要的節點數量,也就是集羣的規模,這個值是彈性的,你能夠在後續動態的更改它。

當服務中某個節點掛掉時,swarm將會搜尋集羣中剩餘的可用節點,頂替上去。也就是說,swarm會動態的調度,老是保持服務是由3個節點運行着的。

-p 用於暴露端口到宿主機,這樣咱們就能訪問到了。

--network用於指定部署service的網絡是哪個

如今在manager1節點中使用docker service ls來查看集羣中的服務:

docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                                       PORTS
kofcno637cmq        judge_swarm         replicated          3/3                 registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0   *:8090->8090/tcp複製代碼

如今咱們嘗試在本地訪問192.168.99.100:8090/ping,就能夠獲得響應了,事實上,如今不管將ip換爲worker1或者worker2的,響應的結果都是同樣,由於此時全部節點已經處在一個共同的集羣網絡下了

通過大量的訪問測試,能夠看到hostname是在變化着的,這說明每次請求,都由swarm動態的調度,選擇了不一樣的節點來進行處理。

遺留問題

至此集羣的部署已經完成,可是咱們還遺留了幾個問題沒有解決:

  • 集羣節點的動態添加刪除不是很方便,這致使在web端管理判題服務機有必定的難度,固然能夠經過docker的REMOTE API來實現,不過複雜度比較高
  • 集羣節點間的文件同步不太好實現,可能須要本身寫腳本同步或是使用rsync之類的服務來實現
  • swarm很是適合快速構建大量集羣來實現業務的處理,不過對於只有幾臺機器的狀況而言,有些"殺雞用牛刀"的感受
相關文章
相關標籤/搜索