docker入門(9)--docker swarm

docker swarm是docker官方提供的一套容器編排系統。它的架構如下:


1. swarm節點

swarm是一系列節點的集合,而節點可以是一臺裸機或者一臺虛擬機。一個節點能扮演一個或者兩個角色,manager或者worker。

1.1 manager節點

Docker Swarm集群需要至少一個manager節點,節點之間使用Raft consensus protocol進行協同工作。
通常,第一個啟用docker swarm的節點將成為leader,后來加入的都是follower。當前的leader如果掛掉,剩余的節點將重新選舉出一個新的leader。
每一個manager都有一個完整的當前集群狀態的副本,可以保證manager的高可用。

1.2 worker節點

worker節點是運行實際應用服務的容器所在的地方。理論上,一個manager節點也能同時成為worker節點,但在生產環境中,我們不建議這樣做。
worker節點之間,通過control plane進行通信,這種通信使用gossip協議,并且是異步的。

2. stacks, services, and tasks

集群中經常談到的stacks, services, tasks,他們之間的關系。



下面簡單解釋一下這三者的含義:

2.1 services

swarm service是一個抽象的概念,它只是一個對運行在swarm集群上的應用服務,所期望狀態的描述。它就像一個描述了下面物品的清單列表一樣:

  • 服務名稱
  • 使用哪個鏡像來創建容器
  • 要運行多少個副本
  • 服務的容器要連接到哪個網絡上
  • 應該映射哪些端口

2.2 task

在Docker Swarm中,task是一個部署的最小單元,task與容器是一對一的關系。

2.3 stack

stack是描述一系列相關services的集合。我們通過在一個YAML文件中來定義一個stack。

3. 多主機網絡

在前面的章節中,我們學習過單主機網絡,那個時候所有的容器都運行在一個docker host上,他們之間的通信一般使用本地的bridge網絡即可。
在Swarm集群中,我們使用前面也簡單提到過的overlay network driver來讓位于不同主機間的容器進行通信。網絡模式如下圖:



當然你也可以使用第三方提供的其他網絡驅動,但對于swarm,還是推薦它自己的overlay network。

4. 實戰

4.1 創建一個單一節點的swarm

創建一個docker swarm非常簡單,現在假設我們只有一臺服務器(裸機或者虛擬機都行)。運行命令docker swarm init,就可以創建一個swarm集群,并讓它成為manager leader:

[root@node2 ~]# docker swarm init 
Swarm initialized: current node (pvj7k2urt8g5k1ucsao2rpiwu) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-2121w9nkk2qsyrgg477bz2jq26iojd5u1agdfa2b0bi8wxi3rk-00octanaf09agpe9v77nsm670 10.10.10.73:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

上面也告訴了你,如何添加一個新的manager或者worker。
查看swarm node信息:

[root@node2 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
pvj7k2urt8g5k1ucsao2rpiwu *   node2.xxx.com    Ready               Active              Leader              18.06.1-ce
[root@node2 ~]# docker node inspect pvj7k2urt8g5k1ucsao2rpiwu

4.2 使用virtualbox來創建一個swarm集群

上一章Docker Machine,我們講到過,可以使用docker machine結合virtualbox來創建多臺docker虛擬機。下面我們進行實踐:
之前,我們使用docker-machine create --driver virtualbox default已經創建了一臺虛擬機。

[root@node2 ~]# docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v18.06.1-ce

通過上面方式創建的虛擬機,默認都將分配1G的內存。后面創建多臺虛擬機時,請確保你的實驗機器有足夠的內存。

1、創建5臺虛擬機
[root@node2 ~]# for NODE in `seq 1 5`; do docker-machine create --driver virtualbox "node-${NODE}"; done

整個過程需要一段時間,請耐心等待。創建完成后可以通過docker-machine ls查看。

[root@node2 ~]# docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v18.06.1-ce   
node-1    -        virtualbox   Running   tcp://192.168.99.101:2376           v18.06.1-ce   
node-2    -        virtualbox   Running   tcp://192.168.99.102:2376           v18.06.1-ce   
node-3    -        virtualbox   Running   tcp://192.168.99.103:2376           v18.06.1-ce   
node-4    -        virtualbox   Running   tcp://192.168.99.104:2376           v18.06.1-ce   
node-5    -        virtualbox   Running   tcp://192.168.99.105:2376           v18.06.1-ce
2、創建swarm集群

按照下面的腳本創建swarm集群,當然你也可以用命令手動逐個創建:

#!/bin/bash

# 這個腳本用于在創建了5個docker虛擬機之后,創建swarm集群。
# 集群內配置如下:node-1為manager leader,node-2和node-3為manager follower
# node-4和node-5為worker

export IP=$(docker-machine ip node-1)
#ssh登錄到node-1,讓他成為swarm leader
docker-machine ssh node-1 docker swarm init --advertise-addr $IP
#獲取leader的token,方便后面其他主機加入
export JOIN_TOKEN=$(docker-machine ssh node-1 docker swarm join-token worker -q)
for NODE in `seq 2 5`
do
  docker-machine ssh node-${NODE} docker swarm join --token ${JOIN_TOKEN} ${IP}:2377
done
#將node-2和node-3主機提權為manager
docker-machine ssh node-1 docker node promote node-2 node-3

完成后,可以在node-1上查看當前集群節點信息

[root@node2 swarm]# docker-machine ssh node-1 docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
zycyeyod3fctve54efs9oms55 *   node-1              Ready               Active              Leader              18.06.1-ce
cwerk7kvtxybp7fgkicpgxe4y     node-2              Ready               Active              Reachable           18.06.1-ce
l3dtf4l64z3bm5eb1sb4uuq2x     node-3              Ready               Active              Reachable           18.06.1-ce
wg5ptfk4suctqvndjo81dqewq     node-4              Ready               Active                                  18.06.1-ce
wcog4ty7anqdixgm5n7ta8bxb     node-5              Ready               Active                                  18.06.1-ce
3、在集群上部署一個單service的stack

現在我們可以使用這5臺虛擬機組成的集群,來實踐一個案例了。
前面我們提到過,一個stack才是所有相關services的集合,組成一個完整的應用服務。可以通過yaml文本來定義一個stack:

version: "3.5"
services:
  whoami:
    image: training/whoami:latest
    networks:
      - test-net
    ports:
      - 81:8000
    deploy:
      replicas: 6
      update_config:
        parallelism: 2
        delay: 10s
      labels:
        app: sample-app
        enviroment: prod-south
        
networks:
  test-net:
    driver: overlay

解讀:

  • 服務的名稱叫whoami
  • 使用的鏡像為training/whoami:latest
  • 使用了一個自定的網絡test-net
  • 將主機端口81映射至容器內的8000端口。
  • 運行6個副本(也就是task,也對應6個容器)
  • 升級策略:每2個task為一組進行升級,且當前組升級成功后,延遲10秒才開始升級下一組。
  • 定義了兩個標簽。

實際上,還有很多其他的設置,我們這里沒有列出來,它們都有自己的默認值。

請注意,services里面各個service的名字在swarm中必須唯一。

現在,我們使用這個配置文件來部署我們的一個集群服務吧:

# 為了更直觀的查看過程,我們可以登錄到manager leader上進行部署
[root@node2 swarm]# docker-machine ssh node-1
# 在manager leader上創建上面的yaml文件
docker@node-1:~$ vi stack.yaml
docker@node-1:~$ docker stack deploy -c stack.yaml samle-stack
# 創建過程需要一定的時間,請耐心等待
docker@node-1:~$ docker stack ls
NAME                SERVICES            ORCHESTRATOR
samle-stack         1                   Swarm
docker@node-1:~$ docker service ls
ID                  NAME                 MODE                REPLICAS            IMAGE                    PORTS
mjx5rdvluyeb        samle-stack_whoami   replicated          6/6                 training/whoami:latest   *:81->8000/tcp

docker stack deploy執行完成后,我使用docker service ls命令,剛開始在REPLICAS那一欄始終都是看到3/6,代表只啟動了3個task,但是實際應該啟動6個。過一段時候之后,我再次查看發現就是6個都啟動了。我當時猜測,有些node可能是拉取鏡像的時候超時了,導致沒有完全啟動,下面命令的輸出也印證了我的猜測。node1、2、5都自動創建了一個新的task。

docker@node-1:~$ docker service ps samle-stack_whoami
ID                  NAME                       IMAGE                    NODE                DESIRED STATE       CURRENT STATE             ERROR                              PORTS
35gp71dh9sgl        samle-stack_whoami.1       training/whoami:latest   node-4              Running             Running 36 minutes ago                                       
b79jr4suvuc2        samle-stack_whoami.2       training/whoami:latest   node-5              Running             Running 29 minutes ago                                       
noferwnjjr5s         \_ samle-stack_whoami.2   training/whoami:latest   node-5              Shutdown            Rejected 29 minutes ago   "No such image: training/whoam…"   
wd59fklp6ayg        samle-stack_whoami.3       training/whoami:latest   node-1              Running             Running 29 minutes ago                                       
z0gxnngq5ipt         \_ samle-stack_whoami.3   training/whoami:latest   node-1              Shutdown            Rejected 29 minutes ago   "No such image: training/whoam…"   
zcf9x5c61a6f        samle-stack_whoami.4       training/whoami:latest   node-2              Running             Running 29 minutes ago                                       
lb3plbt9b3c2         \_ samle-stack_whoami.4   training/whoami:latest   node-2              Shutdown            Rejected 29 minutes ago   "No such image: training/whoam…"   
xfxk4ngiggf3        samle-stack_whoami.5       training/whoami:latest   node-3              Running             Running 36 minutes ago                                       
m647fsycr4rx        samle-stack_whoami.6       training/whoami:latest   node-4              Running             Running 36 minutes ago
查看node-1節點上運行的容器
docker@node-1:~$ docker container ls
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS               NAMES
39c616331871        training/whoami:latest   "/app/http"         33 minutes ago      Up 33 minutes       8000/tcp            samle-stack_whoami.3.wd59fklp6aygpua8289gt978l
查看服務的詳細信息
docker@node-1:~$ docker service inspect samle-stack_whoami

查看services的日志:

docker@node-1:~$ docker service logs samle-stack_whoami
samle-stack_whoami.4.zcf9x5c61a6f@node-2    | Listening on :8000
samle-stack_whoami.6.m647fsycr4rx@node-4    | Listening on :8000
samle-stack_whoami.1.35gp71dh9sgl@node-4    | Listening on :8000
samle-stack_whoami.2.b79jr4suvuc2@node-5    | Listening on :8000
samle-stack_whoami.5.xfxk4ngiggf3@node-3    | Listening on :8000
samle-stack_whoami.3.wd59fklp6ayg@node-1    | Listening on :8000

下面我們來看看集群的高可用,和狀態一致性(意思是集群始終會保持你所期待的樣子),通過上面的輸出,我們可以看到在node-4上是運行了2個容器的,我們手動的刪除一個容器看看:

docker@node-4:~$ docker container rm -f samle-stack_whoami.6.m647fsycr4rxk2epx542bx8n6
samle-stack_whoami.6.m647fsycr4rxk2epx542bx8n6

我們刪除的是編號為6的容器,samle-stack_whoami.6



以上命令顯示,在node-1上重新啟用了一個新的容器,名稱為:samle-stack_whoami.6。

除了像上面這樣,可能某個容器出現問題。但有些時候,也有可能出現某個節點故障,我們可以用如下命令模擬節點故障:
docker-machine stop node-2
相應的node-2上的task就都會自動轉移到其他主機上。

刪除一個stack或者service可以使用如下命令:
docker stack rm ,將會刪除整個stack以及service,還有主機上的task。
docker service rm,會刪除service,還有主機上的task。

4、在集群上部署一個多service的stack

上面的示例在services中只有一個service,下面我們演示一個多service的。
stack配置文件為:

version: "3.5"
services:
  web:
    image: fundamentalsofdocker/ch08-web:1.0
    networks:
      - pets-net
    ports:
      - 3000:3000
    deploy:
      replicas: 3
  db:
    image: fundamentalsofdocker/ch08-db:1.0
    networks:
      - pets-net
    volumes:
      - pets-data:/var/lib/postgresql/data
      
volumes:
  pets-data:
  
networks:
  pets-net:
    driver: overlay

實際在node-1上運行:

docker@node-1:~$ docker stack deploy -c pet_stack.yaml pets_web
Creating network pets_web_pets-net
Creating service pets_web_web
Creating service pets_web_db
docker@node-1:~$ docker stack ls
NAME                SERVICES            ORCHESTRATOR
pets_web            2                   Swarm
docker@node-1:~$ docker stack ps pets_web
ID                  NAME                 IMAGE                               NODE                DESIRED STATE       CURRENT STATE            ERROR                              PORTS
t4sl5hmq4xbr        pets_web_db.1        fundamentalsofdocker/ch08-db:1.0    node-4              Running             Running 7 minutes ago                                       
arqpt9p3bqws        pets_web_web.1       fundamentalsofdocker/ch08-web:1.0   node-2              Running             Running 7 minutes ago                                       
k05n7x67kmig         \_ pets_web_web.1   fundamentalsofdocker/ch08-web:1.0   node-2              Shutdown            Rejected 7 minutes ago   "No such image: fundamentalsof…"   
sivxrv71npj1        pets_web_web.2       fundamentalsofdocker/ch08-web:1.0   node-3              Running             Running 13 minutes ago                                      
bw2h8z3yd3p0        pets_web_web.3       fundamentalsofdocker/ch08-web:1.0   node-1              Running             Running 13 minutes ago

和上一小節區別不大,下面我們驗證一下web服務是否可用。

docker@node-1:~$ curl http://localhost:3000/pet
<html>
<head>
    <link rel="stylesheet" href="main.css">
</head>
<body>
    <div class="container">
        <h4>Cat Gif of the day</h4>
        <img src="http:&#x2F;&#x2F;ak-hdl.buzzfed.com&#x2F;static&#x2F;2013-10&#x2F;enhanced&#x2F;webdr06&#x2F;15&#x2F;9&#x2F;anigif_enhanced-buzz-25158-1381844793-0.gif"" />
        <p><small>Courtesy: <a >Buzzfeed</a></small></p>
        <p>Delivered to you by container 8c6780b1b264<p>
    </div>
</body>

4.3 swarm的路由網絡

對于上面最后一步的驗證過程,我們可以看到3個web的task分別運行在node1、2、3上,但為什么能夠在node-1節點上通過localhost來訪問web服務,并且得到從node-2上的容器返回的結果呢?這一切都歸功于swarm routing mesh,它的工作原理如下圖:


對于每一個service,docker swarm都會自動的給它分配一個virtual IP,對外暴露的也是這個VIP,當有數據請求達到VIP時,它會進行負載均衡,將請求分配到某一個實際正在運行task的節點上。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容