《Docker——容器与容器云》:第五章 构建自己的容器云

我们在第1章介绍了一个云计算平台应有的层次结构,其中平台即服务层(PaaS)是本书重点着墨描述的。尽管在一些经典PaaS平台中,容器技术已经扮演了一个至关重要的角色,但很遗憾,大部分经典PaaS平台中容器功能被局限在了“资源隔离”这狭小的技术范围当中了。当拥有了像Docker这样的容器技术后,是时候开始从一个新的角度来思考容器在云计算平台当中扮演的角色和地位了。

5.1 再谈云平台的层次架构

回顾一下第1章描述的云计算平台层次,IaaS平台接管了所有的资源虚拟化工作,通过软件定义的方式来为云租户提供虚拟的计算、网络和存储资源。PaaS平台接管了所有的运行时环境和应用支撑工作,云平台的租户因此可以申请配额内的计算单元而不是虚拟机资源来运行自己的服务。当前不少经典PaaS平台已经采用容器作为计算单元,那些仍然依靠虚拟机提供应用运行时支持的“PaaS平台”在本书中将被称为“IaaS+平台”。云平台调度这些计算单元用以部署和运行租户的代码制品。在这两层的基础上,用户部署的应用和服务通过API响应的方式组成一系列集合服务于最终用户,这就是所谓SaaS1。上述过程其实描述了一个清晰可见的层次结构,如图5-1所示。

图像说明文字

图5-1 一个传统云计算平台的分层结构

在经典云平台层次体系里,应用实例运行在PaaS平台所提供的容器环境中,容器在虚拟机基础上完成了第二层次基础设施资源的划分;容器封装了应用正常运行所需的运行时环境和系统依赖;同时,容器也成为了租户调度应用、构建应用多实例集群的最直接手段。与IaaS层不同,通常在PaaS层可以采用更贴近应用的资源调度策略。可是,目前遵循这个体系结构构建的经典PaaS平台中存在一个有趣的现象:租户从始至终都无法感受到容器的存在!

相比于基于虚拟机提供运行时支持的IaaS+平台(比如AWS),经典PaaS平台的租户甚至都不能进入自己的计算单元(容器)中,这类PaaS平台就如同一个黑盒,所有"扔"进去的应用就完全脱离了租户的控制,进入了完全被托管的状态。诚然,如果一切都有条不紊的运作,该模式可谓完美,因为“所有用户都是最懒的”这个假设总是成立,而残酷的现实却是:“错误总是会发生在任何意想不到角落里”。

举个简单的例子,一旦应用运行过程中有错误发生,云平台的PaaS层首先会删除故障实例,然后立即在其他位置恢复这个实例和容器。这个过程中,甚至平台默认没有保存现场的过程。浙江大学SEL实验室云计算团队曾在Cloud Foundry中增加了从Websocket日志组件收集容器中的应用日志到ElasticSearch的机制,通过该机制在一定程度上能给用户提供方便的日志信息诊断处理,但对于日志中无法体现的异常还是无能为力,更谈不上调试代码和保存环境上下文了。这样的先天缺陷,也是后来云计算领域会出现大量“云DevOps工具”,提供一个类似“白盒PaaS”解决方案的重要原因之一。

经典PaaS平台中,出于安全、封装等各个方面的考虑,容器总是被故意隐藏在整个云平台的运行过程当中(如图5-1所示),因此开发和运维人员失去了往日对应用及其运行时环境的完全掌控能力,试图重新获得控制权所做的努力往往要求助于过分晦涩的交互方式和hack般的自定义过程。再加上经典PaaS平台通常在应用架构选择、支持的软件环境服务等方面有较强限制。因此在生产环境下,部分企业和个人开发者会倾向于放弃PaaS层,直接依靠运维力量来分配和调度虚拟机,靠大量自动化工具来维护和支撑所有运行时、应用环境配置、服务依赖、操作系统管理等。这时,传统云平台分层结构就会进化成如图5-2所示的状态,即”IaaS+“云平台。

图5-2 一个典型的“IaaS+”云平台

本书认为,这种“返璞归真”的做法是一种值得一试的云计算运维方法,尤其是在大部分IaaS都能够提供标准而丰富的API的今天。高效便捷的虚拟机DevOps工具在很大程度上弥补了IaaS平台脱离应用的缺陷;以虚拟机镜像为基础可以保证生产环境、测试环境、开发环境上的严格一致;IaaS提供商还在不断推出关系数据库、NoSQL、日志、Search、对象存储等构建在虚拟机上的可对外提供服务的镜像。事实上,基于IaaS的云生态环境已经具有相当高的成熟度。

当然,如果没有Docker的话。

经典PaaS平台和IaaS加DevOps工具组成的“IaaS+平台”还在分庭抗礼,随着容器技术逐渐步入视野,云平台建设已经有了新的思路。

相比“IaaS+平台”,Docker容器启停速度比虚拟机提高了一个量级,而在资源利用率上容器独有的高密度部署能力也非普通IaaS提供商所能提供的。更有吸引力的是,大小仅几十MB的Docker镜像就完整封装了Web容器、运行配置、启动命令、服务hook和所需环境变量,提供了一种全新的应用分发方式,给应用开发者带来了弥足珍贵的“全环境一致性”保证。相比之下,动辄GB级的虚拟机镜像在应用部署和分发上就很难再有竞争力了。

相比经典PaaS平台,Docker的出现使得构造一个对开发和运维人员更加开放的容器PaaS云成为可能,基于容器镜像的应用发布流程不仅能覆盖整个应用生命周期,还减少了经典PaaS平台对应用架构、支持的软件环境服务等方面的诸多限制,将更多控制力交还给开发和运维人员。这种“降维攻击”把曾经引起不少争论的话题再次摆在了开发者面前:PaaS应该以何种形态存在?

本书无意给上述问题寻找一个完美答案,更希望能与读者一起研究和探索基于容器的云平台究竟以什么形态出现才更合理。因此,本书为读者介绍多种类型的容器云平台。它们中一类更偏向经典PaaS平台,提供各类“一键xx”服务,它们给予用户最大的方便和更高度的自动化,也因此附加了对应用架构和开发运维自由度限制;另一类则给用户最大的开发运维自由度,但自动化程度较低,使用相对复杂。也许到阅读完第二部分内容后,读者就能找到怎样的容器云平台才是最适合自己的。

值得一提的是,不论是采用哪种形态的云平台,随着Docker等面向开发者的容器大行其道,本书下面将要着重讨论的云平台都已经变成了图5-3所示的结构。

一个基于容器的云平台

图5-3 一个基于容器的云平台

在Docker等容器技术很有成为未来应用发布事实标准的当下,必须指出本书进行讨论的一个基本立足点:由于当前容器在内核完整性、安全性和隔离性上的固有缺陷,使得目前在大部分场景下我们必然需要虚拟机、虚拟网络、虚拟存储的支持;同时,在本书中将不会再过分强调所谓IaaS、PaaS、SaaS三层云计算划分方式,更多的是将这些概念视为经典技术作为容器云的对照。

本书接下来讨论的所有以容器为核心的云平台都不会锁定在某种具体IaaS或者PaaS上面,将始终坚持容器云平台应无差别地工作在物理机上或者虚拟机上这样朴素的思想,并以此为基础剖析各类容器云的原理与本质。这或许不太容易,比如Kubernetes天生就是为GCE定制的,而几乎所有的容器平台也都以AWS和DigitalOcean作为默认的下层资源依赖。浙江大学SEL实验室云计算团队所做的努力将尽可能屏蔽掉这类外部因素,以中立的技术态度贯穿本书的始终。

5.2 从小工到专家

当一个开发者拿到Docker文档之后,一定会按捺不住内心的激动,把所有的Getting Started跑一遍,当然中间可能会碰到问题,仔细阅读过本书第一部分的读者应该能更加游刃有余地做完这些事情。甚至尝试过第4章的高级玩法后,当第一个DEMO开始工作时,终于可以当仁不让地宣布自己已经是个高级玩家。

那么问题来了:接下来该做什么?

以一个开发者的视角继续往下,往后事情的发展无外乎两种可能:第一,开发者默默地记住这些技能,然后把Docker当作自己的独门武器,以至于最后老板都开始怀疑这家伙的开发效率怎么会突然变得这么高。第二,热心的开发者开始向全组推广Docker,甚至鼓动运维也加入Docker行列。一般情况下,我们会称赞第二种开发者为“愿意当将军的士兵”。

于是,我们的“将军开发者”决定从最简单的需求开始演示自己的计划,只用了几分钟,他就搭建好了一个容器集群,这是一个来自The Docker Book的例子,与第2章中我们手把手搭建过的“第一个Docker集群”有点类似。

一个Node.js应用和ELK组合的实例

图5-4 一个Node.js应用和ELK组合的实例

在这个组合实例中,他成功地将一个Node.js应用运行起来,并且使用Redis集群来存储这个应用的session信息,最后还使用ELK组合(ElasticSearch+Logstash+Kibana)完成了应用和Redis的日志转发、存储和检索功能。当然最酷的一定是这些内容全是跑在Docker容器里的,他只用了几条命令外加几分钟的时间就全部搞定了。团队里的其他人只要把Dockerfile拿走,几分钟就可以搭建一套一模一样的环境出来!

“真不错!”大家纷纷称赞这种基于容器来构建服务栈的方式是多么地优雅。

“可是要上线的话,负载均衡总要有的吧?”一位不大讨人喜欢的开发经理提出了第一个需求

的确,在经典互联网应用场景里,无论后端系统多么地复杂强大,最前面放置一般都该是负载均衡设备而非Web服务器,并且Load Balancer这一环节还有很多必须额外设定的配置(比如session sticky、静态动态内容分离、URL重定向等)。在此基础上,应用还往往被复制成多份,在负载均衡管理下统一提供对外服务,这项技术对于分流、灰度发布、高可用以及弹性伸缩都是必需的。好在有了Docker的帮助,这一切都不算难,“将军开发者”挠挠头的功夫就build了一个HAProxy镜像启动起来,然后又启动了一个完全相同的Node.js应用的容器(得益于镜像,这类操作非常便捷),最后将两个应用容器的IP和端口配置到了HAProxy的backend servers里面,完成了负载均衡实现的所有工作。

一个添加了负载均衡的Node.js应用和ELK组合的实例

图5-5 一个添加了负载均衡的Node.js应用和ELK组合的实例

“好像可以工作了呢。”

“等等,负载均衡里怎么能把后端的实例配置成固定参数呢?”

不招人喜欢的开发经理又提出了第二个需求,而且还有点棘手。

首先要面对的问题是,怎么才能保证后端应用容器失败重启或者升级扩展之后,HAProxy能及时更新自己的配置文件呢?要知道Docker容器可没有静态IP这个说法(至少在学习过本书高级网络实践之前是这样的)。不过如果求助于GitHub情况就不一样了,“将军开发者”很快找到一个专门负责配置文件远程修改的组件confd。

第二个要面对的问题是,哪个组件负责探测应用容器退出或者创建的事件发生然后通知confd修改HAProxy配置文件呢?这可让“将军开发者”着实花了一番心思。

“这好像是一个服务发现的场景呢。”

没错!所有应用容器都应该把本身IP和端口信息注册到etcd当中去(etcd是服务发现存储仓库,将在第6章详细介绍),然后依靠confd定时查询etcd中数据变化来更新HAProxy的配置文件。不需要写很多代码,只需要配置一下confd,然后build一个新的HAProxy和一个etcd容器就足够了。话音未落,“将军开发者”的新系统又上线了。

一个添加了负载均衡和自发现特性的Node.js应用和ELK组合的实例

图5-6 一个添加了负载均衡和自发现特性的Node.js应用和ELK组合的实例

这样应该可以了吧。确切地说,这个服务栈不仅拥有了负载均衡和多实例的功能,还能够以一种“发现”的方式向负载均衡节点注册或者解注册应用实例,而且整个过程都是平滑升级的,不会出现服务中断。

“应用健康检查怎么办?”一直在旁默不作声的运维终于坐不住了。

“自发现”机制确实保证了容器自身高可用能力,但是容器中运行着的应用进程实际上并不是完全保险的。最典型的场景是Java Web Server:当应用异常的时候,Web Server是完全有可能不退出的,用户只能拿到4XX或者5XX的返回值。所以,在一个真实的应用平台需求下,“垂直监控”是非常有必要的,至少需要能检测到应用访问的返回值是2XX。

这还不算完。“将军开发者”虽然构建了一个多实例的应用集群,但生产环境下,这些实例应该将会分布在不同服务器上。这又会带来新的问题,如下所示。

  • 如何保证同一个应用的不同容器实例分布在不同或者指定的宿主节点上?
  • 当一个宿主节点意外退出的时候,如何保证该节点上的容器实例能够在其他宿主节点上恢复?
  • 如何比较当前容器实例的运行情况同期望的运行状态的差异,用以决定是否要进行上述高可用动作?
  • 如何构建一个覆盖“测试-开发-上线”完整流程的运行机制来充分发挥Docker镜像的一致性?
  • Docker容器本身的网络应如何配置,尤其是在跨主机环境下怎么处理,是否需要静态IP?
  • 当开发者创建的镜像非常多时,复杂的镜像关系会大大拖延容器创建和启动速度,这时该如何处理复杂关系对容器性能的影响?
  • 大量删除操作可能带来不可预知的“孤儿”容器,不光占用大量资源,还可能带来各种莫名异常,造成大量“孤儿”容器的局面该如何应对?
  • 挂载Volume的数据该如何进行备份,是否需要实现高可用或跨主机迁移?磁盘写满该如何处理?
  • 所有CPU、MEM、DISK资源限制如何才算合理?不合理的资源限制加上欠考虑的调度策略会不会产生新的资源浪费?

  • ……

“将军开发者”突然发现,原来说服别人接受自己计划所面临的困难要远比搭建DEMO大得多,尤其是需要涉及现有的生产环境时。事实上,Docker是运维友好的,相比传统运维方式,通过流程和规范来保证环境一致性的做法,Docker镜像已经给运维工作带来了很大便利,更不用说它几乎可以忽略的启动时间和简单高效的配置方式了。同样,Docker更是开发者友好的,光是它伸手即来的安装和启动方式以及灵活通用的Dockerfile就足以让传统PaaS提供商汗颜。此外,它不存在任何供应商锁定和引入特殊依赖的问题了。可是,就是这样一种对各利益方都友好的技术,在真正用于生产环境时却需要解决一个棘手的问题:如何使用Docker特性来提供、升级和简化现有生产环境已经具备的运维能力?

引发这个问题的原因其实很简单,Docker给工业界带来的不只是一项技术——容器技术已经足够普及了——它带来的更多是一种思维转变。遗憾的是,Docker的思考方式与目前任何一项业务运行的方式都不是原生兼容的。

这解释了为什么我们在自建的环境中使用Docker能如鱼得水,一旦想要将它推广至生产环境中,就会感到十分棘手。而且我们发现,这些困难往往不是来自容器技术本身,而是与容器相关的网络、存储、集群、高可用等已经在传统场景中得到解决的“泥潭”。为了解决这些问题,我们的“将军开发者”就不得不经历一次又一次“从小工到专家”的历练,他开始研究HAProxy和etcd,开始写Docker scheduler、health checker、stager、builder、deployer,终成一代“Docker大神”。

最后,我们的开发经理终于提出了一个终极需求:能不能让开发愉快地开发,运维轻松地运维,大家一起快乐地做Docker小伙伴呢?

答案当然是:“可以的。”

现在就让我们来聊聊“容器云”吧。

“容器云”最直观的形态都是一个颇具规模的容器集群。但它与开发者或者运维人员自己维护的“裸”容器集群不同。容器云中会被按功能或者依赖敏感性划分成组,不同容器组之间完全隔离,组内容器允许一定程度共享。容器之间的关系不再简单依靠docker link这类原生命令来进行组织,而往往是借助全局网络管理组件来进行统一治理。容器云用户也不需要直接面对Docker API,而是借助某种控制器来完成用户操作到Docker容器之间的调用转译,从而保证底层容器操作对最终用户的友好性。大多数容器云还会提供完善的容器状态健康检查和高可用支持,并尽可能做到旁路控制而非直接侵入Docker体系,从而免除“将军开发者”们不得不重复造轮子的尴尬。“容器云”会提供一个高效、完善、可配置的调度器,调度器可以说是容器云系统需要解决的第一要务,这也正是“将军开发者”最头痛的事情——他面对的容器越多,运维和管理困难程度往往会呈指数级上升。在接下来的章节中,让我们一起来逐层揭开“容器云”的面纱。

它们或来自于小而美的创业团队,或来自于数一数二的业界巨头;有的专注于服务发布,有的专注于数据存储;有的只解决编排与运维,有的却几乎可以媲美一个传统IaaS。但是,无论是那些灵活轻巧的编排工具还是庞大复杂的容器服务,它们都试图为热爱Docker并尝试真正应用Docker的“将军开发者”们解决一个核心问题:如何迈过从“容器运行”到“生产使用”之间的这条鸿沟。


1这个描述见http://www.programmableweb.com/news/new-enterprise-big-data-mobile-and-saas-api-economy/analysis/2013/09/25。


from: http://www.ituring.com.cn/tupubarticle/4444

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值