輕松搭建 Docker Swarm 集群:從零到一的引流指南
本章將和大家分享 Docker Swarm 集群的搭建過程。廢話不多說,下面我們直接進入主題。
一、Docker Swarm 簡介
1、簡介
Docker Swarm 是 Docker 的集群管理工具。它將 Docker 主機池轉(zhuǎn)變?yōu)閱蝹€虛擬 Docker 主機。Docker Swarm 提供了標準的 Docker API,所有任何已經(jīng)與 Docker 守護程序通信的工具都可以使用 Swarm 輕松地擴展到多個主機。
支持的工具包括但不限于以下各項:
- Dokku
- Docker Compose
- Docker Machine
- Jenkins
2、原理
如下圖所示,swarm 集群由管理節(jié)點(manager)和工作節(jié)點(work node)構(gòu)成。
- swarm mananger:負責整個集群的管理工作包括集群配置、服務管理等所有跟集群有關(guān)的工作。
- work node:即圖中的 available node,主要負責運行相應的服務來執(zhí)行任務(task)。
圖片
3、什么是Docker Swarm?
Swarm是Docker的一個編排工具,在之前我們只是在一臺機器來進行docker的管理:
圖片
但是有時容器并不一定都在一臺主機上,如果是分布式的處于多臺主機上,這時就可以借助于Swarm,Swarm是Docker自帶的編排工具,只要你安裝了Docker就會存在Docker Swarm工具。
圖片
Swarm中的模式是有兩大類節(jié)點,一類是manager節(jié)點,另一類是worker節(jié)點,manager節(jié)點負責服務的創(chuàng)建和調(diào)度,worker節(jié)點主要是運行容器服務,當然manager節(jié)點也是可以運行容器服務的。
圖片
manager節(jié)點狀態(tài)、信息的同步根據(jù)Raft consensus group的網(wǎng)絡進行通信同步的,而worker之間的通信依靠的是Gossip network做到的。
另外一個重要的概念就是service,我們可以在一個manager節(jié)點上創(chuàng)建一個服務,但是可以根據(jù)這一個服務創(chuàng)建多個容器的任務,這些容器任務運行在不同的節(jié)點上。
圖片
4、如何進行Swarm集群的搭建?
- 在swarm模式下初始化一個Swarm集群,并且將當前主機加入到該集群作為manager節(jié)點
- 加入其它節(jié)點到該集群中
- 部署service到該集群中
二、Docker Swarm 集群搭建
1、創(chuàng)建多節(jié)點集群
1)準備多臺Linux服務器
此處我準備了3臺機器:
圖片
其中 192.168.4.250 作為 manager 節(jié)點,其它兩臺作為 worker 節(jié)點。
2)查看Swarm命令
docker swarm --help
圖片
可以看到其中有一個 init 命令,這就是初始化一個Swarm,我們再看看這個 init 的參數(shù):
docker swarm init --help
圖片
可以看到它有很多的參數(shù),其中第一個就是將本機的地址添加進去,讓自己成為一個manager節(jié)點,這樣其它的節(jié)點都可以知道這個節(jié)點的存在。
3)創(chuàng)建一個manager節(jié)點
在此之前我們應該先知道自己本機的ip,以便于“--advertise-addr string”這個參數(shù)使用,查看本機ip:
ip addr
圖片
然后就可以初始化 manager 節(jié)點:
docker swarm init --advertise-addr=192.168.4.250
圖片
[root@localhost ~]# docker swarm init --advertise-addr=192.168.4.250
Swarm initialized: current node (c06ilqppns9dg7c1wsk63egyf) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1o3cg3ppm9ylolsb336cfyxp53a2nurn74s0nnt1r8loaf1w6z-5evpjdk9djt3qfude6smjvr5a 192.168.4.250:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[root@localhost ~]#可以看到已經(jīng)創(chuàng)建了一個 swarm manager 節(jié)點,“--advertise-addr string”參數(shù)的值 192.168.4.250 是自己的ip地址,相當于將自己加入到 swarm 中。在運行的結(jié)果中也說明了其它 worker 加入的方式。
以上輸出,證明已經(jīng)初始化成功。需要把以下這行復制出來,在增加工作節(jié)點時會用到:
docker swarm join --token SWMTKN-1-1o3cg3ppm9ylolsb336cfyxp53a2nurn74s0nnt1r8loaf1w6z-5evpjdk9djt3qfude6smjvr5a 192.168.4.250:2377要向此集群添加一個工作節(jié)點,直接運行以上這個命令即可。
4)開放manager節(jié)點的2377端口
# 查看防火墻狀態(tài)
systemctl status firewalld
# 如果開啟了防火墻則永久放行2377端口
firewall-cmd --add-port=2377/tcp --permanent
# 重新加載防火墻
firewall-cmd --reload
# 查看永久開放的端口
firewall-cmd --permanent --list-ports
圖片
5)創(chuàng)建worker節(jié)點
在創(chuàng)建 manager 節(jié)點時我們知道,要向此集群添加一個工作節(jié)點,直接運行以下這個命令(創(chuàng)建manager節(jié)點的時候復制出來的)即可:
docker swarm join --token SWMTKN-1-1o3cg3ppm9ylolsb336cfyxp53a2nurn74s0nnt1r8loaf1w6z-5evpjdk9djt3qfude6smjvr5a 192.168.4.250:2377此處,我另外再開啟了兩臺 Linux 服務器,將它們加入到 swarm 中成為 worker 節(jié)點:


可以看到已經(jīng)成功了。
6)查看節(jié)點狀態(tài)
需要注意的是查看節(jié)點狀態(tài)只能在 manager 節(jié)點那臺機器上查看,普通節(jié)點無法執(zhí)行查看命令:
docker node ls
圖片
可以看到有三臺機器了。
這時候使用 docker info 命令查看,就可以看到 Swarm 處于激活狀態(tài):
docker info
圖片
2、部署服務到集群中
注意:跟集群管理有關(guān)的任何操作,都是在管理節(jié)點上操作的。
上面我們已經(jīng)將節(jié)點創(chuàng)建好了,現(xiàn)在可以在這些節(jié)點上創(chuàng)建服務了,那么就需要看看 docker service 的幫助信息:
docker service --help
圖片
[root@localhost ~]# docker service --help
Usage: docker service COMMAND
Manage Swarm services
Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services
update Update a service
Run 'docker service COMMAND --help' for more information on a command.
[root@localhost ~]#可以看到有 create 這個命令,可以這樣理解,docker service create 相當于docker run 就是創(chuàng)建容器,只不過在 swarm 中是不同的表現(xiàn)方式。
1)在manager節(jié)點上部署服務
docker service create --name nginx-service nginx
圖片
可以查看是否創(chuàng)建成功:
docker service ls
圖片
可以具體查看這個 service 的內(nèi)容(例如:查看服務運行在哪個節(jié)點上):
docker service ps nginx-service
圖片
查看服務 nginx-service 部署的具體信息:
docker service inspect --pretty nginx-service
圖片
2)擴展集群服務(水平擴展)
我們將上述的 nginx-service 服務擴展到多個節(jié)點。
docker service scale nginx-service=5
圖片
已經(jīng)有5個 nginx-service 服務的容器正在運行了??梢韵瓤纯磗erverice:
docker service ls
圖片
再看看具體的容器數(shù)量:
docker service ps nginx-service
圖片
可以看到5個容器在不同的節(jié)點上,其中有2個在manager節(jié)點,有3個在worker節(jié)點上。
當然,每一個節(jié)點都可以自己查看自己目前運行的容器,比如worker節(jié)點查看自己運行的容器:
docker ps
圖片
3)自動修復
scale在swarm中除了水平擴展外,還有一個作用,那就是修復作用,比如將某一個節(jié)點中的容器刪除掉,那么很快swarm中發(fā)覺并進行修復,最終數(shù)量還是會和原來的保持一致。
假如現(xiàn)在刪除worker中的一個容器:
docker rm -f 容器Id
圖片
我們在manager節(jié)點中查看容器情況:
圖片
可以看到紅色就是我們刪掉的容器,但是后面它又馬上補充了一個,保持了整個系統(tǒng)的穩(wěn)定性。
4)刪除服務
# 語法
docker service rm 服務名稱
# 示例
docker service rm nginx-service
# 查看是否已刪除
docker service ps nginx-service5)停止某個節(jié)點接收新的任務
查看所有的節(jié)點:
docker node ls
圖片
可以看到目前所有的節(jié)點都是Active,可以接收新的任務分配。
停止節(jié)點worker-node1:
docker node update --availability drain worker-node1注意:worker-node1狀態(tài)變?yōu)镈rain。不會影響到集群的服務,只是 worker-node1 節(jié)點不再接收新的任務,集群的負載能力有所下降。
重新激活節(jié)點worker-node1:
docker node update --availability active worker-node1補充知識:
問題1:Docker Swarm中5個8081端口的Spring Boot服務如何對外統(tǒng)一提供訪問入口?
核心方案:Swarm原生Ingress網(wǎng)絡+端口發(fā)布 利用Docker Swarm內(nèi)置的ingress覆蓋網(wǎng)絡和端口映射機制,實現(xiàn)外部請求的統(tǒng)一接入與自動負載均衡,無需額外組件。 實現(xiàn)原理
- Swarm初始化時自動創(chuàng)建ingress網(wǎng)絡,所有對外暴露的服務默認接入
- 節(jié)點上的ipvs進程接收外部請求,根據(jù)健康檢查結(jié)果輪詢轉(zhuǎn)發(fā)到后端task
- 外部訪問任意節(jié)點的映射端口,效果一致(Swarm節(jié)點間自動同步路由規(guī)則) 實操步驟
部署5個Spring Boot副本,對外發(fā)布8081端口(容器內(nèi)8081映射到節(jié)點8081)
dockerservicecreate\
--namespringboot-svc\
--replicas5\
--publish8081:8081\# 關(guān)鍵:對外暴露端口,接入ingress網(wǎng)絡
my-springboot:latest# 你的Spring Boot鏡像- 驗證方式
查看服務狀態(tài)(確認5/5副本運行)
dockerservicels查看task分布節(jié)點
dockerservicepsspringboot-svc測試訪問(任意節(jié)點IP+8081)
curlhttp://<節(jié)點IP>:8081問題2:編譯安裝的Nginx(監(jiān)聽8081)如何負載均衡到Swarm的5個Spring Boot服務?缺點是什么?
核心方案:根據(jù)Nginx部署位置選擇「節(jié)點IP直連」或「Overlay網(wǎng)絡接入」
場景1:Nginx部署在Swarm集群外(獨立主機) 實現(xiàn)方式:硬編碼Swarm節(jié)點IP
http{
upstreamspringboot-backend{
# 填寫Spring Boot服務所在的Swarm節(jié)點IP+8081(需先暴露節(jié)點端口)
server192.168.1.10:8081;
server192.168.1.11:8081;
server192.168.1.12:8081;
# 若某節(jié)點有多個task,重復添加該IP
server192.168.1.10:8081;
}
server{
listen8081;# Nginx監(jiān)聽端口
location/{
proxy_passhttp://springboot-backend;
proxy_set_headerHost$host;
proxy_set_headerX-Real-IP$remote_addr;
}
}
}前提:Spring Boot服務需通過--publish 8081:8081暴露節(jié)點端口。
場景2:Nginx部署在Swarm節(jié)點上(集群內(nèi))
實現(xiàn)方式:接入Swarm自定義Overlay網(wǎng)絡
# 1. 創(chuàng)建自定義Overlay網(wǎng)絡(隔離內(nèi)部通信)
dockernetworkcreate--driveroverlaymy-network
# 2. 重啟Spring Boot服務,加入自定義網(wǎng)絡(不暴露節(jié)點端口)
dockerserviceupdate--network-addmy-networkspringboot-svc
# 3. 啟動臨時容器獲取網(wǎng)絡命名空間(讓編譯Nginx接入Overlay)
dockerrun-d--nametemp-net--networkmy-networkbusyboxsleep3600
PID=$(dockerinspect-f'{{.State.Pid}}'temp-net)
# 4. 停止原Nginx,用nsenter接入網(wǎng)絡后重啟
/usr/local/nginx/sbin/nginx-sstop
nsenter--net=/proc/$PID/ns/net/usr/local/nginx/sbin/nginxNginx配置(通過服務名訪問,無需IP):
http{
upstreamspringboot-backend{
serverspringboot-svc:8081;# Swarm服務名+容器內(nèi)端口(自動解析到所有task)
}
server{
listen8081;
location/{
proxy_passhttp://springboot-backend;
proxy_set_headerHost$host;
}
}
}核心缺點:
- 場景1 硬編碼IP:服務擴縮容/節(jié)點變更需手動改配置,無法自動感知健康實例
- 場景2 網(wǎng)絡接入:需手動維護臨時容器(刪則網(wǎng)絡失效),Nginx重啟需重復執(zhí)行nsenter命令
- 無Swarm自愈能力:Nginx故障需手動重啟,無法自動遷移到其他節(jié)點
問題3:為何建議Nginx和后端服務都用Docker Swarm?優(yōu)點及部署步驟是什么?

完整部署步驟
步驟1:創(chuàng)建自定義Overlay網(wǎng)
# 隔離內(nèi)部服務通信,比默認ingress更安全
dockernetworkcreate--driveroverlaymy-network步驟2:部署Spring Boot服務(內(nèi)部服務,不對外暴露)
dockerservicecreate\
--namespringboot-svc\
--replicas5\
--networkmy-network\# 加入自定義網(wǎng)絡
--restart-conditionany\# 故障自動重啟
my-springboot:latest步驟3:準備Nginx配置文件(nginx.conf)
worker_processesauto;
events{worker_connections1024;}
http{
upstreamspringboot-backend{
serverspringboot-svc:8081;# 服務名解析,自動負載
}
server{
listen8081;
location/{
proxy_passhttp://springboot-backend;
proxy_set_headerHost$host;
proxy_set_headerX-Real-IP$remote_addr;
}
}
}步驟4:部署Nginx服務(對外入口)
dockerservicecreate\
--namenginx-svc\
--replicas2\# 2個副本實現(xiàn)高可用
--networkmy-network\# 加入同一網(wǎng)絡
--publish8081:8081\# 對外暴露入口
--mounttype=bind,source=$(pwd)/nginx.conf,target=/etc/nginx/nginx.conf\# 掛載配置
--restart-conditionany\
nginx:latest步驟5:驗證與更新
驗證服務狀態(tài)
dockerservicels查看實例分布
dockerservicepsnginx-svcspringboot-svc更新Nginx配置(修改后執(zhí)行)
dockerserviceupdate--forcenginx-svc





























