您的位置:首页 > 运维架构 > Docker

利用Docker Registry服务实现多数据中心的部署优化

2016-06-04 10:54 651 查看
本文来源:Ghostcloud翻译(https://www.ghostcloud.cn/)

本文主要讲解了Docker在跨远程数据中心的部署中所起的作用,以及如何通过Docker技术实现多个数据中心的部署优化。

在生产环境中用Docker来部署服务

  以我之前的公司为例,我们有6个数据中心,运行的服务有400多个。这些服务每隔几分钟就要部署一遍,而且部署工作是由不同的开发小组分头进行的,一天下来要部署90次左右。

  考虑到我们的部署频率这么高,保证部署接口的一致性和标准化是很有必要的,因此我们引入了Docker容器来进行部署,这样,开发团队就不必再考虑服务所采用的开发技术和开发语言,直接将自己的服务打包到Docker镜像,并以镜像的形式来部署有所服务。

  但是Docker镜像有的时候实在很庞大(数百MB),要想将Docker镜像高效地部署到各个数据中心,还是存在一定的困难,在这一点上我们也没少走弯路。

将Docker服务镜像有效部署到各个数据中心

  在部署服务的时候,所有镜像都是以Docker容器的形式运行在数据中心的服务器上的,我们要做的就是将镜像pull到服务器上,然后运行容器。

  我们的解决方案是这样的,把应用的镜像存在私有的Docker Registry中,这里我们用的Artifactory来做Docker Registry ,因为之前我们也一直用的Artifactory来存储其他一些代码包。

  每次部署的时候,我们可以从Artifactory中心镜像仓库里面直接拉取Docker镜像,但是这么做并不是很经济,毕竟在多个数据中心的服务器之间传输镜像会大大增加网络开销。

  如下图所示,我们的java应用镜像是由两个镜像层构成的:一个基础镜像层(大小约为160MB,包括alpine linux + oracle jdk),还有一个应用层,大概60MB,里面是Spring Java应用。



  如果要在一个数据中心内的10台机子上部署相同的应用,就需要实现10*60MB的跨数据中心传输(从中心仓库传输到远程数据中心的服务器上),这还只是在理想情况下的数据量,前提是在目标服务器上都已经装好了Java基础镜像。

  好在这种情况也不是没有应对之策的,如果我们在本地数据中心建一个Docker registry,并将其作为Docker私有中心镜像仓库的代理缓存的话,就可以最大限度地减少这部分网络开销。

  采用本地数据中心建立Docker registry代理缓存,在10台服务器上部署同一镜像的话,从中心仓库到数据中心就只需要传输60MB的应用层数据,其余9台服务器只需从本地的registry缓存中拉取缓存的应用层数据即可,不过,这种情况的只适合我们目前的部署方式,也就是说,这10台服务器是按顺序进行部署的。



  当然,我们也可以定制一个导出—传输—缓存—导入的Docker镜像部署流程,但是这里我们采用了另一种方式,用开源的Docker registry来做代理和缓存,这个开源项目本身就有这两种功能。

Docker Registry正式登场

  私有Docker registry的搭建并不难,大家可以参考docker官方的帮助文档:https://docs.Docker.com/registry,里面有详尽的描述。 搭建Docker
Registry代理缓存其实也很简单,而且网上还有相关的教程,照着教程很快就可以把代理缓存搭起来,并从Docker Registry拉取镜像。可惜按照这种教程搭出来的代理缓存效果不咋样,无法满足我们的需求。

  但是我们又不可能再映射到其他私有Registry,只有中心Hub才可以映射,这就是个大问题了。

  然而我们又确实需要减小带宽开销,缩短部署时间,该怎么办呢?自己动手丰衣足食,我们就自己来搞定Docker registry缺失的这个功能。

分析问题,解决问题

  Artifactory提供了Docker API接口,可以对托管的各个Docker镜像仓库进行通信。比方说,如果我们需要获取存储在本地Docker镜像仓库里面的busybox镜像的tag,就可以通过托管该仓库的Artifactory 向镜像仓库发送请求,具体如下:



  Docker registry只能映射到公共的Docker Hub,我们的应对办法是对Docker registry镜像调用远程Docker registry URL的每个HTTP请求都进行解析和重写,使之重定向到我们的Artifactory Docker API URL.

这种方案的原理是通过重定向来瞒过Docker registry镜像,用Artifactory Docker镜像仓库取代Docker Hub,与Docker registry进行通信。

引入HAProxy,轻松搞定重定向

  这里我们采用了HAProxy来重写Docker registry发送给中心registry的HTTP请求,当然,HAProxy本身也是以Docker容器的形式运行的。

  HAProxy的详细配置如下,按照这个配置就可以实现HTTP的重写了:



  上述设置会将Docker镜像发送的每个/v2/*被请求重定向到/artifactory/api/docker/docker-local/v2/*,并发送到Artifactory服务器。

  这里我们用了环境变量来配置Artifactory的 IP和端口号,并将授权信息添加到头部数据中,以验证Artifactory用户的有效性。

  此外,上面的配置还开放了HAProxy的统计功能,供前端和后台服务器调用,方便服务器检测Artifactory是否启动,可否可访问,还可以统计镜像产生的的数据流量。

将Docker registry hook到HAProxy

  接下来要做的就是将Docker registry和HAProxy hook起来,实现二者之间的通信,这样HTTP请求才能转发到我们指定的对象。这里我们用的是docker-compose来hook Docker registry和HAProxy。具体的 docker-compose.yml 文件如下:



  同样的,为了提高应用的灵活性,这里我们还是用了大量的环境变量设置。根据上面的配置,Compose会到HAProxy路径下去寻找haproxy.cfg文件,并到docker-registry文件夹下去找Docker registry的config.yml文件,这两个文件夹都位于前面指定的WORK路径下,这里的WORK就是一个相对路径,可以根据实际情况设置不同的值。

  配置完成之后,就可以通过下面的bash脚本来启动docker-compose了,这个脚本包含了docker-compose运行所需的所有环境变量:



  启动docker-compose之后,大家就可以通过mirror.example.com:5000访问我们的镜像了。首先我们要来查看一下镜像的内容:



  可以看到,这个镜像缓存是空的。下面我们要从Docker中心仓库拉取busybox镜像,并测算一下镜像下载耗时:



  首次下载镜像花了3.5秒。

  运行下面的命令,可以看到busybox镜像已经存到Docker镜像缓存中了:



  下面我们把本地busybox镜像删掉,再拉取一遍试试。第二次拉取的速度应该比第一次快,因为这个镜像已经在缓存中,拉取的时候就不用再去访问中心镜像仓库了,直接从缓存拉取即可。



  O了!因为镜像已经存在registry缓存里面了,第二次拉取只花了0.28秒,速度确实有很大的提升。

结论

  本文到这里就结束了。在本教程中,我们在各个远程数据中心建立了本地Docker registry镜像缓存,并映射到私有Artifactory Docker registry中心,此外还实现了应用部署时跨数据中心的数据传输优化。

  当然,这个方案并不完美,还有很大的改进空间。不过,我们最初的目标已经达到了,本教程提供了一种相对简单、透明的方式,优化了多个远程数据中心之间的Docker镜像分布式部署。

  大家也可以在这个方案的基础上加以改进,更好地实现平稳部署。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: