【Docker】Docker三剑客实践之部署集群

做者:不洗碗工做室 - Marklux
出处:marklux.cn/blog/55
版权归做者全部,转载请注明出处node

前言

DOCKER技术在推出后掀起了一阵容器化技术的热潮,容器化使得服务的部署变得极其简易,这为微服务和分布式计算提供了很大的便利。web

为了把容器化技术的优势发挥到极致,docker公司前后推出了三大技术:docker-machine,docker-compose,docker-swarm,能够说是几乎实现了容器化技术中全部可能须要的底层技术手段。算法

在使用go语言实现了判题引擎并打包好docker镜像后,就须要进行分布式判题的编写,此次就让咱们手动实践,尝试使用docker的三大杀器来部署一个多机器构成的判题服务集群。docker

三剑客简介

docker-machine

docker技术是基于Linux内核的cgroup技术实现的,那么问题来了,在非Linux平台上是否就不能使用docker技术了呢?答案是能够的,不过显然须要借助虚拟机去模拟出Linux环境来。安全

docker-machine就是docker公司官方提出的,用于在各类平台上快速建立具备docker服务的虚拟机的技术,甚至能够经过指定driver来定制虚拟机的实现原理(通常是virtualbox)。bash

docker-compose

docker镜像在建立以后,每每须要本身手动pull来获取镜像,而后执行run命令来运行。当服务须要用到多种容器,容器之间又产生了各类依赖和链接的时候,部署一个服务的手动操做是使人感到十分厌烦的。服务器

dcoker-compose技术,就是经过一个.yml配置文件,将全部的容器的部署方法、文件映射、容器链接等等一系列的配置写在一个配置文件里,最后只须要执行docker-compose up命令就会像执行脚本同样的去一个个安装容器并自动部署他们,极大的便利了复杂服务的部署。网络

docker-swarm

swarm是基于docker平台实现的集群技术,他能够经过几条简单的指令快速的建立一个docker集群,接着在集群的共享网络上部署应用,最终实现分布式的服务。架构

相比起zookeeper等集群管理框架来讲,swarm显得十分轻量,做为一个工具,它把节点的加入、管理、发现等复杂的操做都浓缩为几句简单的命令,而且具备自动发现节点和调度的算法,还支持自定制。虽然swarm技术如今还不是很是成熟,但其威力已经可见通常。负载均衡

浅谈docker服务架构和远程API

在正式使用docker技术部署集群应用时,咱们应该先来了解一下docker工做的一些底层原理,和docker远程调用的API,这样才能大致了解集群到底是如何运做的。

daemon

以前的docker入门文章中讲过,docker的基础服务,好比容器的建立、查看、中止、镜像的管理,其实都是由docker的守护进程(daemon)来实现的。

每次执行的docker指令其实都是经过向daemon发送请求来实现的。

daemon的运做(通讯模式)主要有两种,一种是经过unix套接字(默认,但只能在本地访问到,比较安全),一种是经过监听tcp协议地址和端口来实现(这个能够实如今远程调用到docker服务)。

远程API

除了经过远程tcp协议访问远程主机上的docker服务外,docker还提供了一套基于HTTP的API,可使用curl来实现操做远程主机上的docker服务,这为开发基于WEB的docker服务提供了便利。

远程docker使用示例

最终实现集群的时候实际是使用docker的远程调用来将不一样的docker主机链接成一个总体的(经过tcp协议)。

咱们不妨先来手动模拟尝试一下docker服务的远程调用吧。

首先须要在提供服务的主机上将docker的运行方式改成tcp,具体方法为修改/etc/default/docker中的DOCKER_OPTS为以下内容

-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock复制代码

-H 后的参数是本身定义的要绑定的tcp地址和端口,成功绑定后重启docker服务就能够在该端口访问到docker的daemon服务。

不幸的是:

  • 在OSX平台上,并无找到docker的daemon配置文件
  • 在OSX平台上,使用docker -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock -d这样的命令来尝试以tcp的方式启动docker daemon也是失败的,并无任何做用
  • 目前推测除了Linux平台上,其余平台上的配置方法都不太同样,可是在网络上暂时没有找到解决方案,因此后面的操做我只能经过在本地建立多个docker-machine的方式来模拟实现远程调用。

假设咱们在192.168.1.123这台主机上开启了docker服务,监听了2375端口,那么咱们就能够在同一网段的其余主机上(好比192.168.1.233)经过docker -H tcp://192.168.1.123:2345 <command>的方式调用到该主机上的docker服务。

好比

docker -H tcp://192.168.1.123:2345 ps
docker -H tcp://192.168.1.123:2345 images
docker -H tcp://192.168.1.123:2345 run ...复制代码

最终swarm构建集群的时候,就是经过这样的远程服务调用来调度各个节点的。

集群和分布式运算

在正式开始实践集群以前,咱们有必要了解究竟什么是集群,什么是分布式计算。

首先,这二者有一个共同点,就是他们都是使用了多个服务节点的,通俗的说,就是要用到多台服务器协同工做(不必定是实体,也多是虚拟机)。

而二者的区别在于:

  • 集群是多台机器执行同一个业务,每次根据调度算法寻找最合适的节点来执行该业务
  • 分布式计算是将一个业务拆分红多个独立的部分,由多台机器共同协做完成

集群的优势在于,当业务的须要的资源比较大时,能够避免由一个服务器去独自承担压力,并且即使有一个节点宕机了,业务仍然能够继续正常运行。这有点相似于负载均衡。

分布式的优势则是在计算上,能够协同多台机器发挥计算的威力,进行须要超高性能的运算。

构建集群

说如今咱们正式开始构建集群。

使用docker-machine建立节点

因为实体机器的缺少以及在osx上没法正常开启tcp的docker服务,咱们基于docker-machine来建立多个虚拟机,做为集群中的节点。

执行下面的命令就能够建立一个新的docker-machine虚拟机manager1

docker-machine create --driver virtualbox manager1复制代码

在建立了虚拟机后,可使用docker-machine env manager1来查看虚拟机manager1的相关信息,包括IP地址等

如今咱们继续执行命令建立worker1worker2两个节点,使用docker-machine ls命令能够查看到全部正在工做的虚拟机:

docker-machine ls
NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
manager1   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.06.1-ce   
worker1    -        virtualbox   Running   tcp://192.168.99.101:2376           v17.06.1-ce   
worker2    -        virtualbox   Running   tcp://192.168.99.102:2376           v17.06.1-ce复制代码

建立docker machine后,能够经过docker-machine ssh manager1 <command>的方式来访问虚拟机,执行指令。

建立swarm集群

初始化一个swarm集群的命令为:

docker swarm init --listen-addr <MANAGER-IP>:<PORT> --advertise-addr <IP>复制代码

--listen-addr参数是管理者节点的docker服务所在的IP:PORT,也就是说,能够经过这个组合访问到该节点的docker服务。

--advertise-addr是广播地址,也就是其余节点加入该swarm集群时,须要访问的IP

如今咱们在manager1节点里建立swarm网络,执行

docker-machine ssh manager1 docker swarm init --listen-addr 192.168.99.100:2377 --advertise-addr 192.168.99.100复制代码

返回响应:

Swarm initialized: current node (23lkbq7uovqsg550qfzup59t6) is now a manager.

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

    docker swarm join \
    --token SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
    192.168.99.100:2377

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

这样便建立了一个swarm集群,而且manager1节点目前是以管理者的身份加入在节点中的。

如今咱们把worker1worker2两个节点加入到swarm集群中去,分别在两个节点的虚拟机中执行docker swarm join --token ..便可:

docker-machine ssh worker1 docker swarm join --token \
    SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
    192.168.99.100:2377
This node joined a swarm as a worker.复制代码
docker-machine ssh worker2 docker swarm join --token \
    SWMTKN-1-3z5rzoey0u6onkvvm58f7vgkser5d7z8sfshlu7s4oz2gztlvj-c036gwrakjejql06klrfc585r \
    192.168.99.100:2377
This node joined a swarm as a worker.复制代码

在任何一个节点上执行docker node ls均可以查看到当前整个集群中的全部节点:

docker-machine ssh manager1 docker node ls
NAME     ACTIVE    DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
manager1   -       virtualbox   Running   tcp://192.168.99.100:2376           v1.12.3   
worker1    -       virtualbox   Running   tcp://192.168.99.101:2376           v1.12.3   
worker2    -       virtualbox   Running   tcp://192.168.99.102:2376           v1.12.3复制代码

建立跨主机网络

集群创建完毕以后咱们要作的就是在集群上部署咱们的服务。可是首先应该让全部的节点处在一个共享的网络中,这样当咱们把服务部署在这个共享网络中,就至关于部署在整个集群中了。

使用docker network ls能够查看到当前主机所参与的全部网络:

docker-machine ssh manager1 docker network ls
NETWORK ID         NAME            DRIVER          SCOPE
764ff31881e5        bridge          bridge          local                  
fbd9a977aa03        host            host            local               
6p6xlousvsy2        ingress         overlay         swarm            
e81af24d643d        none            null            local复制代码

其中SCOPE为swarm,DRIVER为overlay的即为集群节点中的共享网络。集群创建后会有一个默认的ingress共享网络,如今咱们来再建立一个:

docker-machine ssh manager1 docker network create --driver overlay swarm_test复制代码

在跨主机网络上部署服务

在集群上部署应用,就是在共享网络上部署服务(service)

但首先要保证每一个节点上都已经有所需的镜像和环境了,这点即可以经过将同一份docker-compose配置文件共享到每一个主机上,使用docker-compose在每一个节点上下载镜像和搭建环境的工做。

因为judge_server的服务架构很简单,就一个镜像,因此我在这里直接在每台主机上把它pull下来就行了:

docker-machine ssh manager1 docker pull registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0
docker-machine ssh worker1 docker pull registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0
docker-machine ssh worker2 docker pull registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0复制代码

接下来即是重头戏,咱们使用manager1节点,在共享网络上启动咱们的服务

docker service create --replicas 3 --name judge_swarm -p 8090:8090 --network=swarm_test registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0复制代码

这个命令看起来是否是很像docker run?没错,swarm最终的目的就是把操做集群变得像操做单一的docker服务端同样简单!

--replicas 用于指定服务须要的节点数量,也就是集群的规模,这个值是弹性的,你能够在后续动态的更改它。

当服务中某个节点挂掉时,swarm将会搜寻集群中剩余的可用节点,顶替上去。也就是说,swarm会动态的调度,老是保持服务是由3个节点运行着的。

-p 用于暴露端口到宿主机,这样咱们就能访问到了。

--network用于指定部署service的网络是哪个

如今在manager1节点中使用docker service ls来查看集群中的服务:

docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                                       PORTS
kofcno637cmq        judge_swarm         replicated          3/3                 registry.cn-qingdao.aliyuncs.com/marklux/judge_server:1.0   *:8090->8090/tcp复制代码

如今咱们尝试在本地访问192.168.99.100:8090/ping,就能够获得响应了,事实上,如今不管将ip换为worker1或者worker2的,响应的结果都是同样,由于此时全部节点已经处在一个共同的集群网络下了

通过大量的访问测试,能够看到hostname是在变化着的,这说明每次请求,都由swarm动态的调度,选择了不一样的节点来进行处理。

遗留问题

至此集群的部署已经完成,可是咱们还遗留了几个问题没有解决:

  • 集群节点的动态添加删除不是很方便,这致使在web端管理判题服务机有必定的难度,固然能够经过docker的REMOTE API来实现,不过复杂度比较高
  • 集群节点间的文件同步不太好实现,可能须要本身写脚本同步或是使用rsync之类的服务来实现
  • swarm很是适合快速构建大量集群来实现业务的处理,不过对于只有几台机器的状况而言,有些"杀鸡用牛刀"的感受
相关文章
相关标签/搜索