DockerSwarm 集羣環境搭建

文章首發於公衆號《程序員果果》html

地址:mp.weixin.qq.com/s/RSNL-V4jL…node

1、簡介

1. 什麼是docker swarm?

Swarm 在 Docker 1.12 版本以前屬於一個獨立的項目,在 Docker 1.12 版本發佈以後,該項目合併到了 Docker 中,成爲 Docker 的一個子命令。目前,Swarm 是 Docker 社區提供的惟一一個原生支持 Docker 集羣管理的工具。它能夠把多個 Docker 主機組成的系統轉換爲單一的虛擬 Docker 主機,使得容器能夠組成跨主機的子網網絡。nginx

Docker Swarm 是一個爲 IT 運維團隊提供集羣和調度能力的編排工具。用戶能夠把集羣中全部 Docker Engine 整合進一個「虛擬 Engine」的資源池,經過執行命令與單一的主 Swarm 進行溝通,而沒必要分別和每一個 Docker Engine 溝通。在靈活的調度策略下,IT 團隊能夠更好地管理可用的主機資源,保證應用容器的高效運行。程序員

Swarm的基本架構以下圖所示:web

2. Docker Swarm 優勢

任何規模都有高性能表現 對於企業級的 Docker Engine 集羣和容器調度而言,可拓展性是關鍵。任何規模的公司——不管是擁有五個仍是上千個服務器——都能在其環境下有效使用 Swarm。 通過測試,Swarm 可拓展性的極限是在 1000 個節點上運行 50000 個部署容器,每一個容器的啓動時間爲亞秒級,同時性能無減損。算法

靈活的容器調度docker

Swarm 幫助 IT 運維團隊在有限條件下將性能表現和資源利用最優化。Swarm 的內置調度器(scheduler)支持多種過濾器,包括:節點標籤,親和性和多種容器部策略如 binpack、spread、random 等等。json

服務的持續可用性安全

Docker Swarm 由 Swarm Manager 提供高可用性,經過建立多個 Swarm master 節點和制定主 master 節點宕機時的備選策略。若是一個 master 節點宕機,那麼一個 slave 節點就會被升格爲 master 節點,直到原來的 master 節點恢復正常。 此外,若是某個節點沒法加入集羣,Swarm 會繼續嘗試加入,並提供錯誤警報和日誌。在節點出錯時,Swarm 如今能夠嘗試把容器從新調度到正常的節點上去。bash

和 Docker API 及整合支持的兼容性

Swarm 對 Docker API 徹底支持,這意味着它能爲使用不一樣 Docker 工具(如 Docker CLI,Compose,Trusted Registry,Hub 和 UCP)的用戶提供無縫銜接的使用體驗。

Docker Swarm 爲 Docker 化應用的核心功能(諸如多主機網絡和存儲卷管理)提供原生支持

開發的 Compose 文件能(經過 docker-compose up )輕易地部署到測試服務器或 Swarm 集羣上。Docker Swarm 還能夠從 Docker Trusted Registry 或 Hub 裏 pull 並 run 鏡像。

2、相關概念

1. 節點

有兩種類型的節點: managersworkers.

管理節點(managers)

管理節點用於 Swarm 集羣的管理,docker swarm 命令基本只能在管理節點執行(節點退出集羣命令 docker swarm leave 能夠在工做節點執行)。一個 Swarm 集羣能夠有多個管理節點,但只有一個管理節點能夠成爲 leader,leader 經過 raft 協議實現。

爲了利用swarm模式的容錯功能,Docker建議您根據組織的高可用性要求實現奇數個節點。當您擁有多個管理器時,您能夠從管理器節點的故障中恢復而無需停機。

  • N個管理節點的集羣容忍最多損失 (N-1)/2 個管理節點。
  • Docker建議一個集羣最多7個管理器節點。

重要說明:添加更多管理節點並不意味着可擴展性更高或性能更高。通常而言,狀況正好相反。

工做節點(workers)

工做節點是任務執行節點,管理節點將服務 (service) 下發至工做節點執行。管理節點默認也做爲工做節點。你也能夠經過配置讓服務只運行在管理節點。下圖展現了集羣中管理節點與工做節點的關係。

2. 服務和任務

任務 (Task)是 Swarm 中的最小的調度單位,目前來講就是一個單一的容器。 服務 (Services) 是指一組任務的集合,服務定義了任務的屬性。服務有兩種模式:

  • replicated services (複製服務)按照必定規則在各個工做節點上運行指定個數的任務。
  • global services (全局服務)每一個工做節點上運行一個任務。

兩種模式經過 docker service create 的 --mode 參數指定。下圖展現了容器、任務、服務的關係。

3、Swarm 集羣

準備工做

  • 三個能夠經過網絡進行通訊的Linux主機或虛擬機,並安裝了Docker,或者使用docker-machine 建立三臺虛擬機。
  • 已安裝Docker Engine 1.12或更高版本
  • 在主機之間打開端口(237七、794六、4789)

建立一個集羣

1. 建立虛擬機(已經有Linux主機或虛擬機的跳過此步)

本文經過docker-machine使用VirtualBox驅動程序建立3個VM (已經有Linux主機或虛擬機的跳過此步):

docker-machine create --driver virtualbox myvm-1
docker-machine create --driver virtualbox myvm-2
docker-machine create --driver virtualbox myvm-3
複製代碼

列出虛擬機並獲取其IP地址:

docker-machine ls
複製代碼

如下是此命令的示例輸出:

$docker-machine ls
NAME     ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER           ERRORS
myvm-1   -        virtualbox   Running   tcp://192.168.99.100:2376           v18.09.1-beta2   
myvm-2   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.09.1-beta2   
myvm-3   -        virtualbox   Running   tcp://192.168.99.102:2376           v18.09.1-beta2  
複製代碼

2. 初始化swarm

把第一臺機器myvm-1充當管理節點,第二臺myvm-2 、第三臺myvm-3爲工做節點。

使用 docker-machine ssh 鏈接 myvm-1,Linux主機直接ssh鏈接就行。

docker-machine ssh myvm-1 
複製代碼

初始化swarm

docker swarm init --advertise-addr 192.168.99.100
Swarm initialized: current node (4a8mo8cekpe0vpk0ze963avw9) is now a manager.

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

    docker swarm join --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u 192.168.99.100:2377

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

上面輸出的這一段就是工做節點加入集羣的命令:

docker swarm join --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u 192.168.99.100:2377
複製代碼

若是你的 Docker 主機有多個網卡,擁有多個 IP,必須使用 --advertise-addr 指定 IP。
執行 docker swarm init 命令的節點自動成爲管理節點。

命令 docker info 能夠查看 swarm 集羣狀態:

Server Version: 18.09.1-beta2
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: active
 NodeID: ib1498ex2q18i7gznb2zgicqq
 Is Manager: true
 ClusterID: fbyxxjzrtcxc53op35jnyzl7t
 Managers: 3
 Nodes: 3
 Default Address Pool: 10.0.0.0/8  
複製代碼

命令 docker node ls 能夠查看集羣節點信息:

$docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ib1498ex2q18i7gznb2zgicqq *   myvm-1              Ready               Active              Leader              18.09.1-beta2
複製代碼

3. 工做節點加入 swarm 集羣

鏈接機器myvm-2

docker-machine ssh myvm-2
複製代碼

加入 swarm 集羣

$docker swarm join \
    --token SWMTKN-1-4lzr2216s61ecbyayyqynjwybmxy5y5th5ru8aal2a0d1t2vn3-ekdgf4swlz8fiq4nnzgnbhr5u \
    192.168.99.100:2377

This node joined a swarm as a worker.
複製代碼

節點myvm-3,執行myvm-2相同的操做加入集羣。

集羣的大部分命令須要在管理節點中才能運行

咱們進入管理節點 myvm-1 ,查看集羣的節點信息。

docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ib1498ex2q18i7gznb2zgicqq *   myvm-1              Ready               Active              Leader              18.09.1-beta2
vels0fe3eh5s5cxj1s573v9wx     myvm-2              Ready               Active                                  18.09.1-beta2
obxnnqelh4p16wajrwvyn6j8v     myvm-3              Ready               Active                                  18.09.1-beta2
複製代碼

爲了高可用,咱們升級工做節點爲管理節點。

docker node promote myvm-2
docker node promote myvm-3
複製代碼

這時咱們再看集羣的節點信息

$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ib1498ex2q18i7gznb2zgicqq *   myvm-1              Ready               Active              Leader              18.09.1-beta2
vels0fe3eh5s5cxj1s573v9wx     myvm-2              Ready               Active              Reachable           18.09.1-beta2
obxnnqelh4p16wajrwvyn6j8v     myvm-3              Ready               Active              Reachable           18.09.1-beta2
複製代碼

myvm-二、myvm-3的 集羣狀態變爲 Reachable(選舉者),由於集羣中節點Leader只能有一個,這個相似zookeeper,只不過zookeepers用的算法是paxos,Swarm用的算法是raft。

4. 退出 Swarm 集羣

若是 Manager 想要退出 Swarm 集羣, 在 Manager Node 上執行以下命令:

docker swarm leave
複製代碼

若是集羣中還存在其它的 Worker Node,還但願 Manager 退出集羣,則加上一個強制選項,命令行以下所示:

docker swarm leave --force
複製代碼

工做節點進行退出集羣,須要在工做節點上執行命令:

docker swarm leave
複製代碼

退出後的節點,依然可使用 上面的 docker swarm join --token 從新加入集羣。

集羣上部署應用

命令

$ docker service create --replicas 1 --name 別名  鏡像ID
複製代碼

replicas 指定運行服務的數量。

實例1

建立一個alpine服務(alpine是一個小型liunx系統)

#運行一個alpine鏡像,並執行ping命令
docker service create --replicas 1 --name test1 alpine ping docker.com
複製代碼

查看集羣上的服務

$docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
rnu10rprrwzv        test1               replicated          1/1                 alpine:latest
複製代碼

實例2

如下命令將nginx容器中的端口80發佈到羣集中任何節點的端口8080

docker service create \
  --name my-web \
  --publish published=8080,target=80 \
  --replicas 2 \
  nginx
複製代碼

查看集羣上的服務

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
q6wfiizzosmd        nginx               replicated          3/3                 nginx:latest        *:8080->80/tcp
rnu10rprrwzv        test1               replicated          1/1                 alpine:latest 
複製代碼

service 經過 ingress load balancing 來發布服務,且 swarm 集羣中全部 node 都參與到 ingress 路由網格(ingress routing mesh) 中,訪問任意一個 node+PublishedPort 便可訪問到服務。

當訪問任何節點上的端口8080時,Docker將您的請求路由到活動容器。在羣節點自己,端口8080可能並不實際綁定,但路由網格知道如何路由流量,並防止任何端口衝突的發生。

路由網格在發佈的端口上監聽分配給節點的任何IP地址。對於外部可路由的IP地址,該端口可從主機外部得到。對於全部其餘IP地址,只能從主機內部訪問。

因此訪問 192.169.99.100:8080、192.169.99.101:8080、192.169.99.102:8080 ,均可以訪問到nginx,這樣就實現了負載均衡。由於咱們指定--replicas 3 啓動了3個運行nginx的容器 ,因此三個節點myvm-一、myvm-二、myvm-3 上都運行了一個 nginx 的容器,能夠經過改其中一個節點上的nginx的歡迎頁 ,而後再訪問,來檢查是否實現了負載均衡。

能夠經過scale 來指定運行容器的數量。

docker service scale nginx=2
複製代碼

我經過docker service ls 能夠看出 nginx 的副本變成了2個

$docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
q6wfiizzosmd        nginx               replicated          2/2                 nginx:latest        *:8080->80/tcp
複製代碼

overlay 網絡

1. 概述

初始化swarm或將Docker主機加入現有swarm時,會在該Docker主機上建立兩個新網絡:

  • ingress:稱爲覆蓋網絡ingress,處理與羣集服務相關的控制和數據流量。建立羣組服務而且不將其鏈接到用戶定義的覆蓋網絡時,ingress 是默認鏈接的網絡。
  • docker_gwbridge:稱爲橋接網絡docker_gwbridge,它將各個Docker守護程序鏈接到參與該羣集的其餘守護進程。

在管理節點上查看網絡

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
cb0ccb89a988        bridge              bridge              local
0174fb113496        docker_gwbridge     bridge              local
541b62778c0e        host                host                local
8n7xppn5z4j2        ingress             overlay             swarm
369d459f340d        none                null                local
複製代碼

overlay網絡驅動程序會建立多個Docker守護主機之間的分佈式網絡。該網絡位於(覆蓋)特定於主機的網絡之上,容許鏈接到它的容器(包括羣集服務容器)安全地進行通訊。Docker透明地處理每一個數據包與正確的Docker守護程序主機和正確的目標容器的路由。

2. 自定義 overlay 網絡

建立用於swarm服務的overlay網絡,使用以下命令:

docker network create -d overlay my-overlay
複製代碼

咱們再次查看網絡,發現能夠看到自定義 overlay了。

$docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
cb0ccb89a988        bridge              bridge              local
0174fb113496        docker_gwbridge     bridge              local
541b62778c0e        host                host                local
8n7xppn5z4j2        ingress             overlay             swarm
a23htz7n0pvp        my-overlay          overlay             swarm
369d459f340d        none                null                local
複製代碼

集羣中部署了兩個服務 nginx、alpine,如今咱們進入alpine,去訪問nginx。

docker exec -it test1.1.oonwl8c5g4u3p17x8anifeubi bash
複製代碼
/ # ping nginx
ping: bad address 'nginx'
複製代碼
wget 192.168.99.100:8080
Connecting to 192.168.99.100:8080 (192.168.99.100:8080)
index.html           100% |*************************************************************************************************************|   612   0:00:00 ETA

複製代碼

咱們發現集羣中的各個服務不能用名稱訪問的,只能用集羣服務發現的路由網絡訪問,那麼集羣中的服務怎麼能經過名稱進行訪問呢,這就須要用到上面自定義的 overlay 網絡。

刪除咱們啓動的服務,從新建立指定使用自定義網絡的服務。

docker service rm nginx test1
複製代碼
docker service create --name nginx -p 8080:80 --network my-overlay --replicas 3 nginx
docker service create --name test1 --network my-overlay alpine ping www.baidu.com
複製代碼

進入test1容器中,從新測試下:

/ # ping nginx
PING nginx (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.120 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.094 ms
64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.108 ms
複製代碼
/ # wget nginx
Connecting to nginx (10.0.0.2:80)
index.html           100% |*************************************************************************************************************|   612   0:00:00 ETA
複製代碼

發現能夠經過名稱進行集羣中的容器間的訪問了。

歡迎掃碼或微信搜索公衆號《程序員果果》關注我,關注有驚喜~

相關文章
相關標籤/搜索