docker相關--開始使用swarm模式


Swarm簡介

Swarm 模式簡介

  • 要在Swarm模式下運行docker,需要先安裝docker,參考安裝教程
  • 當前版本的docker包含了swarm模式,用於管理docker集群。可以使用命令行來創建swarm集群,部署應用,管理swarm的行為。
  • 如果你使用低於1.12.0版本的docker,可以使用獨立模式的是swarm,但是建議使用最新版本

特性

  • 與docker集成的集群管理工具
  • 去中心化設計,只使用docker引擎即可創建各類節點
  • 聲明式服務模型。可以聲明的方式來定義應用。
  • 動態伸縮。管理節點自動調整服務數量。
  • 高可用,對於服務期望狀態做到動態調整,swarm的管理節點會持續監控集群狀態,集群中有沒有達到期望狀態的服務,管理節點會自動調度來達到期望狀態。
  • 自定義網絡。可以為你的服務指定一個網絡,容器創建的時候分配一個IP
  • 服務發現。管理節點給集群中每個服務一個特定的DNS名字,並給運行的容器提供負載均衡。
  • 負載均衡。你可以暴露服務端口給外部的負載均衡。內部swarm提供可配置的容器分配到節點的策略。
  • 默認的安全機制。swarm集群中各個節點強制TLS協議驗證。連接加密,你可以自定義根證書。
  • 滾動更新。增量跟新,可以自定義更新下個節點的時間間隔,如果有問題,可以會滾到上個版本。

Swarm主要概念

開始使用Swarm模式

  • 本教程進行如下指導:
    • 在swarm模式下初始化一個基於docker引擎的swarm集群
    • 在swarm集群中添加節點
    • 部署應用服務到swarm集群中
    • 管理swarm集群
  • 本教程使用docker命令行的方式交互

安裝

  • 安裝環境要求:
    • 3台可以網絡通信的Linux主機,並且安裝了docker
    • 安裝1.12.0以上的docker
    • 管理節點的IP地址
    • 主機之間開放端口
准備3台主機
  • 3台主機可以是物理機,虛擬機,雲主機,甚至是docker machine創建的主機。並安裝docker。三台主機分別是manager1,work1和worker2.
安裝1.12.0以上的docker
管理節點的IP地址
  • 所有swarm集群中的節點都會連接到管理節點的IP地址
主機間開放端口
  • 以下端口必須是開放的:
    • TCP port 2377為集群管理通信
    • TCP and UDP port 7946 為節點間通信
    • UDP port 4789 為網絡間流量
  • 如果你想使用加密網絡(--opt encrypted)也需要確保ip protocol 50 (ESP)是可用的

創建一個Swarm集群

  • 完成上面的開始過程后,可以開始創建一個swarm集群。確保docker的后台應用已經在主機上運行了。
  1. 登陸到manager1上,如果使用docker-machine創建的主機,可以docker-machine ssh manager1
  2. 運行以下命令來創建一個新的swarm集群:
docker swarm init --advertise-addr <MANAGER1-IP>
  • 本教程中使用如下命令在manager1上創建swarm集群:
james@james-CW65:~ > docker swarm init --advertise-addr 192.168.99.1
Swarm initialized: current node (5n1l6261akogeuxysrgn2ipxz) is now a manager.

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

    docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momddh5kru 192.168.99.1:2377

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

  • --advertise-addr選項表示管理節點公布它的IP是多少。其它節點必須能通過這個IP找到管理節點。
  • 命令輸出了加入swarm集群的命令。通過--token選項來判斷是加入為管理節點還是工作節點
  1. 運行docker info來查看當前swarm集群的狀態:
james@james-CW65:~ > docker info
Containers: 4
 Running: 2
 Paused: 0
 Stopped: 2
Images: 7
Server Version: 17.12.0-ce
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 37
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: active
 NodeID: 5n1l6261akogeuxysrgn2ipxz
 Is Manager: true
 ClusterID: nhkp9f1l5yq76e0zu0bage2h4
 Managers: 1
 Nodes: 1
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot Interval: 10000
  Number of Old Snapshots to Retain: 0
  Heartbeat Tick: 1
  Election Tick: 3
 Dispatcher:
  Heartbeat Period: 5 seconds
 CA Configuration:
  Expiry Duration: 3 months
  Force Rotate: 0
 Autolock Managers: false
 Root Rotation In Progress: false
 Node Address: 192.168.99.1
 Manager Addresses:
  192.168.99.1:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 89623f28b87a6004d4b785663257362d1658a729
runc version: b2567b37d7b75eb4cf325b77297b140ea686ce8f
init version: 949e6fa
Security Options:
 apparmor
Kernel Version: 3.19.0-32-generic
Operating System: Ubuntu 14.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 3.755GiB
Name: james-CW65
ID: EMVF:D3TL:KMEY:2QTR:HESQ:J5ZA:WDYM:GSEV:INSU:Z4QI:DCIX:LMGK
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

  1. 運行docker node ls來查看節點信息:
james@james-CW65:~ > docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
5n1l6261akogeuxysrgn2ipxz *   james-CW65          Ready               Active              Leader
  • nodeId旁邊的*號表示你當前連接到的節點。
  • docker引擎的swarm模式自動使用宿主機的主機名作為節點名。

將節點加入到swarm集群中

  • 一旦前面的創建swarm集群完成,你就可以加入工作節點了。
  1. ssh到要加入集群的節點上,我們要加入worker1.
  2. 運行創建swarm集群時候產生的命令來將woker1加入到集群中:
docker@default:~$ docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momd
dh5kru 192.168.99.1:2377
This node joined a swarm as a worker.
  • 如果你找不到加入命令了,可以在管理節點運行下列命令找回加入命令:
james@james-CW65:~ > docker swarm join-token worker
To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momddh5kru 192.168.99.1:2377

  1. ssh到worker2
  2. 運行加入集群的命令來將worker2加入到集群:
Boot2Docker version 17.12.0-ce, build HEAD : 378b049 - Wed Dec 27 23:39:20 UTC 2017
Docker version 17.12.0-ce, build c97c6d6
docker@lab:~$ docker swarm join --token SWMTKN-1-2bgkinnbc0rmlj6kpotyrlj0uz51l2ikinttsk960dxro558x4-6zajfnahtv9ye39momddh5k
ru 192.168.99.1:2377
This node joined a swarm as a worker.
  1. ssh到manager節點運行docker node ls命令來查看集群節點情況:
james@james-CW65:~ > docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
k89s71elf81vbn7pytwszmgr5     default             Ready               Active
5n1l6261akogeuxysrgn2ipxz *   james-CW65          Ready               Active              Leader
ye5x8hci1chmo8nyjx8y4thhy     lab                 Ready               Active
  • MANAGER列表明了集群中的管理節點。worker節點的空意味着它們是工作節點

在swarm集群上部署一個服務

  • 在創建一個swarm集群后,就可以部署服務了。本教程中你也可以加入工作節點,但是不是必須的。
  1. ssh到manager節點
  2. 運行如下命令:
james@james-CW65:~ > docker service create --replicas 1 --name helloworld alpine ping docker.com
060zo3u0g3mjdmrilezzbckbe
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
  • docker service create用來創建服務
  • --name表明服務名字是helloworld
  • --replicas 表示期望1個服務實例
  • alpine ping docker.com 表示運行鏡像是alpine,命令是ping
  1. 運行docker service ls來查看運行的服務:
james@james-CW65:~ > docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
060zo3u0g3mj        helloworld          replicated          1/1                 alpine:latest

檢查Swarm集群上的服務

  • 在你部署服務到Swarm集群上后,可以使用命令行來檢查運行的服務
  1. ssh到管理節點
  2. 運行命令docker service inspect --pretty 來查看優化顯示的服務詳情
james@james-CW65:~ > docker service inspect --pretty 060zo3u0g3mj

ID:		060zo3u0g3mjdmrilezzbckbe
Name:		helloworld
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:		alpine:latest@sha256:7b848083f93822dd21b0a2f14a110bd99f6efb4b838d499df6d04a49d0debf8b
 Args:		ping docker.com
Resources:
Endpoint Mode:	vip
  • 去掉--pretty選項將以json格式輸出
  1. 運行docker service ps 將查看到哪些節點在運行該服務實例:
james@james-CW65:~ > docker service ps  060zo3u0g3mj
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
cbiq1ne3ij9a        helloworld.1        alpine:latest       james-CW65          Running             Running 9 minutes ago
  • 服務可能運行在管理或工作節點上,默認的管理節點可以像工作節點一樣運行任務。
  • 該命令也顯示服務期望的狀態DESIRED STATE ,和實際的狀態CURRENT STATE。
  1. 在運行任務的節點上運行docker ps也能看到這個任務運行的容器
james@james-CW65:~ > docker ps
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                                                                    NAMES
cad59e7398de        alpine:latest           "ping docker.com"        2 minutes ago       Up 2 minutes                                                                                 helloworld.1.ngbknb89dzyxdas81emw0jz63

在swarm集群中動態伸縮服務實例數

  • 一旦你在swarm集群中部署一個服務后,你就可以使用命令行來改變服務的實例個數。在服務中運行的容器稱為“任務”
  1. ssh到manager節點
  2. 運行以下命令來改變服務的期望實例數:
james@james-CW65:~ > docker service scale 060zo3u0g3mj=3
060zo3u0g3mj scaled to 3
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Waiting 1 seconds to verify that tasks are stable...
verify: Service converged
  1. 運行以下命令來查看更新的任務列表:
james@james-CW65:~ > docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
060zo3u0g3mj        helloworld          replicated          3/3                 alpine:latest
james@james-CW65:~ > docker service ps 060zo3u0g3mj
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR                       PORTS
ngbknb89dzyx        helloworld.1        alpine:latest       james-CW65          Running             Running 9 minutes ago
cbiq1ne3ij9a         \_ helloworld.1    alpine:latest       james-CW65          Shutdown            Failed 9 minutes ago         "task: non-zero exit (1)"
3fl3mfrvubu1        helloworld.2        alpine:latest       default             Running             Running about a minute ago
hy5pqcmqfw67        helloworld.3        alpine:latest       lab                 Running             Running about a minute ago
  • 可以看到這3個任務被分布到了集群中的不同節點
  1. ssh到運行服務的主機上運行docker ps查看運行的容器:
docker@default:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
cad897086027        alpine:latest       "ping docker.com"   4 minutes ago       Up 4 minutes                            helloworld.2.3fl3mfrvubu1hf16argabe5qt

從swarm集群上刪除應用

  • 接下來刪除應用
  1. ssh到管理節點
  2. 運行docker service rm helloworld來刪除服務:
james@james-CW65:~ > docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
060zo3u0g3mj        helloworld          replicated          3/3                 alpine:latest
james@james-CW65:~ > docker service rm 060zo3u0g3mj
060zo3u0g3mj
james@james-CW65:~ > docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
  1. 運行docker service inspect 會發現服務不存在了
james@james-CW65:~ > docker service inspect  060zo3u0g3mj
[]
Status: Error: no such service: 060zo3u0g3mj, Code: 1
  1. 盡管服務不存在了,任務容器還需要幾秒鍾來清理,你可以在節點上docker ps查看任務什么時候被移除。

滾動更新

  • 在前面的章節中,修改了實例數。本節使用Ghost0.11.12 鏡像來部署服務,然后滾動升級到Ghost1.21.3
  1. ssh到管理節點
  2. 部署Ghost0.11.12 服務,配置10s的更新間隔:
james@james-CW65:~ > docker service create --replicas 2 --name ghost --update-delay 10s ghost:0.11.12
tynb9d9pu0nqm7f1vmmffy9j0
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged
  • 注意:教程使用的是redis鏡像,我使用的是Ghost博客鏡像,拉
  • 在服務部署階段就指定滾動升級策略
  • --update-delay配置了更新服務的時間間隔,你可以指定時間T為秒是Ts,分是Tm,或時是Th,所以10m30s就是10分30秒的延遲
  • 默認的調度器scheduler一次更新一個任務.你可以傳入參數--update-parallelism來配置調度器同時更新的最大任務數量
  • 默認的當一個更新任務返回RUNNING狀態后,調度器才調度另一個更新任務,直到所有任務都更新了。如果更新過程中任何任務返回了FAILED,調度器就會停止更新。你可以給命令docker service create or docker service update配置配置--update-failure-action,來配置這個行為。
  1. 查看redis服務:
james@james-CW65:~ > docker service inspect --pretty ghost

ID:		tynb9d9pu0nqm7f1vmmffy9j0
Name:		ghost
Service Mode:	Replicated
 Replicas:	2
Placement:
UpdateConfig:
 Parallelism:	1
 Delay:		10s
 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:		ghost:0.11.12@sha256:45811b5a50254bdf0a05d683ddf1dd9eb1be98640305fb82317bcaa35a00c20e
Resources:
Endpoint Mode:	vip
  1. 現在可以更新redis的容器鏡像了。運行以下命令,swarm的管理節點將會根據更新策略UpdateConfig來更新各個節點:
james@james-CW65:~ > docker service update --image ghost:1.21.3 ghost
ghost
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged
  • 調度器依照以下步驟來滾動更新:
    • 停止第一個任務
    • 對停止的任務進行更新
    • 對更新的任務進行啟動
    • 如果更新的任務返回RUNNING,等待特定間隔后啟動下一個任務
    • 如果在任何更新的時間,任務返回了FAILED,則停止更新。
  1. 運行命令docker service inspect --pretty redis來查看新鏡像的期望狀態,可以看到顯示了UpdateStatus完成。
james@james-CW65:~ > docker service  inspect  --pretty ghost

ID:		tynb9d9pu0nqm7f1vmmffy9j0
Name:		ghost
Service Mode:	Replicated
 Replicas:	2
UpdateStatus:
 State:		completed
 Started:	2 minutes ago
 Completed:	2 minutes ago
 Message:	update completed
Placement:
UpdateConfig:
 Parallelism:	1
 Delay:		10s
 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:		ghost:1.21.3@sha256:4c8868f41180589583e6eb208a8529ca8dad3d18bddf56834740b715f3e6b691
Resources:
Endpoint Mode:	vip
james@james-CW65:~ >
  • 如果中間有升級失敗的,則會顯示如下信息:
$ docker service inspect --pretty redis

ID:             0u6a4s31ybk7yw2wyvtikmu50
Name:           redis
...snip...
Update status:
 State:      paused
 Started:    11 seconds ago
 Message:    update paused due to failure or early termination of task 9p7ith557h8ndf0ui9s0q951b
...snip...

  • 重新開始一個升級過程:docker service update
  • 為了避免重復失敗升級,要重新配置服務服務,添加適當的參數在運行docker service update
  1. 運行docker service ps 來查看本次滾動更新的過程:
james@james-CW65:~ > docker service ps ghost
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
5ae8hwemegrg        ghost.1             ghost:1.21.3        james-CW65          Running             Running 54 seconds ago
akwqfsarjvy1         \_ ghost.1         ghost:0.11.12       james-CW65          Shutdown            Shutdown 54 seconds ago
hzzq00ckovdg        ghost.2             ghost:1.21.3        default             Running             Running 41 seconds ago
ivtd60xuggk0         \_ ghost.2         ghost:0.11.12       default             Shutdown            Shutdown 42 seconds ago
james@james-CW65:~ >
  • 注意升級后老的容器只是停止了,並沒有刪除
docker@default:~$ docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                     PORTS               NAMES
f855c00da7b7        ghost:1.21.3             "docker-entrypoint.s…"   6 minutes ago       Up 6 minutes               2368/tcp            ghost.2.hzzq00ckovdgb48373lwn8xp6
c151f3535a3b        ghost:0.11.12            "docker-entrypoint.s…"   32 minutes ago      Exited (0) 6 minutes ago                       ghost.2.ivtd60xuggk0y56oguehtirni

從集群中下線一個節點

  • 前面的教程中管理節點會把任務分配給ACTIVE的節點,所有ACTIVE的節點都能接到任務
  • 有時候,例如特定的維護時間,我們就需要從集群中下線一個節點。下線節點使節點不會接受新任務,管理節點會停止該節點上的任務,分配到別的ACTIVE的節點上。
  • 注意:下線一個節點不移除節點中的獨立容器,如docker run,docker-compose up或docker API啟動的容器都不會刪除。節點的狀態僅影響集群服務的負載是否分到該節點。
  1. ssh到manageer1
  2. 運行docker node ls,驗證所有節點都是ACTIVE的:
james@james-CW65:~ > docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
k89s71elf81vbn7pytwszmgr5     default             Ready               Active
5n1l6261akogeuxysrgn2ipxz *   james-CW65          Ready               Active              Leader
  1. 如果弄的redis服務還沒有從滾動更新中起來,需要啟動起來:
  2. 運行docker service ps redis查看管理節點如何分配任務到不同節點:
james@james-CW65:~ > docker service ps ghost
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
5ae8hwemegrg        ghost.1             ghost:1.21.3        james-CW65          Running             Running 19 minutes ago
akwqfsarjvy1         \_ ghost.1         ghost:0.11.12       james-CW65          Shutdown            Shutdown 19 minutes ago
hzzq00ckovdg        ghost.2             ghost:1.21.3        default             Running             Running 19 minutes ago
ivtd60xuggk0         \_ ghost.2         ghost:0.11.12       default             Shutdown            Shutdown 19 minutes ago
  1. 運行docker node update --availability drain 來下線一個節點:
james@james-CW65:~ > docker node update --availability drain default
default
  1. 運行以下來檢查節點的可用性:
  • 可以看到該節點的可用性是Drain
james@james-CW65:~ > docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
k89s71elf81vbn7pytwszmgr5     default             Ready               Drain
5n1l6261akogeuxysrgn2ipxz *   james-CW65          Ready               Active              Leader
james@james-CW65:~ > docker node inspect --pretty default
ID:			k89s71elf81vbn7pytwszmgr5
Hostname:              	default
Joined at:             	2018-02-28 06:25:23.718220559 +0000 utc
Status:
 State:			Ready
 Availability:         	Drain
 Address:		192.168.99.100
Platform:
 Operating System:	linux
 Architecture:		x86_64
Resources:
 CPUs:			1
 Memory:		995.9MiB
Plugins:
 Log:		awslogs, fluentd, gcplogs, gelf, journald, json-file, logentries, splunk, syslog
 Network:		bridge, host, macvlan, null, overlay
 Volume:		local
Engine Version:		17.12.0-ce
Engine Labels:
 - provider=virtualbox
TLS Info:
 TrustRoot:
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIUJdysIbjEKr/Xr+SvWKd8S0UpgqcwCgYIKoZIzj0EAwIw
EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTgwMjI4MDYwNDAwWhcNMzgwMjIzMDYw
NDAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
A0IABFgzZnc/77Zo87KKNrJK83z6ASk1YNHwXYWQvfnyf5aqhLUuOOdGXMgvEj5s
GHGkNitCK2y11XQdSzsRQE5JsGKjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBSaliomGnuL2p+xndnzrIfncS9TezAKBggqhkjO
PQQDAgNIADBFAiA8c7Qn3OA62I4APdAqzwK8z4rNgJug7Nheuo7pOOBybgIhAM5W
t2NvL1EBMjCQZGRk45W/X0C2UN2NQ+cA7CVBHh7I
-----END CERTIFICATE-----

 Issuer Subject:	MBMxETAPBgNVBAMTCHN3YXJtLWNh
 Issuer Public Key:	MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWDNmdz/vtmjzsoo2skrzfPoBKTVg0fBdhZC9+fJ/lqqEtS4450ZcyC8SPmwYcaQ2K0IrbLXVdB1LOxFATkmwYg==
  1. 運行docker service ps redis來查看管理節點是如何重新分配任務的:
  • 可以看到管理節點將下線節點的任務停止了,為了保障副本數量,重新在active的節點上調度了任務。
james@james-CW65:~ > docker service ps ghost
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
5ae8hwemegrg        ghost.1             ghost:1.21.3        james-CW65          Running             Running 21 minutes ago
akwqfsarjvy1         \_ ghost.1         ghost:0.11.12       james-CW65          Shutdown            Shutdown 21 minutes ago
lefwcfo1s44k        ghost.2             ghost:1.21.3        james-CW65          Running             Running 22 seconds ago
hzzq00ckovdg         \_ ghost.2         ghost:1.21.3        default             Shutdown            Shutdown 22 seconds ago
ivtd60xuggk0         \_ ghost.2         ghost:0.11.12       default             Shutdown            Shutdown 21 minutes ago
  1. 運行docker node update --availability active 來重新active該節點:
james@james-CW65:~ > docker node update --availability active default
default
james@james-CW65:~ > docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
k89s71elf81vbn7pytwszmgr5     default             Ready               Active
5n1l6261akogeuxysrgn2ipxz *   james-CW65          Ready               Active              Leader
  1. 查看節點狀態,可以看到節點狀態重新為ACtive:
james@james-CW65:~ > docker node inspect --pretty default
ID:			k89s71elf81vbn7pytwszmgr5
Hostname:              	default
Joined at:             	2018-02-28 06:25:23.718220559 +0000 utc
Status:
 State:			Ready
 Availability:         	Active
 Address:		192.168.99.100
Platform:
 Operating System:	linux
 Architecture:		x86_64
Resources:
 CPUs:			1
 Memory:		995.9MiB
Plugins:
 Log:		awslogs, fluentd, gcplogs, gelf, journald, json-file, logentries, splunk, syslog
 Network:		bridge, host, macvlan, null, overlay
 Volume:		local
Engine Version:		17.12.0-ce
Engine Labels:
 - provider=virtualbox
TLS Info:
 TrustRoot:
  • 當節點重新active的時候,在以下情況下它會重新接受任務:
    • 當一個服務縮容擴容時
    • 在滾動更新的時候
    • 當另一個節點Drain下線的時候
    • 當一個任務在另一個active節點上運行失敗的時候

使用swarm模式的路由網絡

  • docker的swarm模式使服務暴露給外部端口更加方便。所有的節點都在一個路由網絡里。這個路由網絡使得集群內的所有節點都能在開放的端口上接受請求。即使節點上沒有任務運行,這個服務的端口也暴露的。路由網絡路由所有的請求到暴露端口的節點上。
  • 前提是需要暴露以下端口來使節點間能通信
    • Port 7946 TCP/UDP for container network discovery.用於容器間網絡發現
    • Port 4789 UDP for the container ingress network.用於容器進入網絡
  • 你也必須開放節點之間的公開端口,和任何外部資源端口,例如一個外部的負載均衡。
  • 你也可以使特定服務繞過路由網絡

為一個服務暴露端口

  • 使用--publish來在創建一個服務的時候暴露端口。target指明容器內暴露的端口。published指明綁定到路由網絡上的端口。如果不寫published,就會為每個服務綁定一個隨機的高數字端口。你需要檢查任務才能確定端口
james@james-CW65:~ > docker service create --name ghostBlog --publish published=80,target=2368 --replicas 1 ghost:1.21.3
xpnc3ga8yvh71zx5dvq94fbsn
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged
james@james-CW65:~ > docker service ps ghostBlog
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
5a0tepfqasqu        ghostBlog.1         ghost:1.21.3        default             Running             Running 18 seconds ago
  • 注意舊版的語法是冒號分開的published:target,例如 -p 8080:80。新語法更易讀且靈活。
  • 當你在任何節點訪問8080端口時,路由網絡將把請求分發到一個active的容器中。在各個節點,8080端口可能並沒有綁定,但是路由網絡知道如何路由流量,並防止任何端口沖突。
  • 路由網絡監聽各個節點的IP上的 published port 。從外面看,這些端口是各個節點暴露的。對於別的IP地址,只在該主機內可以訪問。
    image
    https://docs.docker.com/engine/swarm/images/ingress-routing-mesh.png
  • 你可以用以下命令給一個已經存在的服務暴露端口。
james@james-CW65:~ > docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
tynb9d9pu0nq        ghost               replicated          2/2                 ghost:1.21.3
xpnc3ga8yvh7        ghostBlog           replicated          1/1                 ghost:1.21.3        *:80->2368/tcp
james@james-CW65:~ > docker service update --publish-add published=8080,target=2368 ghost
ghost
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged
  • 你可以使用docker service inspect來查看服務暴露的端口:
james@james-CW65:~ > docker service inspect --format="{{json .Endpoint.Spec.Ports}}" ghost
[{"Protocol":"tcp","TargetPort":2368,"PublishedPort":8080,"PublishMode":"ingress"}]
james@james-CW65:~ > docker service inspect --format="{{json .Endpoint.Spec.Ports}}" ghostBlog
[{"Protocol":"tcp","TargetPort":2368,"PublishedPort":80,"PublishMode":"ingress"}]
  • The output shows the (labeled TargetPort) from the containers and the (labeled PublishedPort) where nodes listen for requests for the service.

僅暴露一個TCP或UDP端口

  • 默認你暴露的端口都是TCP的。如果你使用長語法(Docker 1.13 and higher),設置protocol為tcp或udp即可暴露相應端口
僅TCP
長語法
$ docker service create --name dns-cache \
  --publish published=53,target=53 \
  dns-cache
短語法
$ docker service create --name dns-cache \
  -p 53:53 \
  dns-cache
TCP和UDP
長語法
$ docker service create --name dns-cache \
  --publish published=53,target=53 \
  --publish published=53,target=53,protocol=udp \
  dns-cache
 短語法
$ docker service create --name dns-cache \
  -p 53:53 \
  -p 53:53/udp \
  dns-cache
只暴露UDP
長語法
$ docker service create --name dns-cache \
  --publish published=53,target=53,protocol=udp \
  dns-cache
短語法
$ docker service create --name dns-cache \
  -p 53:53/udp \
  dns-cache

繞過路由網絡

  • 你可以繞過路由網絡,直接和一個節點上的端口通信,來訪問服務。這叫做Host模式:
    • 如果該節點上沒有服務運行,服務也沒有監聽端口,則可能無法通信。
    • 你不能在一個節點上運行多個服務實例他們綁定同一個靜態target端口。或者你讓docker分配隨機高數字端口(通過空配置target),或者確保該節點上只運行一個服務實例(通過配置全局服務global service 而不是副本服務,或者使用配置限制)。
  • 為了繞過路由網絡,必須使用長格式--publish,設置模式mode為host模式。如果你忽略了mode設置或者設置為內網ingress,則路由網絡將啟動。下面的命令創建了全局應用使用host模式繞過路由網絡:
$ docker service create --name dns-cache \
  --publish published=53,target=53,protocol=udp,mode=host \
  --mode global \
  dns-cache

配置外部的負載均衡

  • 你可以為swarm集群配置外部的負載均衡,或者結合路由網絡使用或者完全不使用:

使用路由網絡

  • 你可以使用一個外部的HAProxy來負載均衡,服務是8080端口上的nginx服務:
    image
  • 在這個例子中負載均衡器和集群節點之間的8080端口必須是開放的。swarm集群節點在一個外部不可訪問的內網中,節點可以與HAProxy通信。
  • 你可以配置負載均衡器分流請求到不同的集群節點,即使節點上沒有服務運行。例如你可以如下配置HAProxy:/etc/haproxy/haproxy.cfg:
global
        log /dev/log    local0
        log /dev/log    local1 notice
...snip...

# Configure HAProxy to listen on port 80
frontend http_front
   bind *:80
   stats uri /haproxy?stats
   default_backend http_back

# Configure HAProxy to route requests to swarm nodes on port 8080
backend http_back
   balance roundrobin
   server node1 192.168.99.100:8080 check
   server node2 192.168.99.101:8080 check
   server node3 192.168.99.102:8080 check
  • 當你請求HAProxy的80端口的時候,它會轉發請求到后端節點。swarm的路由網絡會路由到相應的服務節點。這樣無論任何原因swarm的調度器調度服務到不同節點,都不需要重新配置負載均衡。
  • 你可以配置任何類型的負載均衡來分流請求。關於HAProxy參考 HAProxy documentation

不使用路由網絡

  • 如果不使用路由網絡,配置--endpoint-mode的值為dnsrr,而不是vip。在本例子中沒有一個固定的虛擬IP。Docker為服務做了DNS注冊,這樣一個服務的DNS查詢會返回一系列IP地址。客戶端就可以直接連接其中一個節點。你負責提供這一系列的IP地址,開放端口給你的負載均衡器。參考Configure service discovery.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM