Docker三劍客之Docker Swarm

1、什麼是Docker Swarm

  Swarm是Docker公司推出的用來管理docker集羣的平臺,幾乎所有用GO語言來完成的開發的,代碼開源在https://github.com/docker/swarm, 它是將一羣Docker宿主機變成一個單一的虛擬主機,Swarm使用標準的Docker API接口做爲其前端的訪問入口,換言之,各類形式的Dockerhtml

Client(compose,docker-py等)都可以直接與Swarm通訊,甚至Docker自己均可以很容易的與Swarm集成,這大大方便了用戶將本來基於單節點的系統移植到Swarm上,同時Swarm內置了對Docker網絡插件的支持,用戶也很容易的部署跨主機的容器集羣服務。前端

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

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

  Swarm deamon只是一個調度器(Scheduler)加路由器(router),Swarm本身不運行容器,它只是接受Docker客戶端發來的請求,調度適合的節點來運行容器,這就意味着,即便Swarm因爲某些緣由掛掉了,集羣中的節點也會照常運行,放Swarm從新恢復運行以後,他會收集重建集羣信息。git

2、Docker Swarm 基本結構圖

在結構圖能夠看出 Docker Client使用Swarm對 集羣(Cluster)進行調度使用。github

上圖能夠看出,Swarm是典型的master-slave結構,經過發現服務來選舉manager。manager是中心管理節點,各個node上運行agent接受manager的統一管理,集羣會自動經過Raft協議分佈式選舉出manager節點,無需額外的發現服務支持,避免了單點的瓶頸問題,同時也內置了DNS的負載均衡和對外部負載均衡機制的集成支持web

三.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容器並在容器中執行任務。

4、Swarm的工做模式

1. Node算法

2. Servicedocker

3. 任務與調度shell

4. 服務副本與全局服務

 

5、Swarm的調度策略

Swarm在調度(scheduler)節點(leader節點)運行容器的時候,會根據指定的策略來計算最適合運行容器的節點,目前支持的策略有:spread, binpack, random.
1)Random
顧名思義,就是隨機選擇一個Node來運行容器,通常用做調試用,spread和binpack策略會根據各個節點的可用的CPU, RAM以及正在運
行的容器的數量來計算應該運行容器的節點。
 
2)Spread
在同等條件下,Spread策略會選擇運行容器最少的那臺節點來運行新的容器,binpack策略會選擇運行容器最集中的那臺機器來運行新的節點。
使用Spread策略會使得容器會均衡的分佈在集羣中的各個節點上運行,一旦一個節點掛掉了只會損失少部分的容器。
 
3)Binpack
Binpack策略最大化的避免容器碎片化,就是說binpack策略儘量的把還未使用的節點留給須要更大空間的容器運行,儘量的把容器運行在
一個節點上面。

6、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"
能夠看到任務運行在哪一個節點上。容器啓動後,有時須要等待一段時間才能完成容器建立。

7、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) 修改主機名
# 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加速器配置教程

二、建立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

三、在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任務實例)所有刪除了

四、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

五、多服務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

測試

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

 

加入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連通性的正確的工具。
相關文章
相關標籤/搜索