环境说明:

主机名 操作系统版本 IP地址 docker版本 说明
manager Ubuntu 16.04.5 172.27.9.71 18.09.2 manager管理主机
work01 Ubuntu 16.04.5 172.27.9.75 18.09.2 worker主机01
work02 Ubuntu 16.04.5 172.27.9.76 18.09.2 worker主机02

本文所有测试都在Vmware虚拟机(版本为12.5.2)上完成
ubuntu安装详见:Ubuntu16.04.5以lvm方式安装全记录
docker安装详见:Ubuntu16.04安装Docker
docker-machine安装详见:docker machine实践

一、简介

Docker实践(六):Docker Swarm

1.Swarm是Docker公司推出的用来管理docker集群的平台,基于GO语言实现,代码开源在https://github.com/docker/swarm, 其核心设计是将几台安装Docker的机器组成一个大的集群,相当于变成一个单一的虚拟主机,该集群提供给用户的管理集群所有容器的操作接口与使用一台Docker几乎相同。
 
2.作为容器集群管理器,Swarm最大的优势之一就是原生支持Docker API,给用户带来极大的便利。各种基于标准API的工具如Compose、Docker SDK、各种管理软件甚至Docker本身都可以很容易的与Swarm集成,这大大方便了用户将原本基于单节点的系统移植到Swarm上,同时Swarm内置了对Docker网络插件的支持,用户也很容易的部署跨主机的容器集群服务。
 
3.Docker Swarm和Docker Compose一样,都是Docker官方容器编排项目,但不同的是Docker Compose是一个在单个服务器或主机上创建多个容器的工具,而Docker Swarm则可以在多个服务器或主机上创建容器集群服务
 
4.从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。

二、基本概念

  • Swarm集群  Swarm集群(Cluster)为一组被统一管理起来的Docker主机。这些主机通过Docker引擎的Swarm模式相互沟通,其中部分主机作为管理节点(manager)响应外部的管理需求,其他主机作为工作节点(worker)来实际运行Docker容器
  • Node  节点(Node)是Swarm集群的最小资源单位,每个节点实际上都是一台Docker主机。节点分为管理节点(manager node)和工作节点(worker node)
  • Service  服务(Service)由多个Task(任务)组成,每个任务为某个具体的应用,Service的所有Task状态对等,Service定义了worker node上要执行的任务
  • Task  任务(Task)是Swarm集群中最小的调度单位,任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点,一个任务包含了一个容器及其运行的命令

Node:
Docker实践(六):Docker Swarm

Service:
Docker实践(六):Docker Swarm

任务与调度:
Docker实践(六):Docker Swarm

replicated services和global services:
Docker实践(六):Docker Swarm

三、功能测试

1. 创建Swarm集群

在管理节点上执行如下命令创建Swarm集群

root@manager:~# docker swarm init --advertise-addr 172.27.9.71
Swarm initialized: current node (prgucud40k77t38uadcq4rboq) is now a manager.

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

    docker swarm join --token SWMTKN-1-3fcb2bna1livym0xvq6b4m4re9dewyxm51ie6su9plog7hr3xd-cutz7yabg6k28dsna83mzgwkt 172.27.9.71:2377

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

默认情况下管理节点也是work节点,如果希望管理节点专用,即不作为work节点,可以使用‘--availability’参数:

root@manager:~# docker swarm init --advertise-addr 172.27.9.71 --availability=drain

2. work node加入集群

2.1 查看加入命令

root@manager:~# docker swarm join-token worker 
To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-3fcb2bna1livym0xvq6b4m4re9dewyxm51ie6su9plog7hr3xd-cutz7yabg6k28dsna83mzgwkt 172.27.9.71:2377

加入命令可以通过在管理节点执行‘docker swarm join-token worker ’命令查看,也可以直接使用步骤1中创建集群时的命令提示。

2.2 加入集群

在两个work节点上分别执行如下命令

root@work01:~# docker swarm join --token SWMTKN-1-3fcb2bna1livym0xvq6b4m4re9dewyxm51ie6su9plog7hr3xd-cutz7yabg6k28dsna83mzgwkt 172.27.9.71:2377
This node joined a swarm as a worker.

与join对应的是leave

root@work01:~# docker swarm leave 

leave命令会离开集群,node上面的容器也会迁移到其他node

3. 查看集群信息

root@manager:~# docker node ls
root@manager:~# docker info

Docker实践(六):Docker Swarm

4. service创建和删除

4.1 创建service

root@manager:~# docker service create --name web-service --replicas 3 nginx

创建service:web-service,参数‘--replicas’指定副本数量。
Swarm集群服务类型有两种:replicated servicesglobal services。默认为replicated services(复制服务)模式,通过--replicas参数指定副本数量;global service(全局服务)模式,在每个node上运行一个且最多一个副本。

4.2 查看service

root@manager:~# docker service ls
root@manager:~# docker service ps web-service 
root@manager:~# docker service inspect web-service --pretty 

Docker实践(六):Docker Swarm
可以看到3个副本分布在三个节点上,参数‘--pretty’表示以适合阅读格式输出。

4.3 删除service

root@manager:~# docker service rm web-service 
web-service

Docker实践(六):Docker Swarm

5. service扩容与缩容

使用docker service scale命令可以对service进行扩容和缩容操作。

5.1 service扩容

将4.1中创建的service扩容至5个副本。

root@manager:~# docker service scale web-service=5

Docker实践(六):Docker Swarm

节点manager和work02上分别新建副本4和副本5。

5.2 service缩容

root@manager:~# docker service scale web-service=2

Docker实践(六):Docker Swarm

将service缩容至2个副本。

6. service灰度升级

6.1 新建service

新建service my-web,使用镜像httpd:2.4,副本数为6。httpd版本查看:https://hub.docker.com/_/httpd?tab=tags

root@manager:~# docker service  create --name my-web --replicas 6  --update-delay 30s --update-parallelism 2  httpd:2.4

Docker实践(六):Docker Swarm
Docker实践(六):Docker Swarm

参数‘--update-delay’指定更新间隔,默认为0,‘--update-parallelism’指定并行更新副本数量,默认为1。

6.2 升级my-web

将my-web由2.4升级至2.4.39

root@manager:~# docker service update --image httpd:2.4.39  my-web 

Docker实践(六):Docker Swarm
Docker实践(六):Docker Swarm
Docker实践(六):Docker Swarm
my-web升级至2.4.39,并且每次升级两个副本,间隔30s。

6.3 回滚

root@manager:~# docker service rollback my-web 

使用docker service rollback命令可以将service回滚到上一个版本。这里的上一个版本指最近的一个版本,比如httpd服务由2.4升级至2.4.38再升级至2.4.39,第一次rollback会回退至2.4.38,第二次rollback则回退至上一个版本2.4.39而不是2.4,即不能无限回退。
Docker实践(六):Docker Swarm

7. 外部访问service

7.1 删除所有service

root@manager:~# docker service rm $(docker service ls -q)

7.2 新建service my-httpd

root@manager:~# docker service create --name my-httpd --replicas 3 --publish 8080:80 httpd

新建三副本的service:my-httpd,使用--publish参数配置容器NAT网络的端口映射。

7.3 service查看并进入容器

Docker实践(六):Docker Swarm

7.4 更新apt源

tee /etc/apt/sources.list <<-'EOF'
deb http://mirrors.163.com/debian/ jessie main non-free contrib
deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib
deb http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib
deb-src http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib
EOF

Docker实践(六):Docker Swarm

7.5 安装ping和ip命令

root@6dc5f0b86e9f:/usr/local/apache2#  apt-get install iproute2 -y
root@6dc5f0b86e9f:/usr/local/apache2# apt-get install iputils-ping -y

7.6 查看ip

Docker实践(六):Docker Swarm
eth0对应的是ingress network网络,用于容器之间访问;eth1对应的是docker_gwbridge,用于容器访问外网。

三个node节点上对应的eth0网卡ip分别为:10.255.0.6/7/8

  • ingress network 是一个特殊的 overlay 网络,用于服务节点间的负载均衡。当任何 Swarm 节点在发布的端口上接收到请求时,它将该请求交给一个名为 IPVS 的模块。IPVS 跟踪参与该服务的所有IP地址,选择其中的一个,并通过 ingress 网络将请求路由到它。
    初始化或加入 Swarm 集群时会自动创建 ingress 网络,大多数情况下,用户不需要自定义配置,但是 docker 17.05 和更高版本允许你自定义。

  • docker_gwbridge是一种桥接网络,将 overlay 网络(包括 ingress 网络)连接到一个单独的 Docker 守护进程的物理网络。默认情况下,服务正在运行的每个容器都连接到本地 Docker 守护进程主机的 docker_gwbridge 网络。

7.7 ping测试

Docker实践(六):Docker Swarm
在manager节点上的容器中分别指定网卡eth0和eth1做ping测试,证实了7.6的结论:eth0用于容器间通讯;eth1用于访问外网。

7.8 RoutingMesh

分别修改三个节点的index.html主页内容

tee htdocs/index.html <<-'EOF'
<html><body><h1>manager node 172.27.9.71 !</h1></body></html>
EOF

主页内容为hostname+ip
访问service

[root@centos7 ~]# for i in {1..10};do sleep 1; curl http://172.27.9.71:8080; done 

Docker实践(六):Docker Swarm
routing mesh会将我们对任何节点的8080端口的访问通过swarm内部的load balancer将请求以轮询方式转发给my-httpd中的每一个副本。
小结:

  • 1.通过端口映射方式实现外部对service访问;
  • 2.容器内的eth0用于容器间通讯,eth1用于容器访问外部网络;;
  • 3.routing mesh会将请求以轮询方式发送给每一个副本;

8. service间的访问

8.1 新建overlay network loong

root@manager:~# docker network create -d overlay loong

需要相互通信的service必须属于同一个overlay网络,默认的overlay网络ingress不提供DNS服务,故创建一个新的overlay网络loong

8.2 新建service my-web

root@manager:~# docker service create --name my-web --replicas 3 --network loong  httpd

Docker实践(六):Docker Swarm
新建service:my-web

8.3修改index.html

分别修改my-web三个副本的index.html:hostname+ip
参见7.8

8.4 新建service centos

root@manager:~# docker service create --name centos --network loong centos sleep 100000

安装nslookup命令
Docker实践(六):Docker Swarm

8.5 service访问测试

Docker实践(六):Docker Swarm
小结:将service接入Overlay网络时,Swarm会给service分配一个VIP,VIP与一个包含service名称的DNS记录形成映射关系,这个service的所有container共享这条DNS记录,Swarm也会创建一个load balance将访问的VIP流量均衡到所有的副本上。

9. service logs

root@manager:~# docker service logs my-web 

Docker实践(六):Docker Swarm
通过docker service logs获取某个服务或者task的日志信息。

10. failover

10.1 新建service mybusybox

root@manager:~# docker service create --name mybusybox --replicas 3 busybox sleep 100000

Docker实践(六):Docker Swarm
新建三副本的service mybusybox,查看得知mybusybox分布在三个节点上。

10.2 设置节点work01不可用

root@manager:~# docker node update --availability drain work01

设置节点work01状态为drain,即可不用

10.3 查看work01状态

root@manager:~# docker node inspect work01 --pretty 

Docker实践(六):Docker Swarm
节点work01状态为不可用

10.4 查看service

Docker实践(六):Docker Swarm
可以看到原先在work01上的mybusybox.3处于shutdown状态,上面的task被迁移至work02

10.5 重置work01为可用

root@manager:~# docker node update --availability active work01

Docker实践(六):Docker Swarm
重置work01为active状态,此时运行在work02的mybusybox.3不会回切

11. 节点角色互换

使用promote/demote命令可以对节点的角色进行管理,方便对Manager节点进行容灾处理。

11.1work节点升级为manager

root@manager:~# docker node promote work01

Docker实践(六):Docker Swarm
Docker实践(六):Docker Swarm
将work01节点升级为manager,升级后节点work01可成功运行管理节点命令。

11.2 manager降级为work节点

root@manager:~# docker node demote manager 

Docker实践(六):Docker Swarm
将主机manager运行的manager节点降级为work节点,此时该节点已无法运行管理节点命令
Docker实践(六):Docker Swarm
work01上查看节点状态,发现manager只有work01

12. service指定node部署

通过设置label,可以灵活描述node的属性,service可通过lable选择部署的节点。

12.1 设置lable

root@manager:~# docker node update --label-add env=manager manager

Docker实践(六):Docker Swarm
分别设置节点manager、work01、work02的lable为tag=manager、tag=work01、tag=work02,‘tag=manager’等号两边都为自定义值。

12.2 指定节点新建service

root@manager:~# docker service create  --name my_nginx --replicas 3 --constraint  'node.labels.tag == work01' nginx  

Docker实践(六):Docker Swarm
新建service my_nginx,指定node为work01

12.3 service节点迁移

root@manager:~# docker service update --constraint-rm 'node.labels.tag == work01' my_nginx 
root@manager:~# docker service update --constraint-add 'node.labels.tag == work02' my_nginx

Docker实践(六):Docker Swarm
将my_nginx由节点work01迁移至work02

12.4 删除label

root@manager:~# docker node update --label-add tag2=manager2 manager
root@manager:~# docker node update --label-rm tag manager

Docker实践(六):Docker Swarm
一个node上可以有多个label,通过参数‘--label-rm’可以删除label