一 前言 相信Docker 技术大家都有所了解, 单个Docker 能发挥的作用毕竟有限,也不便于管理,所以Docker要组集群来使用才能发挥强大的技术优势。既然要组集群那就涉及诸如Docker的资源调度、管理等等一系列问题。目前涉及Docker集群的三个主要技术无外乎Swarm、Kubernetes、Mesos三种。今天我们主要介绍Docker Swarm。
二 什么是Docker Swarm
Swarm是一套较为简单的工具,用以管理Docker集群,使得Docker集群暴露给用户时相当于一个虚拟的整体。Swarm使用标准的Docker API接口作为其前端访问入口,换言之,各种形式的Docker Client(dockerclient in go, docker_py, docker等)均可以直接与Swarm通信,Swarm几乎全部用Go语言来完成开发。
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。
架构如下:
三 Swarm 关键概念
1. swarm节点
swarm集群是一系列节点的集合,而节点可以是一台裸机或者一台虚拟机。一个节点能扮演一个或者两个角色,manager或者worker。
Docker Swarm集群需要至少一个manager节点,节点之间使用Raft consensus protocol
进行协同工作。
通常,第一个启用docker swarm的节点将成为leader,后来加入的都是follower。当前的leader如果挂掉,剩余的节点将重新选举出一个新的leader。
每一个manager都有一个完整的当前集群状态的副本,可以保证manager的高可用。
worker节点是运行实际应用服务的容器所在的地方。理论上,一个manager节点也能同时成为worker节点,但在生产环境中,我们不建议这样做。
worker节点之间,通过control plane
进行通信,这种通信使用gossip
协议,并且是异步的。
集群中经常谈到的stacks, services, tasks,他们之间的关系。
下面简单解释一下这三者的含义:
swarm service是一个抽象的概念,它只是一个对运行在swarm集群上的应用服务,所期望状态的描述。它就像一个描述了下面物品的清单列表一样:
在Docker Swarm中,task是一个部署的最小单元,task与容器是一对一的关系。
stack是描述一系列相关services的集合。我们通过在一个YAML文件中来定义一个stack。
若所有的容器都运行在一个docker host上,他们之间的通信一般使用本地的bridge网络即可。(也就是单主机网络) 在Swarm集群中,我们使用多主机网络overlay network driver来让位于不同主机间的容器进行通信。当然你也可以使用第三方提供的其他网络驱动,但对于swarm,还是推荐它自己的overlay network。
四 Swarm 集群创建
下面我们尝试用Docker Swarm 搭建Nginx集群
准备工作:
)机器环境(三台机器,centos系统) 请先配置好IP和主机名
IP:192.168.1.101 主机名:manager 担任角色:swarm manager
IP:192.168.1.102 主机名:workernode1 担任角色:swarm node
IP:192.168.1.106 主机名:workernode2 担任角色:swarm node
)关闭防火墙
关闭三台机器上的防火墙。如果开启防火墙,则需要在所有节点的防火墙上依次放行/tcp(管理端口)、/udp(节点间通信端口)、/udp(overlay 网络端口)端口。
[root@manager ~]# systemctl disable firewalld.service
[root@manager ~]# systemctl stop firewalld.service
)配置hosts文件(可配置可不配置)
[root@manager ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
:: localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.101 manager
192.168.1.102 workernode1
192.168.1.106 workernode2
# 使用scp复制到node主机
[root@manager ~]# scp /etc/hosts root@192.168.1.102:/etc/hosts
[root@manager ~]# scp /etc/hosts root@192.168.1.106:/etc/hosts
)安装docker并配置加速器(在三台主机都要安装哟...)
[root@manager ~]# yum -y install docker
[root@workernode1 ~]# yum -y install docker
[root@workernode2 ~]# yum -y install docker
#下面我们开始真正搭建Swarm集群
1. 创建swam 集群
[root@manager ~]# docker swarm init --advertise-addr 192.168.1.101
Swarm initialized: current node (l7j2uil42mg4encop1yoxjijc) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-5sksptkfzeasb9zvi0h4gpdgwsb2gr6q9pfohk35j5e2kqi7dz-1oaozlbno19pb8g493wf8f24v \
192.168.1.101:
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[root@localhost ~]#
[root@workernode1 ~]# docker swarm join \
> --token SWMTKN-1-5sksptkfzeasb9zvi0h4gpdgwsb2gr6q9pfohk35j5e2kqi7dz-1oaozlbno19pb8g493wf8f24v \
> 192.168.1.101:
This node joined a swarm as a worker.
[root@localhost ~]#
[root@workernode2 ~]# docker swarm join \
> --token SWMTKN-1-5sksptkfzeasb9zvi0h4gpdgwsb2gr6q9pfohk35j5e2kqi7dz-1oaozlbno19pb8g493wf8f24v \
> 192.168.1.101:
This node joined a swarm as a worker.
[root@localhost ~]#
在manager主机上面查看node信息: (这样我们就创建了一个master节点, 两个workder 节点)
[root@manager ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
l7j2uil42mg4encop1yoxjijc * manager Ready Active Leader
wmdo7ua2lyo8uv8t9kcrl3e1f workernode2 Ready Active
x6ahnxn9e1uoahea2vzuau651 workernode1 Ready Active
[root@manager ~]#
、在Swarm中部署服务(nginx为例)
) 创建overlay网络,实现两个容器之间的通信
[root@manager ~]# docker network create -d overlay nginx_net
[root@manager ~]# docker network ls | grep -i over
khn3cwd8r385 ingress overlay swarm
zed6kjrrc3y nginx_net overlay swarm
)部署服务
#docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 docker.io/nginx
[root@manager ~]# docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 docker.io/nginx
ud2ozr63scv2le06y5csuy7ma
[root@manager ~]#
)查看正在运行服务的列表
[root@manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
ud2ozr63scv2 my_nginx replicated / docker.io/nginx:latest
[root@manager ~]#
) 查询swam 中服务的信息:
[root@manager ~]# docker service inspect --pretty my_nginx
ID: ud2ozr63scv2le06y5csuy7ma
Name: my_nginx
Service Mode: Replicated
Replicas:
Placement:
UpdateConfig:
Parallelism:
On failure: pause
Max failure ratio:
ContainerSpec:
Image: docker.io/nginx:latest@sha256:d81f010955749350ef31a119fb94b180fde8b2f157da351ff5667ae037968b28
Resources:
Networks: nginx_net
Endpoint Mode: vip
Ports:
PublishedPort
Protocol = tcp
TargetPort =
[root@manager ~]#
) 查看到哪个节点正在运行该服务, 可以看到该服务正在manager-node节点上面运行。
root@manager ~]# docker service ps my_nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
49e5nyg390y7 my_nginx.1 docker.io/nginx:latest manager Running Running minutes ago
a7mg2anh3yvz \_ my_nginx.1 docker.io/nginx:latest manager Shutdown Failed minutes ago "task: non-zero exit (0): No s…"
[root@manager ~]#
登录该节点, 查看到正在运行的容器:
[root@manager ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a4fbc93a2ab8 docker.io/nginx@sha256:d81f010955749350ef31a119fb94b180fde8b2f157da351ff5667ae037968b28 "nginx -g 'daemon ..." minutes ago Up minutes /tcp my_nginx.1.49e5nyg390y7qnvy99fle4us5
[root@manager ~]#
)在Swarm中动态扩展服务(scale)
当然,如果只是通过service启动容器,swarm也算不上什么新鲜东西了。Service还提供了复制(类似kubernetes里的副本)功能。可以通过 docker service scale 命令来设置服务中容器的副本数
比如将上面的my_nginx容器动态扩展到个
[root@manager ~]# docker service scale my_nginx=4
my_nginx scaled to
[root@manager ~]#
[root@manager ~]# docker service ps my_nginx 可以看到有一个在manager 上面运行, 有两个在workernode1上面运行, 有1个在workernode2 上面运行。
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
49e5nyg390y7 my_nginx.1 docker.io/nginx:latest manager Running Running minutes ago
a7mg2anh3yvz \_ my_nginx.1 docker.io/nginx:latest manager Shutdown Failed minutes ago "task: non-zero exit (0): No s…"
lr84dqiwt0dz my_nginx.2 docker.io/nginx:latest workernode2 Running Preparing seconds ago
woka1riehnd4 my_nginx.3 docker.io/nginx:latest workernode1 Running Preparing seconds ago
i873l6pz64u3 my_nginx.4 docker.io/nginx:latest workernode1 Running Preparing seconds ago
[root@manager ~]#
) 模拟宕机node节点:
特别需要清楚的一点:
如果一个节点宕机了(即该节点就会从swarm集群中被踢出),则Docker应该会将在该节点运行的容器,调度到其他节点,以满足指定数量的副本保持运行状态。
如我们将workernode1 的节点down 掉:
[root@workernode1 ~]# systemctl stop docker
[root@workernode1 ~]#
可以看到原workernode2 上面的task 转到workernode1 上面运行了:swarm的负载均衡会把请求路由到一个任意节点的可用的容器上
[root@manager ~]# docker service ps my_nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
49e5nyg390y7 my_nginx.1 docker.io/nginx:latest manager Running Running minutes ago
a7mg2anh3yvz \_ my_nginx.1 docker.io/nginx:latest manager Shutdown Failed minutes ago "task: non-zero exit (0): No s…"
lr84dqiwt0dz my_nginx.2 docker.io/nginx:latest workernode2 Running Preparing minutes ago
oc61q1gt0fjl my_nginx.3 docker.io/nginx:latest workernode2 Running Preparing seconds ago
woka1riehnd4 \_ my_nginx.3 docker.io/nginx:latest workernode1 Shutdown Preparing minutes ago
n659zjv0i2b3 my_nginx.4 docker.io/nginx:latest workernode2 Running Preparing seconds ago
k0fhmkndh842 \_ my_nginx.4 docker.io/nginx:latest workernode1 Shutdown Assigned seconds ago
i873l6pz64u3 \_ my_nginx.4 docker.io/nginx:latest workernode1 Shutdown Rejected seconds ago "No such image: docker.io/ngin…"
[root@manager ~]#
结论:即在swarm cluster集群中启动的容器,在worker node节点上删除或停用后,该容器会自动转移到其他的worker node节点上
) Swarm 动态缩容服务(scale)
同理,swarm还可以缩容,同样是使用scale命令
如下,将my_nginx容器变为个
[root@manager ~]# docker service scale my_nginx=1
my_nginx scaled to
[root@manager ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
ud2ozr63scv2 my_nginx replicated / docker.io/nginx:latest
[root@manager ~]#
[root@manager ~]# docker service ps my_nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
49e5nyg390y7 my_nginx.1 docker.io/nginx:latest manager Running Running minutes ago
a7mg2anh3yvz \_ my_nginx.1 docker.io/nginx:latest manager Shutdown Failed minutes ago "task: non-zero exit (0): No s…"
[root@manager ~]#
今天我们就介绍到这里。以后会继续分享docker的内容。
参考资料:
https://www.cnblogs.com/zhujingzhi/p/9792432.html
https://www.jianshu.com/p/5fb854827660