基于OSS搭建跨区域部署的分布式Docker镜像仓库

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 大规模分布式Docker应用需要部署在在不同的地域(region)中。为了提升部署速度并节省网络成本,需要在每个region部署Docker Registry。本文将结合阿里云OSS的新特性来介绍跨区域部署的分布式Docker镜像仓库方案。

基于OSS搭建跨区域部署的分布式Docker镜像仓库

Docker镜像是Docker的核心价值之一,Docker镜像仓库(Registry)是用于Docker镜像的管理和分发的基础设施。现在已经有了Docker Hub等多家公有镜像管理服务供应商,阿里云容器Hub服务也是您在云端的一个非常好的选择。但是有些情况,为了更加灵活的部署控制和一些管控要求,您也许会考虑在云端的部署一个私有镜像仓库。

为了满足异地容灾和就近访问等需求,需要在不同的区域(region)部署分布式Docker应用;在不同的region中,为了提升部署速度并节省网络成本,需要在每个region部署私有Docker Registry。然而,这就会给分布式部署中的镜像管理带来很多挑战。本文将结合阿里云OSS的新特性来介绍跨域部署的Docker镜像仓库的解决方案。

14572203169236

阿里云搭建Docker Registry入门

Docker Registry是存储和网络密集型应用。Docker镜像存储需要使用大量的存储资源,采用本地存储无法满足用户对容量和可用性的需求;同时镜像的上传,下载需要高速的网络带宽。Docker Registry自从2.1版本开始,就已经加入了对阿里云开放存储服务(OSS)的正式支持。这为Docker Registry提供一个支持海量存储,高性能访问,高可用,安全,低成本,无需运维的存储后端。而且利用ECS构建私有仓库可以使用OSS内部数据流量,降低公网网络流量成本。在集团内部和阿里云的镜像仓库服务,我们都采用了OSS的对象存储服务,来支持对内和对外的Docker镜像管理和分发。

在阿里云上ECS上搭建一个Docker Registry是非常方便的,最方便的方法是利用Docker镜像的方式来进行安装。

首先我们要在ECS上有一个Docker运行环境,你可以手工安装Docker Engine到已有的ECS实例上;或者,利用Docker Machine的ECS驱动方便的创建一个新的Docker就绪的ECS实例。请参见入门指南

启动一个使用OSS的存储的Docker Registry也是非常简单的,我推荐的方法是利用Docker Compose的方式配置和启动:

一个包含最简单的配置的docker-compose.yml如下

registry:
  restart: always
  image: "registry:2.3"
  ports:
    - 5000:5000
  environment:
    - REGISTRY_STORAGE=oss
    - REGISTRY_STORAGE_OSS_ACCESSKEYID=******
    - REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=******
    - REGISTRY_STORAGE_OSS_REGION=oss-cn-beijing
    - REGISTRY_STORAGE_OSS_BUCKET=aliyungo-beijing
    - REGISTRY_STORAGE_OSS_INTERNAL=true
    - REGISTRY_STORAGE_OSS_SECURE=false

这里,我们将利用Docker Registry 2.3官方镜像创建一个私有镜像仓库,通过环境变量的方式配置了OSS的Access Key ID, Access Key Secret, Region, Bucket等信息。关于OSS配置的详细信息请参见官方文档

然后执行 docker-compose up -d 命令, 私有镜像就启动成功了。

我们可以在ECS实例上执行下面命令来验证相关工作

docker pull node:5.7
docker tag node:5.7 127.0.0.1:5000/node:5.7
docker push 127.0.0.1:5000/node:5.7

执行结果如下,已经成功将镜像推送成功

[root@iZ25cz6gdslZ ~]# docker pull node:5.7
5.7: Pulling from library/node
fdd5d7827f33: Already exists 
a3ed95caeb02: Pull complete 
0f35d0fe50cc: Already exists 
627b6479c8f7: Already exists 
67c44324f4e3: Already exists 
b52090f6ca00: Pull complete 
1df855d9e713: Pull complete 
Digest: sha256:cde7a4fca0a3dd2330977078c3773164b172a0ec582bafced6db955dca02a5c4
Status: Downloaded newer image for node:5.7
[root@iZ25cz6gdslZ ~]# docker tag node:5.7 127.0.0.1:5000/node:5.7
[root@iZ25cz6gdslZ ~]# docker push 127.0.0.1:5000/node:5.7
The push refers to a repository [127.0.0.1:5000/node]
5f70bf18a086: Mounted from ubuntu 
1967867932fe: Pushed 
6b4fab929601: Pushed 
550f16cd8ed1: Mounted from python 
44267ec3aa94: Mounted from java 
bd750002938c: Mounted from java 
917c0fc99b35: Mounted from java 
5.7: digest: sha256:64413fb300f4dd491397dbf16edbc8499c521640ac52e68bdfee8241a8d0dafe size: 2389

注意:一定要配置Docker Hub加速器呀,要不会有欲哭无泪的赶脚。

在生产环节中使用,您还需要添加Nginx等组件来增加TLS访问,认证授权,负载均衡等能力。详见官方参考),本文不再详述。

分布式跨区域Docker Registry方案讨论

回到正题,为了支持多区域部署Docker应用的需求,我们需要在每个region部署Docker Registry。然而如何在分布式的Docker Registry之间实现内容同步?我们有以下几种可能的方案

  1. 当客户端推送镜像时,分别向不同region的Docker Registry推送。

    • 好处:没有任何外部依赖
    • 不足:手工同步导致客户端逻辑复杂;当扩展region之后需要手工同步已有镜像
  2. 利用Docker Registry的通知机制,实现Web Hook;当一个Docker Registry收到镜像推送完成事件之后,由Web Hook的实现向其他region的Docker Registry推送刚完成的镜像

    • 好处:没有任何外部依赖,自动化同步
    • 不足:基于事件的同步逻辑实现复杂,需要考虑网络中断,region变更等多种边界情况
  3. 利用存储复制的机制,实现不同region的镜像复制

    • 好处:自动化同步,实现简单
    • 不足:需要底层存储驱动支持

由于Docker Registry本身是无状态的应用,非常适合采用数据复制的方案实现分布式部署。去年一系列公司提出了分布式Docker Registry的解决方案,大多基于其商业化的数据复制技术,比如NetApp在DockerCon的演讲。

然而利用阿里云OSS的新特性,Bucket跨区域复制和回源设置,我们也可以轻松实现一个大规模分布式的镜像仓库。在下面示例中:我们会把北京registry作为主registry,允许用户推送、拉取镜像;创建上海registry作为从registry,允许用户拉取镜像。其高层架构图如下:

14571909981240

利用OSS跨区域复制轻松实现分布式镜像仓库

OSS的Bucket Cross-Region Replication是跨不同区域数据中心的自动化、异步复制技术。它会将对源Bucket中的对象的改动(新建、覆盖、删除等)同步到目标Bucket。详细信息请参见帮助文档

首先,我们创建一个上海region的bucket,作为目标bucket

14571876877887

然后选择北京region的bucket作为源bucket; 并配置跨区域复制规则到目标bucket
14571885643390

14571886754062

同步规则配置完成之后,等待几分钟同步完成的效果如下
14571877603740

在上海region的ECS实例上,我们利用上文的方法也创建一个Docker Registry,"docker-compose.yml"的配置如下,并配置上海region的OSS Bucket作为镜像存储

registry:
  restart: always
  image: registry:2.3
  ports:
    - 127.0.0.1:5000:5000
  environment:
    - REGISTRY_STORAGE=oss
    - REGISTRY_STORAGE_OSS_ACCESSKEYID=******
    - REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=******
    - REGISTRY_STORAGE_OSS_REGION=oss-cn-shanghai
    - REGISTRY_STORAGE_OSS_BUCKET=aliyungo-shanghai
    - REGISTRY_STORAGE_OSS_INTERNAL=true
    - REGISTRY_STORAGE_OSS_SECURE=false

然后执行docker-compose up -d命令启动Docker Registry

我们可以通过下面的命令来验证镜像复制是否成功

# docker pull 127.0.0.1:5000/node:5.7
5.7: Pulling from node
fdd5d7827f33: Already exists 
a3ed95caeb02: Pull complete 
0f35d0fe50cc: Already exists 
627b6479c8f7: Already exists 
67c44324f4e3: Already exists 
b52090f6ca00: Pull complete 
1df855d9e713: Pull complete 
Digest: sha256:64413fb300f4dd491397dbf16edbc8499c521640ac52e68bdfee8241a8d0dafe
Status: Downloaded newer image for 127.0.0.1:5000/node:5.7

大家可以看到,无需任何编程,我们已经简单地实现了分布式数据的Docker Registry的自动化数据同步。用户可以在北京registry上push新的镜像,在上海registry上pull镜像,没有任何的手工维护工作。

需要注意的是:OSS的bucket复制是单向的,所以我们要在部署方案中确定registry的主从关系。只有在主registry的镜像是可以读写的,而在从registry中,镜像应是只读的。本文中主registy在北京region,而从registry在上海region。

目前为止,这个方案还不够完美。由于Bucket复制是异步的,采用的是最终一致性。对象从源复制到目的bucket需要一定的时间,这取决于复制对象的大小。我们知道Docker镜像是采用分层存储机制,每个layer包含相应的blob对象,元数据和digest信息。其中layer的blob对象可能非常大,数据复制完成时间会比较长。

所以,当我们在上海registry拉取镜像时,如果blob对象没有复制完成,则我们会遇到如下"unknown blob"错误

# docker pull 127.0.0.1:5000/redis:2
2: Pulling from redis
fdd5d7827f33: Already exists 
a3ed95caeb02: Download complete 
3868e1e933d6: Pulling fs layer 
1d007c18c656: Pulling fs layer 
ad75a8697e9c: Waiting 
8de500daf5d7: Waiting 
788fee3bdabf: Waiting 
8f359895dbf8: Waiting 
unknown blob

目前实现对于时效性不敏感的场景,这个方案已经足够。当然,也需要应用层做一些调整,在镜像未复制完成之前,需要反复尝试等待复制完成。

如果用户希望能够立刻从上海region的registry访问刚在北京region推送的镜像,有没有更好的解决方案?

利用OSS回源设置实现镜像按需热迁移

对于上面的问题一个自然的想法就是:如果在上海registry请求尚未同步完成的Docker layer数据时,就从北京region的源bucket中读取对象,并返回。

为了减少开发的复杂度,我们尝试使用OSS的回源设置(详见帮助文档)来自动化这个过程。当上海region的bucket中所需blob对象不存在时,让OSS可以从北京region的bucket中自动进行回源读取;在将layer内容返回给Docker请求的同时,自动将内容复制到上海region的目标bucket。

我们在上海region的bucket上配置回源规则如下
14571903064338

这里我们使用镜像方式:将回源地址指向北京bucket的公网访问地址
14571903652298

当然我们还需要对registry中的OSS driver的Stat和URLFor实现做一些调整,当Registry检查到文件的元数据不存在时,强制通过回源方式返回北京registry中的内容。对Docker Registry的修改可以从Github访问

您也可以直接利用编译过的"registry.aliyuncs.com/denverdino/registry:2.3"镜像来替换官方镜像。只需修改上海region部署所用的"docker-compose.yml"的image值修改即可。

registry:
  restart: always
  image: registry.aliyuncs.com/denverdino/registry:2.3
  ports:
    - 127.0.0.1:5000:5000
  environment:
    - REGISTRY_STORAGE=oss
    - REGISTRY_STORAGE_OSS_ACCESSKEYID=******
    - REGISTRY_STORAGE_OSS_ACCESSKEYSECRET=******
    - REGISTRY_STORAGE_OSS_REGION=oss-cn-shanghai
    - REGISTRY_STORAGE_OSS_BUCKET=aliyungo-shanghai
    - REGISTRY_STORAGE_OSS_INTERNAL=true
    - REGISTRY_STORAGE_OSS_SECURE=false

再次尝试,我们已经近乎同时地从上海region的registry访问刚刚在北京region推送的Docker镜像了。在这里,我们将异步的对象复制,和同步的按需复制结合在一起,可以满足绝大多数场景对分布式镜像仓库的要求。

大功告成!

总结

跨区域部署的Docker Registry可以在不同数据中心的用户高效、简单的利用Docker镜像进行软件交付、部署和运维;可以支持异地容灾、分布式DevOps等场景。

在本文介绍的这个分布式、跨域部署的Docker Registry的方案中,无需额外的手工运维就可保证不同地域Docker镜像仓库的数据一致性。其技术要点如下:

  • 使用OSS作为Docker镜像存储实现,不同region的registry配置到本地region的bucket上
  • 利用OSS提供的跨区域bucket复制能力,在主从registry中实现自动数据复制
  • 在从registry中,如果镜像layer对象存在于本地的OSS bucket中,则直接利用bucket中对象返回;
    如果镜像layer对象还未同步成功,则回源到主registry的bucket中

感谢阿里云OSS团队一直以来的大力协助和支持。

欢迎大家使用阿里云容器服务阿里云Docker镜像仓库服务。它能帮助你大大加速云端Docker应用的交付流程。

相关实践学习
通过workbench远程登录ECS,快速搭建Docker环境
本教程指导用户体验通过workbench远程登录ECS,完成搭建Docker环境的快速搭建,并使用Docker部署一个Nginx服务。
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
2天前
|
测试技术 Linux 网络安全
【好玩的开源项目】使用Docker部署SyncTV视频同步和共享平台
【4月更文挑战第16天】使用Docker部署SyncTV视频同步和共享平台
37 1
|
6天前
|
测试技术 Linux 数据安全/隐私保护
【Docker项目实战】使用Docker部署Seatsurfing预订座位系统
【4月更文挑战第12天】使用Docker部署Seatsurfing预订座位系统
32 3
|
9天前
|
JavaScript 前端开发 Docker
全栈开发实战:结合Python、Vue和Docker进行部署
【4月更文挑战第10天】本文介绍了如何使用Python、Vue.js和Docker进行全栈开发和部署。Python搭配Flask创建后端API,Vue.js构建前端界面,Docker负责应用的容器化部署。通过编写Dockerfile,将Python应用构建成Docker镜像并运行,前端部分使用Vue CLI创建项目并与后端交互。最后,通过Nginx和另一个Dockerfile部署前端应用。这种组合提升了开发效率,保证了应用的可维护性和扩展性,适合不同规模的企业使用。
|
10天前
|
应用服务中间件 Docker 容器
docker 镜像常用命令
docker 镜像常用命令
30 0
|
10天前
|
Linux Shell 虚拟化
linux 部署docker容器虚拟化平台(二)--------docker 镜像制作方法
linux 部署docker容器虚拟化平台(二)--------docker 镜像制作方法
14 0
|
10天前
|
存储 Linux Shell
centos 部署docker容器 安装 、基本使用方法(一)
centos 部署docker容器 安装 、基本使用方法(一)
19 0
|
13天前
|
测试技术 Linux 数据安全/隐私保护
【Docker项目实战】使用Docker部署PicoShare共享文件平台
【4月更文挑战第5天】使用Docker部署PicoShare共享文件平台
46 4
|
3月前
|
虚拟化 Docker Windows
win10使用Docker以及在天池比赛上提交容器镜像文件
win10使用Docker以及在天池比赛上提交容器镜像文件
63 1
|
4月前
|
jenkins 持续交付 数据安全/隐私保护
Docker 打包镜像 | 发布至阿里云镜像仓库
Docker 打包镜像 | 发布至阿里云镜像仓库
431 1
|
5月前
|
存储 数据库 Docker
Docker Hub和镜像仓库
Docker Hub 是 Docker 公司提供的官方公共 Docker 镜像注册表,允许用户存储、分享和获取 Docker 镜像。在 Docker Hub 上,你可以找到许多官方和社区维护的 Docker 镜像,这些镜像涵盖了各种常见的应用程序和服务,如数据库、Web 服务器、应用程序框架等。
3092 0

相关产品

  • 容器镜像服务