创建 Swarm 集群
本节将创建三节点的 swarm 集群。其中,swarm-manager(192.168.137.104) 是
manager node,swarm-worker1(vm1,192.168.137.105) 和 swarm-worker2(vm2,
192.168.137.106)是 worker node。所有节点的 Docker 版本均不低于 v1.12,操作系统为
centos7.4
1、在 swarm-manager 上执行如下命令创建 swarm
[root@host2 ~]# docker swarm init --advertise-addr 10.10.84.175
--advertise-addr 指定与其他节点通信的地址。
docker swarm init 输出包括:
① swarm 创建成功,swarm-manager 成为 manager 节点。
② 添加 worker 节点需要执行的命令:
③ 添加 manager node 需要执行的命令:
docker swarm join-token manager
执行 docker node ls 查看当前 swarm 集群的 node 节点,当前只有 manager。
复制前面的 docker swarm join 命令,在 vm1 和 vm2 上执行,将它们添加到 swarm
集群中,注意要删除 docker-machine 的配置(--cluster-store=consul://192.168.137.104:8500 --
cluster-advertise=ens33:2376):
vim /etc/systemd/system/docker.service.d/10-machine.conf
重启 docker daemon:
systemctl daemon-reload
systemctl restart docker.service
然后把上面那个复制然后在工作节点上执行
docker swarm join --token SWMTKN-1-0m6emsxmn5mc919rvmpicj5d5ziq5t9rqjc1esmxihctflt0p5-30jd66ockwo5s6klj9u9n739h 10.10.84.175:2377
docker node ls 查看添加结果
如没有记录 docker swarm init 给出的添加 worker node 的命令,可通过 docker swarm
join-token worker 查看:
2、运行第一个 Service (master 上操作)
现在部署一个运行 httpd 镜像的 service(服务),执行如下命令:
#docker service create --name web_server httpd
其中,--name 为 service 命名,httpd 为镜像的名字。
通过 docker service ls 查看当前 swarm 集群中的 service。
REPLICAS 显示副本信息,0/1 的意思是 web_server 应用期望的容器副本数量为 1,
目前已经启动的副本数量为 0。也就是当前 service 还没有部署完成。
命令 docker service ps 可以查看 service 服务的每个副本的状态。
#docker service ps web_server
可看到 service 唯一的副本被分派到 master,状态是 Running,如果状态为 Preparing,
说明还没达到期望的状态 Running,Preparing 的工作是说 master是在 pull 镜像,下载完成
后,副本就会处于 Running 状态了,service 的运行副本数也正常了。
还可以到 master去确认容器已经运行。
上一节只部署一个副本的 Service,不过对于企业应用如 web 服务,通常会运行多个
副本以实现负载均衡以及高可用,这要求增加副本数。
在 swarm-manager 上执行如下命令:
#docker service scale web_server=5
副本数增加到 5,通过 docker service ls 和 docker service ps 查看副本的详细信息。
5 个副本已经分布在 swarm 的所有三个节点上。
默认配置下 manager 节点也是 worker 节点,所以 swarm-manager 上也运行了副本。
如果不希望在 manager 上运行 service,可以执行如下命令:
#docker node update --availability drain host2(主机名)
Drain 表示 swarm-manager 不负责运行 service,原来 swarm-manager 运行的副本会迁
移到其他主机上,用 docker service ps 查看一下:
#docker service ps web_server
还可以 scale down,减少副本数,运行下面的命令:
#docker service scale web_server=3
4、实现故障切换 Failover
在企业用中,故障是难免的,容器可能崩溃,Docker 所在的主机可能宕机。Swarm 已
经内置了故障切换策略。
创建 service 的时候,只指定了期望的状态(比如运行 3 个副本),swarm 会尽最大
的努力达成该期望状态。以部署的 Service 为例,当前 3 个副本分布在 wc1 和 wc2 上。
测试 swarm 的故障切换特性,关闭 wc1 主机
Swarm 检测到 wc1 的故障,标记为 Down,并将 wc1 上的副本调度到其他可用节点:
Docker node ls
可通过 docker service ps 观察 failover 过程:
5、访问 Service
为了便于分析访问应用的过程,重新部署 web_server
① docker service rm 删除 web_server,service 的所有副本(容器)都会被删除。
② 重新创建 service,用 --replicas=2 创建两个副本。
③ 每个 worker node 上运行了一个副本。
要访问 http 服务,网络得通,要知道服务的 IP。每个副本都是一个运行的容器,先
看看容器的网络配置。
在 wc1 上运行了一个容器,是 web_server 的一个副本,容器监听
了 80 端口,但没有端口映射,只能通过容器的 IP 访问。
查看一下容器的 IP:
docker inspect (可以是id 和name)
Ip为172.17.0.4
用curl 172.17.0.4 可以访问容器httpd
但这样的访问也只能在 Docker 主机上访问。换句话说,外部网络无法访问应用
web_server。
要将 service 通告给外部(相当于针对 service 作一个端口映射),执行以下命令在master上执行:
#docker service update --publish-add 800:80 web_server
在新建 service 时,可以直接用使用 --publish 参数:
#docker service create --name web_server --publish 8080:80 --replicas=2 httpd
容器在 80 端口上监听 http 请求,--publish-add 8080:80 将容器的 80 映射到主机的
8080 端口,此时,外部网络就能访问到 web_server:
这里已经建好了所以就不用就直接执行这个命令就可以了docker service update --publish-add 800:80 web_server
此时可以外网可以访问了
用curl命令curl本主机的IP就能访问httpd了
#curl 10.10.84.175:800(管理节点的IP)
当访问任何节点的 800 端口时,swarm 内部的 load balancer 会将请求转发给
web_server 的一个副本。这是 routing mesh 的作用。所以,无论访问哪个节点,即使该节
点上没有运行 service 的副本,都能访问到 service。
6、ingress 网络
当使用 --publish-add 800:80 时,swarm 会重新配置 service,通过 docker service ps
web_server 命令查看:
docker service ps web_server
之前所有副本都被 Shutdown,又启动了新的副本。查看一下新副本的容
器网络配置。
[root@vm2 ~]#docker ps
[root@vm2 ~]# docker exec -it web_server.1.4wlgb5raw8slxjhswm34y7ngw /bin/sh
# apt-get update
# apt-get install net-tools
#ifconfig(查看IP)
容器的网络与 --publish-add 之前已经大不一样了,现在有两块网卡。其中,eth0 连接
的是一个 overlay 类型的网络,名字为 ingress,每个节点都能使用,作用是让运行在不同
主机节点上的容器可以相互通信。eth1 连接的是一个 bridge 网络,名字
为 docker_gwbridge,作用是让容器能够访问到外网。
7、Service 之间的通信
微服务架构的应用由若干 service 组成。比如有运行 httpd 的 web 前端,有提供缓
存的 memcached,有存放数据的 mysql,每一层都是 swarm 的一个 service,service 之间
是必然要通信的,此时通信是通过服务发现实现的。( ingress 没有提供服务发现功能)
服务发现能够:
1)让一个 service 通过简单的方法访问或连接到其他 service。
2)当 service 副本的 IP 或副本数发生变化时,不会影响访问该 service 的其他
service。
通过服务发现,使用者不需要知道 service 服务运行在哪里,有多少个副本,就能与
service 通信。
1)创建 overlay 网络(master 上操作)
服务发现要求通信的 service 属于同一个 overlay 网络:
[root@host2 ~]# docker network create --driver overlay wc_net
2)部署 service 到 overlay(master 上操作)
部署一个 web 服务,并连接到新创建的 overlay 网络:
[root@host2 ~]# docker service create --name my_web --replicas=3 --network wc_net
httpd
部署一个名为 wcc1 的服务用于测试,连接到同一个 overlay 网络:
[root@host2 ~]# docker service create --name wcc1 --network wc_net busybox sleep
10000000
sleep 10000000 的作用是保持 busybox 容器处于运行状态,方便进入到容器中访问
service my_web。
验证
通过 docker service ps wcc1 确认 wcc1 所在的节点为 wc1
登录到 wc1,在容器 wcc1 中 ping 服务 my_web。
docker ps 查看容器
然后docker exec -it wcc1.1.azfht4l9zemvqnj8biyoigxov /bin/sh 进入容器ping my_wed
可以看到 my_web 的 IP 为 10.0.1.2,是 my_web service 的 VIP(Virtual IP),swarm
会将对 VIP 的访问负载均衡到每一个副本
执行下面的命令查看每个副本的 IP。
[root@vm2 ~]# docker network inspect wc_net
但是对于服务的使用者只需直接
用 service 的名字 my_web 就能访问服务。
3. 滚动升级
滚动更新降低了应用更新的风险,如果某个副本更新失败,整个更新将暂停,其他副
本可以继续提供服务。同时,在更新的过程中,总是有副本在运行的,因此也保证了业务
的连续性。
部署三副本的服务,镜像使用 httpd:2.2.31,之后更新到 httpd:2.2.32。
1、创建服务 在master上操作
#docker service create --name my_web1 --replicas=3 httpd:2.2.31
2、更新
将 service 更新到最新版本
docker service update --image httpd my_web1
#docker service ps 查看更新结果。
#docker service ps my_web1
3、回滚
如果更新效果不理想,可通过 --rollback 快速恢复到更新之前的状态。
[root@host2 ~]# docker service update --rollback my_web1
稍微等待,查看状态:
#docker service ps my_web1 service 所有副本都已经恢复到 httpd:2.2.31。
注:--rollback 只能回滚上一次执行 docker service update 之前的状态,不能无限回滚