使用docker-machine及swarmkit创建集群

目录

作者:杨冬 欢迎转载,也请保留这段声明。谢谢!
出处:https://andyyoung01.github.io/http://andyyoung01.16mb.com/

Swarm是Docker公司在2014年12月初发布的一套较为简单的工具,用来管理Docker集群,它将一群Docker宿主机变成一个单一的,虚拟的主机。随着Docker的不断发展,Swarm也不断更新。目前的Swarm有三种类型:Swarm, Swarmkit 和 Swarm模式。

简单来说,旧的Swarm可以作为容器运行,与Docker Engine是分离的;SwarmKit是可独立运行的二进制文件,需要从源码构建;而Swarm模式已经将SwarmKit整合到Docker引擎当中,可以通过Docker命令进行Swarm集群的操作。三者的区别也可以参考这里。本文主要通过SwarmKit进行Swarm集群的搭建。多个集群节点的创建通过docker-machine来完成。SwarmKit的概念和架构这里不再赘述。

对于集群来说,必然涉及到多个节点。当集群节点的数量较多时,如何创建和管理这些节点便成为急需解决的问题。所幸的是,目前有许多的配置管理工具可以完成这些任务,可以是puppet,chef,ansible或salt;另外,目前可选的大量公有云和私有云解决方案,简化了集群节点的创建,可以通过其提供的API进行操作,省略了繁杂的物理服务器搭建配置过程。下面就使用docker-machine来创建集群节点,并完成swarm集群的搭建过程。
由于SwarmKit需要通过编译生成二进制可执行文件,为了简化这个过程,我们直接使用已经编译好的SwarmKit的容器镜像。

  1. 通过如下命令创建swarmkit-master节点,然后运行swarmkit的manager:

    1
    2
    $ docker-machine.exe create -d virtualbox swarmkit-master
    $ docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 4242:4242 fsoppelsa/swarmkit swarmd --listen-remote-api 0.0.0.0:4242

    上面第1行命令创建了virtualbox的虚拟机节点,并命名为swarmkit-master;
    第2行命令直接运行了一个fsoppelsa/swarmkit的docker镜像,此镜像包含了编译后的swarmkit可执行文件swarmd及管理工具swarmctl,将docker主机的4242端口映射到容器的4242端口,并且将docker主机的socket挂载到了容器内部,最后运行了swarmd程序,通过参数将其置于监听模式,监听来自于所有ip地址对4242端口的请求。

  2. 通过如下命令创建3个worker节点:

    1
    2
    3
    for i in $(seq 3); do
    docker-machine.exe create -d virtualbox worker-$i &
    done

    上述命令运行了一个bash循环,注意循环体内部命名结尾处的“&”,它使命令放入背景执行,其效果是并行创建3个节点。命令正常结束后,可以查看一下节点的状态:

    1
    2
    3
    4
    5
    6
    7
    $ docker-machine.exe ls
    NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
    default - virtualbox Stopped Unknown
    swarmkit-master * virtualbox Running tcp://192.168.99.100:2376 v17.05.0-ce
    worker-1 - virtualbox Running tcp://192.168.99.101:2376 v17.05.0-ce
    worker-2 - virtualbox Running tcp://192.168.99.103:2376 v17.05.0-ce
    worker-3 - virtualbox Running tcp://192.168.99.102:2376 v17.05.0-ce

    可见,docker-machine创建了4个节点,一个master,3个worker,并且都在其上安装了docker引擎。

  3. 将3个worker节点依次加入第一步创建的master节点中:

    1
    2
    3
    4
    for i in $(seq 3); do
    eval $(docker-machine env worker-$i);
    docker run -d -v /var/run/docker.sock:/var/run/docker.sock fsoppelsa/swarmkit swarmd --join-addr $(docker-machine ip swarmkit-master):4242;
    done

    在加入master时,在bash循环体内部并没有使用“&”,效果是命令串行执行。这是因为每次循环,都需要先通过第2行命令连接到相应的worker节点,然后通过第3行命令执行加入manager的指令,如果并行执行会造成连接节点和执行加入manager命令的混乱。这在worker节点较多时,会降低程序执行的效率。解决思路可以通过每次循环内部先创建一个新的bash运行环境,然后在这个新的bash环境下连接相应节点然后加入manager,这样就可以并行运行命令了。

    最后,连接到master节点上,通过swarmctl检查一下集群的状态:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ eval $(docker-machine env swarmkit-master)
    $ docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    504034b93e64 fsoppelsa/swarmkit "swarmd --listen-r..." About an hour ago Up About an hour 0.0.0.0:4242->4242/tcp brave_mahavira
    $ docker exec -it 504034b93e64 swarmctl node ls
    ID Name Membership Status Availability Manager Status
    -- ---- ---------- ------ ------------ --------------
    4zcn39amwdb4tafxwgvdurpym worker-1 ACCEPTED READY ACTIVE
    avghwb14ud25fe07snoj3ihj4 worker-3 ACCEPTED READY ACTIVE
    boju4nrb4kp41ghc7fmr1u1tp swarmkit-master ACCEPTED READY ACTIVE REACHABLE *
    e6b5id41wm273kotiaizowvdw worker-2 ACCEPTED READY ACTIVE

    可见,我们的swarm集群已经成功创建。

  4. 通过SwarmKit创建service:
    下面我们通过swarmctl程序,创建一个由nginx容器组成的service。首先检查一下集群中是否已经存在service:

    1
    2
    3
    $ docker exec -it 504034b93e64 swarmctl service ls
    ID Name Image Replicas
    -- ---- ----- --------

    可见集群中还没有任何service。下面来创建一个名为web的服务:

    1
    2
    $ docker exec -it 504034b93e64 swarmctl service create --name web --image nginx --replicas 3
    7xrywybkmhukd9qg37zd6ldow

    上述命令创建了一个名为web的由nginx镜像组成的有3个replicas的service。这需要一段时间来生效,因为每个节点都需要下载nginx的镜像。可以再查询一下集群中的服务:

    1
    2
    3
    4
    $ docker exec -it 504034b93e64 swarmctl service ls
    ID Name Image Replicas
    -- ---- ----- --------
    7xrywybkmhukd9qg37zd6ldow web nginx 3/3

    上述命令3/3说明需要3个replicas,当前有3个replicas正在运行。可以进一步查看任务的详细信息:

    1
    2
    3
    4
    5
    6
    $ docker exec -it 504034b93e64 swarmctl task ls
    ID Service Desired State Last State Node
    -- ------- ------------- ---------- ----
    9gltkiutyz3i1uegzghh4hp2b web.2 RUNNING RUNNING 19 minutes ago worker-2
    awenk8yr7lut5fioqlfbjrpmi web.3 RUNNING RUNNING 19 minutes ago worker-1
    cfnq0g6va3mqo18xme6s475kz web.1 RUNNING RUNNING 19 minutes ago swarmkit-master

    通过上述命令可以发现在master的节点上也运行了一个web任务,在SwarmKit中默认这是允许的。如果在生产环境中不想让任务分配到manager节点上,可以通过使用labels和constrains来限制任务可以运行的节点。

结束语:本文通过docker-machine创建了4个集群节点,通过使用其virtualbox的driver,在单台主机上创建了4台基于virtualbox的虚拟机。这对于搭建开发或测试环境是非常方便的。
如果使用docker-machine提供的其它的driver,可以在各种公有云如AWS上创建节点。在公有云或私有云上,可以不受单台主机内存的约束,调整创建主机时bash循环运行的次数,从而创建大量节点。
另外,本文通过SwarmKit搭建的服务,只是一个很初级的集群,没有使用集群的一些高级特性,例如负载均衡和VxLAN的网络。这些高级特性都集成在Docker的Swarm模式中,所以在以后创建Swarm集群时,可以通过使用docker版本1.12+来创建Swarm模式的集群。