天天看點

Docker三劍客之Docker Swarm

一、什麼是Docker Swarm

Docker三劍客之Docker Swarm

  Swarm是Docker公司推出的用來管理docker叢集的平台,幾乎全部用GO語言來完成的開發的,代碼開源在https://github.com/docker/swarm, 它是将一群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三劍客之Docker Swarm

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

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

三.Swarm的幾個關鍵概念

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

Docker三劍客之Docker Swarm

2. Service

Docker三劍客之Docker Swarm

3. 任務與排程

Docker三劍客之Docker Swarm

4. 服務副本與全局服務

Docker三劍客之Docker Swarm

五、Swarm的排程政策

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)批量建立服務
建立容器之前先建立一個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) 修改主機名
# 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 [email protected]:/etc/hosts
[root@manager43 ~]# scp /etc/hosts [email protected]:/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) 建立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為例)

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) 檢視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教程)

溫馨提示:
我們這裡要部署的服務有三個(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三劍客之Docker Swarm
Docker三劍客之Docker Swarm
Docker三劍客之Docker Swarm
Docker三劍客之Docker Swarm
Docker三劍客之Docker Swarm

八、Docker Swarm 容器網絡

在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,整個網絡結構如下圖所示:
      

 

Docker三劍客之Docker Swarm

加入ngx_net網絡的容器彼此之間可以通過IP位址通信,也可以通過名稱通信。

[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連通性的正确的工具。      

作者:朱敬志

出處:https://www.cnblogs.com/zhujingzhi/

-------------------------------------------

個性簽名:在逆境中要看到生活的美,在希望中别忘記不斷奮鬥

如果覺得這篇文章對你有小小的幫助的話,記得在右下角點個“推薦”哦,部落客在此感謝!

萬水千山總是情,打賞一分行不行,是以如果你心情還比較高興,也是可以掃碼打賞部落客,哈哈哈(っ•̀ω•́)っ✎⁾⁾!

Docker三劍客之Docker Swarm
Docker三劍客之Docker Swarm

也可以關注我的微信公衆号,不定時更新技術文章(kubernetes,Devops,Python)等

Docker三劍客之Docker Swarm

繼續閱讀