接之前的文章:
容器技术|Docker三剑客之docker-machine
容器技术|Docker三剑客之Compose
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<
192.168.22.177 manager
192.168.22.175 node1
192.168.22.178 node2
EOF
[root@manager ~]# tail -3 /etc/hosts
192.168.22.177 manager
192.168.22.175 node1
192.168.22.178 node2
[root@manager ~]# ping node1
PING node1 (192.168.22.175) 56(84) bytes of data.
64 bytes from node1 (192.168.22.175): icmp_seq=1 ttl=64 time=3.64 ms
64 bytes from node1 (192.168.22.175): icmp_seq=2 ttl=64 time=1.64 ms
^C
--- node1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1006ms
rtt min/avg/max/mdev = 1.648/2.644/3.641/0.997 ms
[root@manager ~]# ping node2
PING node2 (192.168.22.178) 56(84) bytes of data.
64 bytes from node2 (192.168.22.178): icmp_seq=1 ttl=64 time=9.70 ms
64 bytes from node2 (192.168.22.178): icmp_seq=2 ttl=64 time=1.95 ms
^C
--- node2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 1.951/5.826/9.701/3.875 ms
#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
root 11981 1 1 10: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
root 11986 11981 0 10:55 ? 00:00:00 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc --runtime-args --systemd-cgroup=true
root 12076 11823 0 10:55 pts/0 00:00:00 grep --color=auto docker
[root@manager ~]# lsof -i :2375
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dockerd-c 11981 root 5u IPv6 41829 0t0 TCP *: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) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya \
192.168.22.177:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow 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 swarm as a worker.
[root@node2 ~]# docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
This node joined a swarm as a worker.
#如果加入集群时报错如下
[root@node1 ~]# docker swarm join --token SWMTKN-1-32h92m334z80z270d4duqdc3ysl1oyrjmxe1upyyfjyln12xxa-4gm603mczorxgh6751n5q7jya 192.168.22.177:2377
Error response from daemon: rpc error: code = 13 desc = 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: Pulling from docker.io/portainer/portainer
d1e017099d17: Pull complete
0d90a7ef0797: Pull complete
Digest: sha256:2933caa6e578e94b5d91429ea7f47ae9741ee11b71d7cb740e76c5f234cc1d87
Status: Downloaded newer image for docker.io/portainer/portainer:latest
798b3bea009792321519f5b7144e357ce9c5cea3b9341b5276a4d29f7571684a
[root@manager ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
798b3bea0097 portainer/portainer "/portainer" 6 seconds ago Up 5 seconds 0.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 bridge local
c737cf269524 docker_gwbridge bridge local
pmn1fi6lj421 dockernet overlay swarm
eac1d68d35d7 host host local
wxshzhdvq52y ingress overlay swarm
c5986aec6119 none null local
复制代码
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 replicated 1/1 nginx:latest
[root@manager ~]# docker service ps nginx-cluster
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7t7xjpmao533 nginx-cluster.1 nginx:latest manager Running Running 17 seconds ago
[root@manager ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9d78079fdc7 nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0 "nginx -g 'daemon ..." 22 seconds ago Up 22 seconds 80/tcp nginx-cluster.1.7t7xjpmao5335zaa8wp0c896a
复制代码
3、在线动态扩容服务
[root@manager ~]# docker service scale nginx-cluster=5
nginx-cluster scaled to 5
[root@manager ~]# docker service ps nginx-cluster
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7t7xjpmao533 nginx-cluster.1 nginx:latest manager Running Running 2 hours ago
vitsgxpdf3bn nginx-cluster.2 nginx:latest manager Running Running 2 seconds ago
o9w529mmttsw nginx-cluster.3 nginx:latest node1 Running Preparing 2 seconds ago
cfz8dkx9p6ih nginx-cluster.4 nginx:latest node2 Running Preparing 2 seconds ago
9p35iunijoro nginx-cluster.5 nginx:latest node2 Running Preparing 2 seconds ago
#从输出结果可以看出已经将服务动态扩容至5个,也就是5个容器运行着相同的服务
[root@node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f3a4fb24480a nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0 "nginx -g 'daemon ..." 3 minutes ago Up 3 minutes 80/tcp nginx-cluster.5.9p35iunijorol1d2ikhyj11oi
f8b0b2e514eb nginx@sha256:3e2ffcf0edca2a4e9b24ca442d227baea7b7f0e33ad654ef1eb806fbd9bedcf0 "nginx -g 'daemon ..." 3 minutes ago Up 3 minutes 80/tcp nginx-cluster.4.cfz8dkx9p6ih40lwwwvd96xdg
#登录node2查看正在运行的容器,发现与管理节点上显示的结果相同,node2上运行两个容器
复制代码
4、节点故障
[root@manager ~]# docker service ps nginx-cluster
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7t7xjpmao533 nginx-cluster.1 nginx:latest manager Running Running 2 hours ago
vitsgxpdf3bn nginx-cluster.2 nginx:latest manager Running Running 10 minutes ago
f13cun1wyxlt nginx-cluster.3 nginx:latest manager Running Running 9 minutes ago
q60fo5mja1ab \_ nginx-cluster.3 nginx:latest node1 Shutdown Failed 9 minutes ago "starting container failed: sh…"
mao4htxp7afr \_ nginx-cluster.3 nginx:latest node1 Shutdown Failed 9 minutes ago "starting container failed: sh…"
fhiecco742y4 \_ nginx-cluster.3 nginx:latest node1 Shutdown Failed 10 minutes ago "starting container failed: sh…"
8qp5kryo62ha \_ nginx-cluster.3 nginx:latest node1 Shutdown Failed 10 minutes ago "starting container failed: sh…"
cfz8dkx9p6ih nginx-cluster.4 nginx:latest node2 Running Running 9 minutes ago
9p35iunijoro nginx-cluster.5 nginx:latest node2 Running Running 9 minutes ago
#如果集群中节点发生故障,会从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:
create Create a new service
inspect Display detailed information on one or more services
ls List services
ps List the tasks of a service
rm Remove one or more services
scale Scale one or multiple replicated services
update Update a service
Run 'docker service COMMAND --help' for more information on a command.
[root@manager ~]# docker rm nginx-cluster
#将所有节点上的所有容器全部删除,任务也将全部删除复制代码