使用 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 三剑客 之一的 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:2377

To 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
This node joined a swarm as a worker.

当然,主机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 主机1的IP:2377

注意:这个 token 和前面的 token 是不一样的

主机2 上执行对应的命令作为 manager 节点加入集群。可以添加 --listen-addr--advertise-addr 选项 ( 同创建集群步骤 )

$ docker swarm join --token SWMTKN-1-1023ixl3yabjyws8tjdyvob7r40mljsu8atzsmlju18wz2itlj-07q9wti67nkvqixykkcbi1ge8 主机1的IP:2377
This node joined a swarm as a manager.

查看集群节点


$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
kwsp26dy6gwjhocl6nxbez0bu *   主机1               Ready               Active              Leader              18.03.0-ce
19nnijmzs16o1f92e6wdmltsf     主机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               PORTS
8mgu08gmy0bf        service_test.1      nginx:alpine        主机1               Running             Running 4 minutes ago
310uv4k6aro8        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                    NAMES
43704a7989ed        nginx:alpine        "nginx -g 'daemon of…"   About a minute ago   Up 2 minutes        80/tcp                   service_test.2.310uv4k6aro8n47c37zj0w1c8

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

调整服务的实例个数


$ docker service scale service_test=3
service_test scaled to 3
overall progress: 3 out of 3 tasks
1/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.xdl050dxdrzfpdzjwjf40mook
1b998a72b03b        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.1
$ docker 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.2
$ docker 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.1
$ docker 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.1service_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.280 端口上,而这个 172.18.0.2IP 就属于 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 命令用于管理 Swarm 群集中的服务
命令 描述
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 之前的配置

系列文章


Docker 学习总结

Docker 常用指令详解

使用 Dockerfile 构建镜像

使用 Docker Compose 构建容器

Docker Daemon 连接方式详解

Docker 下的网络模式


转载请注明出处:https://www.jianshu.com/p/47fa426ff767

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容