容器技術|Docker三劍客之docker-swarm
docker-swarm簡介
Swarm是Docker官方提供的一款叢集管理工具,其主要作用是把若干臺Docker主機抽象為一個整體,並且通過一個入口統一管理這些Docker主機上的各種Docker資源。Swarm和Kubernetes比較類似,但是更加輕,具有的功能也較kubernetes更少一些。
swarm叢集提供給使用者管理叢集內所有容器的操作介面與使用一臺Docker主機基本相同。
Swarm叢集目前有兩個版本:V1、V2
1、Swarm v1它是master-slave架構。需要通過服務發現來選舉出管理節點,其它各個節點通過執行agent來接受管理節點的統一管理
2、Swarm v2叢集是自動通過Raft協議分散式選舉出管理節點,不需要配置發現服務,從而避免發現服務的單點故障問題。且它自帶了DNS負載均衡和對外部負載均衡機制的支援
Swarm的基本架構如下圖所示
Swarm一些概念說明
1、Swarm
使用swarmkit嵌入docker Engine中的叢集管理和編排功能。docker容器初始化啟動的一種模式
2、Node
節點,是一個已加入到docker swarm叢集中的一個容器例項。
3、Service
服務主要是在工作節點上執行任務,建立服務時,需要指定容器的映象。
4、Task
任務是在容器中執行的命令
Swarm 工作方式
1、節點
2、服務、任務、容器
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”可以看到任務執行在哪個節點上。容器啟動後,有時需要等待一段時間才能完成容器建立。
Swarm命令列說明
docker swarm:叢集管理
init#初始化叢集
join#將節點加入叢集
join-token#管理加入令牌
leave#從叢集中刪除某個節點,強制刪除加引數--force
update#更新叢集
unlock#解鎖叢集
docker node:節點管理,
demote#將叢集中一個或多個節點降級
inspect#顯示一個或多個節點的詳細資訊
ls#列出叢集中的節點
promote#將一個或多個節點提升為管理節點
rm#從叢集中刪除停止的節點,--force強制刪除引數
ps#列出一個或多個節點上執行的任務
update#更新節點
docker service:服務管理,
create#建立一個新的服務
inspect#列出一個或多個服務的詳細資訊
ps#列出一個或多個服務中的任務資訊
ls#列出服務
rm#刪除一個或多個服務
scale#擴充套件一個或多個服務
update#更新服務
docker stack/deploy:試驗特性,用於多應用部署
安裝佈署swarm叢集服務
1、修改主機名,配置hosts檔案
[root@manager ~]# cat >>/etc/hosts<<EOF
192.168.22.177manager
192.168.22.175node1
192.168.22.178node2
EOF
[root@manager ~]# tail -3 /etc/hosts
192.168.22.177manager
192.168.22.175node1
192.168.22.178node2
[root@manager ~]# ping node1
PINGnode1(192.168.22.175) 56(84) bytes of data.
64 bytesfromnode1(192.168.22.175): icmp_seq
=1ttl=64time=3.64ms
64bytesfromnode1(192.168.22.175): icmp_seq=2ttl=64time=1.64ms
^C
--- node1 ping statistics ---
2packets transmitted,2received,0% packet loss, time1006ms
rtt min/avg/max/mdev =1.648/2.644/3.641/0.997ms
[root@manager ~]# ping node2
PINGnode2(192.168.22.178) 56(84) bytes of data.
64 bytesfromnode2(192.168.22.178): icmp_seq
=1ttl=64time=9.70ms
64bytesfromnode2(192.168.22.178): icmp_seq=2ttl=64time=1.95ms
^C
--- node2 ping statistics ---
2packets transmitted,2received,0% packet loss, time1003ms
rtt min/avg/max/mdev =1.951/5.826/9.701/3.875ms
#node1 node2配置同上一致即可
2、安裝docker環境
具體安裝過程參考前面的文章
配置docker
[root@manager ~]# vim /etc/sysconfig/docker
# /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
OPTIONS='-H 0.0.0.0:2375 -H unix:///var/run/docker.sock --selinux-enabled --log-driver=journald --signature-verification=false'
#所有節點加上上面標記的部分,開啟2375埠
[root@manager ~]# systemctl restart docker
[root@manager ~]# ps -ef|grep docker
root119811110:55?00:00:00/usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json -H 0.0.0.0:2375 -H unix:///var/run/docker.sock --selinux-enabled --log-driver=journald --signature-verification=false--storage-driver overlay2
root1198611981010:55?00:00:00/usr/bin/docker-containerd-current -lunix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0--start-timeout2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc --runtime-args --systemd-cgroup=true
root1207611823010:55pts/000:00:00grep --color=auto docker
[root@manager ~]# lsof -i :2375
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dockerd-c11981root5u IPv6418290t0TCP *:2375(LISTEN)
3、所有節點下載swarm映象檔案
[root@manager ~]# docker pull swarm
Using default tag: latest
Trying to pull repository docker.io/library/swarm ...
latest: Pulling from docker.io/library/swarm
d85c18077b82: Pull complete
1e6bb16f8cb1: Pull complete
85bac13497d7: Pull complete
Digest: sha256:406022f04a3d0c5ce4dbdb60422f24052c20ab7e6d41ebe5723aa649c3833975
Status: Downloaded newer image for docker.io/swarm:latest
[root@manager ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/swarm latest ff454b4a0e84 12 days ago 12.7 MB
4、建立swarm並初始化
[root@manager ~]# docker swarm init --advertise-addr 192.168.22.177
Swarm initialized: current node (elyfa6h1lx5o2s98une5vas4x)isnow a manager.
To add a worker tothisswarm, run the following command:
docker swarm join \
--token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya \
192.168.22.177:2377
To add a manager tothisswarm, run'docker swarm join-token manager'andfollow the instructions.
#執行上面的命令後,當前的伺服器就加入到swarm叢集中,同時會產生一個唯一的token值,其它節點加入叢集時需要用到這個token。
#--advertise-addr 表示swarm叢集中其它節點使用後面的IP地址與管理節點通訊,上面也提示了其它節點如何加入叢集的命令。
5、檢視下當前的資訊
[root@manager ~]# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 1
Server Version: 1.13.1
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: journald
Cgroup Driver: systemd
Plugins:
Volume: local
Network: bridge host macvlan null overlay
**Swarm: active
NodeID: elyfa6h1lx5o2s98une5vas4x
Is Manager: true
ClusterID: vi716cgvw33gzicrfqopasf9p
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
Node Address: 192.168.22.177
Manager Addresses:
192.168.22.177:2377
Runtimes: docker-runc runc
Default Runtime: docker-runc
Init Binary: /usr/libexec/docker/docker-init-current
containerd version: (expected: aa8187dbd3b7ad67d8e5e3a15115d3eef43a7ed1)
runc version: e9c345b3f906d5dc5e8100b05ce37073a811c74a (expected: 9df8b306d01f59d3a8029be411de015b7304dd8f)
init version: 5b117de7f824f3d3825737cf09581645abbe35d4 (expected: 949e6facb77383876aeff8a6944dde66b3089574)
Security Options:
seccomp
WARNING: You're not using the default seccomp profile
Profile: /etc/docker/seccomp.json
Kernel Version: 3.10.0-693.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
Number of Docker Hooks: 3
CPUs: 1
Total Memory: 2.238 GiB
Name: manager
ID: 653Y:7CME:GFPW:35SX:IGZL:UJP7:YSPZ:4OMV:J4EV:Z6FS:WFW2:YYHS
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: bridge-nf-call-ip6tables is disabled
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Registries: docker.io (secure)
[root@manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x * manager Ready Active Leader
#當前節點的資訊,這個*表示當前連線在這個節點上
6、將node1,node2加入到叢集中
[root@node1 ~]# docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
This node joined a swarmasa worker.
[root@node2 ~]# docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
This node joined a swarmasa worker.
#如果加入叢集時報錯如下
[root@node1 ~]# docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
Error responsefromdaemon: rpc error: code =13desc = connection error: desc ="transport: x509: certificate has expired or is not yet valid"
#注意伺服器時間同步問題,解決即可。
7、管理節點檢視叢集節點狀態
[root@manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x * manager Ready Active Leader
tcuv2p8wd6rvmwg39pdav5ozk node1 Ready Active
twytwc5dlp77vu1b7cakks9w2 node2 Ready Active
#swarm叢集中node的AVAILABILITY狀態有兩種:Active、drain。其中actice狀態的節點可以接受管理節點的任務指派;drain狀態的節點會結束任務,也不會接受管理節點的任務指派,節點處於下線狀態。
[root@manager ~]# docker node update --availability drain node2
node2
[root@manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x * manager Ready Active Leader
tcuv2p8wd6rvmwg39pdav5ozk node1 Ready Active
twytwc5dlp77vu1b7cakks9w2 node2 Ready Drain
[root@manager ~]# docker node update --availability active node2
node2
[root@manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
elyfa6h1lx5o2s98une5vas4x * manager Ready Active Leader
tcuv2p8wd6rvmwg39pdav5ozk node1 Ready Active
twytwc5dlp77vu1b7cakks9w2 node2 Ready Active
#在manager節點上檢視狀態資訊
[root@manager ~]# docker node inspect self
[
{
"ID":"elyfa6h1lx5o2s98une5vas4x",
"Version": {
"Index": 9
},
"CreatedAt":"2018-06-14T15:01:19.850821157Z",
"UpdatedAt":"2018-06-14T15:01:20.472379584Z",
"Spec": {
"Role":"manager",
"Availability":"active"
},
"Description": {
"Hostname":"manager",
"Platform": {
"Architecture":"x86_64",
"OS":"linux"
},
"Resources": {
"NanoCPUs": 1000000000,
"MemoryBytes": 2402566144
},
"Engine": {
"EngineVersion":"1.13.1",
"Plugins": [
{
"Type":"Network",
"Name":"bridge"
},
{
"Type":"Network",
"Name":"host"
},
{
"Type":"Network",
"Name":"macvlan"
},
{
"Type":"Network",
"Name":"null"
},
{
"Type":"Network",
"Name":"overlay"
},
{
"Type":"Volume",
"Name":"local"
}
]
}
},
"Status": {
"State":"ready",
"Addr":"127.0.0.1"
},
"ManagerStatus": {
"Leader":true,
"Reachability":"reachable",
"Addr":"192.168.22.177:2377"
}
}
]
Swarm 的Web管理
[root@manager ~]# docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
Unable to find image'portainer/portainer:latest'locally
Trying to pull repository docker.io/portainer/portainer ...
latest: Pullingfromdocker.io/portainer/portainer
d1e017099d17: Pull complete
0d90a7ef0797: Pull complete
Digest: sha256:2933caa6e578e94b5d91429ea7f47ae9741ee11b71d7cb740e76c5f234cc1d87
Status: Downloaded newer imagefordocker.io/portainer/portainer:latest
798b3bea009792321519f5b7144e357ce9c5cea3b9341b5276a4d29f7571684a
[root@manager ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
798b3bea0097 portainer/portainer"/portainer"6seconds ago Up5seconds0.0.0.0:9000->9000/tcp amazing_snyder
瀏覽器訪問
docker-swarm佈署服務
1、佈署服務前創建於個用於叢集內不同主機之間容器通訊的網路
[root@manager ~]# docker network create -d overlay dockernet
pmn1fi6lj421hn1nk7652m41h
[root@manager ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
d913c7a275fe bridge bridgelocal
c737cf269524 docker_gwbridge bridgelocal
pmn1fi6lj421 dockernet overlay swarm
eac1d68d35d7 host hostlocal
wxshzhdvq52y ingress overlay swarm
c5986aec6119 none nulllocal
2、建立服務(nginx為例)
[root@manager ~]# docker service create --replicas 1 --network dockernet --name nginx-cluster -p 80:80 nginx
k7lupo9xu0cnd5ng1g4f7i7jx
#--replicas 指定副本數量
[root@manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
k7lupo9xu0cn nginx-cluster replicated1/1nginx:latest
[root@manager ~]# docker service ps nginx-cluster
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7t7xjpmao533 nginx-cluster.1nginx:latest manager Running Running17seconds ago
[root@manager ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9d78079fdc7 nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0"nginx -g 'daemon ..."22seconds ago Up22seconds80/tcp nginx-cluster.1.7t7xjpmao5335zaa8wp0c896a
3、線上動態擴容服務
[root@manager ~]# docker service scale nginx-cluster=5
nginx-cluster scaled to5
[root@manager ~]# docker service ps nginx-cluster
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7t7xjpmao533 nginx-cluster.1nginx:latest manager Running Running2hours ago
vitsgxpdf3bn nginx-cluster.2nginx:latest manager Running Running2seconds ago
o9w529mmttsw nginx-cluster.3nginx:latest node1 Running Preparing2seconds ago
cfz8dkx9p6ih nginx-cluster.4nginx:latest node2 Running Preparing2seconds ago
9p35iunijoro nginx-cluster.5nginx:latest node2 Running Preparing2seconds ago
#從輸出結果可以看出已經將服務動態擴容至5個,也就是5個容器執行著相同的服務
[root@node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f3a4fb24480a nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0"nginx -g 'daemon ..."3minutes ago Up3minutes80/tcp nginx-cluster.5.9p35iunijorol1d2ikhyj11oi
f8b0b2e514eb nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0"nginx -g 'daemon ..."3minutes ago Up3minutes80/tcp nginx-cluster.4.cfz8dkx9p6ih40lwwwvd96xdg
#登入node2檢視正在執行的容器,發現與管理節點上顯示的結果相同,node2上執行兩個容器
4、節點故障
[root@manager ~]#dockerservicepsnginx-cluster
IDNAMEIMAGENODEDESIREDSTATECURRENTSTATEERRORPORTS
7t7xjpmao533nginx-cluster.1nginx:latestmanagerRunningRunning2hoursago
vitsgxpdf3bnnginx-cluster.2nginx:latestmanagerRunningRunning10minutesago
f13cun1wyxltnginx-cluster.3nginx:latestmanagerRunningRunning9minutesago
q60fo5mja1ab\_nginx-cluster.3nginx:latestnode1ShutdownFailed9minutesago"startingcontainerfailed:sh…"
mao4htxp7afr\_nginx-cluster.3nginx:latestnode1ShutdownFailed9minutesago"startingcontainerfailed:sh…"
fhiecco742y4\_nginx-cluster.3nginx:latestnode1ShutdownFailed10minutesago"startingcontainerfailed:sh…"
8qp5kryo62ha\_nginx-cluster.3nginx:latestnode1ShutdownFailed10minutesago"startingcontainerfailed:sh…"
cfz8dkx9p6ihnginx-cluster.4nginx:latestnode2RunningRunning9minutesago
9p35iunijoronginx-cluster.5nginx:latestnode2RunningRunning9minutesago
#如果叢集中節點發生故障,會從swarm叢集中被T除,然後利用自身的負載均衡及排程功能,將服務排程到其它節點上
5、其它常用命令介紹
除了上面使用scale來實現線上動態擴容、縮容之外,還可以使用update來對服務進行調整
[root@manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
k7lupo9xu0cn nginx-cluster replicated 5/5 nginx:latest
[root@manager ~]# docker service update --replicas 2 nginx-cluster
nginx-cluster
[root@manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
k7lupo9xu0cn nginx-cluster replicated 2/2 nginx:latest
#將服務縮減到2個
[root@manager ~]# docker service update --image nginx:new nginx-cluster
#更新服務的映象版本
[root@manager ~]# docker service --help
Usage: docker service COMMAND
Manage services
Options:
--help Print usage
Commands:
createCreateanewservice
inspect Display detailed informationononeormore services
lsListservices
psListthe tasksofa service
rm Remove oneormore services
scale Scale oneormultiple replicated services
updateUpdatea service
Run'docker service COMMAND --help'formore informationona command.
[root@manager ~]# docker rm nginx-cluster
#將所有節點上的所有容器全部刪除,任務也將全部刪除
歡迎工作一到五年的Java工程師朋友們加入Java架構開發:744677563
群內提供免費的Java架構學習資料(裡面有高可用、高併發、高效能及分散式、Jvm效能調優、Spring原始碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!