藉助dockerSwarm搭建叢集部署

lhrbest發表於2020-04-07



為了讓學習的知識融匯貫通,目前是把所有的叢集都放在了一個虛擬機器上,如果這個虛擬機器當機了怎麼辦?俗話說雞蛋不要都放在一個籃子裡面,把各種叢集的節點拆分部署,應該把各種節點分機器部署,多個宿主機,這樣部署隨便掛哪個主機我們都不擔心。
原始碼:


一起在說說docker swarm

swarm 是docker的三劍客一員,之前都說過了,可以看中級和高階啊 。

  1. docker machine 容器服務
  2. docker compose 指令碼服務
  3. docker swarm 容器叢集技術



  • 去中心化的設計

Swarm Manager 也承擔worker節點的作用。 
Swarm Worker 執行容器部署專案

Swarm是沒有中心節點的,掛到其中一個其他是不會掛掉的。Swarm Manager 如果master掛了,立馬選舉一個新的master。

  • 建立叢集環境

首先機器已經安裝了docker環境。

docker swarm init
  • 加入swarm叢集
#加入到manager中
docker swarm join-token manager
#加入到worker中
docker swarm join-token worker

環境搭建

應用 IP地址 服務 配置 安裝應用 安裝方式
docker-swarm-manager1 192.168.66.100 docker-swarm-manager1 單核 2g記憶體 docker-swarm-manager1 docker
docker-swarm-manager2 192.168.66.101 docker-swarm-manager2 單核 2g記憶體 docker-swarm-manager2 docker
docker-swarm-node1 192.168.66.102 docker-swarm-node1 單核 2g記憶體 docker-swarm-node1 docker
docker-swarm-node2 192.168.66.103 docker-swarm-node2 單核 2g記憶體 docker-swarm-node2 docker


docker swarm環境

一共4個節點,2個manager節點,2個work節點,manager不光是管理,而且也幹活,說白了一共4個幹活的節點。

建立docker swarm叢集

su -
#密碼vagrant
docker swarm init

報錯注意:如果你在新建叢集時遇到雙網路卡情況,可以指定使用哪個 IP,例如上面的例子會有可能遇到下面的錯誤。

Error response from daemon: could not choose an IP address to
 advertise since this system has multiple addresses on different
 interfaces (10.0.2.15 on enp0s3 and 192.168.66.100 on enp0s8) 
- specify one with --advertise-addr

再次建立docker swarm叢集192.168.66.100

docker swarm init --advertise-addr 192.168.66.100 --listen-addr 192.168.66.100:2377
docker swarm join-token manager


再次建立docker swarm叢集192.168.66.101 
當前節點以manager的身份加入swarm叢集

docker swarm join --token SWMTKN-1-4itumtscktomolcau8a8cte98erjn2420fy2oyj18ujuvxkkzx-9qutkvpzk87chtr4pv8770mcb 192.168.66.100:2377

再次建立docker swarm叢集192.168.66.102 
當前節點以worker的身份加入swarm叢集

docker swarm join --token SWMTKN-1-4itumtscktomolcau8a8cte98erjn2420fy2oyj18ujuvxkkzx-f2dlt8g3hg86gyc9x6esewtwl 192.168.66.100:2377

再次建立docker swarm叢集192.168.66.103 
當前節點以worker的身份加入swarm叢集

docker swarm join --token SWMTKN-1-4itumtscktomolcau8a8cte98erjn2420fy2oyj18ujuvxkkzx-f2dlt8g3hg86gyc9x6esewtwl 192.168.66.100:2377

檢視swarm叢集

只能在manager節點內執行 
leader掛掉後,reachable就可以管理叢集了。

docker node ls


檢視swarm叢集的網路

只能在manager節點內執行

docker network ls


建立容器間的共享網路

只能在manager節點內執行

docker network create -d overlay --attachable swarm_test
docker network ls

目前是4臺機器,如果想讓4臺機器內的容器可以進行共享,overlay的網路就可以了,只需要在建立容器的時候--net=swarm_test

建立5個pxc容器

  • 192.168.66.100

建立2個容器。之前也說過如何建立,最為重要的是共享網路一定要使用swarm的共享網路。

docker volume create v1
docker volume create backup1
#增加域名解析
echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null 
sudo curl -sSL | sh -s 
sudo systemctl restart docker
docker run -d -p 3306:3306  --net=swarm_test \
        --name=node1 \
        -e CLUSTER_NAME=PXC \
        -e MYSQL_ROOT_PASSWORD=a123456 \
        -e XTRABACKUP_PASSWORD=a123456 \
        -v v1:/var/lib/mysql \
        --privileged \
        -v backup1:/data \
        percona/percona-xtradb-cluster
docker ps
docker volume create v2
docker run -d -p 3307:3306  --net=swarm_test \
        --name=node2 \
        -e CLUSTER_NAME=PXC \
        -e MYSQL_ROOT_PASSWORD=a123456 \
        -e XTRABACKUP_PASSWORD=a123456 \
        -v v2:/var/lib/mysql \
        --privileged \
        -v backup1:/data \
        -e CLUSTER_JOIN=node1 \
        percona/percona-xtradb-cluster
docker ps
  • 192.168.66.101

建立1個容器。之前也說過如何建立,最為重要的是共享網路一定要使用swarm的共享網路。

docker volume create v3
docker volume create  backup3
docker run -d -p 3307:3306  --net=swarm_test \
        --name=node3 \
        -e CLUSTER_NAME=PXC \
        -e MYSQL_ROOT_PASSWORD=a123456 \
        -e XTRABACKUP_PASSWORD=a123456 \
        -v v3:/var/lib/mysql \
        --privileged \
        -v backup3:/data \
        -e CLUSTER_JOIN=node1 \
        percona/percona-xtradb-cluster
docker ps
  • 192.168.66.102

建立1個容器。之前也說過如何建立,最為重要的是共享網路一定要使用swarm的共享網路。

docker volume create v4
docker volume create  backup4
docker run -d -p 3307:3306  --net=swarm_test \
        --name=node4 \
        -e CLUSTER_NAME=PXC \
        -e MYSQL_ROOT_PASSWORD=a123456 \
        -e XTRABACKUP_PASSWORD=a123456 \
        -v v4:/var/lib/mysql \
        --privileged \
        -v backup4:/data \
        -e CLUSTER_JOIN=node1 \
        percona/percona-xtradb-cluster
docker ps
  • 192.168.66.103

建立1個容器。之前也說過如何建立,最為重要的是共享網路一定要使用swarm的共享網路。

docker volume create v4
docker volume create  backup4
docker run -d -p 3307:3306  --net=swarm_test \
        --name=node4 \
        -e CLUSTER_NAME=PXC \
        -e MYSQL_ROOT_PASSWORD=a123456 \
        -e XTRABACKUP_PASSWORD=a123456 \
        -v v4:/var/lib/mysql \
        --privileged \
        -v backup4:/data \
        -e CLUSTER_JOIN=node1 \
        percona/percona-xtradb-cluster
docker ps

容器叢集

在這個示意圖裡面,畫了4個linux的主機,都安裝了docker虛擬機器,假如我現在想安裝A程式,直接選擇Docker-1這個主機裡面的容器安裝A程式,這樣沒有問題。但是單節點單容器來部署,一旦這個節點掛掉的話,A程式就沒有,為了防止這樣我們有冗餘設計,直接在Docker-2這個主機裡面的容器也安裝A程式,這樣的話,Docker-1裡面的A程式掛了,Docker-2裡面的A程式也可以執行。這個功能有點像負載均衡,其實真的很像。docker swarm提供的東西跟負載均衡還是有區別的。swarm 只是提供了容器狀態的管理,如果Docker-1裡面的A程式掛了,發現本來二個,現在變成1個了危險,立馬在起一個吧。實時保證docker容器內的數量。



容器叢集適合的場景

容器叢集不適合有狀態程式,例如資料庫,快取等等


退出Swarm叢集

#Manager退出必須加--force
docker swarm leave --force

刪除節點

service docker stop
#Manager節點需要先降級
docker node demoted  <nodeID>
docker node rm <nodeID>
docker network

PS:這次主要說了3點比較重要的:透過docker-swarm的網路搭建容器化通訊網路,建立叢集的時候--net 加入docker-swarm建立的網路,方便通訊。不哪些適合做容器化叢集,資料庫和快取。如何操作docker-swarm中的節點。


Docker三劍客之Docker Swarm

 


一、什麼是Docker Swarm

  Swarm是Docker公司推出的用來管理docker叢集的平臺,幾乎全部用GO語言來完成的開發的,程式碼開源在 , 它是將一群Docker宿主機變成一個單一的虛擬主機,Swarm使用標準的Docker API介面作為其前端的訪問入口,換言之,各種形式的Docker

Client(compose,docker-py等)均可以直接與Swarm通訊,甚至Docker本身都可以很容易的與Swarm整合,這大大方便了使用者將原本基於單節點的系統移植到Swarm上,同時Swarm內建了對Docker網路外掛的支援,使用者也很容易的部署跨主機的容器叢集服務。

  Docker Swarm 和 Docker Compose 一樣,都是 Docker 官方容器編排專案,但不同的是,Docker Compose 是一個在單個伺服器或主機上建立多個容器的工具,而 Docker Swarm 則可以在多個伺服器或主機上建立容器叢集服務,對於微服務的部署,顯然 Docker Swarm 會更加適合。

從 Docker 1.12.0 版本開始,Docker Swarm 已經包含在 Docker 引擎中(docker swarm),並且已經內建了服務發現工具,我們就不需要像之前一樣,再配置 Etcd 或者 Consul 來進行服務發現配置了。

  Swarm deamon只是一個排程器(Scheduler)加路由器(router),Swarm自己不執行容器,它只是接受Docker客戶端發來的請求,排程適合的節點來執行容器,這就意味著,即使Swarm由於某些原因掛掉了,叢集中的節點也會照常執行,放Swarm重新恢復執行之後,他會收集重建叢集資訊。

二、Docker Swarm 基本結構圖

在結構圖可以看出 Docker Client使用Swarm對 叢集(Cluster)進行排程使用。

上圖可以看出,Swarm是典型的master-slave結構,透過發現服務來選舉manager。manager是中心管理節點,各個node上執行agent接受manager的統一管理,叢集會自動透過Raft協議分散式選舉出manager節點,無需額外的發現服務支援,避免了單點的瓶頸問題,同時也內建了DNS的負載均衡和對外部負載均衡機制的整合支援

三.Swarm的幾個關鍵概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1.Swarm
叢集的管理和編排是使用嵌入docker引擎的SwarmKit,可以在docker初始化時啟動swarm模式或者加入已存在的swarm
 
2.Node
一個節點是docker引擎叢集的一個例項。您還可以將其視為Docker節點。您可以在單個物理計算機或雲伺服器上執行一個或多個節點,但生產群集部署通常包括分佈在多個物理和雲端計算機上的Docker節點。
要將應用程式部署到swarm,請將服務定義提交給 管理器節點。管理器節點將稱為任務的工作單元分派 給工作節點。
Manager節點還執行維護所需群集狀態所需的編排和叢集管理功能。Manager節點選擇單個領導者來執行編排任務。
工作節點接收並執行從管理器節點分派的任務。預設情況下,管理器節點還將服務作為工作節點執行,但您可以將它們配置為僅執行管理器任務並且是僅管理器節點。代理程式在每個工作程式節點上執行,並報告分配給它的任務。工作節點向管理器節點通知其分配的任務的當前狀態,以便管理器可以維持每個工作者的期望狀態。
 
3.Service
一個服務是任務的定義,管理機或工作節點上執行。它是群體系統的中心結構,是使用者與群體互動的主要根源。建立服務時,你需要指定要使用的容器映象。
 
4.Task
任務是在docekr容器中執行的命令,Manager節點根據指定數量的任務副本分配任務給worker節點
 
------------------------------------------使用方法-------------------------------------
docker swarm:叢集管理,子命令有init,  join , leave, update。(docker swarm --help檢視幫助)
docker service:服務建立,子命令有create, inspect, update, remove, tasks。(docker service--help檢視幫助)
docker node:節點管理,子命令有accept, promote, demote, inspect, update, tasks,  ls rm 。(docker node --help檢視幫助)
   
node是加入到swarm叢集中的一個docker引擎實體,可以在一臺物理機上執行多個node,node分為:
manager nodes,也就是管理節點
worker nodes,也就是工作節點
 
1)manager node管理節點:執行叢集的管理功能,維護叢集的狀態,選舉一個leader節點去執行排程任務。
2)worker node工作節點:接收和執行任務。參與容器叢集負載排程,僅用於承載task。
3)service服務:一個服務是工作節點上執行任務的定義。建立一個服務,指定了容器所使用的映象和容器執行的命令。
    service是執行在worker nodes上的task的描述,service的描述包括使用哪個docker 映象,以及在使用該映象的容器中執行什麼命令。
4)task任務:一個任務包含了一個容器及其執行的命令。task是service的執行實體,task啟動docker容器並在容器中執行任務。

四、Swarm的工作模式

1. Node

2. Service

3. 任務與排程

4. 服務副本與全域性服務

 

五、Swarm的排程策略

1
2
3
4
5
6
7
8
9
10
11
12
Swarm在排程(scheduler)節點(leader節點)執行容器的時候,會根據指定的策略來計算最適合執行容器的節點,目前支援的策略有:spread, binpack, random.
1)Random
顧名思義,就是隨機選擇一個Node來執行容器,一般用作除錯用,spread和binpack策略會根據各個節點的可用的CPU, RAM以及正在運
行的容器的數量來計算應該執行容器的節點。
  
2)Spread
在同等條件下,Spread策略會選擇執行容器最少的那臺節點來執行新的容器,binpack策略會選擇執行容器最集中的那臺機器來執行新的節點。
使用Spread策略會使得容器會均衡的分佈在叢集中的各個節點上執行,一旦一個節點掛掉了只會損失少部分的容器。
  
3)Binpack
Binpack策略最大化的避免容器碎片化,就是說binpack策略儘可能的把還未使用的節點留給需要更大空間的容器執行,儘可能的把容器執行在
一個節點上面。

六、Swarm Cluster模式特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1)批次建立服務
建立容器之前先建立一個overlay的網路,用來保證在不同主機上的容器網路互通的網路模式
   
2)強大的叢集的容錯性
當容器副本中的其中某一個或某幾個節點當機後,cluster會根據自己的服務註冊發現機制,以及之前設定的值--replicas n,
在叢集中剩餘的空閒節點上,重新拉起容器副本。整個副本遷移的過程無需人工干預,遷移後原本的叢集的load balance依舊好使!
不難看出,docker service其實不僅僅是批次啟動服務這麼簡單,而是在叢集中定義了一種狀態。Cluster會持續檢測服務的健康狀態
並維護叢集的高可用性。
   
3)服務節點的可擴充套件性
Swarm Cluster不光只是提供了優秀的高可用性,同時也提供了節點彈性擴充套件或縮減的功能。當容器組想動態擴充套件時,只需透過scale
引數即可複製出新的副本出來。
   
仔細觀察的話,可以發現所有擴充套件出來的容器副本都run在原先的節點下面,如果有需求想在每臺節點上都run一個相同的副本,方法
其實很簡單,只需要在命令中將 "--replicas n" 更換成 "--mode=global" 即可!
  
複製服務(--replicas n)
將一系列複製任務分發至各節點當中,具體取決於您所需要的設定狀態,例如“--replicas 3”。
  
全域性服務(--mode=global)
適用於叢集內全部可用節點上的服務任務,例如“--mode global”。如果大家在 Swarm 叢集中設有 7 臺 Docker 節點,則全部節點之上都將存在對應容器。
   
4. 排程機制
所謂的排程其主要功能是cluster的server端去選擇在哪個伺服器節點上建立並啟動一個容器例項的動作。它是由一個裝箱演算法和過濾器
組合而成。每次透過過濾器(constraint)啟動容器的時候,swarm cluster 都會呼叫排程機制篩選出匹配約束條件的伺服器,並在這上面執行容器。
   
------------------Swarm cluster的建立過程包含以下三個步驟----------------------
1)發現Docker叢集中的各個節點,收集節點狀態、角色資訊,並監視節點狀態的變化
2)初始化內部排程(scheduler)模組
3)建立並啟動API監聽服務模組
   
一旦建立好這個cluster,就可以用命令docker service批次對叢集內的容器進行操作,非常方便!
   
在啟動容器後,docker 會根據當前每個swarm節點的負載判斷,在負載最優的節點執行這個task任務,用 "docker service ls"  "docker service ps + taskID"
可以看到任務執行在哪個節點上。容器啟動後,有時需要等待一段時間才能完成容器建立。

七、Dcoker Swarm 叢集部署

溫馨提示:

機器環境(三臺機器,centos系統)

IP:192.168.31.43 主機名:manager43 擔任角色:swarm manager

IP:192.168.31.188 主機名:node188 擔任角色:swarm node

IP:192.168.31.139 主機名:node139 擔任角色:swarm node

1、準備工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1) 修改主機名
# 192.168.31.43  主機上執行
[root@manager43 ~] # hostnamectl set-hostname manager43
 
# 192.168.31.188 主機上執行
[root@node188 ~] # hostnamectl set-hostname node188
 
# 192.168.31.139 主機上執行
[root@node139 ~] # hostnamectl set-hostname node139
 
2)配置hosts檔案(可配置可不配置)
[root@manager43 ~] # cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
 
192.168.31.43 manager43
192.168.31.188 node188
192.168.31.139 node139
 
# 使用scp複製到node主機
[root@manager43 ~] # scp /etc/hosts root@192.168.31.188:/etc/hosts
[root@manager43 ~] # scp /etc/hosts root@192.168.31.139:/etc/hosts
 
3) 設定防火牆
關閉三臺機器上的防火牆。如果開啟防火牆,則需要在所有節點的防火牆上依次放行2377 /tcp (管理埠)、7946 /udp (節點間通訊埠)、4789 /udp (overlay 網路埠)埠。
[root@manager43 ~] # systemctl disable firewalld.service
[root@manager43 ~] # systemctl stop firewalld.service
 
4) 安裝docker並配置加速器(在三臺主機都要安裝喲...)
[root@manager43 ~] # yum -y install docker
[root@node188 ~] # yum -y install docker
[root@node139 ~] # yum -y install docker

也可以安裝最新版docker,可查考: docker安裝教程

加速器配置,可查考: docker加速器配置教程

2、建立Swarm並新增節點

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
1) 建立Swarm叢集
[root@manager43 ~] # docker swarm init --advertise-addr 192.168.31.43
Swarm initialized: current node (z2n633mty5py7u9wyl423qnq0) is now a manager.
 
To add a worker to this swarm, run the following  command :
 
     # 這就是新增節點的方式(要儲存初始化後token,因為在節點加入時要使用token作為通訊的金鑰)
     docker swarm  join  --token SWMTKN-1-2lefzq18zohy9yr1vskutf1sfb2a590xz9d0mjj2m15zu9eprw-2938j5f50t35ycut0vbj2sx0s 192.168.31.43:2377  
 
To add a manager to this swarm, run  'docker swarm join-token manager'  and follow the instructions.
 
上面命令執行後,該機器自動加入到swarm叢集。這個會建立一個叢集token,獲取全球唯一的 token,作為叢集唯一標識。後續將其他節點加入叢集都會用到這個token值。
其中,--advertise-addr參數列示其它swarm中的worker節點使用此ip地址與manager聯絡。命令的輸出包含了其它節點如何加入叢集的命令。
 
這裡無意中遇到了一個小小的問題:
# 在次執行上面的命令,回報下面的錯誤
[root@manager43 ~] # docker swarm init --advertise-addr 192.168.31.43
Error response from daemon: This node is already part of a swarm. Use  "docker swarm leave"  to leave this swarm and  join  another one.
# 解決方法
[root@manager43 ~] # docker swarm leave -f
這裡的leave就是在叢集中刪除節點,-f引數強制刪除,執行完在重新執行OK
 
2) 檢視叢集的相關資訊
[root@manager43 ~] # docker info
上面的命令執行後 找到Swarm的關鍵字,就可以看到相關資訊了
 
[root@manager43 ~] # docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
3jcmnzjh0e99ipgshk1ykuovd *   manager43           Ready               Active              Leader              18.06.0-ce
上面的命令是檢視叢集中的機器(注意上面node ID旁邊那個*號表示現在連線到這個節點上)
 
3) 新增節點主機到Swarm叢集
上面我們在建立Swarm叢集的時候就已經給出了新增節點的方法
 
# 192.168.31.188 主機上執行
[root@node188 ~] # docker swarm join --token SWMTKN-1-2lefzq18zohy9yr1vskutf1sfb2a590xz9d0mjj2m15zu9eprw-2938j5f50t35ycut0vbj2sx0s 192.168.31.43:2377
This node joined a swarm as a worker.
 
# 192.168.31.139 主機上執行
[root@node139 ~] # docker swarm join --token SWMTKN-1-2lefzq18zohy9yr1vskutf1sfb2a590xz9d0mjj2m15zu9eprw-2938j5f50t35ycut0vbj2sx0s 192.168.31.43:2377
This node joined a swarm as a worker.
 
如果想要將其他更多的節點新增到這個swarm叢集中,新增方法如上一致
 
在manager43主機上我們可以看一下叢集中的機器及狀態
[root@manager43 ~] # docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
3jcmnzjh0e99ipgshk1ykuovd *   manager43           Ready               Active              Leader              18.06.0-ce
vww7ue2xprzg46bjx7afo4h04     node139             Ready               Active                                  18.06.1-ce
c5klw5ns4adcvumzgiv66xpyj     node188             Ready               Active                                  18.06.1-ce
 
--------------------------------------------------------------------------------------------------------------------
溫馨提示:更改節點的availablity狀態
swarm叢集中node的availability狀態可以為 active或者drain,其中:
active狀態下,node可以接受來自manager節點的任務分派;
drain狀態下,node節點會結束task,且不再接受來自manager節點的任務分派(也就是下線節點)
[root@manager43 ~] # docker node update --availability drain node139               # 將node139節點下線。如果要刪除node139節點,命令是"docker node rm --force node139"
node139
[root@manager43 ~] # docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
3jcmnzjh0e99ipgshk1ykuovd *   manager43           Ready               Active              Leader              18.06.0-ce
vww7ue2xprzg46bjx7afo4h04     node139             Ready               Drain                                   18.06.1-ce
c5klw5ns4adcvumzgiv66xpyj     node188             Ready               Active                                  18.06.1-ce
 
如上,當node1的狀態改為drain後,那麼該節點就不會接受task任務分發,就算之前已經接受的任務也會轉移到別的節點上。
再次修改為active狀態(及將下線的節點再次上線)
[root@manager43 ~] # docker node update --availability active node139
node139
[root@manager43 ~] # docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
3jcmnzjh0e99ipgshk1ykuovd *   manager43           Ready               Active              Leader              18.06.0-ce
vww7ue2xprzg46bjx7afo4h04     node139             Ready               Active                                  18.06.1-ce
c5klw5ns4adcvumzgiv66xpyj     node188             Ready               Active                                  18.06.1-ce

3、在Swarm中部署服務(nginx為例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
Docker 1.12版本提供服務的Scaling、health check、滾動升級等功能,並提供了內建的dns、vip機制,實現service的服務發現和負載均衡能力
1) 建立網路在部署服務
# 建立網路
[root@manager43 ~] # docker network create -d overlay nginx_net
a52jy33asc5o0ts0rq823bf0m
[root@manager43 ~] # docker network ls | grep nginx_net
a52jy33asc5o        nginx_net           overlay             swarm
 
# 部署服務
[root@manager43 ~] # docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 nginx    # 就建立了一個具有一個副本(--replicas 1 )的nginx服務,使用映象nginx
olexfmtdf94sxyeetkchwhehg
overall progress: 1 out of 1 tasks
1 /1 : running   [==================================================>]
verify: Service converged
在manager-node節點上使用上面這個覆蓋網路建立nginx服務:
其中,--replicas 引數指定服務由幾個例項組成。
注意:不需要提前在節點上下載nginx映象,這個命令執行後會自動下載這個容器映象(比如此處建立tomcat容器,就將下面命令中的映象改為tomcat映象)。
 
# 使用 docker service ls 檢視正在執行服務的列表
[root@manager43 ~] # docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
olexfmtdf94s        my_nginx            replicated          1 /1                  nginx:latest        *:80->80 /tcp
 
2) 查詢Swarm中服務的資訊
-pretty 使命令輸出格式化為可讀的格式,不加 --pretty 可以輸出更詳細的資訊:
[root@manager43 ~] # docker service inspect --pretty my_nginx
ID:             zs7fw4ereo5w7ohd4n9ii06nt
Name:           my_nginx
Service Mode:   Replicated
  Replicas:      1
Placement:
UpdateConfig:
  Parallelism:   1
  On failure:    pause
  Monitoring Period: 5s
  Max failure ratio: 0
  Update order:      stop-first
RollbackConfig:
  Parallelism:   1
  On failure:    pause
  Monitoring Period: 5s
  Max failure ratio: 0
  Rollback order:    stop-first
ContainerSpec:
  Image:         nginx:latest@sha256:b73f527d86e3461fd652f62cf47e7b375196063bbbd503e853af5be16597cb2e
  Init:           false
Resources:
Networks: nginx_net
Endpoint Mode:  vip
Ports:
  PublishedPort = 80
   Protocol = tcp
   TargetPort = 80
   PublishMode = ingress
 
# 查詢到哪個節點正在執行該服務。如下該容器被排程到manager-node節點上啟動了,然後訪問http://192.168.31.43即可訪問這個容器應用(如果排程到其他節點,訪問也是如此)
[root@manager43 ~] # docker service ps my_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE               ERROR               PORTS
yzonph0zu7km        my_nginx.1          nginx:latest        manager43           Running             Running about an hour ago                      
溫馨提示:如果上面命令執行後,上面的 STATE 欄位中剛開始的服務狀態為 Preparing,需要等一會才能變為 Running 狀態,其中最費時間的應該是下載映象的過程
 
有上面命令可知,該服務在manager-node節點上執行。登陸該節點,可以檢視到nginx容器在執行中
[root@manager43 ~] # docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
0dc7103f8030        nginx:latest         "nginx -g 'daemon of…"    About an hour ago   Up About an hour    80 /tcp               my_nginx.1.yzonph0zu7km0211uj0ro5brj
 
3) 在Swarm中動態擴充套件服務(scale)
當然,如果只是透過service啟動容器,swarm也算不上什麼新鮮東西了。Service還提供了複製(類似kubernetes裡的副本)功能。可以透過 docker service scale 命令來設定服務中容器的副本數
比如將上面的my_nginx容器動態擴充套件到4個
[root@manager43 ~] # docker service scale my_nginx=4
my_nginx scaled to 4
overall progress: 4 out of 4 tasks
1 /4 : running   [==================================================>]
2 /4 : running   [==================================================>]
3 /4 : running   [==================================================>]
4 /4 : running   [==================================================>]
verify: Service converged
 
和建立服務一樣,增加scale數之後,將會建立新的容器,這些新啟動的容器也會經歷從準備到執行的過程,過一分鐘左右,服務應該就會啟動完成,這時候可以再來看一下 nginx 服務中的容器
[root@manager43 ~] # docker service ps my_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE               ERROR               PORTS
yzonph0zu7km        my_nginx.1          nginx:latest        manager43           Running             Running about an hour ago                      
mlprstt9ds5x        my_nginx.2          nginx:latest        node139             Running             Running 52 seconds ago                         
y09lk90tdzdp        my_nginx.3          nginx:latest        node139             Running             Running 52 seconds ago                         
clolfl3zlvj0        my_nginx.4          nginx:latest        node188             Running             Running 2 minutes ago  
 
可以看到,之前my_nginx容器只在manager-node節點上有一個例項,而現在又增加了3個例項。
這4個副本的my_nginx容器分別執行在這三個節點上,登陸這三個節點,就會發現已經存在執行著的my_nginx容器
 
 
4) 模擬當機node節點
特別需要清楚的一點:
如果一個節點當機了(即該節點就會從swarm叢集中被踢出),則Docker應該會將在該節點執行的容器,排程到其他節點,以滿足指定數量的副本保持執行狀態。
    
比如:
將node139當機後或將node139的docker服務關閉,那麼它上面的task例項就會轉移到別的節點上。當node139節點恢復後,它轉移出去的task例項不會主動轉移回來,
只能等別的節點出現故障後轉移task例項到它的上面。使用命令 "docker node ls" ,發現node139節點已不在swarm叢集中了(狀態為:Down)。
[root@node139 ~] # systemctl stop docker
[root@manager43 ~] # docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
ppk7q0bjond8a58xja7in1qid *   manager43           Ready               Active              Leader              18.06.0-ce
mums8azgbrffnecp3q8fz70pl     node139             Down                Active                                  18.06.1-ce
z3n36maf03yjg7odghikuv574     node188             Ready               Active                                  18.06.1-ce
    
然後過一會查詢服務的狀態列表
[root@manager43 ~] # docker service ps my_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
yzonph0zu7km        my_nginx.1          nginx:latest        manager43           Running             Running about an hour ago                       
wb1cpk9k22rl        my_nginx.2          nginx:latest        node188             Running             Running about a minute ago                      
mlprstt9ds5x         \_ my_nginx.2      nginx:latest        node139             Shutdown            Running 4 minutes ago                           
rhbj4bcr4t2c        my_nginx.3          nginx:latest        manager43           Running             Running about a minute ago                      
y09lk90tdzdp         \_ my_nginx.3      nginx:latest        node139             Shutdown            Running 4 minutes ago                           
clolfl3zlvj0        my_nginx.4          nginx:latest        node188             Running             Running 6 minutes ago
 
上面我們可以發現node139故障後,它上面之前的兩個task任務已經轉移到node188和manager43節點上了
 
登陸到node188和manager43節點上,可以看到這兩個執行的task任務。當訪問192.168.31.188和192.168.31.43節點的80埠,swarm的負載均衡會把請求路由到一個任意節點的可用的容器上
[root@manager43 ~] # docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
ae4c5c2e6f3f        nginx:latest         "nginx -g 'daemon of…"    4 minutes ago       Up 4 minutes        80 /tcp               my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21
0dc7103f8030        nginx:latest         "nginx -g 'daemon of…"    About an hour ago   Up About an hour    80 /tcp               my_nginx.1.yzonph0zu7km0211uj0ro5brj
 
[root@node188 ~] # docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
a63ef253f7dd        nginx:latest         "nginx -g 'daemon of…"    3 minutes ago       Up 3 minutes        80 /tcp               my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5
74a1a1db81d4        nginx:latest         "nginx -g 'daemon of…"    8 minutes ago       Up 8 minutes        80 /tcp               my_nginx.4.clolfl3zlvj0ewmh85c2ljnza
 
再次在node188和manager43節點上將從node139上轉移過來的兩個task關閉
[root@manager43 ~] # docker stop my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21
my_nginx.3.rhbj4bcr4t2c3y2f8vyfmbi21
 
[root@node188 ~] # docker stop my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5
my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5
 
再次查詢服務的狀態列表,發現這兩個task又轉移到node139上了
[root@manager43 ~] # docker service ps my_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
yzonph0zu7km        my_nginx.1          nginx:latest        manager43           Running             Running 2 hours ago                          
j2q61f8jtzba        my_nginx.2          nginx:latest        node188             Running             Running 24 seconds ago                       
wb1cpk9k22rl         \_ my_nginx.2      nginx:latest        node188             Shutdown            Complete 29 seconds ago                      
mlprstt9ds5x         \_ my_nginx.2      nginx:latest        node139             Shutdown            Running 11 minutes ago                       
oz9wyjuldw1t        my_nginx.3          nginx:latest        manager43           Running             Running 40 seconds ago                       
rhbj4bcr4t2c         \_ my_nginx.3      nginx:latest        manager43           Shutdown            Complete 45 seconds ago                      
y09lk90tdzdp         \_ my_nginx.3      nginx:latest        node139             Shutdown            Running 11 minutes ago                       
clolfl3zlvj0        my_nginx.4          nginx:latest        node188             Running             Running 12 minutes ago    
結論:即在swarm cluster叢集中啟動的容器,在worker node節點上刪除或停用後,該容器會自動轉移到其他的worker node節點上
 
 
5) Swarm 動態縮容服務(scale)
同理,swarm還可以縮容,同樣是使用scale命令
如下,將my_nginx容器變為1個
[root@manager43 ~] # docker service scale my_nginx=1
my_nginx scaled to 1
overall progress: 1 out of 1 tasks
1 /1 :  
verify: Service converged
 
[root@manager43 ~] # docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
zs7fw4ereo5w        my_nginx            replicated          1 /1                  nginx:latest        *:80->80 /tcp
 
[root@manager43 ~] # docker service ps my_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
yzonph0zu7km        my_nginx.1          nginx:latest        manager43           Running             Running 11 hours ago                         
wb1cpk9k22rl        my_nginx.2          nginx:latest        node188             Shutdown            Complete 9 hours ago                         
mlprstt9ds5x         \_ my_nginx.2      nginx:latest        node139             Shutdown            Shutdown 29 seconds ago                      
rhbj4bcr4t2c        my_nginx.3          nginx:latest        manager43           Shutdown            Complete 9 hours ago                         
y09lk90tdzdp         \_ my_nginx.3      nginx:latest        node139             Shutdown            Shutdown 29 seconds ago      
 
透過docker service  ps  my_nginx 可以看到node節點上已經為Shutdown狀態了
 
在登入到node節點主機上檢視
[root@node188 ~] # docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
f93c0a27374a        nginx:latest         "nginx -g 'daemon of…"    9 hours ago         Exited (0) 44 seconds ago                       my_nginx.2.j2q61f8jtzba9kb3unupkhl25
a63ef253f7dd        nginx:latest         "nginx -g 'daemon of…"    9 hours ago         Exited (0) 9 hours ago                          my_nginx.2.wb1cpk9k22rl1ydab7aozl2b5
[root@node139 ~] # docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS               NAMES
e8ac2e44f5c4        nginx:latest         "nginx -g 'daemon of…"    9 hours ago         Exited (0) 9 hours ago                       my_nginx.2.mlprstt9ds5xi48u1rzscgfdk
5b031aa5a2cc        nginx:latest         "nginx -g 'daemon of…"    9 hours ago         Exited (0) 9 hours ago                       my_nginx.3.y09lk90tdzdp8cwj6mm5oyr3f
登入node節點,使用docker  ps  -a 檢視,會發現容器被stop而非 rm
 
6) 除了上面使用scale進行容器的擴容或縮容之外,還可以使用docker service update 命令。 可對 服務的啟動 引數 進行 更新/修改。
[root@manager43 ~] # docker service update --replicas 3 my_nginx
my_nginx
overall progress: 3 out of 3 tasks
1 /3 : running   [==================================================>]
2 /3 : running   [==================================================>]
3 /3 : running   [==================================================>]
verify: Service converged
 
[root@manager43 ~] # docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
zs7fw4ereo5w        my_nginx            replicated          3 /3                  nginx:latest        *:80->80 /tcp
 
[root@manager43 ~] # docker service ps my_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
yzonph0zu7km        my_nginx.1          nginx:latest        manager43           Running             Running 11 hours ago                        
j3hduzd9pret        my_nginx.2          nginx:latest        node188             Running             Running 18 seconds ago                      
wb1cpk9k22rl         \_ my_nginx.2      nginx:latest        node188             Shutdown            Complete 9 hours ago                        
mlprstt9ds5x         \_ my_nginx.2      nginx:latest        node139             Shutdown            Shutdown 4 minutes ago                      
gng96vc5vqpv        my_nginx.3          nginx:latest        node139             Running             Running 18 seconds ago                      
rhbj4bcr4t2c         \_ my_nginx.3      nginx:latest        manager43           Shutdown            Complete 9 hours ago                        
y09lk90tdzdp         \_ my_nginx.3      nginx:latest        node139             Shutdown            Shutdown 4 minutes ago    
 
docker service update 命令,也可用於直接 升級 映象等
[root@manager43 ~] # docker service update --image nginx:new my_nginx
 
[root@manager43 ~] # docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
zs7fw4ereo5w        my_nginx            replicated          3 /3                  nginx:new           *:80->80 /tcp
注意IMAGE列 變成了nginx:new
 
 
7) 為了下面的直觀顯示,我這裡把my_nginx服務直接刪除了
[root@manager43 ~] # docker service rm my_nginx
 
這樣就會把所有節點上的所有容器(task任務例項)全部刪除了

4、Swarm中使用Volume(掛在目錄,mount命令)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
1) 檢視volume的幫助資訊
[root@manager43 ~] # docker volume --help
 
Usage:  docker volume COMMAND
 
Manage volumes
 
Commands:
   create      Create a volume
   inspect     Display detailed information on one or  more  volumes
   ls           List volumes
   prune       Remove all unused  local  volumes
   rm           Remove one or  more  volumes
 
Run  'docker volume COMMAND --help'  for  more  information on a  command .
 
2) 建立一個volume
[root@manager43 ~] # docker volume create --name testvolume
testvolume
 
# 檢視建立的volume
[root@manager43 ~] # docker volume ls
DRIVER              VOLUME NAME
local                testvolume
 
# 檢視volume詳情
[root@manager43 ~] # docker volume inspect testvolume
[
     {
         "CreatedAt" "2018-10-21T10:50:02+08:00" ,
         "Driver" "local" ,
         "Labels" : {},
         "Mountpoint" "/var/lib/docker/volumes/testvolume/_data" ,
         "Name" "testvolume" ,
         "Options" : {},
         "Scope" "local"
     }
]
 
 
3) 建立新的服務並掛載testvolume(nginx為例)
[root@manager43 ~] # docker service create --replicas 3 --mount type=volume,src=testvolume,dst=/zjz --name test_nginx nginx
sh7wc8yzcvr0xaedo4tnraj7l
overall progress: 3 out of 3 tasks
1 /3 : running   [==================================================>]
2 /3 : running   [==================================================>]
3 /3 : running   [==================================================>]
verify: Service converged
 
溫馨提示:
引數src寫成 source 也可以;dst表示容器內的路徑,也可以寫成target
 
# 檢視建立服務
[root@manager43 ~] # docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
sh7wc8yzcvr0        test_nginx          replicated          3 /3                  nginx:latest       
[root@manager43 ~] # docker service ps test_nginx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
m7m41kwt4q6w        test_nginx.1        nginx:latest        node188             Running             Running 56 seconds ago                      
kayh81q1o1kx        test_nginx.2        nginx:latest        node139             Running             Running 56 seconds ago                      
eq11v0rcwy38        test_nginx.3        nginx:latest        manager43           Running             Running 56 seconds ago           
 
# 檢視有沒有掛載成功(登入各個節點的容器看看有沒有指定的目錄並建立檔案測試)
# 容器中操作
[root@manager43 ~] # docker exec -it 63451219cb4e /bin/bash
root@63451219cb4e:/ # cd /zjz/
root@63451219cb4e: /zjz # ls
root@63451219cb4e: /zjz # echo "gen wo xue docker" > docker.txt
root@63451219cb4e: /zjz # ls
docker.txt
 
執行docker volume inspect testvolume 可以看到本地的路徑(上面已經執行過了)
本地路徑: /var/lib/docker/volumes/testvolume/_data
[root@manager43 ~] # cd /var/lib/docker/volumes/testvolume/_data
[root@manager43 _data] # ls
docker.txt
[root@manager43 _data] # cat docker.txt
gen wo xue docker
 
還可以將node節點機上的volume資料目錄做成軟連結
[root@manager43 _data] # ln -s /var/lib/docker/volumes/testvolume/_data /zjz
[root@manager43 _data] # cd /zjz/
[root@manager43 zjz] # ls
docker.txt
[root@manager43 zjz] # echo "123" > 1.txt  
[root@manager43 zjz] # ll
總用量 8
-rw-r--r-- 1 root root  4 10月 21 11:04 1.txt
-rw-r--r-- 1 root root 18 10月 21 11:00 docker.txt
 
# 容器中檢視
[root@manager43 zjz] # docker exec -it 63451219cb4e /bin/bash
root@63451219cb4e:/ # cd /zjz/
root@63451219cb4e: /zjz # ls
1.txt  docker.txt
root@63451219cb4e: /zjz # cat 1.txt
123
root@63451219cb4e: /zjz # cat docker.txt
gen wo xue docker
 
# 還有一種掛載方式簡單說一下吧,上面的會了下面的肯定簡單
命令格式:
docker service create -- mount  type =bind,target= /container_data/ , source = /host_data/
其中,引數target表示容器裡面的路徑, source 表示本地硬碟路徑
 
# 示例建立並掛載並使用網路
[root@manager43 ~] # docker service create --replicas 1 --mount type=bind,target=/usr/share/nginx/html/,source=/opt/web/ --network nginx_net --name zjz_nginx -p 8880:80 nginx

5、多服務Swarm叢集部署

問:上面我們只是對單獨的一個nginx服務進行的叢集部署,那如果要統一編排多個服務呢?
答:docker 三劍客中有個compose 這個就是對單機進行統一編排的,它的實現是透過docker-compose.yml的檔案,這裡我們就可以結合compose和swarm進行多服務的編排( docker compose教程)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
溫馨提示:
我們這裡要部署的服務有三個(nginx服務,visualizer服務,portainer服務) 都是叢集 GUI 管理服務
docker service部署的是單個服務,我們可以使用docker stack進行多服務編排部署
 
1) 編寫docker-compose.yml檔案
[root@manager43 ~] # mkdir testswarm
[root@manager43 ~] # cd testswarm/
[root@manager43 testswarm] # cat docker-compose.yml
version:  "3"
services:
   nginx:
     image: nginx
     ports:
       - 8888:80
     deploy:
       mode: replicated
       replocas: 3
 
   visualizer:
     image: dockersamples /visualizer
     ports:
       "8080:8080"
     volumes:
       "/var/run/docker.sock:/var/run/docker.sock"
     deploy:
       replicas: 1
       placement:
         constraints: [node.role == manager]
 
   portainer:
     image: portainer /portainer
     ports:
       "9000:9000"
     volumes:
       "/var/run/docker.sock:/var/run/docker.sock"
     deploy:
       replicas: 1
       placement:
         constraints: [node.role == manager]
 
2) 透過這個yml檔案部署服務
[root@manager43 testswarm] # docker stack deploy -c docker-compose.yml deploy_deamon
Creating network deploy_deamon_default
Creating service deploy_deamon_portainer
Creating service deploy_deamon_nginx
Creating service deploy_deamon_visualizer
 
透過上面的執行過程可以看出這樣建立會預設建立一個網路並使用它,名字都是我們給的名字的字首加上服務名
 
# 檢視建立服務
[root@manager43 testswarm] # docker service ls
ID                  NAME                       MODE                REPLICAS            IMAGE                             PORTS
xj2f1t5ax3nm        deploy_deamon_nginx        replicated          3 /3                  nginx:latest                      *:8888->80 /tcp
ky9qpldr5abb        deploy_deamon_portainer    replicated          1 /1                  portainer /portainer :latest        *:9000->9000 /tcp
r47ff177x1ir        deploy_deamon_visualizer   replicated          1 /1                  dockersamples /visualizer :latest   *:8080->8080 /tcp
 
[root@manager43 testswarm] # docker service ps deploy_deamon_nginx
ID                  NAME                    IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
z3v4uc1ujsnq        deploy_deamon_nginx.1   nginx:latest        node139             Running             Running about a minute ago                      
jhg3ups0cko5        deploy_deamon_nginx.2   nginx:latest        manager43           Running             Running about a minute ago                      
3e6guv791x21        deploy_deamon_nginx.3   nginx:latest        node188             Running             Running about a minute ago        
 
[root@manager43 testswarm] # docker service ps deploy_deamon_portainer
ID                  NAME                        IMAGE                        NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
whyuvy82cvvw        deploy_deamon_portainer.1   portainer /portainer :latest   manager43           Running             Running about a minute ago                      
 
[root@manager43 testswarm] # docker service ps deploy_deamon_visualizer
ID                  NAME                         IMAGE                             NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
wge5w1eqykg3        deploy_deamon_visualizer.1   dockersamples /visualizer :latest   manager43           Running             Starting 7 seconds ago                      

測試

八、Docker Swarm 容器網路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
在Docker版本1.12之後swarm模式原生支援覆蓋網路(overlay networks),可以先建立一個覆蓋網路,然後啟動容器的時候啟用這個覆蓋網路,
這樣只要是這個覆蓋網路內的容器,不管在不在同一個宿主機上都能相互通訊,即跨主機通訊!不同覆蓋網路內的容器組之間是相互隔離的(相互 ping 不通)。
   
swarm模式的覆蓋網路包括以下功能:
1)可以附加多個服務到同一個網路。
2)預設情況下,service discovery為每個swarm服務分配一個虛擬IP地址(vip)和DNS名稱,使得在同一個網路中容器之間可以使用服務名稱為互相連線。
3)可以配置使用DNS輪循而不使用VIP
4)為了可以使用swarm的覆蓋網路,在啟用swarm模式之間你需要在swarm節點之間開放以下埠:
5)TCP /UDP 埠7946 – 用於容器網路發現
6)UDP埠4789 – 用於容器覆蓋網路
   
例項如下:
-----------在Swarm叢集中建立overlay網路------------
[root@manager-node ~] # docker network create --driver overlay --opt encrypted --subnet 10.10.19.0/24 ngx_net
   
引數解釋:
–opt encrypted  預設情況下swarm中的節點通訊是加密的。在不同節點的容器之間,可選的–opt encrypted引數能在它們的vxlan流量啟用附加的加密層。
--subnet 命令列引數指定overlay網路使用的子網網段。當不指定一個子網時,swarm管理器自動選擇一個子網並分配給網路。
   
[root@manager-node ~] # docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d7aa48d3e485        bridge              bridge               local            
9e637a97a3b9        docker_gwbridge     bridge               local            
b5a41c8c71e7        host                host                 local            
7f4fx3jf4dbr        ingress             overlay             swarm            
3x2wgugr6zmn        ngx_net             overlay             swarm            
0808a5c72a0a        none                null                 local
   
由上可知,Swarm當中擁有2套覆蓋網路。其中 "ngx_net" 網路正是我們在部署容器時所建立的成果。而 "ingress" 覆蓋網路則為預設提供。
Swarm 管理節點會利用 ingress 負載均衡以將服務公佈至叢集之外。
在將服務連線到這個建立的網路之前,網路覆蓋到manager節點。上面輸出的SCOPE為 swarm 表示將服務部署到Swarm時可以使用此網路。
在將服務連線到這個網路後,Swarm只將該網路擴充套件到特定的worker節點,這個worker節點被swarm排程器分配了執行服務的任務。
在那些沒有執行該服務任務的worker節點上,網路並不擴充套件到該節點。
   
------------------將服務連線到overlay網路-------------------
[root@manager-node ~] # docker service create --replicas 5 --network ngx_net --name my-test -p 80:80 nginx
   
上面名為 "my-test" 的服務啟動了3個task,用於執行每個任務的容器都可以彼此透過overlay網路進行通訊。Swarm叢集將網路擴充套件到所有任務處於Running狀態的節點上。
[root@manager-node ~] # docker service ls
ID            NAME     REPLICAS  IMAGE  COMMAND
dsaxs6v463g9  my- test   5 /5        nginx
   
在manager-node節點上,透過下面的命令檢視哪些節點有處於running狀態的任務:
[root@manager-node ~] # docker service ps my-test
ID                         NAME       IMAGE  NODE          DESIRED STATE  CURRENT STATE          ERROR
8433fuiy7vpu0p80arl7vggfe  my- test .1  nginx  node2         Running        Running 2 minutes ago
f1h7a0vtojv18zrsiw8j0rzaw  my- test .2  nginx  node1         Running        Running 2 minutes ago
ex73ifk3jvzw8ukurl8yu7fyq  my- test .3  nginx  node1         Running        Running 2 minutes ago
cyu73jd8psupfhken23vvmpud  my- test .4  nginx  manager-node  Running        Running 2 minutes ago
btorxekfix4hcqh4v83dr0tzw  my- test .5  nginx  manager-node  Running        Running 2 minutes ago
   
可見三個節點都有處於running狀態的任務,所以my-network網路擴充套件到三個節點上。
   
可以查詢某個節點上關於my-network的詳細資訊:
[root@manager-node ~] # docker network inspect ngx_net
[
     {
         "Name" "ngx_net" ,
         "Id" "3x2wgugr6zmn1mcyf9k1du27p" ,
         "Scope" "swarm" ,
         "Driver" "overlay" ,
         "EnableIPv6" false ,
         "IPAM" : {
             "Driver" "default" ,
             "Options" : null,
             "Config" : [
                 {
                     "Subnet" "10.10.19.0/24" ,
                     "Gateway" "10.10.19.1"
                 }
             ]
         },
         "Internal" false ,
         "Containers" : {
             "00f47e38deea76269eb03ba13695ec0b0c740601c85019546d6a9a17fd434663" : {
                 "Name" "my-test.5.btorxekfix4hcqh4v83dr0tzw" ,
                 "EndpointID" "ea962d07eee150b263ae631b8a7f8c1950337c11ef2c3d488a7c3717defd8601" ,
                 "MacAddress" "02:42:0a:0a:13:03" ,
                 "IPv4Address" "10.10.19.3/24" ,
                 "IPv6Address" ""
             },
             "957620c6f7abb44ad8dd2d842d333f5e5c1655034dc43e49abbbd680de3a5341" : {
                 "Name" "my-test.4.cyu73jd8psupfhken23vvmpud" ,
                 "EndpointID" "f33a6e9ddf1dd01bcfc43ffefd19e19514658f001cdf9b2fbe23bc3fdf56a42a" ,
                 "MacAddress" "02:42:0a:0a:13:07" ,
                 "IPv4Address" "10.10.19.7/24" ,
                 "IPv6Address" ""
             }
         },
         "Options" : {
             "com.docker.network.driver.overlay.vxlanid_list" "257"
         },
         "Labels" : {}
     }
]
   
從上面的資訊可以看出在manager-node節點上,名為my- test 的服務有一個名為my- test .5.btorxekfix4hcqh4v83dr0tzw和
my- test .4.cyu73jd8psupfhken23vvmpud的task連線到名為ngx_net的網路上(另外兩個節點node1和node2同樣可以用上面命令檢視)
[root@node1 ~] # docker network inspect ngx_net
.......
         "Containers" : {
             "7d9986fad5a7d834676ba76ae75aff2258f840953f1dc633c3ef3c0efd2b2501" : {
                 "Name" "my-test.3.ex73ifk3jvzw8ukurl8yu7fyq" ,
                 "EndpointID" "957ca19f3d5480762dbd14fd9a6a1cd01a8deac3e8e35b23d1350f480a7b2f37" ,
                 "MacAddress" "02:42:0a:0a:13:06" ,
                 "IPv4Address" "10.10.19.6/24" ,
                 "IPv6Address" ""
             },
             "9e50fceada1d7c653a886ca29d2bf2606debafe8c8a97f2d79104faf3ecf8a46" : {
                 "Name" "my-test.2.f1h7a0vtojv18zrsiw8j0rzaw" ,
                 "EndpointID" "b1c209c7b68634e88e0bf5e100fe03435b3096054da6555c61e6c207ac651ac2" ,
                 "MacAddress" "02:42:0a:0a:13:05" ,
                 "IPv4Address" "10.10.19.5/24" ,
                 "IPv6Address" ""
             }
         },
.........
  
[root@node2 web] # docker network inspect ngx_net
........
         "Containers" : {
             "4bdcce0ee63edc08d943cf4a049eac027719ff2dc14b7c3aa85fdddc5d1da968" : {
                 "Name" "my-test.1.8433fuiy7vpu0p80arl7vggfe" ,
                 "EndpointID" "df58de85b0a0e4d128bf332fc783f6528d1f179b0f9f3b7aa70ebc832640d3bc" ,
                 "MacAddress" "02:42:0a:0a:13:04" ,
                 "IPv4Address" "10.10.19.4/24" ,
                 "IPv6Address" ""
             }
         },
   
可以透過查詢服務來獲得服務的虛擬IP地址,如下:
[root@manager-node ~] # docker service inspect --format='{{json .Endpoint.VirtualIPs}}' my-test
[{ "NetworkID" : "7f4fx3jf4dbrp97aioc05pul4" , "Addr" : "10.255.0.6/16" },{ "NetworkID" : "3x2wgugr6zmn1mcyf9k1du27p" , "Addr" : "10.10.19.2/24" }]
   
由上結果可知,10.10.19.2其實就是swarm叢集內部的vip,整個網路結構如下圖所示:

 

加入ngx_net網路的容器彼此之間可以透過IP地址通訊,也可以透過名稱通訊。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
[root@node2 ~] # docker ps
CONTAINER ID    IMAGE           COMMAND                  CREATED         STATUS             PORTS    NAMES
4bdcce0ee63e    nginx:latest     "nginx -g 'daemon off"    22 minutes ago  Up 22 minutes      80 /tcp    my- test .1.8433fuiy7vpu0p80arl7vggfe
  
[root@node2 ~] # docker exec -ti 4bdcce0ee63e /bin/bash
root@4bdcce0ee63e:/ # ip addr                                                                                          
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
     link /loopback  00:00:00:00:00:00 brd 00:00:00:00:00:00
     inet 127.0.0.1 /8  scope host lo
        valid_lft forever preferred_lft forever
     inet6 ::1 /128  scope host
        valid_lft forever preferred_lft forever
1786: eth0@if1787: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
     link /ether  02:42:0a:ff:00:08 brd ff:ff:ff:ff:ff:ff link-netnsid 0
     inet 10.255.0.8 /16  scope global eth0
        valid_lft forever preferred_lft forever
     inet 10.255.0.6 /32  scope global eth0
        valid_lft forever preferred_lft forever
     inet6 fe80::42:aff:feff:8 /64  scope link
        valid_lft forever preferred_lft forever
1788: eth1@if1789: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
     link /ether  02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 1
     inet 172.18.0.3 /16  scope global eth1
        valid_lft forever preferred_lft forever
     inet6 fe80::42:acff:fe12:3 /64  scope link
        valid_lft forever preferred_lft forever
1791: eth2@if1792: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
     link /ether  02:42:0a:0a:13:04 brd ff:ff:ff:ff:ff:ff link-netnsid 2
     inet 10.10.19.4 /24  scope global eth2
        valid_lft forever preferred_lft forever
     inet 10.10.19.2 /32  scope global eth2
        valid_lft forever preferred_lft forever
     inet6 fe80::42:aff:fe0a:1304 /64  scope link
        valid_lft forever preferred_lft forever
  
root@4bdcce0ee63e:/ # ping 10.10.19.3
PING 10.10.19.3 (10.10.19.3): 56 data bytes
64 bytes from 10.10.19.3: icmp_seq=0 ttl=64  time =0.890 ms
64 bytes from 10.10.19.3: icmp_seq=1 ttl=64  time =0.622 ms
.....-
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min /avg/max/stddev  = 0.622 /0 .756 /0 .890 /0 .134 ms
  
root@4bdcce0ee63e:/ # ping 10.10.19.6
PING 10.10.19.6 (10.10.19.6): 56 data bytes
64 bytes from 10.10.19.6: icmp_seq=0 ttl=64  time =0.939 ms
64 bytes from 10.10.19.6: icmp_seq=1 ttl=64  time =0.590 ms
  
----------------------------使用swarm模式的服務發現--------------------------
預設情況下,當建立了一個服務並連線到某個網路後,swarm會為該服務分配一個VIP。此VIP根據服務名對映到DNS。在網路上的容器共享該服務的DNS對映,
所以網路上的任意容器可以透過服務名訪問服務。
  
在同一overlay網路中,不用透過埠對映來使某個服務可以被其它服務訪問。Swarm內部的負載均衡器自動將請求傳送到服務的VIP上,然後分發到所有的
active的task上。
  
如下示例:
在同一個網路中新增了一個centos服務,此服務可以透過名稱my- test 訪問前面建立的nginx服務:
[root@manager-node ~] # docker service create --name my-centos --network ngx_net centos       
  
查詢centos執行在哪個節點上(上面建立命令執行後,需要一段時間才能完成這個centos服務的建立)
[root@manager-node ~] # docker service ps my-centos
ID                         NAME             IMAGE   NODE   DESIRED STATE  CURRENT STATE            ERROR
e03pqgkjs3l1qizc6v4aqaune  my-centos.1      centos  node2  Running        Preparing 4 seconds ago
  
登入centos執行的節點(由上可知是node2節點),開啟centos的互動shell:
[root@node2 ~] # docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS            NAMES
e4554490d891        centos:latest             "/bin/bash"              About an hour ago   Up About an hour   my-centos.1.9yk5ie28gwk9mw1h1jovb68ki
  
[root@node2 ~] # docker exec -ti my-centos.1.9yk5ie28gwk9mw1h1jovb68ki /bin/bash
root@4bdcce0ee63e:/ # nslookup my-test
Server: 127.0.0.11
Address 1: 127.0.0.11
  
Name: my- test
Address 1: 10.10.19.2 10.10.19.2
  
  
從centos容器內部,使用特殊查詢 查詢DNS,來找到my- test 服務的所有容器的IP地址:
root@4bdcce0ee63e:/ # nslookup tasks.my-test
Server: 127.0.0.11
Address 1: 127.0.0.11
  
Name: tasks.my- test
Address 1: 10.10.19.4 my- test .1.8433fuiy7vpu0p80arl7vggfe
Address 2: 10.10.19.5 my- test .2.f1h7a0vtojv18zrsiw8j0rzaw
Address 3: 10.10.19.6 my- test .3.ex73ifk3jvzw8ukurl8yu7fyq
Address 2: 10.10.19.7 my- test .4.cyu73jd8psupfhken23vvmpud
Address 3: 10.10.19.3 my- test .5.btorxekfix4hcqh4v83dr0tzw
  
從centos容器內部,透過wget來訪問my- test 服務中執行的nginx網頁伺服器
root@4bdcce0ee63e:/ # wget -O- my-test     
Connecting to my- test  (10.10.19.2:80)
<!DOCTYPE html>
<html>
< head >
<title>Welcome to nginx!< /title >
...
  
Swarm的負載均衡器自動將HTTP請求路由到VIP上,然後到一個active的task容器上。它根據round-robin選擇演算法將後續的請求分發到另一個active的task上。
  
-----------------------------------為服務使用DNS round-robin-----------------------------
在建立服務時,可以配置服務直接使用DNS round-robin而無需使用VIP。這是透過在建立服務時指定 --endpoint-mode dnsrr 命令列引數實現的。
當你想要使用自己的負載均衡器時可以使用這種方式。
  
如下示例(注意:使用DNS round-robin方式建立服務,不能直接在命令裡使用-p指定埠)
[root@manager-node ~] # docker service create --replicas 3 --name my-dnsrr-nginx --network ngx_net --endpoint-mode dnsrr nginx
  
[root@manager-node ~] # docker service ps my-dnsrr-nginx
ID                         NAME              IMAGE  NODE          DESIRED STATE  CURRENT STATE          ERROR
65li2zbhxvvoaesndmwjokouj  my-dnsrr-nginx.1  nginx  node1         Running        Running 2 minutes ago
5hjw7wm4xr877879m0ewjciuj  my-dnsrr-nginx.2  nginx  manager-node  Running        Running 2 minutes ago
afo7acduge2qfy60e87liz557  my-dnsrr-nginx.3  nginx  manager-node  Running        Running 2 minutes ago
  
  
當透過服務名稱查詢DNS時,DNS服務返回所有任務容器的IP地址:
root@4bdcce0ee63e:/ # nslookup my-dnsrr-nginx
Server:    127.0.0.11
Address 1: 127.0.0.11
  
Name:      my-dnsrr-nginx
Address 1: 10.10.19.10 my-dnsrr-nginx.3.0sm1n9o8hygzarv5t5eq46okn.my-network
Address 2: 10.10.19.9  my-dnsrr-nginx.2.b3o1uoa8m003b2kk0ytl9lawh.my-network
Address 3: 10.10.19.8  my-dnsrr-nginx.1.55za4c83jq9846rle6eigiq15.my-network
  
需要注意的是:一定要確認VIP的連通性
通常Docker官方推薦使用 dig nslookup 或其它DNS查詢工具來查詢透過DNS對服務名的訪問。因為VIP是邏輯IP, ping 並不是確認VIP連通性的正確的工具。


 Swarm是Docker官方提供的一款叢集管理工具,其主要作用是把若干臺Docker主機抽象為一個整體,並且透過一個入口統一管理這些Docker主機上的各種Docker資源。Swarm和Kubernetes比較類似,但是更加輕,具有的功能也較kubernetes更少一些。

  Swarm的基本架構如下圖所示,

  這個圖作為一個整體實際上都處於一個所謂的叢集中,它可能對應了一到多臺的實際伺服器。每臺伺服器上都裝有Docker並且開啟了基於HTTP的DockerAPI。這個叢集中有一個SwarmManager的管理者,用來管理叢集中的容器資源。管理者的管理物件不是伺服器層面而是叢集層面的,也就是說透過Manager,我們只能籠統地向叢集 發出指令而不能具體到某臺具體的伺服器上要幹什麼(這也是Swarm的根本所在)。至於具體的管理實現方式,Manager向外暴露了一個HTTP介面,外部使用者透過這個HTTP介面來實現對叢集的管理。對於稍微大一點的叢集,最好是拿出一臺實際的伺服器作為專門的管理者,作為學習而言,也可以把管理者和被管理者放在一臺伺服器上。

  下面就來講一下如何簡單地透過swarm搭建一個叢集

■  安裝與簡單叢集建立

  ●  開啟帶有HTTPAPI的Docker服務

  我的虛擬機器環境是CentOS7的,Docker則是透過yum來安裝的。如要使用swarm,則必須讓Docker開放其HTTP的API。預設情況下這個API沒有開啟,而開啟此API需要在啟動時加入-H引數。

  網上有的人說執行/usr/bin/docker的時候直接加,有的又說修改/etc/sysconfig/docker之類的檔案,都不適用於我,可能是由於系統以及docker本身的版本的緣故。而我的正確姿勢是修改/lib/systemd/system/docker.service這個檔案中的引數,並且用systemctl來管理啟動docker服務。

  上述這個檔案的ExecStart很明顯是指出了docker的啟動引數,在第一行的後面直接加上:

-H tcp://0.0.0.0:2375

   (有些文章也指出對於CentOS6還需要加上-H unix:///var/run/docker.sock)  修改完成之後別忘了執行一下systemctl daemon-reload重新整理配置

  然後再重啟/啟動Docker服務,此時透過netstat -ntlp可以看到一個新開的2375埠,此乃預設的DockerHTTPAPI的埠。如果是一個叢集則需要注意叢集中所有相關的主機都記得要啟動帶這個埠的Docker服務。

  ●  沒有正確退出swarm叢集時引發的問題

  退出swarm叢集用的命令是docker swarm leave,然而存在這樣一種情況:沒有完全退出swarm叢集時就關掉了Docker服務。隨後網路環境變化了(主機的IP變了)。此時若再systemctl start docker將會報錯,透過systemctl status docker -l可以檢視完整的報錯資訊,提示找不到老IP地址云云。其實這是啟動swarm時報的錯誤。

  google了一下之後,發現比較方便的解決辦法是手動修改/var/lib/docker/swarm下面的docker-state.json和state.json兩個檔案。把這兩個json檔案中原來的老地址都改成現在的新地址。應該就可以順利啟動了。

  ●  建立小叢集

  前面提到的Swarm Manager,其本身其實是一個容器,其他一些swarm的角色基本上也透過容器的方式來實現。Swarm源於Docker而基於Docker。但是Docker在剛安裝的時候是沒有swarm支援的,需要我們docker pull swarm去DockerHub裡下載swarm的映象。這個映象本身不大,最新版的大概15MB左右,一會兒就下載完了。

  當然,如果是叢集的話那麼需要在所有相關的主機上都pull到這個映象。

  第一步,建立一個叢集並且取得叢集標誌。Swarm支援自動發現功能,如果在一個網路中存在多個叢集,那麼就需要每個叢集都有一個區別於其他叢集的標誌來防止混淆。這個標誌就是所謂的叢集token,在叢集創立之初就被指定且無法更改。在被選為管理者角色的伺服器上執行命令:

docker run --rm swarm create

   這個命令返回中帶有一串token字串(以dfb4fb3a8767835d799ce429fb4d7c4d為例),這個資訊需要記錄下來,之後所有操作中都需要用到它來指出我們對哪個叢集操作。而且目前還沒找到如何檢視一個既存叢集的token,所以一定要記錄一下。。

  建立叢集過後實際上並沒有真的增加什麼Docker資源,仍然是一個空的叢集。

 

  第二步,建立叢集獲取到叢集token之後,目前我們手上拿著的還是一個空叢集,接下來就往裡面加入節點主機吧。加入節點主機的方法是再各個節點主機上執行這條命令:

docker run -d swarm join --addr=192.168.1.102:2375 token://dfb4fb3a8767835d799ce429fb4d7c4d

  其中--addr引數指出的是本主機的Docker服務的socket,自然,IP要和各個主機自身的IP一致。另外我嘗試了一下,若在本機指定addr為localhost或者0.0.0.0之類的IP,最終是無法正常工作的。所以即便是在管理者本機,也要老老實實寫出IP。完成後可以在當前主機上docker ps看一下,應該可以看到一個在執行中的swarm容器。這個容器扮演的角色就是向上和管理者容器通訊,向下管理所在本機的docker資源,所謂被管理主機的代理。

  建立完後,可以透過

docker run -d swarm list token://dfb4fb3a8767835d799ce429fb4d7c4d

 

  來檢視這個指定的叢集(由token指出)中存在哪些join進來的節點。需要注意的是,swarm join命令只是簡單的加入叢集的宣告,swarm並不會去驗證給出的地址和埠是否真的可以訪問到一個Docker服務。對於沒有發現正常Docker服務的節點,將置狀態為Pending而不是Healthy,這個狀態以及其他節點相關資訊怎麼看下面會說。

 

   第三步,開啟管理者容器。上面建立了叢集框架,並且往叢集中加入了join節點(即被管理主機的代理),但是還沒有出現管理者容器(管理主機的代理)。建立管理者容器的方法是在管理者主機上:

docker run -d -p 8888:2375 swarm manage token://dfb4fb3a8767835d799ce429fb4d7c4d

 

  同樣,docker ps之後可以看到管理容器。-p表名管理者容器做了一個埠對映。因為2375埠在本機上已經被Docker程式佔用(當然啟動時指定的埠不是預設的2375就另當別論了),而管理容器暴露的這個埠要提供出來,實現外界對叢集的管理,所以做了一個埠對映。這個8888,也可以換成其他任何合理的埠號。

  有了管理容器,並且管理容器給出了8888埠作為管理的入口,我們就可以執行以下這些命令了:

docker -H 192.168.1.101:8888 info
docker -H 127.0.0.1:8888 ps
docker -H 192.168.1.101:8888 images

 

  由於這個8888埠就可以看做是一個網路中的普通埠,在本機上訪問的話自然IP寫127.0.0.1也是可以的。但是注意不能寫成localhost,不然會報錯。。

  這三條命令,去掉-H引數的話就是一般的docker用來檢視資訊的命令。加上-H之後,比如-H 192.168.1.101:8888之後,其意義就變成了,檢視一個叢集的相關資訊。這個叢集是192.168.1.101的8888埠對應的管理容器所對應的那個叢集。

  透過這幾條命令呈現出來的docker資源如容器和映象是不強調具體處於那臺主機上的,這就使得叢集的概念得以發揚光大。另外透過這個socket得到的叢集的資訊會把swarm本身除外。比如目前這個狀態透過-H xxx ps看到的容器列表應該是空的。因為我們還沒有讓叢集執行任何容器。但是docker ps會有swarm的容器顯示出來。如果想在-H的時候(所謂叢集檢視)也看到swarm容器資訊可以用ps -a。

  順便,info命令的結果和普通的docker info命令結果不太一樣,最主要的是有了nodes這個欄位。這個欄位包含了各個節點的資訊,包括前面提到的節點狀態等資訊。

 

■  叢集簡單使用

  下面正式使用叢集來跑個容器試試看。其實和原生docker命令相比,就是多了個-H引數來指明一個叢集管理入口而已:

docker -H 127.0.0.1:8888 run -d -p 10022:22 --name swarmtest tomcatssh:v1

 

  tomcatssh是我本地一個自定義的映象,和docker run類似的,其他的很多命令如docker start/stop/rm等等也都可以透過叢集管理的入口來對叢集做出。

  如果我們的叢集中有多型機器用於跑容器,即有多個被管理主機的話,那麼透過這樣的方式啟動起來的容器會透過一定的策略選擇一臺合適的主機作為真實的跑容器的平臺來執行容器。策略分成好多種,預設是spread(這個欄位在docker -H xxx info中的Strategy中有顯示),具體是指當叢集要執行一個新的容器,將會根據演算法和收集到的各個被管理主機CPU,記憶體等資訊進行智慧的選擇,使得各個執行容器的主機儘量均衡。

  既然能夠做到自動選擇一臺主機作為容器執行的寄託,那麼自然也可以恢復手動模式。這在swarm中就是所謂的filter功能。filter可以分成多種,

  ●  約束過濾器(Constraint Filter)

  約束過濾器透過啟動Docker守護程式時指定的標籤label來查詢合適的被管理主機。label是透過啟動引數的方式在啟動時被固定的:

--label datacenter=us-east1

 

  這個引數加入到之前說過的docker.service,或者手動加在啟動docker的命令後面等等。

  而在啟動容器時透過這樣的方式來指定過濾器:

docker -H 127.0.0.1:8888 run -e constraint:datacenter==us-east1 -d --name www-use1 nginx

 

  -e後面跟過濾器,constraint指出了約束過濾器,後面的約束標籤支援==,!=兩種判斷,後面可以寫字串和正規表示式如us-east*。

  ●  親和過濾器(Affinity Filter)

  親和過濾器以現有的某個容器為基準,讓新容器執行在/不在已經執行了某個現有容器的主機上執行。

docker run -d -e --name db affinity:container!=www-use1 mysql

 

  比如上面這條命令說的就是要根據mysql映象啟動一個名為db的容器,但是這個容器不能在已經預www-use1容器執行的主機上執行。

  ●  埠過濾器

  埠過濾器嚴格來說並不是一個真的過濾器。。它只是在啟動容器時透過-p引數來申請對一個主機埠的使用權。如果一臺主機上這個埠正在被使用那麼自然是不能把容器放到這個主機上執行的。

  

  除了上述三種,過濾器還有很多,可以透過swarm manage --help或者去官網查。總的來說,過濾器是一種主動指定主機的手段,配合swarm自身的自動分配機制,可以靈活地確定一臺主機來執行容器。

  如果當前叢集中swarm找不到一臺符合條件的主機來執行容器,那麼swarm會明確指出哪個過濾器條件得不到滿足,從而啟動容器失敗。

  

========================================================================================================

  意識到,上面的swarm介紹居然是老版本的!orz

  現在的Docker(1.12版本以後的)都是帶了原生的swarm命令,也就是說不需要不需要進行復雜的swarm create之類的操作,僅需要簡單幾條命令即可。

  【http://blog.csdn.net/candcplusplus/article/details/53836703】

  ■  新版本上構建swarm叢集和節點

  啟動一個swarm叢集十分簡單,只需要執行

docker swarm init --listen-addr 192.168.1.112:8888 --advertise-addr 192.168.1.112

   兩個引數也很好懂,--listen-addr指出的是這個叢集暴露給外界呼叫的HTTPAPI的socket地址。這個就是類似於上面老版本中swarm manage時-p指定的埠。新增--advertise-addr引數的原因是大多數情況下我們的主機都不只有一張網路卡。而一個swarm叢集需要辨明叢集所在的子網路是哪張網路卡的。

  另外需要注意,在新版本的swarm下,manage節點自身也作為被worker節點的一個,自動加入建立起來的swarm叢集中。

  命令執行成功的話會提示一串類似於這樣的資訊:

    docker swarm join \
    --token SWMTKN-1-2vndbzp43eff6vaiornhbafew242arz29qngrql0slqg4zmi4j-1hpha7vnelkbg4gg1d293qus4 \
    192.168.1.112:8888

 

  這是在說明,通網路下的被管理主機上,只要執行這串命令就可以將該主機加入叢集。如果不小心忘了這個命令那麼可以在manager上執行docker swarm join-token manager命令,隨時調取出這部分資訊來看。我特意多建了兩臺虛擬機器,裝上docker作為被管理機器。為方便下面稱管理者角色的機器為A,另兩臺為B、C。

  在B、C上分別執行上面這個命令(有時可以在命令後加上--listen-addr引數,倒不是說被管理主機也需要監聽,而是存在一些將被管理主機升級為管理主機的場景)後,在A上執行命令:

docker node ls

 

  可以檢視swarm各個節點的情況。同樣的docker info 中也會多出Swarm: True以及一系列相關欄位。docker node ls的返回類似於:

ID                           HOSTNAME               STATUS  AVAILABILITY  MANAGER STATUS
2hzmnrb0vddow7jlr7zdx86s0    localhost.localdomain  Ready   Active
444w5u9i9tf8h1dmvp404tluy *  localhost.localdomain  Ready   Active        Leader
89z0l64mitjyhwijj6o0ps3m3    localhost.localdomain  Ready   Active

 

  節點id後的星號據說表示的是你當前連線著的節點。

  於是,我們就得到了一個由三個節點組成的swarm小叢集。在這個叢集中有一個manager節點和三個worker節點(別忘了manager本身自動作為worker一員加入叢集)。

  相比較於之前還需要手動pull映象,然後敲好多docker run命令,新版本下整合到docker內部的swarm明顯就要好多了。然而我們現在也只是搭建了一個小叢集,並沒有實質內容在其中執行。

 

  ■  構建服務

  說到實質內容,由於swarm會自動地做一些如負載均衡,保持容器副本數量等工作,所以swarm對外提供的和k8s類似也是屬於一個“服務”的概念。

docker service create --replicas 1 --name swarmtest tomcatssh:v1

 

  透過上面這個命令可以建立一個服務(tomcatssh是我自己的映象)。--replicas引數指出希望保持這個服務始終有多少容器在執行,name引數指定的是服務的名字而非容器的名字,雖然兩者最終會很像。

  建立完成的服務可以在manage節點上透過docker service ls命令檢視,可能replicas是0/1,這表示服務仍在建立過程中。稍等一會兒就會變成1/1了。更加詳細的資訊,則可以透過docker service inspect --pretty swarmtest來檢視。pretty引數使輸出更加友好,不加此引數的輸出是JSON格式的。

  同時也可以順便到各臺worker上去docker ps看下容器的執行情況。一般情況下再manager上會出現一個正在執行的容器,如果你停掉或者刪掉這個容器,那麼swarm會自動重啟它。

  進一步的docker service ps swarmtest,可以檢視swarmtest這個Service的各個容器到底在哪個節點上執行且執行狀態如何。比如我剛才建立了一個replicas為3的swarmtest服務,docker service ps swarmtest後的結果是:

ID                         NAME             IMAGE         NODE                   DESIRED STATE  CURRENT STATE             ERROR
a6ubuiush8l821rncxkd231le   \_ swarmtest.1  tomcatssh:v1  localhost.localdomain  Shutdown       Rejected 8 minutes ago    "No such image: tomcatssh:v1"
3sk5cowp4bve0zklvydwdgwba  swarmtest.2      tomcatssh:v1  localhost.localdomain  Running        Running 6 minutes ago
8tku51hecc6pza21urs5oz5zk  swarmtest.3      tomcatssh:v1  localhost.localdomain  Running        Preparing 32 seconds ago

 

  可以看到,在要求啟動3個容器作為swarmtest服務的支撐時,swarm分別試圖在叢集(僵硬的是我叢集中三個主機的主機名都是localhost.localdomain。。。意思一下吧,總之知道這裡雖然寫的一樣但是裡面是三臺不同的機子)中去啟動swarmtest.1,swarmtest.2以及swarmtest.3三個容器,可以看到swarm.1檢視執行的主機上沒有tomcatssh:v1映象因此啟動失敗,swarm.2啟動成功,開始執行;swarm.3仍在準備中。可以想到的是,因為swarm.1已經啟動失敗,所以swarm會繼續尋找機會啟動它,儘量保證啟動服務時replicas為3的要求。

  

  另外服務還有一個重要的功能就是伸縮。透過命令:

docker service scale swarmtest=5

  可以將服務現有的replica為3的狀態擴充套件到5,期間已經啟動的容器不受影響。

 

  對於不需要的服務,可以docker service rm swarmtest來刪除。刪除後所有節點上的相關容器都會被刪除。

  對於一個服務來說,常會遇到的一件事是滾動更新,swarm為我們封裝了命令docker service update。只要給這個命令加上--image引數指定一個新映象,那麼該服務中的所有容器都會被更新成這個新映象的內容。但為了保證可用性,必然不能同時更新所有容器。swarm就內建了一個滾動更新的機制,可以讓我們依次更新各個容器從而避免更新期間的不可用。在docker service create 的時候可以指出--upgrade-delay引數,表示更新服務對應的任務或一組任務之間的時間間隔。時間間隔用數字和時間單位表示,m 表示分,h 表示時,所以 10m30s 表示 10 分 30 秒的延時。另外--update-parallelism引數標誌配置排程器每次同時更新的最大任務數量,預設情況下此引數值為1,即一個一個容器地更新。

  在有了滾動更新的保障之後,再來執行docker service update,比如docker service update --image tomcatssh:v2 swarmtest,則swarm會自動地去按照滾動更新的策略更新各個容器(實際上就是把舊容器關停並啟動新容器)。在更新過程中docker service ps swarmtest可以檢視更新的實時情況,最終更新完成後這條命令看到的結果應該是類似於這樣子的:

ID                         NAME             IMAGE         NODE                   DESIRED STATE  CURRENT STATE            ERROR
5v3purlp28bg93ngkmp9x1dy9  swarmtest.1      tomcatssh:v2  worker1                Running        Running 45 seconds ago
055xxourdnlsylmnjgwvs718t   \_ swarmtest.1  tomcatssh:v1  worker1                Shutdown       Shutdown 49 seconds ago
4b1am22wx1w0abo3ylxt7qcfe  swarmtest.2      tomcatssh:v2  localhost.localdomain  Running        Running 11 seconds ago
euyu700dikpqmgzq8hyoijvdq   \_ swarmtest.2  tomcatssh:v1  worker2                Shutdown       Shutdown 7 minutes ago
efgfvp2wd0x655dy136qrt47y  swarmtest.3      tomcatssh:v2  worker2                Running        Running 7 minutes ago
1m7muogeuitfsllhcyu942ac1   \_ swarmtest.3  tomcatssh:v1  localhost.localdomain  Shutdown       Shutdown 32 seconds ago

 

  過程中,swarm先Shutdown了一臺節點上的老容器並且啟動新容器,如果新容器啟動成功後就再等10秒(建立service時指定的引數),然後開始操作下一臺。另外,如果操作一臺的過程中發生錯誤導致新容器沒有正確執行起來,那麼更新任務會到此暫停,不會繼續往下。docker service update後面的--update-failure-action引數可以指定是否要跳過錯誤。

  ■  節點管理

  之前所有的演示中,三個節點始終都保持著Active的可用性。Swarm管理器會自動根據演算法將任務(啟停容器等)分配給Active的節點。

  除了Active,其他常見的可用性狀態還有Drain,處於Drain的節點不會被分配新任務,而且當前執行著的容器也都會被停止,swarm管理器則會在其他節點上新建這些任務。

  執行命令

docker node update --availability drain worker2

 

  可以手動將某個節點的可用性設定為Drain,比如這裡將名為worker2的節點設定為drain了之後,可以看到在docker service ps swarmtest中出現的新資訊:

anrqum9q6zg0jw12ds5jnloyb  swarmtest.3      tomcatssh:v2  localhost.localdomain  Running        Running 9 seconds ago
efgfvp2wd0x655dy136qrt47y   \_ swarmtest.3  tomcatssh:v2  worker2                Shutdown       Shutdown 7 minutes ago

 

  由於worker2不再接受任務並關停現有任務,所以swarmtest.3這個容器被轉移到了localhost(即manage節點所在)。docker node ls或者docker node inspect --pretty worker2就可以看到起可用性的變更了。

  如果使用docker node update再次將worker2的可用性設定為active,那麼worker2節點就可以再次獲取任務了(剛才被轉移到localhost上的任務是不會有再轉回來的,所以worker2的任務只有在接下來的分配中獲得)。總的來說,一個處於Active狀態的節點在這些情況下可能收到新任務:當服務規模擴大時;滾動更新時;其他節點被設定為Drain而本節點需要擔當時;其他節點上任務啟動失敗時。







About Me

........................................................................................................................

● 本文作者:小麥苗,部分內容整理自網路,若有侵權請聯絡小麥苗刪除

● 本文在itpub、部落格園、CSDN和個人微 信公眾號( DB寶)上有同步更新

● 本文itpub地址: http://blog.itpub.net/26736162

● 本文部落格園地址: http://www.cnblogs.com/lhrbest

● 本文CSDN地址: https://blog.csdn.net/lihuarongaini

● 本文pdf版、個人簡介及小麥苗雲盤地址: http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答: http://blog.itpub.net/26736162/viewspace-2134706/

● DBA寶典今日頭條號地址:

........................................................................................................................

● QQ群號: 230161599 、618766405

● 微 信群:可加我微 信,我拉大家進群,非誠勿擾

● 聯絡我請加QQ好友 646634621 ,註明新增緣由

● 於 2020-04-01 06:00 ~ 2020-04-30 24:00 在西安完成

● 最新修改時間:2020-04-01 06:00 ~ 2020-04-30 24:00

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

........................................................................................................................

小麥苗的微店

小麥苗出版的資料庫類叢書http://blog.itpub.net/26736162/viewspace-2142121/

小麥苗OCP、OCM、高可用網路班http://blog.itpub.net/26736162/viewspace-2148098/

小麥苗騰訊課堂主頁https://lhr.ke.qq.com/

........................................................................................................................

使用 微 信客戶端掃描下面的二維碼來關注小麥苗的微 信公眾號( DB寶)及QQ群(DBA寶典)、新增小麥苗微 信, 學習最實用的資料庫技術。

........................................................................................................................

歡迎與我聯絡

 

 



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2684761/,如需轉載,請註明出處,否則將追究法律責任。

相關文章