Fork me on GitHub

Docker 三剑客之 Docker Swarm

上一篇:Docker 三剑客之 Docker Compose

阅读目录:

  • Docker Machine 创建 Docker 主机
  • Docker Swarm 配置集群节点
  • Docker Service 部署单个集群服务
  • Docker Stack 部署多个集群服务,以及 GUI 管理页面
  • docker-machine、docker swarm、docker node、docker service 和 docker stack 常用命令

Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。

从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。

1. Docker Machine 创建 Docker 主机

在进行 Docker Swarm 配置之前,我们还需要说下 Docker 另外一个官方工具 Docker Machine(也是 Docker 三剑客之一),其作用就是快速帮助我们搭建 Docker 主机环境,比如我们要使用 Docker Swarm,就必须有很多的 Docker 主机来进行操作,Docker Machine 就是最理想的工具。

因为我是在 Mac OS 上进行操作的,并且 Docker for Mac 已经包含了 Docker Machine(docker machine),所以我不需要再额外进行安装了,如果使用 Linux 系统的话,安装也非常简单,命令:

$ sudo curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine
$ sudo chmod +x /usr/local/bin/docker-machine

好了,我们先使用 Docker Machine 创建四个 Docker 主机,命令:

$ docker-machine create -d virtualbox manager1 && 
docker-machine create -d virtualbox manager2 && 
docker-machine create -d virtualbox worker1 && 
docker-machine create -d virtualbox worker2

Running pre-create checks...
(worker1) No default Boot2Docker ISO found locally, downloading the latest release...
(worker1) Latest release for github.com/boot2docker/boot2docker is v17.11.0-ce
(worker1) Downloading /Users/xishuai/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v17.11.0-ce/boot2docker.iso...

执行上面命令,你会发现速度巨慢(如上),原因是从 GitHub 上下载一个boot2docker.iso文件(国内网络没办法),怎么解决呢?很简单,我们使用翻X的浏览器手动下载boot2docker.iso文件,然后拷贝到对应目录下(我电脑的目录/Users/xishuai/.docker/machine/cache/),然后再执行上面的命令,发现速度快的一批。

我们可以查看下创建的 Docker 主机信息,命令:

$ docker-machine ls
NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
manager1   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.11.0-ce   
manager2   -        virtualbox   Running   tcp://192.168.99.101:2376           v17.11.0-ce   
worker1    -        virtualbox   Running   tcp://192.168.99.102:2376           v17.11.0-ce   
worker2    -        virtualbox   Running   tcp://192.168.99.103:2376           v17.11.0-ce   

可以看到,我们创建了四个 Docker 主机(两个 Manager 和两个 Worker),我们还可以连接到任何一台服务器进行操作,命令:

$ docker-machine ssh manager1
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 17.11.0-ce, build HEAD : e620608 - Tue Nov 21 18:11:40 UTC 2017
Docker version 17.11.0-ce, build 1caf76c

2. Docker Swarm 配置集群节点

我们执行下面命令:

$ docker-machine ssh manager1 "docker swarm init --advertise-addr 192.168.99.100"
Swarm initialized: current node (n0ub7dpn90rxjq97dr0g8we0w) is now a manager.

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

    docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

上面是在manager1主机上,创建一个 Docker Swarm 管理节点(初始化集群的时候,会自动把当前节点设置为管理节点)。

接着,我们在worker1worker2主机上,创建两个工作节点,并加入到集群中,命令:

$ docker-machine ssh worker1 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
This node joined a swarm as a worker.

$ docker-machine ssh worker2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
This node joined a swarm as a worker.

还有另外一个manager2主机,需要配置为管理节点,我们需要先在manager1主机上,获取管理节点对应的token,然后再配置为管理节点,命令:

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

    docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377

$ docker-machine ssh manager2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377"
This node joined a swarm as a manager.

配置好之后,我们进入manager1主机内(上面的命令也可以在主机内执行),然后查看集群节点的信息,命令:

$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
n0ub7dpn90rxjq97dr0g8we0w *   manager1            Ready               Active              Leader
t4cy67qp0bf2spgabsutwxnzt     manager2            Ready               Active              Reachable
if0kmzp4ww3oy57y7cha7v36t     worker1             Ready               Active              
jgg61cujzaeb3du5796fm0x2g     worker2             Ready               Active       

Leader表示当然集群的头,Reachable可以理解为头的候选人,头一挂掉它就顶上去了。


需要注意的是,我当天配置好之后,把所有的 Docker 主机都stop了,然后隔天重新start之后,出现了下面问题:

docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.

好像是集群节点丢失了头,相关问题:如何处理 docker swarm 集群"The swarm does not have a leader"问题,按照文章进行解决:

$ docker swarm init --force-new-cluster
Error response from daemon: could not choose an IP address to advertise since this system has multiple addresses on different interfaces (10.0.2.15 on eth0 and 192.168.99.102 on eth1) - specify one with --advertise-addr
$ docker swarm init --force-new-cluster --advertise-addr 192.168.99.102
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
$ docker node ls
卡死
$ docker-machine restart manager1 
重启不了,一直转圈

没办法,后来我只能删掉四个 Docker 主机,重新进行创建了。

3. Docker Service 部署单个集群服务

在部署集群服务之前,我们需要做些准备工作,因为 Docker 主机中没有配置 Docker 镜像加速地址,所以在拉取官方镜像的时候,肯定会非常慢,除了配置 Docker 镜像加速地址之外,我们还可以使用 Docker 私有镜像仓库,来解决这个问题。

参考文章:Ubuntu Docker Registry 搭建私有仓库

这边,我再简单说明下配置步骤,首先,在 Mac OS 上执行下面命令:

$ docker run -d -v /Users/xishuai/Documents/Docker:/var/lib/registry -p 5000:5000 --restart=always --name registry registry

$ docker tag nginx 192.168.99.1:5000/nginx:latest && 
docker push 192.168.99.1:5000/nginx:latest && 
docker pull 192.168.99.1:5000/nginx:latest

$ curl http://192.168.99.1:5000/v2/_catalog
{"repositories":["nginx"]}

我们在 Mac OS 上创建了一个私有仓库容器,并把nginx镜像放到私有仓库中,因为没有使用 Https,所以在拉取和推送镜像的时候,会报如下错误(Mac OS 和 Docker 主机都会报错):

$ docker pull 192.168.99.1:5000/nginx:latest
The push refers to a repository [192.168.99.1:5000/nginx]
Get https://192.168.99.1:5000/v1/_ping: http: server gave HTTP response to HTTPS client

解决方式,我们需要分别在四个 Docker 主机中添加配置(Docker for Mac 在管理界面配置即可),命令:

$ sudo touch /etc/docker/daemon.json && 
sudo chmod 777 /etc/docker/daemon.json && 
sudo echo '{ "insecure-registries":    ["192.168.99.1:5000"] }' > /etc/docker/daemon.json

然后重启四个 Docker 主机(Docker for Mac 也需要重启),命令:

$ docker-machine restart manager1 && 
docker-machine restart manager2 && 
docker-machine restart worker1 && 
docker-machine restart worker2

上面比较啰嗦,我们接下来正式部署集群服务,还是拿nginx镜像做为示例,命令(docker service create命令详细说明):

$ docker service create --replicas 4 -p 8088:80 --name nginx 192.168.99.1:5000/nginx:latest
ap8h8srb8yh3mni0h2nz61njz
overall progress: 4 out of 4 tasks 
1/4: running   [==================================================>] 
2/4: running   [==================================================>] 
3/4: running   [==================================================>] 
4/4: running   [==================================================>] 
verify: Service converged 

需要注意的是,--replicas 4表示创建服务的实例个数(默认是一个),啥意思?比如4,就是在四个 Docker 主机上,分别创建一个nginx服务,如果是3,那就是三个 Docker 主机,或者你可以理解为 Docker 主机的个数,另外,REPLICAS会有进度显示,并且执行是异步的。

我们也可以手动设置实例个数,命令:

$ docker service scale nginx=4

部署好服务后,我们就可以进行查看了,命令:

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                            PORTS
ap8h8srb8yh3        nginx               replicated          4/4                 192.168.99.1:5000/nginx:latest   *:8080->8080/tcp

$ docker service ps nginx
ID                  NAME                IMAGE                            NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
l2rdrwzs5zog        nginx.1             192.168.99.1:5000/nginx:latest   manager1            Running             Running about a minute ago                       
vsfczzbwanx3        nginx.2             192.168.99.1:5000/nginx:latest   manager2            Running             Running about a minute ago                           
qtbgw5h6dsi9        nginx.3             192.168.99.1:5000/nginx:latest   worker              Running             Running about a minute ago                           
za2ejnvb3n6z        nginx.4             192.168.99.1:5000/nginx:latest   worker2             Running             Running about a minute ago

我们任意使用四个 Docker 主机中的一个 IP 地址,浏览器打开:http://192.168.99.100:8088/

4. Docker Stack 部署多个集群服务,以及 GUI 管理页面

docker service部署的是单个服务,我们可以使用docker stack进行多服务编排部署,使用的同样是docker-compose.yml配置文件,示例:

version: "3"

services:
  nginx:
    image: 192.168.99.1:5000/nginx:latest
    ports:
      - 8088:80
    deploy:
      mode: replicated
      replicas: 4

  visualizer:
    image: 192.168.99.1:5000/dockersamples/visualizer:latest
    ports:
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]

  portainer:
    image: 192.168.99.1:5000/portainer/portainer:latest
    ports:
      - "9000:9000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]

如上所示,我们总共需要部署三个服务,出了nginx服务作为示例之外,visualizer官方地址)和portainer官方地址)都是集群 GUI 管理服务。

部署命令:

$ docker stack deploy -c docker-compose.yml deploy-demo
Creating service deploy-demo_nginx
Creating service deploy-demo_visualizer
Creating service deploy-demo_portainer

部署成功之后,我们可以查看具体详情,命令:

$ docker stack ls
NAME                SERVICES
deploy-demo         3

查看visualizerGUI 集群管理,浏览器打开:http://192.168.99.100:8080/

查看portainerGUI 集群管理,需要先配置账号信息,浏览器打开:http://192.168.99.100:9000/

可以看到,portainervisualizer强大太多了,甚至我们所有的操作都可以在portainer上完成。

5. docker-machine、docker swarm、docker node、docker service 和 docker stack 常用命令

docker-machine 常用命令

命令 说明
docker-machine create 创建一个 Docker 主机(常用-d virtualbox
docker-machine ls 查看所有的 Docker 主机
docker-machine ssh SSH 到主机上执行命令
docker-machine env 显示连接到某个主机需要的环境变量
docker-machine inspect 输出主机更多信息
docker-machine kill 停止某个主机
docker-machine restart 重启某台主机
docker-machine rm 删除某台主机
docker-machine scp 在主机之间复制文件
docker-machine start 启动一个主机
docker-machine status 查看主机状态
docker-machine stop 停止一个主机

docker swarm 常用命令

命令 说明
docker swarm init 初始化集群
docker swarm join-token worker 查看工作节点的 token
docker swarm join-token manager 查看管理节点的 token
docker swarm join 加入集群中

docker node 常用命令

命令 说明
docker node ls 查看所有集群节点
docker node rm 删除某个节点(-f强制删除)
docker node inspect 查看节点详情
docker node demote 节点降级,由管理节点降级为工作节点
docker node promote 节点升级,由工作节点升级为管理节点
docker node update 更新节点
docker node ps 查看节点中的 Task 任务

docker service 常用命令

命令 说明
docker service create 部署服务
docker service inspect 查看服务详情
docker service logs 产看某个服务日志
docker service ls 查看所有服务详情
docker service rm 删除某个服务(-f强制删除)
docker service scale 设置某个服务个数
docker service update 更新某个服务

docker stack 常用命令

命令 说明
docker stack deploy 部署新的堆栈或更新现有堆栈
docker stack ls 列出现有堆栈
docker stack ps 列出堆栈中的任务
docker stack rm 删除堆栈
docker stack services 列出堆栈中的服务
docker stack down 移除某个堆栈(不会删除数据)

参考资料:

posted @ 2017-12-06 08:04  田园里的蟋蟀  阅读(43903)  评论(6编辑  收藏  举报