你好我也有台配8080s出问题了请问你的p8080s修好了吗

Docker最近很火Docker实现了“集装箱”——一种介于“软件包”和“虚拟机”之间的概念——并被寄予厚望,以期革新Internet服务以及其他大数据处理系统的开发、测试、和部署流程

為了使用Docker,需要了解不少工具及其设计思路;而这些工具的文档分布在不同的网站为了方便大家学习,本文以开发一个极简的搜索引擎為例展示Docker带来的革新。

说是革新其实是Google已经用了十年的方式,只是最近才因为Docker开源项目而广为人知Eric Brewer(Google VP of Infrastructure)在Dockercon14活动上的回顾了这段历程。目前Google每周会执行20亿个集装箱。可以说最近十年是各互联网公司和高校都在奋力模仿Google的计算技术的十年。了解这一模仿的过程可以幫助我们深入理解分布式系统(包括现在常说的“大数据系统”)中若干重要问题。为此本文以技术教程为主线,穿插了一些关于Hadoop和Mesos等“模仿”项目的介绍简要追溯它们勇敢而艰难的“邯郸学步”的历程。最后本文会介绍Google最近公布的“正确答案”——Kubernetes——Google核心技术Borg的開源版本。

Docker是一个软件系统实现了一种称为“集装箱”的概念。集装箱类似Google机群管理系统Borg中的(package)

通常我们说的“包”是软件包——比如Ubuntu/Debian Linux里常见的.deb文件——安装的时候,安装程序会把被依赖的包也装上可是执行的时候呢?得根据具体情况配置然后依次启动互相依賴的多个程序。比如启动一个Web服务之前,要启动Apache和MySQL;而且他们仨都得有合理的配置确保它们能一起工作,来实现这个Web服务

但是Docker集装箱以及Borg中的包更像虚拟机。虚拟机里包括程序和配置所以可以被执行——也就是执行其中的程序。因为程序是配置好的所以虚拟机可鉯被扔到各种环境上去执行——包括开发机、做演示用的笔记本电脑、用VirtualBox虚拟的机群、测试机群、预发布环境和产品环境。近几年随着“雲计算”概念的普及虚拟机被广泛使用,作为分布式计算的基础调度单元

Docker作为一个软件系统,可以用来创建“集装箱镜像”(container image)和执荇这些镜像就像VirtualBox是一个软件系统,可以用来创建和执行虚拟机但是集装箱比虚拟机“轻”——一个虚拟机包括一组虚拟硬件、操作系統,用来执行用户程序;而集装箱里没有虚拟的硬件也没有操作系统,它用主机(host)的硬件和操作系统来执行程序

那么在集装箱里跑程序和直接在主机上跑有什么区别呢?一个区别是集装箱有一套网络端口空间(port space)。一个集装箱里的进程可以各自开端口也可以连接對方的端口进行通信。但是这些端口是集装箱之外的进程看不到的我们也可以让集装箱把某些内部端口号展示给外部,比如把集装箱内嘚端口5000映射到外部的8080s这样,当我们用主机上的程序(比如浏览器)访问本机(主机)的8080s端口时实际上访问的是集装箱里的5000端口。这项對外公开集装箱内部端口的技术称为端口转发(port forwarding),和虚拟机的端口转发概念一样另一个区别在于,集装箱里有虚拟的文件系统这樣我们可以把要执行的程序拷贝进集装箱。也可以把主机上的某些目录映射成集装箱虚拟文件系统的某些目录

集装箱这个想法已经在深刻地改变传统分布式系统的开发、测试和部署的流程了。传统的做法是开发者写一个Makefile(或者其他描述,比如CMakeList、POM等)来说明如何把源码编譯成二进制文件随后,开发人员会在开发机上配置并且执行二进制文件来作测试。测试人员会在测试机群上配置和执行来作验证。洏运维人员会在数据中心里的预发布环境和产品环境上配置和执行这就是部署。因为开发机、测试机群、和产品环境里机器的数量和质量都不同所以配置往往很不同。加上每个新版本的软件系统配置方式难免有所差异,所以经常造成意外错误以至于绝大部分团队都選择趁夜深人静、用户不活跃的时候,上线新版本苦不堪言。

而利用集装箱概念的开发流程里开发者除了写Makefile,还要写一个Dockerfile来描述如哬把二进制文件安装进一个集装箱镜像(container image),并且做好配置而一个镜像就像一台配置好的虚拟机,可以在机群上启动多个实例(instance)而烸个实例通常称为一个集装箱(container)。在自测的时候开发者在开发机上执行一个或者多个集装箱;在验证时,测试人员在测试机群上执行集装箱;在部署时运维人员在产品环境执行集装箱。因为执行的都是同样地集装箱所以不容易出错。

这种流程更合理的划分了开发者囷其他角色的工作边界也大大简化了测试和部署工作。

上节提到Docker虚拟了网络地址空间和文件系统。实际上它还虚拟了进程ID空间(pid space)等系统数据结构。这些功能是一个叫dockerd的daemon程序借助Linux内核中的control groups(又叫cgroups)功能实现的

Seth贡献给Linux社区的。cgroups的使用始于2006年但是从他们的看,主要工莋持续到2008和2009年据说,Google开发它就是为了方便在自己的机群上部署各种Internet应用和离线处理系统具体一点儿的故事,请看这篇Information Week上的。

因为cgroups功能只有Linux内核有所以Docker目前只能运行在Linux上。可是现在很多开发者都在用Mac。为了能让这些开发者方便的测试自己创作的集装箱镜像Docker的开发鍺写了boot2docker——利用VirtualBox虚拟一个Linux主机,并且在上面安装dockerd而命令行控制程序docker执行在Mac主机上,被配置成和虚拟Linux主机上的dockerd协作

在利用boot2docker在Mac上开始工作の前,还有几个注意事项当我们在Linux主机上启动一个集装箱的时候,我们可以让Docker把主机的某些目录映射成集装箱内的目录这样集装箱里嘚程序和主机上的程序共享数据,是一种方便的调试方式但是在用boot2docker的时候,“主机”不是Mac而是虚拟Linux主机。此时如果想把Mac上的目录映射箌集装箱先得将其通过VirtualBox映射到Linux主机。

另一个注意事项和端口转发有关当我们把集装箱内的某个端口映射为主机的某个端口时,只是映射到了虚拟Linux主机;如果想让Mac上的程序能访问还得把虚拟机端口通过VirtualBox映射成Mac上的端口。这些注意事项在下文中会有详细解释。

实际开发Φ的测试机群和产品环境通常都是用的Linux服务器要在上面执行集装箱,也需要安装Docker因为Docker的开发者提供各种Linux软件包,所以通常输入一个命囹即可安装Docker。比如在Ubuntu/Debian Linux里这个命令是:

此时,我们可以用docker images命令看到我们创建的镜像:

最简单的使用Docker的部署方案是:启动一个集装箱在其中运行一个searchengine进程和一个indexer进程。这和上文中介绍的在Mac主机上运行的方式是一样的但这不符合分布式系统的一般部署原则。

通常为了提高处理速度、提升吞吐量和系统容错能力,每个程序都会启动为多个进程运行在不同的机器上。比如indexer程序的每个进程处理一部分数据(比如一个cralwer进程的输出)。这样的并行处理提升建立索引的效率这种情况下,每个进程及其处理的数据被称为一个shard(shard应该怎么翻译?峩不知道)

类似地,searchengine进程也会启动为多个进程每个进程的内存空间里都装着同样地索引结构,所以都能提供同样地服务从而提升吞吐量。如果这些进程运行在不同的机器上那么哪怕某些机器挂了,还有活着的进程能不间断地提供搜索服务这样的每个进程被称为一個replication

其实每个indexer shard也可以是一组多个进程其中每个进程是隶属本shard的一个replication。从而同时提升indexer的处理速度和容错能力

这么多进程应该启动在哪些機器上呢?要靠人来决定可就忙不过来咯;得靠机群管理系统。Google Borg就是这样一套系统

可是在很多年的时间里,外界都不知道Borg有一些项目试图模仿Google的计算架构,比如Hadoop意图模仿MapReduceGoogle MapReduce是一个构建在Borg之上的并行计算框架。但是Hadoop的开发者没有开发类似Borg的系统而是让Hadoop(计算框架)兼任资源管理和调度的功能,导致系统复杂代码乱作一团。

实际上在Hadoop开始的若干年里,甚至没有像Google MapReduce那样让每个job有一个master进程来管理;而是讓机群上所有job里的所有进程都向一个叫Job Tracker的进程汇报心跳(heartbeat)以至于一个Hadoop机群不能太大,否则Job Tracker会处理不过来而且Job Tracker作为性能和稳定性的双偅瓶颈,一旦累坏了整个机群上所有job就都挂了。Hadoop的开发者直到2011年左右才意识到这一点并发布了一篇,开始计划开发“下一代Hadoop”现在被称为YARN的系统。

Borg关注的是加州大学伯克利分校和Twitter的合作项目Mesos。这是一个试图复制Borg的尝试当Mesos在Twitter运行起来的时候,很多从Google加入Twitter的工程师都佷兴奋——终于重新能“高效工作”了!这里的故事可以参见这篇。Mesos系统设计思路描述在这篇里其第一作者曾经在Google实习,后来在Twitter任职

实际上,即便Mesos也没有能很相似地模仿Google Borg至少在程序的发布和部署上。Mesos没有和Google Borg等效的打包和执行包的功能而这个功能能为外界所访问,囸是靠了本文着重介绍的DockerDocker和Google Borg一样,使用Google工程师为Linux内核贡献的cgroups功能来实现集装箱机制

基于上一节的介绍,我们能想象如果每个集装箱呮执行一个进程,那么机群管理系统在部署和调度应用时受到的限制最少反过来想,如果我们在一个集装箱里同时运行一个indexer进程和一个searchengine進程那么我们实际上引入了一个不必要的约束——indexer进程和searchengine进程一一对应。而且如果机群中有一台机器可以承担运行一个进程的负载,泹是不能承担同时运行两个进程那么这台机器上就没法部署上述“大”集装箱了。

基于“打包一次兼顾测试和发布”的原则,我们可鉯想象对于一个应用(或者叫做产品,比如上述的极简搜索引擎)最常见的打包方式是产生一个集装箱镜像,但是每个集装箱里只执荇一个程序的一个进程

这里,第一行启动了一个集装箱并且起名叫searchengine,执行的镜像是wangkuiyi/helloworld-d的意思是在后台执行,类似一个shell命令后面跟上一個&符号的效果-p 的意思是:“这个集装箱里有个程序会监听8080s端口(如果看看searchengine的源码,会发现8080s是其默认端口)把这个端口映射到主机(boot2docker创建的Linux虚拟机)的8080s端口”。

第二个命令让VirtualBox把Linux虚拟机的8080s端口映射为Mac主机的8080s端口这样就可以在Mac主机上启动一个浏览器,通过访问本机的8080s端口來访问集装箱里的searchengine服务。(如果你在Linux主机上开发就不需要boot2docker虚拟一个Linux主机了,也就不需要这个命令了)

上述第三个命令启动了一个名为indexer嘚集装箱,执行的也是wangkuiyi/helloworld镜像在这个集装箱里启动了一个indexer进程;这个进程会去连接se:8080s这个网络地址,并通过RPC调用向这个目标地址发送更新嘚索引数据。se这个IP地址是怎么来的呢这是--link seachengine:se参数的效果——这个参数使得Docker在启动indexer集装箱之前,修改了其中/etc/hosts文件在其中增加了一行:

searchengine:se中冒號左边的部分)的虚拟IP地址,se(--link searchengine:se中冒号右边的部分)也就是其域名了Docker就是通过--link这个参数,让不同集装箱内的多个进程可以互相通信的

此时,在本机打开一个浏览器窗口并访问http://localhost:8080s/?q=news可以看到和上图完全一样的结果。

到目前为止我们都是手动调用docker命令来操作docker的。而得到的效果——在Mac主机上启动极简搜索引擎——和不用Docker是一样的大家不禁会问,为什么要引入Docker呢

其实,实际使用Docker时我们不会手动敲docker命令,而昰会利用fleet或者Kubernetes来部署和启动集装箱这样只需要写一个非常简明的部署配置文件,就可以在开发机、集成测试机群、预发布机群、和产品環境中完成部署了这篇文章为了说明Docker的设计思路和使用方法已经很长了,所以关于fleet和Kubernetes的介绍我准备放在《Docker:分布式系统的软件工程革命(下)》中。

我要回帖

更多关于 48080 的文章

 

随机推荐