docker 架构图中为什么分那么多层

进阶 “百万并发” 背后的架构实践_Docker_传送门
进阶 “百万并发” 背后的架构实践
2016 年 1 月 10 日,数人云举办了 “Hold 住高并发,唯架构与运维不可辜负” 的主题沙龙,当当、宜人贷、京东、Kuick 纷纷献策,分享 “高并发” 场景下的架构变迁 。3 月 27 日,“百万并发” 升级 2.0 讨论,数人云邀请小米、唯品会、云智慧的资深工程师一起分享支撑 “百万并发” 背后的架构实践,定不辜负每一个参会者。〈分享嘉宾小米、唯品会、云智慧、数人云〉秦晓辉,小米运维研发技术负责人互联网公司监控解决方案
OpenFalcon 主程,国内第一套开源 PaaS 平台 DINP 主程,企业级业务监控 Minos 作者,Gopher,现负责小米运维平台的搭建。关注运维自动化、PaaS 领域。邱戈川,唯品会分布式架构平台产品经理16
个年头的 IT 老兵,除了销售和老板角色,做过 IT 中的各种角色,游走于架构与产品间。关注 Docker,
等容器化技术领域的实践。主导的分布式服务框架已经广泛用于唯品会各大核心业务系统,以高性能、低延迟广受好评。现任唯品会( VIP.COM
)基础架构部分布式服务框架、定时任务调度系统以及容器化管理平台产品经理。陈书德(Rudy Chen),云智慧技术中心(Technical Center)资深技术咨询经理在加入云智慧之前,拥有超过6年的IT行业咨询和项目管理经验,企业级方案顾问。拥有政企、旅游、医疗、教育和电商行业咨询经验,是资深的行业IT、云计算和应用性能解决方案顾问。现负责云智慧技术咨询的工作。庞铮,数人云运维负责人15 年以上运维工作经验。就职过宏碁戏谷、第三波、SQUARE ENIX CO., LTD.等。2015年加入数人云,从事数人云平台运维管理。〈议程安排14:00—17:30〉13:30 - 14:00
签到14:00 - 14:15
开场14:15 - 14:55
《小米:OpenFalcon 应对并发的一些手段》秦晓辉 14:55 - 15:35
《数人云:分布式百万并发测试实践》庞铮 15:35 - 15:50
茶歇15:50 - 16:30
《云智慧:应用系统“承压”测试实践》陈书德16:30 - 17:10
《唯品会:分布式服务框架实践与容器化演进》邱戈川时间:3月27日 14:00 - 17:10地点:P2 联合创业办公社 北京市海淀区中关村大街11号亿世界财富中心A座B2〈关于数人云下一代 DCOS〉数人云()是一款部署在公有云、私有云以及混合云之上的 DCOS(Data Center Operating System ),旨在帮助用户在云端快速建立并稳定运行一个高性能生产环境,将应用弹性做到极致,实现一站式的微服务架构集群系统。基于领先的 Mesos 和 Docker 技术,数人云可为用户的业务系统带来高可用的服务质量,快速的性能伸缩,高效的资源利用以及便捷的可视化管理和监控;同时,数人云保证用户的计算资源和数据完全为用户私有可控。数人云()是一款部署在公有云、私有云以及混合云之上的 DCOS(Data Center Operating System ),旨在帮助用户在云端快速建立并稳定运行一个高性能生产环境,将应用弹性做到极致,实现一站式的微服务架构集群系统。基于领先的 Mesos 和 Docker 技术,数人云可为用户的业务系统带来高可用的服务质量,快速的性能伸缩,高效的资源利用以及便捷的可视化管理和监控;同时,数人云保证用户的计算资源和数据完全为用户私有可控。点击“阅读原文”赶快报名吧!
觉得不错,分享给更多人看到
Docker 微信二维码
分享这篇文章
3月13日 20:24
Docker 最新文章&-&&-&&-&【承上启下】Docker所知总结 Docker+Nginx架构详解
这是我近期有关Nextcloud/ownCloud的最后一篇文章了,我也是时候进入下一个阶段了。短短一年来,有关的教程也写了六七十篇,自己也觉得有些疲倦。接下来,我的关注点将是服务器后端知识,也就是说我将更少地写些浅显的东西。这篇文章算是给过去我的所学做个收尾,也给接下来的学习起个头。
本篇文章会十分冗长,这不是一篇典型的教程,我只是尽量在里面记下我所知的大多数东西。
Nginx是一款功能强大的反向代理服务器,支持HTTP、HTTPS、SMTP、IMAP、POP3等协议,它也可以作为负载均衡器、HTTP缓存或是Web服务器。
Docker是一款轻量级虚拟机软件,他充分利用操作系统本身已有的机制和特性,实现远超传统虚拟机额度轻量级虚拟化。
Nextcloud是一款功能强大的PHP网盘程序,衍生自著名开源项目ownCloud,拥有美观的Web界面和强大的扩展能力,以及优秀的安全性能。可满足复杂条件下对私有云的需求。
Nextcloud复杂的功能和高安全似乎决定了它的臃肿——但我们不能像对于WordPress一样责怪开发人员。但Nextcloud无后端设计使它在性能落后于Seafile这样的程序,我一直坚持Apache+PHP是Nextcloud最好的搭档,现在我依旧坚持这一点,看看那冗长的Nginx配置文件,而Apache几乎什么都不用做。尽管如此,我还是不得不嫉妒Nginx处理静态文件的优秀性能。
或许以上就是LNMPA诞生的原因吧。但我今天并不准备演示一遍如何搭建LNMPA环境,而是寻找另一种更简易的方法:Nginx+Docker。
其实很简单,不过是将Apache装入容器中而已:
由此图可以看出,这并没有什么复杂的地方,根本谈不上高深。
那么,将Apache\MySQL等服务放进容器有什么好处呢?
易部署:所使用的都是现成的景象,随时启用,随时删除。
高容错:操作出现任何问题也不会对宿主机有什么影响。
模块化:附加的服务(ONLYOFFICE、Collabora Online、XMPP等)均运行于独立的容器中,互不干扰,增删方便。
免于处理各种复杂的兼容问题。
但我今天就是要简单的问题复杂化,把每一部分都分析透彻。
Nextcloud在Docker Hub上有已经配置完成的镜像,使用Apache+PHP或是Nginx+FPM,但是不包含MySQL或MariaDB这样的数据库应用,也不直接支持HTTPS访问。
对于缺少的数据库应用,当然可以使用SQLite来应付这个问题,但是,显然不是最佳的解决方案。
最佳的解决方案也不是使用宿主机的数据库服务,而是使用Docker的一个关键功能——容器互联。
容器互联(linking)是一种让多个容器中的应用进行快速交互的方式。它会在源和接受容器中间创建连接关系,接受容器可以通过容器名快速访问到源容器而不用指出具体的IP地址。
举个例子,我们运行一个容器的命令一般是这样的:
dock run -d &container&
来为这个容器指定一个名字吗,比如“c1”
docker run -d --name c1 &container&
概念:Docker网桥(Net Bridge)
Docker在创建容器时会默认将容器连接于一个虚拟网桥(docker0)上,这实际上是一个Linux网桥,可以理解为是一个软件交换机(和家里的路由器有几分相像)。它会在挂载其上的接口进行转发,如图:
docker0可以理解为一个局域网,就像你家的网络与电信服务商之间隔了一个路由器,两个网络之间无法直接访问,除非映射端口。
(映射端口的操作使用
-p 宿主机端口:容器端口
如果你操作过路由器上的端口映射功能,这部分会很好理解。
对于docker0内部,每个容器都会分配到一个IP地址,同时,在每个容器内的hosts文件中会记下IP地址与容器的对应关系,这样,如果一个容器想要访问另一个容器,只需要知道容器的ID或者容器名,就像域名一样,而不必获知它的IP地址。
有了网桥,我们就可以将Apache和MySQL分别部署到两个容器中,通过容器名来访问。
数据的操作和持久化
无论是使用Docker,还是Virtualbox亦或是VMware这样的虚拟机软件,实现宿主机和虚拟机之间的文件互访一直是很重要的一件事。这儿我们要用到Docker的数据管理方式之一——数据卷。
数据卷(Data Volumes):容器内数据直接映射到本地主机环境。
数据卷是一个可供容器使用的特殊目录,它会将主机操作系统目录直接映射至容器。
一个典型的例子:我创建了一个带有HTTP服务器的容器,在宿主机上使用Nginx反向代理指向它的请求,为了提高性能,需要分离客户端的动态请求和静态请求。此时,我就可以将容器内的文件映射出来,对于动态请求,Nginx会与容器进行通信,而对于静态请求,Nginx可以直接从本地获得静态文件,提高速度。
提前说一下,上面的例子并不适用于Nextcloud,或者说,我还没找到正确的途径。
1.在容器内创建一个数据卷
在用Docker run命令的时候,使用
标记可以在容器内创建一个数据卷。标记可重复使用。示例:
docker run -d -P --name web -v /webapp training/webapp python app.py
2.挂载一个主机目录作为数据卷
格式和映射端口相同,
-v 本地目录:容器内目录
(本地目录必须为绝对路径)。
如果想更集中地去管理容器的数据的话,可以使用数据卷容器,不再赘述。
Nginx在这里的身份是反向代理服务器,之前我一直将Nginx用作HTTP服务器,现在才正式接触Nginx一直所标榜的功能。
反向代理的配置可以十分简单,直接在server{}中加入:
location /
proxy_pass http://代理地址:端口;
以上就是一个反向代理配置,但是这还不够,并且在接下来的时间里就会发现这远远不够。
所谓反向代理,对真实服务器来说无感知,也就是说它并不知道有Nginx这一个的存在。因为对服务端来说,它一直只被一个永户访问,就是反向代理服务器Nginx,而且一直是使用一个URL访问(http://代理地址:端口)。所幸的是,这些状况都是由上方的那简单的配置而导致的,通过添加一些配置信息,就可以解决这个问题:
location / {
proxy_pass http://代理地址:端口;
proxy_set_header Host $http_
proxy_set_header X-Forwarded-Proto $
proxy_set_header X-Real-IP $remote_
看看,都添加了哪些东西。
proxy_set_header Host $http_
传递了客户端(相对于Nginx)的URL地址,使得服务端得知访问它所用的URL是外部客户端所访问的真实URL。
proxy_set_header X-Real-IP $remote_
获得客户端的真实IP,而不是Nginx的127.0.0.1
proxy_set_header X-Forwarded-Proto $
使服务端能正确识别客户端所用的是HTTP协议还是HTTPS协议
WebSocket代理
现在还有一个棘手的问题,很多Web应用都使用了WebSocket技术,以实现ajax难以实现的一些功能。但在前文中的配置下,Nginx并不会去代理WebSocket请求,Websocket协议是这样的:
ws://服务器地址/
wss://服务器地址/
既然我这儿都把问题说出来了,那肯定就有解决方法咯。
在前文的配置中再加入以下内容:
proxy_set_header Upgrade $http_
proxy_set_header Connection $connection_
这样,我们就得到了一个靠谱的反向代理配置:
location / {
proxy_pass http://代理地址:端口;
proxy_set_header Host $http_
proxy_set_header X-Forwarded-Proto $
proxy_set_header X-Real-IP $remote_
proxy_set_header Upgrade $http_
proxy_set_header Connection $connection_
它应该能应付大多数应用了。
欸?为什么反向代理就高效了?
明明没有啊?
的确没有。
在目前的配置下,我们只是在客户端和服务端之间安排了一个中间人,而且既符合常理也符合实际地说,它变慢了(虽然感觉上微乎其微)。就好比给网站做CDN,做了的全站CDN却没有缓存,所有请求由CDN服务器转发给源服务器,再由源服务器将所有回应全部转发给CDN服务器,实际上增加了中间过程,对响应速度没有丝毫改善。而如果做了CDN缓存,CDN服务器会承担相当一部分请求,回源的请求会大幅减少甚至为0。
同样的,Nginx也是如此,我们得想办法让Nginx自己去根据静态请求返回静态文件,让服务端少为它不擅长的静态文件传输浪费功夫,全心全意地去处理静态请求(Tomcat是个典型的例子,所以我们经常看到把Nginx和Tomcat结合起来用)。
这个解决办法就叫动静分离。
只需要对客户端发来的请求过滤一下,分出其中哪些是动态请求,哪些是静态请求。至于分离方法,可以使用强大正则表达式来匹配URL:
.*\.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*)
应用到Nginx中:
location / {
proxy_pass http://代理地址:端口;
proxy_set_header Host $http_
proxy_set_header X-Forwarded-Proto $
proxy_set_header X-Real-IP $remote_
proxy_set_header Upgrade $http_
proxy_set_header Connection $connection_
location ~ .*\.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*)
root /var/www/html/ #静态文件存放位置
expires 30d; #缓存30天
这就将动静态请求分离了出来,凡是带有gif、jpg、png……的请求统统从本地 /var/www/html/static目录中获取。而动态请求则发送至服务端。
为什么之前说不适用于Nextcloud呢?
因为Nextcloud的一些静态文件实则是由动态语言实时生成的,比如这个:
https://cloud.orgleaf.com/index.php/css/files/969dc0aad-merged.css
对于这种请求,Nginx仍然会傻乎乎地到/var/www/html/static里去找,当然找不到。
这种问题也许能用更复制的正则表达式来解决,但有没有更简单的办法呢?
直接设置缓存所有静态请求,这样第二次访问的时候就自动从自身的缓存中获取,缓存中没有的内容就找服务端获取,然后再缓存下来:
location ~ .*\.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*) {
proxy_pass http://代理地址:端口;
proxy_set_header Host $
proxy_cache cache_
proxy_cache_valid 200 302 1h;
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
expires 30d;
另外还要在http{}中加入以下内容:
proxy_temp_path /app/nextcloud/temp_
#临时文件夹
proxy_cache_path /app/nextcloud/cache levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
好了,现在Nginx的反向代理真的有了它的积极作用。
还有一点——post最大体积
使用Docker和Nginx搭建Nextcloud完成后,我在上传一个约70MB的文件时出现错误,Nextcloud本身没什么动静。看了下console,发现服务器返回错误码413:请求实体太大。
POST的最大体积需要在http{}中的
client_max_body_size
设置,例如:
client_max_body_size 100m;
完成后就可以上传小于100MB的文件了。
或许我应该把这部分放到Docker里说。
从hub.docker.com获得的官方Nextcloud镜像是不包含数据库服务的,而镜像也阉割了很多常用命令。这样我们就不得不用容器互联来用上数据库了。
如前所述,如果我添加了两个容器,一个运行Nextcloud,另一个运行MySQL,这两个容器默认是在同一网桥上,而我就可以把它们连接起来。
首先运行MySQL容器,我给它起名为db1,然后在MYSQL_ROOT_PASSWORD后面指定root密码为my-secret-pw
docker run --name db1 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
然后运行Nextcloud容器,用
--link my-mysql:mysql
把它和MySQL容器连接起来
docker run -d -p 8080:80
--link db1:mysql nextcloud
官方提供了一个docker-compose文件,可以看出他这儿使用MariaDB作为数据库,命名为db,并在nextcloud服务中连接
version: '2'
nextcloud:
image: mariadb
restart: always
- db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_PASSWORD=
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
image: nextcloud
- nextcloud:/var/www/html
restart: always
启动容器后访问Nextcloud容器,填入MySQL/MariaDB的服务器地址时直接填“db”就可以了,因为“db”就是MySQL容器的主机名,hosts文件中已经指明了“db”对应的容器。
把数据卷映射至本地,这样我们如果要更改Nextcloud的文件,直接在宿主机上就可以操作了,即前文中所说的方法。
我们一共要映射这三个目录:
nextcloud:/var/www/html
#Nextcloud的程序
data:/var/www/html/data
#Nextcloud的数据目录
config:/var/www/html/config
#Nextcloud的配置文件所在目录
apps:/var/www/html/apps
#Nextcloud应用的目录
具体命令就是这样:
docker run -d nextcloud \
-v nextcloud:/var/www/html \
-v apps:/var/www/html/custom_apps \
-v config:/var/www/html/config \
-v data:/var/www/html/data
注意:冒号前面的nextcloud、apps、config、data要全部替换为本地的绝对路径
使用docker exec命令以在宿主机上为容器执行OCC命令:
docker exec --user www-data CONTAINER_ID php occ
CONTAINER_ID就是运行的Nextcloud容器的ID,如果你给容器命了名,那么也可以是这个容器的名字。
本文到此结束,我也要暂时的疏远Nextcloud/ownCloud了,更广阔的世界还等着我去探索。
图片编辑工具:
参考资料:Docker 技术入门与实战·第二版(机械工程出版社)
本文由 橙叶博客 作者: 发表,转载请注明来源!
我是技术向!!
最赞的文章
用户名/邮箱/手机
用户名/邮箱/手机17分钟快速浏览一遍
Docker内部构建
要理解Docker内部构建,需要理解以下三种部件:
Docker镜像(Image)
Docker容器(Container)
Docker仓库(repository)
基本上理解了这三个概念,就理解了Docker的整个生命周期。
1)Docker镜像(Image)
Docker镜像就是一个只读的模板。比如,一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了apache或用户需要的其他应用程序。镜像可以用来创建Docker容器。另外Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人哪里下载一个已经做好的镜像来直接使用。
2)Docker容器(Container)
Docker利用容器来运行应用。容器是从镜像创建的运行实例,它可以被启动、开始、停止、 删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
注:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
3)Docker仓库(repository)
仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈, 并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是Docker Hub, 存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库。当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上pull下来就可以了。
注:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。
Docker总架构分解
Docker对使用者来讲是一个C/S模式的架构,而Docker的后端是一个非常松耦合的架构,模块各司其职,并有机组合,支撑Docker的运行。
在此,先附上Docker总架构:
从上图不难看出,用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者。
而Docker Daemon作为Docker架构中的主体部分,首先提供Server的功能使其可以接受Docker Client的请求;而后Engine执行Docker内部的一系列工作,每一项工作都是以一个Job的形式的存在。
Job的运行过程中,当需要容器镜像时,则从Docker Registry中下载镜像,并通过镜像管理驱动graphdriver将下载镜像以Graph的形式存储;当需要为Docker创建网络环境时,通过网络管理驱动networkdriver创建并配置Docker容器网络环境;当需要限制Docker容器运行资源或执行用户指令等操作时,则通过execdriver来完成。
而libcontainer是一项独立的容器管理包,networkdriver以及execdriver都是通过libcontainer来实现具体对容器进行的操作。当执行完运行容器的命令后,一个实际的Docker容器就处于运行状态,该容器拥有独立的文件系统,独立并且安全的运行环境等。
一、Docker架构内各模块的功能与实现分析
接下来,我们将从Docker总架构图入手,抽离出架构内各个模块,并对各个模块进行更为细化的架构分析与功能阐述。主要的模块有:Docker Client、Docker Daemon、Docker Registry、Graph、Driver、libcontainer以及Docker container。
1.1)Docker Client
Docker Client是Docker架构中用户用来和Docker Daemon建立通信的客户端。用户使用的可执行文件为docker,通过docker命令行工具可以发起众多管理container的请求。
Docker Client可以通过以下三种方式和Docker Daemon建立通信:tcp://host:port,unix://path_to_socket和fd://socketfd。为了简单起见,本文一律使用第一种方式作为讲述两者通信的原型。与此同时,与Docker Daemon建立连接并传输请求的时候,Docker Client可以通过设置命令行flag参数的形式设置安全传输层协议(TLS)的有关参数,保证传输的安全性。
Docker Client发送容器管理请求后,由Docker Daemon接受并处理请求,当Docker Client接收到返回的请求相应并简单处理后,Docker Client一次完整的生命周期就结束了。当需要继续发送容器管理请求时,用户必须再次通过docker可执行文件创建Docker Client。
1.2)Docker Daemon
Docker Daemon是Docker架构中一个常驻在后台的系统进程,功能是:接受并处理Docker Client发送的请求。该守护进程在后台启动了一个Server,Server负责接受Docker Client发送的请求;接受请求后,Server通过路由与分发调度,找到相应的Handler来执行请求。
Docker Daemon启动所使用的可执行文件也为docker,与Docker Client启动所使用的可执行文件docker相同。在docker命令执行时,通过传入的参数来判别Docker Daemon与Docker Client。
Docker Daemon的架构,大致可以分为以下三部分:Docker Server、Engine和Job。Daemon架构如下图。
Docker:架构分解
1.3)Docker Server
Docker Server在Docker架构中是专门服务于Docker Client的server。该server的功能是:接受并调度分发Docker Client发送的请求。Docker Server的架构如下图。
在Docker的启动过程中,通过包gorilla/mux,创建了一个mux.Router,提供请求的路由功能。在Golang中,gorilla/mux是一个强大的URL路由器以及调度分发器。该mux.Router中添加了众多的路由项,每一个路由项由HTTP请求方法(PUT、POST、GET或DELETE)、URL、Handler三部分组成。
若Docker Client通过HTTP的形式访问Docker Daemon,创建完mux.Router之后,Docker将Server的监听地址以及mux.Router作为参数,创建一个httpSrv=http.Server{},最终执行httpSrv.Serve()为请求服务。
在Server的服务过程中,Server在listener上接受Docker Client的访问请求,并创建一个全新的goroutine来服务该请求。在goroutine中,首先读取请求内容,然后做解析工作,接着找到相应的路由项,随后调用相应的Handler来处理该请求,最后Handler处理完请求之后回复该请求。
需要注意的是:Docker Server的运行在Docker的启动过程中,是靠一个名为”serveapi”的job的运行来完成的。原则上,Docker Server的运行是众多job中的一个,但是为了强调Docker Server的重要性以及为后续job服务的重要特性,将该”serveapi”的job单独抽离出来分析,理解为Docker Server。
1.4)Engine
Engine是Docker架构中的运行引擎,同时也Docker运行的核心模块。它扮演Docker container存储仓库的角色,并且通过执行job的方式来操纵管理这些容器。
在Engine数据结构的设计与实现过程中,有一个handler对象。该handler对象存储的都是关于众多特定job的handler处理访问。举例说明,Engine的handler对象中有一项为:{“create”: daemon.ContainerCreate,},则说明当名为”create”的job在运行时,执行的是daemon.ContainerCreate的handler。
一个Job可以认为是Docker架构中Engine内部最基本的工作执行单元。Docker可以做的每一项工作,都可以抽象为一个job。例如:在容器内部运行一个进程,这是一个job;创建一个新的容器,这是一个job,从Internet上下载一个文档,这是一个job;包括之前在Docker Server部分说过的,创建Server服务于HTTP的API,这也是一个job,等等。
Job的设计者,把Job设计得与Unix进程相仿。比如说:Job有一个名称,有参数,有环境变量,有标准的输入输出,有错误处理,有返回状态等。
1.6)Docker Registry
Docker Registry是一个存储容器镜像的仓库。而容器镜像是在容器被创建时,被加载用来初始化容器的文件架构与目录。
在Docker的运行过程中,Docker Daemon会与Docker Registry通信,并实现搜索镜像、下载镜像、上传镜像三个功能,这三个功能对应的job名称分别为”search”,”pull” 与 “push”。
其中,在Docker架构中,Docker可以使用公有的Docker Registry,即大家熟知的Docker Hub,如此一来,Docker获取容器镜像文件时,必须通过互联网访问Docker Hub;同时Docker也允许用户构建本地私有的Docker Registry,这样可以保证容器镜像的获取在内网完成。
1.7)Graph
Graph在Docker架构中扮演已下载容器镜像的保管者,以及已下载容器镜像之间关系的记录者。一方面,Graph存储着本地具有版本信息的文件系统镜像,另一方面也通过GraphDB记录着所有文件系统镜像彼此之间的关系。Graph的架构如下图。
其中,GraphDB是一个构建在SQLite之上的小型图数据库,实现了节点的命名以及节点之间关联关系的记录。它仅仅实现了大多数图数据库所拥有的一个小的子集,但是提供了简单的接口表示节点之间的关系。
同时在Graph的本地目录中,关于每一个的容器镜像,具体存储的信息有:该容器镜像的元数据,容器镜像的大小信息,以及该容器镜像所代表的具体rootfs。
1.8)Driver
Driver是Docker架构中的驱动模块。通过Driver驱动,Docker可以实现对Docker容器执行环境的定制。由于Docker运行的生命周期中,并非用户所有的操作都是针对Docker容器的管理,另外还有关于Docker运行信息的获取,Graph的存储与记录等。因此,为了将Docker容器的管理从Docker Daemon内部业务逻辑中区分开来,设计了Driver层驱动来接管所有这部分请求。
在Docker Driver的实现中,可以分为以下三类驱动:graphdriver、networkdriver和execdriver。
graphdriver主要用于完成容器镜像的管理,包括存储与获取。即当用户需要下载指定的容器镜像时,graphdriver将容器镜像存储在本地的指定目录;同时当用户需要使用指定的容器镜像来创建容器的rootfs时,graphdriver从本地镜像存储目录中获取指定的容器镜像。
在graphdriver的初始化过程之前,有4种文件系统或类文件系统在其内部注册,它们分别是aufs、btrfs、vfs和devmapper。而Docker在初始化之时,通过获取系统环境变量”DOCKER_DRIVER”来提取所使用driver的指定类型。而之后所有的graph操作,都使用该driver来执行。
graphdriver的架构如图
networkdriver的用途是完成Docker容器网络环境的配置,其中包括Docker启动时为Docker环境创建网桥;Docker容器创建时为其创建专属虚拟网卡设备;以及为Docker容器分配IP、端口并与宿主机做端口映射,设置容器防火墙策略等。networkdriver的架构如下图。
execdriver作为Docker容器的执行驱动,负责创建容器运行命名空间,负责容器资源使用的统计与限制,负责容器内部进程的真正运行等。在execdriver的实现过程中,原先可以使用LXC驱动调用LXC的接口,来操纵容器的配置以及生命周期,而现在execdriver默认使用native驱动,不依赖于LXC。具体体现在Daemon启动过程中加载的ExecDriverflag参数,该参数在配置文件已经被设为”native”。这可以认为是Docker在1.2版本上一个很大的改变,或者说Docker实现跨平台的一个先兆。execdriver架构如下图:
1.9)libcontainer
libcontainer是Docker架构中一个使用Go语言设计实现的库,设计初衷是希望该库可以不依靠任何依赖,直接访问内核中与容器相关的API。
正是由于libcontainer的存在,Docker可以直接调用libcontainer,而最终操纵容器的namespace、cgroups、apparmor、网络设备以及防火墙规则等。这一系列操作的完成都不需要依赖LXC或者其他包。libcontainer架构如下图:
另外,libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。或者说,libcontainer屏蔽了Docker上层对容器的直接管理。又由于libcontainer使用Go这种跨平台的语言开发实现,且本身又可以被上层多种不同的编程语言访问,因此很难说,未来的Docker就一定会紧紧地和Linux捆绑在一起。而于此同时,Microsoft在其著名云计算平台Azure中,也添加了对Docker的支持,可见Docker的开放程度与业界的火热度。
暂不谈Docker,由于libcontainer的功能以及其本身与系统的松耦合特性,很有可能会在其他以容器为原型的平台出现,同时也很有可能催生出云计算领域全新的项目。
1.10)Docker container
Docker container(Docker容器)是Docker架构中服务交付的最终体现形式。
Docker按照用户的需求与指令,订制相应的Docker容器:
用户通过指定容器镜像,使得Docker容器可以自定义rootfs等文件系统; 用户通过指定计算资源的配额,使得Docker容器使用指定的计算资源; 用户通过配置网络及其安全策略,使得Docker容器拥有独立且安全的网络环境; 用户通过指定运行的命令,使得Docker容器执行指定的工作。
对于整个Docker的介绍先到这里,真正去理解Docker架构还需要多去实践Docker才行。
阅读(...) 评论() &}

我要回帖

更多关于 docker 分布式架构图 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信