欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

如何用Docker Swarm轻松管理你的Docker集群?

最编程 2024-02-14 20:47:16
...

前言


之前介绍了使用 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 叫板的实力。

  • Docker Swarm 和 Swarm mode 的区别
  • 注:本文所说的 swarm 指的是 Swarm mode

配置说明


有两台主机 ( 主机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 下的网络模式


转载请注明出处:www.jianshu.com/p/47fa426ff…