菜单
坐看云起时,谈笑无还期

云计算平台在2008年出现在公众面前的时候,我和大多数人一样,并没有意识到这是一场影响深远的技术变革。并不是缺乏洞见,而是因为云计算的概念非常混乱。

 

云起时


当时,作为倡导云计算的两大巨头——Amazon和Google,分别拿出了EC2GAE(Google App Engine)。今天我们自然可以很清楚地知道,这两个产品分别对应IaaS和PaaS两类云计算模型。但是在2008年,它们则是两大巨头分别指定的唯一“云计算”平台。它们都倡导让计算像水电一样成为基础资源并能够随时低成本地获取。显然,对于计算能力,两者的定义是不同的。

 

EC2对于能力的定义偏向于裸能力——也就是硬件能力,而GAE的定义则偏向于在“某个特定场景下的特定计算”。最终“特定场景下的计算”又分成了PaaS和SaaS。于是云计算的三种计算模型IaaS、PaaS和SaaS才成为广为人知的概念。

 

那么这三种计算模型是否在一开始就凸显了革命性呢?当然不是。IaaS无论从概念到使用场景,都极度类似IDC服务器托管;GAE作为web框架先天畸形,完全不同于当时主流的编程模型,让人不得不怀疑为了获得“云计算”的好处是否真的值得;而SaaS到云计算兴起的时候,大概已经存在快10年了。

 

作为一名务实的技术人员,我个人在当时认为所谓云计算又是一种无聊的商业包装,还是拼凑感特别强烈的包装。我是逐渐才意识到了云计算的革命性以及它对软件行业的深远影响,而云计算平台本身也在过去的十年中逐步发展,成为了我们这个行业事实上的标准。

 

下面我们来简单地回顾一下云计算在过去十年中的关键技术点以及它们带来的影响。

 

虚拟化与IaC


在EC2推出之前,使用镜像维护物理机器已流行了相当长的时间。然而这种方式并没有对研发带来什么特别的影响,毕竟镜像仍然需要通过复制才能转移到物理机器上。这一过程仍然相当费时费力。


虚拟化技术可以通过机器镜像直接启动虚拟机,这使得通过镜像管理虚拟机和直接管理虚拟机没什么本质区别了。

 

EC2更加强化了这一实践,而作为远程服务的EC2为其虚拟机管理和镜像管理提供了充分而有效的API。从而使得机器的分配、启用、停止、镜像加载都可以通过脚本自动化完成。


至此,信息技术行业的一大革命就这么静悄悄地完成了。

首先,硬件被抽象化为一种计算能力的描述。

 什么计算力的CPU、多少个内核、多少内存。而至于具体的硬件规格已经不再重要。将硬件抽象为标准化的计算能力这是一大进步。

 

一旦我们摆脱了对于具体硬件规格的讨论,转而描述计算能力,硬件就好像被软件定义了一样。比如在EC2平台上,只要围绕着它的API和AMI镜像编写自动化脚本,就能在云端“无中生有”地产生一个符合预期的硬件。

 

这种方法极大地改变了硬件采购的流程,从对于某个特定型号的硬件的采购,转化为了对于某种计算能力的要求。

其次,被软件定义了的硬件可以当作软件一样地进行管理。

软件这个概念从诞生之日起,就是和硬件对立的存在。硬件相对固定,更新改进和维护都需要相当长的响应时间;而软件则被认为可以较容易地演化和改进。

 

围绕着软件配置管理(scm)、工作区、构建流水线、持续集成、持续交付等概念。软件建立起了高效且自动化的变革管理流程。但是硬件却仍然需要依赖人工操作,相对同期的软件变革管理,易错且低效。

 

同样是从EC2p开始,虚拟机的启动脚本、镜像的生成过程都可以通过脚本自动化。于是所有适用于软件的变化管理实践也同样可以用于被虚拟化的硬件了。

 

这便是我们今日所说的基础设施即代码(IaC)。IaC无疑是巨大的变革,不仅仅从技术上,更是从观念上对于我们如何认识软件研发有了根本性的冲击,并带领了其后的软件定义网络(SDN)、软件定义存储(SDS)直至软件定义一切(SDE)。

 

弹性与运维革命

 

云平台声称的另一个好处是计算弹性。云平台厂商通常都会将计算弹性解释为根据业务需要动态调整计算资源的能力。比如业务的旺季需要一万台机器并不意味着在淡季也需要维持这种计算容量。

Demand for data center resources often spikes
Demand for data center resources often spikes

弹性不仅提供业务能力

这是一个很容易理解的概念。但是放在更具体的场景下,我们才能看出它真正的革命性所在。

 

比如一个看起来毫无关联的场景是这样的:假如我们就一台机器,使用了某软件A版本1.0,如果我们需要将A的版本升级为2.0,那么在云环境下究竟应该怎么办?

 

从机器管理的角度来说,我们可以登陆到这台机器上,通过脚本完成对组件版本的升级。这属于常规操作。

 

而如果完全从弹性角度出发,我们可以将这个问题描述为三个不同弹性需求阶段:

  • 只有一个机器使用A 1.0;
  • 需要2个计算资源,其中一个使用A 1.0,另一个使用A 2.0;
  • 重新回归一个机器使用A 2.0。


这两种操作在观念上的差异是巨大的!在第一个场景下,我们其实默认了环境不具备任何弹性—当然在历史上这是事实。“计算环境弹性有限—甚至是没有”是我们根深蒂固的观念。所以哪怕云平台提供了灵活的弹性能力,我们也不一定能利用得好。

 

比如在这个例子里,如果完全从弹性出发,我们可以使用完全不可以修改的服务器(immutable server 2012 radar),通过不同镜像实例的替换完成对于已有服务器的维护!

Cloud affects how we approach software updates
Cloud affects how we approach software updates

如果将这个范围扩大到整个环境,“通过踏板机更新”这种技术根本没什么用处。我们可以通过对于环境的整体替换,完成类似的操作。


在我们理解云计算平台弹性的过程中,我们也犯过很多错误,也被一些利益引诱了,比如效率。

 

掌握配置管理

如果你控制3000台ec2虚拟机,那么通过phoenix env完成版本升级是一个相当耗时的操作。而如果简单地登陆到每台机器上去修改配置,则有更快的效率。比如puppet和chef作为DevOps的先驱,不约而同地选择忽略云平台弹性(与当时云并未成为主流有关)。它们所推荐的部署方式,是通过一台中控配置管理服务器,对生产化境下的机器进行更新。

 

历史证明,在一个更简单的模型和一个更有效率的模型竞争的时候,总有一个拐点使得“更有效率”变得不那么有吸引力。

 

随着我们对于云平台一手经验的积累,对弹性有了更好的理解与认识。弹性的易用性、高可重复性和一致性逐渐显示了更多的优势。我们在雷达上推荐了Masterless Chef/Puppet,就反映了这种思考。

 

弹性实际上是一种统一的软件部署和升级模式。它极大地简化了这两种操作,使得软件部署不在需要专才。IaC使得硬件可以用软件定义和弹性成为统一部署模型,最终引发了DevOps运动—一场尚在进行中的软件交付革命。

 

镜像管理


在IaC发展的过程中,有一个核心难题:镜像是一种二进制格式。而传统的软件变化管理都是建立在文本对比的基础上的。比如软件版本控制系统,是以文本格式可以diff和merge为基础前提的。那么镜像作为一种二进制格式天然不满足这个前提。

 

两种管理镜像的传统方式

为了使得镜像能够被有效地管理起来,产生了各种不同的实践。总的来说可以分为两类:基础镜像加脚本和最终镜像加验证。

 

基础镜像加脚本的方式是采用一个尽可能简洁的基础镜像,然后在虚拟机器启动之后,通过钩子去执行一段脚本,逐步安装所有的软件,最终完成镜像的初始化。

 

这种方式的优点是非常明显的。所有对于镜像的管理都转化为对于镜像初始化脚本的管理。那么版本控制、构建流水线等等最佳实践都可以很容易地应用于镜像初始化脚本;只需维护极少的基础镜像,所有的定制化工作都由脚本构成,在集中管理和研发团队自主性上是个显而易见的平衡。

 

当然缺陷不多只有一个,就是虚拟机初始化的响应速度。在加载镜像之后,要经过重重更新与安装,才能达到真正可用的状态。这也增加人们对于弹性使用的成本。对于响应速度有较高要求的场景,比如动态扩容,这种方式往往达不到真正所需的响应时间。

Virtual machines can quickly get out of hand
Virtual machines can quickly get out of hand

而另一种方式则可以提供所需的响应速度。最终镜像加验证是提前在一台镜像构建虚拟机上将镜像定制的脚本执行完毕,然后截取这个虚拟机的镜像成为新的基本镜像,然后使用这个镜像到生产化境中去启动真正的虚拟机。由于绝大部分安装和配置工作都在镜像构建过程中完成了,因而并不需要额外的等待时间,所以这是一种更具响应速度和更低弹性成本的方式。

这种方式的缺点在于极大的增加了所需管理镜像的数量,尤其在整个IT部门共用同一云平台的情况下,每个团队都可能有几个甚至十几个不同的镜像,那么可能需要同时管理几百个镜像。这些二进制的镜像无法diff,因而很难抉择到底这些镜像的差异在哪里。通过增加标签的方式来判别又往往与内容不符。 

 

另外,一旦作为二进制的镜像单独存储,就很难再追溯到构件它时所用的软件代码。理论上说,通过标注配置管理工具版本信息,能够提供一定的追溯性,但是这也很难避免偶然的修改或者其他因素带来的信息脱节。

 

对于镜像内的内容,也较难有很直观的印象。最终只能转换一种方式,通过管理服务器测试代码来完成对镜像的管理。通过使用虚拟机测试——比如ServerSpec这样的工具——来验证二进制的镜像中的内容。那么这些虚拟机的规格说明,从某种程度上说,就成为了可以被管理的软件代码。

 

这两类不同的处理方式在弹性成本和镜像管理成本上有很大差异,因而在不同的场景下各自有无可替代的价值。比如Travis CI,作为持续集成服务提供商,他们对使用CI的客户的弹性成本不敏感,而镜像的成本极其敏感,因而不可能采用第二类方式。

 

从具体实践上看,第一种方式采用的是代码视角,也就是将镜像归结于构造镜像的代码,通过代码对镜像进行管理;第二种方式是从镜像管理出发,但是在镜像相关代码的管理上缺乏足够的支撑。

 

统一的镜像管理方法

我们也曾畅想过最理想的镜像管理模式:将镜像、构件代码和测试代码统一在版本控制工具中管理;最好有一种清亮的镜像格式,使得版本控制工具能够有效地存储它们;最好能够提取代码的diff在镜像上的增量。

Docker containerization
Docker containerization

但是从始至终这样的工具就没有出现过,因为Docker来了。依托于Lxc container的Docker完美地完成了IaC最后的拼图:一种完全从镜像出发的版本管理工具或者说一种具有代码版本控制能力的镜像仓库。

 

容器化与云的重思考


Docker以及其所依赖的LXC container对于虚拟化提出了不同的思考。

 

虚拟化及容器化新浪潮

虚拟化技术主要通过硬件模拟出一台完整的机器,再在这台机器上去执行对应的操作系统。这不可避免地带来了极大的性能开销。虽然当代操作系统内核允许虚拟机透过操作系统直接执行一些操作,以提高性能,但是额外的开销仍然不可避免。

 

虚拟机技术从最终结果上看,提供了独立的部署单元和隔离沙盒。所谓隔离沙盒是指虚拟机内的程序或操作系统崩溃不会传递到其他虚拟机。同时虚拟机对于硬件设备的设置也不会传递给其他虚拟机。

Virtualization enables you to make better use of computing resources
Virtualization enables you to make better use of computing resources

LXC就是从这个角度出发:如果可以提供同等的隔离能力,那么用以执行计算的单元究竟是不是虚拟机也就不重要了。容器化就是在操作系统上提供接近机虚拟机沙盒隔离能力的容器,并以此作为基础提供轻量虚拟化的技术。

Containerization allows sandbox isolation capability
Containerization allows sandbox isolation capability

容器化预示着云原生时代

从某种程度上来说,容器化技术非常类似云计算的SaaS模式。我们可以将容器看作同一台计算机上的多个租户中的一个。由操作系统提供的隔离机制保证容器间的彼此隔离;而从容器内运行的应用来看,好像这个应用独占全部的计算资源一样。

 

通过容器化,哪怕是一台机器也可以支持云计算的SaaS模式了。这就模糊了云与单台服务器的差距,究竟是由一组硬件服务器组成一个计算网格,还是在一台服务器上通过多个容器去执行多个应用(抑或是同一个应用的多个实例)。从概念上来说,已经不存在太大的差别了。

 

如果我们将IaC和弹性作为最基础的概念,那么云和单台服务器之间只有能力差异,而无概念的差别了。至此,云就不再是一个衍生概念了,而成为了一个原生概念。这也标志着我们彻底地完全地进入了云时代——也就是云原生时代。


DCOS为私有云的成功铺平道路


云原生时代我们可以从云的角度定义并理解任意的计算平台:IaC——计算能力和基础设施的软件化描述、弹性的容量和成本。无论是单台服务器、数据中心、公有云平台都可以在这个框架下理解为具有某种弹性能力的计算平台。

 

特别是以Docker container为代表的轻量化容器,无论是从IaC还是计算成本上都具有巨大的优势。在极短时间里,作为新一代云计算平台的基础渗透到了各个领域(Radar theme docker, docker, docker)。企业的数据中心(data center)也以docker为基础以DCOS(数据中心操作系统)为核心开始了第二次私有云的尝试。

 

在谈论DCOS之前,我们先要介绍一个看起来非常简单的技术——端口绑定(port binding)。

 

端口绑定赢得了胜利

Docker容器提供了隔离沙盒,沙盒之间需要一定的连通性才能协作完成有用的功能。但是如何在不破坏隔离性的前提下让配置在不同的沙盒间可见呢?通常有三种做法,分布式配置管理库——比如etcd、zookeeper;动态DNS;而最简洁优雅的方案就是端口绑定。

 

端口绑定采用一个本地化假设——即所有需要的外部资源在概念上都是本地服务。这些服务通过本地端口为容器内的应用提供服务。以访问数据库为例,容器内的应用不需要知道数据库在哪个IP的哪个端口,它只需要假设数据都在本地的某个端口上——比如8051——可用。那么它只需要去访问这个端口就能够访问到数据库了。而容器在启动的时候,可由某个控制器将这个端口绑定到本机或远程的另一个容器或服务器上。

 

端口绑定的优雅之处在于,所有后台应用在概念上都成了本地应用,容器调度器负责通过端口映射到具体服务。这使得通过容器部署的应用看起来非常像在操作系统中的进程,而跨物理机器边界的调度也类似操作系统的调度一样。

 

面向数据中心的操作系统

于是我们就想,能不能就从类比出发,将容器看作增强了的进程空间,而将容器的调度器看作在一组物理机器上执行的操作系统呢?(“容器即进程,PaaS即机器,微服务架构即编程模式”)这就是数据中心操作系统(DCOS)的由来。

 

DCOS是一种透明的弹性扩展方案。比如,将同时在单台机器上运行的数据库和应用分离到两台机器,那么对于这应用和数据库的容器而言,不需要发生任何改变。只需要在容器启动的时候绑定到远程端口即可。那么这种扩展也可以很容易的从几台机器扩展到整个数据中心,或是利用云计算平台增加所管理的计算资源。

 

DCOS还是一种渐进式方案,它并不是需要在一开始就规划出整个平台的容量。无论是一台机器还是一百台机器,都可以使用同样的方式管理。这种项目在第一天和第五百天的部署方式都有一样的特点,甚至产生了“哪怕一台机器也要上mesos/k8s(DCOS)”的最佳实践。

 

DCOS恰好解决了第一次云私有化过程中弹性扩展和切换成本过高的问题。企业可以很容易地围绕某个特定的应用,采纳DCOS的方式作为基础部署方案,在上线之后根据弹性需要逐步扩容。因而围绕着DCOS兴起了第二次私有云浪潮。

 

这次云私有化另一个特点就是企业不再追求模仿Amazon提供通用计算能力的云平台,而更加注重实际弹性效果,围绕关键应用去构建私有云。因而我们也将这个过程称为私有PaaS,或者Domain speific PaaS。

 

PaaS平台的兴起


如果我们回顾过去十年的云计算的发展,会发现作为早期云计算平台先驱的GAE一直没有得到应有的关注。一方面在于Google将GAE定位于特定类型的Web应用开发,另一方面是因为它缺少对应的私有化方案。使得企业必须面对要么GAE要么什么也没有的境地。同样的尴尬一直都存在与PaaS供应商们,比如Heroku。虽然也有一些私有化PaaS方案,比如Deis,CloudFoundary,但在企业彻底解决了弹性部署方案之前,都难成大器。

 

而因为DCOS近年来大获成功,无论是Mesos还是最终的王者Kubernetes都成为大多数企业的基础平台。围绕应用去构建PaaS平台成为了企业云计算发展的主题。以至于当年风光无限的公有云平台也纷纷推出了容器化弹性方案。

 

这就是今天我们所处的云计算的业态:一方面企业终于找到了合理利用数据中心资源的实现私有云的方式,另一方面云计算平台也逐渐从裸计算资源缓慢转向为平台化计算能力。

 

而在这个过程中,不同的云计算供应商甚至有了自己的专长。比如Google围绕Tensorflow打造了机器学习云,微软以图像和语言识别为切入提供了特别的能力,而Amazon则继续降低弹性成本,提出了Lambda无服务器架构

 

混合云(Hybrid)多种云(Ploycloud)正在逐渐成为IT组织的基础IT战略。云计算正在逐步实现它当年的诺言:计算像水电一样成为基础资源并能够随时低成本地获取。而我们交付和运维软件的方式,甚至是对于软硬件的理解都在这一过程中,发生了翻天覆地的改变。

 

我们在这里对于云计算的简单回顾,希望可以帮助大家更好地理解这个趋势从何而来,正在向哪里而去。

如何实现更快的增长?