docker-swarm

重要概念

swarm

swarm 运行 Docker Engine 的多个主机组成的集群。

从 v1.12 开始,集群管理和编排功能已经集成进 Docker Engine。当 Docker Engine 初始化了一个 swarm 或者加入到一个存在的 swarm 时,它就启动了 swarm mode。

没启动 swarm mode 时,Docker 执行的是容器命令;运行 swarm mode 后,Docker 增加了编排 service 的能力。

Docker 允许在同一个 Docker 主机上既运行 swarm service,又运行单独的容器。

node

swarm 中的每个 Docker Engine 都是一个 node,有两种类型的 node:managerworker

service

service 定义了 worker node 上要执行的任务。swarm 的主要编排任务就是保证 service 处于期望的状态下。

创建warm 集群

1.在 swarm-manager 上执行如下命令创建 swarm。

docker swarm init --advertise-addr 192.168.180.5

docker swarm init 输出信息为:

① swarm 创建成功,swarm-manager 成为 manager node。

② 添加 worker node 需要执行的命令。

③ 添加 manager node 需要执行的命令。

2.添加节点

到其他节点添加

docker swarm join --token SWMTKN-1-3616eclvdajf6bus0vver28w5x7bqfhseq6k6rgfkorhzentz8-day0r29hlu5gurplptjnm2s91 192.168.180.5:237

mark

service

部署一个service

部署一个运行 httpd 镜像的 service,执行如下命令:

docker service create --name web_server httpd

部署 service 的命令形式与运行容器的 docker run 很相似,--name 为 service 命名,httpd 为镜像的名字。

mark

部署 service 的命令形式与运行容器的 docker run 很相似,--name 为 service 命名,httpd 为镜像的名字。

通过 docker service ls 可以查看当前 swarm 中的 service。

mark

REPLICAS 显示当前副本信息,0/1 的意思是 web_server 这个 service 期望的容器副本数量为 1,目前已经启动的副本数量为 0。也就是当前 service 还没有部署完成。命令 docker service ps 可以查看 service 每个副本的状态。

mark

可知node2,3上没有httpd的镜像,副本运行失败,在node2,node3上拉取镜像

mark

删除service

root@node3:~# docker service rm web_server
web_server

重新创建

mark

查看存在一个副本

mark

service弹性伸缩

scale up

增加 service 的副本数,在 swarm-manager 上执行如下命令:

docker service scale web_server=5

5 个副本已经分布在 swarm 的所有三个节点上。

mark

默认配置下 manager node 也是 worker node,所以 swarm-manager 上也运行了副本。如果不希望在 manager 上运行 service,可以执行如下命令:

docker node update --availability drain node3

mark

mark

Drain 表示 swarm-manager 已经不负责运行 service,swarm-manager 上的副本 web_server.1 已经被 Shutdown 了,为了达到 5 个副本数的目标,node2 上添加了副本 web_server.1

scale down

可以 scale down,减少副本数,运行下面的命令:

docker service scale web_server=3

mark

mark

副本2,4被删除

failover 策略

测试 swarm 的 failover 特性,关闭node2。Swarm 会检测到 node2 的故障,并标记为 Down。

mark

Swarm 会将 node2 上的副本调度到其他可用节点。通过 docker service ps 观察这个 failover 过程。

mark

访问service

1.重新部署

root@node3:~# docker service rm qbtde5mks4a6   
qbtde5mks4a6

docker service rm 删除 web_server,service 的所有副本(容器)都会被删除。

mark

重新创建 service,使用 --replicas=2 创建两个副本。

mark

2.访问

每个service副本都是一个运行的容器,可以进入到副本对应的容器,查看对应的容器

mark

在node1 上运行了一个容器,是 web_server 的一个副本,容器监听了 80 端口,但并没有映射到 Docker Host,所以只能通过容器的 IP 访问。查看一下容器的 IP。

所以可以通过10.2.10.2访问

mark

可见swarm使用的是overlay网络

从外部访问 service

要将 service 暴露到外部,方法其实很简单,执行下面的命令:

docker service update --publish-add 8080:80 web_server

mark

mark

curl 集群中任何一个节点的 8080 端口,都能够访问到 web_server

这个功能叫做 routing mesh

如果是新建 service,可以直接用使用 --publish 参数,比如:

docker service create --name web_server --publish 8080:80 --replicas=2 httpd

routing mesh

1.访问任何节点的 8080 端口时,swarm 内部的 load balancer 会将请求转发给 web_server 其中的一个副本

所以,无论访问哪个节点,即使该节点上没有运行 service 的副本,最终都能访问到 service。

另外,还可以配置一个外部 load balancer,将请求路由到 swarm service。比如配置 HAProxy,将请求分发到各个节点的 8080 端口。

ingress 网络

当应用 --publish-add 8080:80 时,swarm 会重新配置 service,之前的所有副本都被 Shutdown,然后启动了新的副本。。

查看一下新副本的容器网络配置。

容器的网络与 --publish-add 之前已经大不一样了,现在有两块网卡,每块网卡连接不同的 Docker 网络。

实际上:

  1. eth0 连接的是一个 overlay 类型的网络,名字为 ingress,其作用是让运行在不同主机上的容器可以相互通信。

  2. eth1 连接的是一个 bridge 类型的网络,名字为 docker_gwbridge,其作用是让容器能够访问到外网。

    ingress 网络是 swarm 创建时 Docker 创建的,swarm 中的每个 node 都能使用 ingress

service 之间通信

服务发现

一种实现方法是将所有 service 都 publish 出去,然后通过 routing mesh 访问。但明显的缺点是把 memcached 和 mysql 也暴露到外网,增加了安全隐患。

如果不 publish,那么 swarm 就要提供一种机制,能够:

  1. 让 service 通过简单的方法访问到其他 service。
  2. 当 service 副本的 IP 发生变化时,不会影响访问该 service 的其他 service。
  3. 当 service 的副本数发生变化时,不会影响访问该 service 的其他 service。

这其实就是服务发现(service discovery)。Docker Swarm 原生就提供了这项功能,通过服务发现,service 的使用者不需要知道 service 运行在哪里,IP 是多少,有多少个副本,就能与 service 通信。

创建 overlay 网络

要使用服务发现,需要相互通信的 service 必须属于同一个 overlay 网络,所以得创建一个新的 overlay 网络。

docker network create --driver overlay myapp_net

部署 service 到 overlay

部署一个 web 服务,并将其挂载到新创建的 overlay 网络。

docker service create --name my_web --replicas=3 --network myapp_net httpd

部署一个 util 服务用于测试,挂载到同一个 overlay 网络。

docker service create --name util --network myapp_net busybox sleep 10000000

验证

通过 docker service ps util 确认 util 所在的节点为node1,然后ping myweb。

mark

my_web 的 IP 为 10.0.0.5,这是哪个副本的 IP 呢?

其实哪个副本的 IP 都不是。10.0.0.5 是 my_web` service 的 VIP(Virtual IP),swarm 会将对 VIP 的访问负载均衡到每一个副本。

我们可以执行下面的命令查看每个副本的 IP。

滚动更新service

镜像使用 httpd:2.2.31,然后将其更新到 httpd:2.2.32。

创建服务:

docker service create --name my_web --replicas=3 httpd:2.2.31

docker service update --image httpd:2.2.32 my_web

Swarm 将按照如下步骤执行滚动更新:

  1. 停止第一个副本。

  2. 调度任务,选择 worker node。

  3. 在 worker 上用新的镜像启动副本。

  4. 如果副本(容器)运行成功,继续更新下一个副本;如果失败,暂停整个更新过程。

  5. docker service ps 查看更新结果。

    下图事更新失败后的状态

    mark

    下图是全部更新后的状态

mark

默认配置下,Swarm 一次只更新一个副本,并且两个副本之间没有等待时间。我们可以通过 --update-parallelism 设置并行更新的副本数目,通过 --update-delay 指定滚动更新的间隔时间。

比如执行如下命令:

docker service update --replicas 6 --update-parallelism 2 --update-delay 1m30s my_web

service 增加到六个副本,每次更新两个副本,间隔时间一分半钟。

docker service inspect 查看 service 的当前配置。

Swarm 还有个方便的功能是回滚,如果更新后效果不理想,可以通过 --rollback 快速恢复到更新之前的状态。

docker service update my_web --rollback

遇到的问题

1.

一直指定了docker的集群配置了,需要更改docker配置文件,注释之前的--cluster-store

重启docker服务

systemctl daemon-reload

systemctl restart docker.service

2.Error response from daemon: rpc error: code = Unavailable desc = grpc: the connection is unavailable

防火墙问题,关闭防火墙

iptables -F

或者

开放对应端口

firewall-cmd --add-port=2376/tcp --permanent
firewall-cmd --add-port=2377/tcp --permanent
firewall-cmd --add-port=7946/tcp --permanent
firewall-cmd --add-port=7946/udp --permanent
firewall-cmd --add-port=4789/udp --permanent

3.Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid

原理:docker swarm node之间是加密传输,docker swarm init时会创建CA证书。这里提示证书过期,可能是主机当前时间不对。

mark

mark

更新节点时间一致

posted @ 2018-10-12 09:54  mrwuzs  阅读(1022)  评论(0编辑  收藏  举报