手记

使用 Docker Swarm 管理 Docker 集群

前言


之前介绍了使用 Docker Compose 在一台 Docker 主机下对多服务多容器进行编排,本文来介绍使用 Docker Swarm 实现对多台 Docker 主机的集群管理。

什么是 Docker Swarm


Swarm 是 Docker 公司在2014年12月初发布的一套用来管理 Docker 集群的较为简单的工具,由于 Swarm 使用标准的Docker API接口作为其前端访问入口,所以各种形式的Docker Client(dockerclient in go, docker_py, docker等)都可以直接与Swarm通信。老的 Docker Swarm 使用独立的外部KV存储(比如Consul、etcd、zookeeper),搭建独立运行的Docker主机集群,用户像操作单台Docker 机器一样操作整个集群,Docker Swarm 把多台 Docker 主机当做一台 Docker 主机来管理。新的 Swarm mode 是在docker 1.12版本中集成到 Docker 引擎中的,引入服务的概念,提供了众多的新特性,比如:具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。使得 Docker 原生的 Swarm mode 集群具备与 Mesos、Kubernetes 叫板的实力。

配置说明


有两台主机(主机1、主机2),都已安装docker。当然也可以使用三剑客之一的 Docker Machine 来创建一批运行 Docker 的虚拟机。

创建集群


在主机1上创建 swarm 集群,主机1作为 manager 节点

$ docker swarm init --listen-addr 0.0.0.0:2377 --advertise-addr 主机1的IP
Swarm initialized: current node (kwsp26dy6gwjhocl6nxbez0bu) is now a manager.

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

    docker swarm join --token SWMTKN-1-1023ixl3yabjyws8tjdyvob7r40mljsu8atzsmlju18wz2itlj-br6gzae8focpm0ccpjaquz251 主机1的IP:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

注意:主机1的防火墙要开放对应的端口

加入集群


主机2作为 worker 节点加入上面创建的集群

# 也就是上面创建完集群提示的命令docker swarm join --token SWMTKN-1-1023ixl3yabjyws8tjdyvob7r40mljsu8atzsmlju18wz2itlj-br6gzae8focpm0ccpjaquz251 主机1的IP:2377

当然,主机2也可作为 manager 节点加入上面创建的集群,当主机1挂掉的时候它可以晋升为 Leader。

在主机1上查询对应的 token

$ docker swarm join-token manager
To add a manager to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1023ixl3yabjyws8tjdyvob7r40mljsu8atzsmlju18wz2itlj-07q9wti67nkvqixykkcbi1ge8 119.27.177.81:2377

主机2上执行对应的命令,可以添加 --listen-addr 和 --advertise-addr 参数(同创建集群)

docker swarm join --token SWMTKN-1-1023ixl3yabjyws8tjdyvob7r40mljsu8atzsmlju18wz2itlj-07q9wti67nkvqixykkcbi1ge8 119.27.177.81:2377

查看集群节点


$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
kwsp26dy6gwjhocl6nxbez0bu *   主机1               Ready               Active              Leader              18.03.0-ce19nnijmzs16o1f92e6wdmltsf     主机2               Ready               Active              Reachable           18.03.0-ce

创建一个 overlay 网络


docker network create --driver overlay network_swarm

在 swarm 集群上创建服务,并指定使用的网络


docker service create --replicas 2 --name service_test --network=network_swarm nginx:alpine

查看服务状态


$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
yp2tn16eqaqc        service_test        replicated          2/2                 nginx:alpine

$ docker service ps service_test
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS8mgu08gmy0bf        service_test.1      nginx:alpine        主机1               Running             Running 4 minutes ago310uv4k6aro8        service_test.2      nginx:alpine        主机2               Running             Running 4 minutes ago

主机1上查看容器

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
d9df9c365d68        nginx:alpine        "nginx -g 'daemon of…"   About a minute ago   Up About a minute   80/tcp              service_test.1.8mgu08gmy0bf9pxovz5zxn8ih

主机2上查看容器

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES43704a7989ed        nginx:alpine        "nginx -g 'daemon of…"   About a minute ago   Up 2 minutes        80/tcp                   service_test.2.310uv4k6aro8n47c37zj0w1c8

可以看到有一个服务名为 service_test,有两个实例(service_test.1.xxx 和 service_test.2.xxx)分别部署在两台机器上。

调整服务的实例个数


$ docker service scale service_test=3service_test scaled to 3overall progress: 3 out of 3 tasks1/3: running   [==================================================>]2/3: running   [==================================================>]3/3: running   [==================================================>]
verify: Service converged# 主机1$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
ed226d0dc795        nginx:alpine        "nginx -g 'daemon of…"   24 seconds ago      Up 23 seconds       80/tcp              service_test.3.u6iop1v2gup15asywx6g927vo
d9df9c365d68        nginx:alpine        "nginx -g 'daemon of…"   2 minutes ago       Up 8 minutes        80/tcp              service_test.1.8mgu08gmy0bf9pxovz5zxn8ih

服务发现与自动恢复


手动删除或关闭运行中的容器,过几秒之后就能发现 Swarm 会创建新的容器来顶替失效的容器。

负载均衡


在单机模式下进行测试,情况会简单点

  1. 删除已有的服务

docker service rm service_test
  1. worker 节点退出集群,使 manager 节点成为单节点的集群

docker swarm leave
  1. 创建带端口映射的服务 service_test

docker service create --replicas 2 --name service_test -p 80:80 --network=network_swarm nginx:alpine
  1. 创建作为干扰的服务 service_test2 (和 service_test 共用一个网络)

docker service create --replicas 1 --name service_test2 -p 81:80 --network=network_swarm nginx:alpine
  1. 查看所有容器

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
c2d9a5111659        nginx:alpine        "nginx -g 'daemon of…"   19 seconds ago       Up 17 seconds       80/tcp              service_test2.1.rdseqv5oq2cli3vojsk5unibm
cf09fa224a32        nginx:alpine        "nginx -g 'daemon of…"   About a minute ago   Up About a minute   80/tcp              service_test.2.xdl050dxdrzfpdzjwjf40mook1b998a72b03b        nginx:alpine        "nginx -g 'daemon of…"   About a minute ago   Up About a minute   80/tcp              service_test.1.fgu08x9mi33xd002ctdjoeyv0
  1. 修改每个nginx的页面内容

# 注意:容器id修改为实际的容器id# service_test.1docker exec -i 1b sed -i 's$<title>Welcome to nginx!</title>$<title>Welcome to nginx-1!</title>$' /usr/share/nginx/html/index.html# service_test.2docker exec -i cf sed -i 's$<title>Welcome to nginx!</title>$<title>Welcome to nginx-2!</title>$' /usr/share/nginx/html/index.html# service_test2.1docker exec -i c2 sed -i 's$<title>Welcome to nginx!</title>$<title>Welcome to nginx-3!</title>$' /usr/share/nginx/html/index.html
  1. 查看效果

$ curl 127.0.0.1:81|grep title
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   614  100   614    0     0   181k      0 --:--:-- --:--:-- --:--:--  199k
<title>Welcome to nginx-3!</title>
$ curl 127.0.0.1|grep title
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   614  100   614    0     0   196k      0 --:--:-- --:--:-- --:--:--  299k
<title>Welcome to nginx-2!</title>
$ curl 127.0.0.1|grep title
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   614  100   614    0     0   164k      0 --:--:-- --:--:-- --:--:--  299k
<title>Welcome to nginx-1!</title>
curl 127.0.0.1|grep title
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   614  100   614    0     0   174k      0 --:--:-- --:--:-- --:--:--  299k
<title>Welcome to nginx-2!</title>
...

可以看出访问80端口会交替访问 service_test.1 和 service_test.2 且不会转发到 service_test2.1 上,说明负载均衡成功。

  1. 查看宿主机的 NAT 映射情况

$ sudo iptables -t nat -nL
...
Chain DOCKER-INGRESS (2 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:81 to:172.18.0.2:81
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.18.0.2:80
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

可以看出宿主机的80端口被映射到了 172.18.0.2 的80端口上,而这个 172.18.0.2 的ip就属于 overlay 网络 network_swarm。对于 overlay 网络的原理不是很清楚,也没深入研究下去,有了解的小伙伴欢迎指教。不过,我猜测应该是 overlay 网络内部实现了某种一对多的端口映射从而实现负载均衡的效果。

使用Docker Stack 部署多服务集群(参考


Docker Swarm 只能实现对单个服务的简单部署,如果要实现和 Docker-compose 一样的多服务编排就需要用到 Docker Stack 命令,具体用法请看另一篇文章

Swarm的不足


  • 功能简单有限

  • 当集群中某台机器的资源(cpu、内存等)不足时,Swarm在部署服务的时候还是会傻傻地平均分配容器到这台机器上。

常用命令


  • docker swarm 命令用于管理 Swarm 群集

命令描述
docker swarm init初始化一个 swarm 群集
docker swarm join加入群集作为节点或管理器
docker swarm join-token管理用于加入群集的令牌
docker swarm leave离开 swarm 群集
docker swarm unlock解锁 swarm 群集
docker swarm unlock-key管理解锁钥匙
docker swarm update更新 swarm 群集
  • docker node 命令用于管理 Swarm 群集中的机器节点

命令描述
docker node demote从 swarm 群集管理器中降级一个或多个节点
docker node inspect显示一个或多个节点的详细信息
docker node ls列出 swarm 群集中的节点
docker node promote将一个或多个节点推入到群集管理器中
docker node ps列出在一个或多个节点上运行的任务,默认为当前节点
docker node rm从 swarm 群集删除一个或多个节点
docker node update更新一个节点
  • docker service 命令用于管理服务

命令描述
docker service create创建服务
docker service inspect显示一个或多个服务的详细信息
docker service logs获取服务的日志
docker service ls列出服务
docker service rm删除一个或多个服务
docker service scale设置服务的实例数量
docker service update更新服务
docker service rollback恢复服务至update之前的配置



作者:anyesu
链接:https://www.jianshu.com/p/47fa426ff767

0人推荐
随时随地看视频
慕课网APP