一、什么是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 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
2. Service
3. 任務與調度
4. 服務副本與全局服務
五、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 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) 創建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 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連通性的正確的工具。