前言:


很多时候,对于一个研发人员来说,往往更关注软件实现层面的东西,缺少了怎么把一些知识串联起来对软件特性设计本身的一些思考,基于一门底层技术之上的猜想,比如说它为什么要去设计这些特性,基于这些特性我们能干什么是值得我们去深思。这次我主要不是针对容器技术是怎么实现的去分享,而是从openstack能使用容器技术的特性来干什么的纬度展开讨论。对于我而言,无论是什么事,我都习惯从Why -> How -> What来思考问题,我相信这个世界没有无缘无故的爱,也没有无缘无故的恨,有句话叫“存在即合理”,那么openstack为什么要做容器平台也一定有它得理由。因此我以Why How What的顺序来给大家分享下openstack集成容器技术的方案。


一、Why:openstack为什么要集成容器技术


首先:要明确知道得是openstack的“根”是要做集成引擎,因此也就确定了它必然会往集成方向发展。具体点说,openstack只要管好三个模块:计算、存储、网络,着重在如何让这三个模块高效的协同工作,而对于主流的计算、存储、网络解决方案,openstack都可以将它们集成进来供使用者选择适合他们业务场景得解决方案组合。最初的openstack的计算模块的解决方案是以虚拟化技术为主的VM,随着这两年以docker为主得容器技术迅猛发展,openstack看到了在VM之外的计算方案,因此openstack自然会将docker集成到计算模块中来,以此来丰富自己的计算能力。其次:openstack一直致力于打造一个统一的硬件和软件无关的IT基础设施框架,那就意味着它必须去考虑两件事:


  • 一个部署了openstack的IT厂商如果想使用docker这样的容器技术的时候该怎么办?总不能让IT厂商在垂直领域去重新找一个新得容器管理方案。

  • 一个想使用容器技术的IT厂商,如何去帮他们考虑硬件资源的弹性问题?


Peter Thiel有句名言:失败者才去竞争,创业者应当选择垄断。以其说openstack是“被逼上梁山”的,不如说openstack选择了在IaaS市场的垄断。如果openstack将以docker为主的容器技术集成进来,那么IT厂商就可以通过openstack找到一个统一的跨平台得API来管理他们的虚机、容器和裸机,即不失容器固有的功能,又能给容器提供一个托管平台。再者:以docker为主的生态圈的发展势头大有取代以VM为主的openstack的趋势。CloudFoundry Diego版本Garden项目中加入了docker的支持,Garden的前身是warden,而warden其实比docker发展的更早,早期的docker和warden一样都是基于lxc来做,但是warden起初的定位并没有针对用户使用,只是提供给cloudfoundry一个运行时隔离环境而已,因此失去了市场先机。openshit V3中也加入了docker的支持,还有两个针对云计算的操作系统的CoreOS和Atomic,也都加入docker的支持,CoreOS自家还有针对企业级市场的rocket(rkt)容器技术。因此我个人觉得从战略上考虑,openstack怎么能允许docker取我而代之呢?相反,如果我把你招入麾下,那么自然就告诉别人这个行业谁才是老大。


二、How:openstack是如何集成容器技术方案


我曾经思考过计算机为何会如此的高效,思考过如何像计算机一样提高自己的工作效率,我觉得有两点:管理和执行力。对于计算机而言,执行力自不必说,非0即1。那么效率就落在管理上面,在计算机的世界里,管理的最终目的即是如何充分的利用资源来做更多的事。管理离不开组织,组织离不开规模,规模离不开个人,docker就像个人一样,接下来让我们看下openstack是如何去考虑管理容器这件事。


起初openstack社区在将docker集成进来的时候有过两个方案:heat driver和nova driver,这两个都是以插件得形式接入openstack,但是都是直接将docker当成VM来使用,缺少了对docker得抽象封装,如果大规模的使用docker的时候,那么管理上就会出现很大的问题(就像一个上了规模的上市公司的CEO每天去管理公司保洁阿姨的工作),自然也就无法发挥docker的价值,结论就是将docker作为控制粒度直接集成进来是不可取的,因此就必须要对docker进行抽象封装(可以理解为进行组织划分),把控制粒度控制在docker的抽象封装上。docker对于个人开发者而言,已经很好用了,但是对于像前面提到的大规模部署容器得企业而言,手动操作docker的批量创建、调度和管理会成为了制约docker在任何组织内大规模应用的重要障碍。有问题,那就必然有解决问题的对策,因此docker的生态圈出了一些工具来解决这些问题:比如:针对容器编排和部署的Compose(Fig)、Machine、Swarm以及后来的Fleet,针对应用支持和运行时的Flynn、Deis等等,到最后实现大一统的是google公司开源的一款专门针对容器集群管理得工具kubernetes,国人一般直接音译成k8s,我们后面再重点介绍kubernetes。Compose、Machine、Swarm、Fleet这类的工具主要focus在容器的编排和部署上面,如何让容器更易于使用,但是在管理效率上不是很高效。Flynn、Deis、openshift V3、CF V3这类的主要focus在构建一个PaaS平台上,对于PaaS平台来说,最重要的问题就是解决应用依赖问题,拿CloudFoundry来说,它使用一个Buildpack模块来做平台应用依赖管理,很多特殊的应用往往就需要对Buildpack做定制化开发才可以支持,而如果使用docker来做这件事,就很easy了,一个Dockerfile就可以搞定一个应用的依赖问题。确实在docker刚出来的时候,就很多人预言了基于docker的微PaaS平台会大热,当然了,我个人觉得openstack不选择这类PaaS平台是因为它不想自己所提供的容器平台只是一个解决应用依赖的平台,它应该还可以做更多的事。既然有专门针对容器技术的编排管理工具,openstack自然不会想到自己重新去实现一个,而是想着怎么把它们直接集成进来。除此之外,openstack还考虑如何把容器集成做成一个可以像其它的openstack服务,比如:nova、cinder、trove、glance、ironic等等一样得服务(跟着组织走),我想用的时候直接把服务起来就可以了。基于这两个需求,Rackspace的工程师Adrian Otto主导了magnum项目,专门用来对接openstack和容器技术平台,下面我们来介绍下magnum这个项目是如何做这件事。


1、magnum项目介绍


前面已经说到,magnum项目其实只要做好两件事:


  • 怎么把容器编排管理工具集成进来。

  • 怎么把自己作为一个openstack的服务。


对于第二件事比较简单,照着其他服务得架构思路就可以实现,但是针对第一件事,就必须要思考如何去抽象封装。magnum的抽象思路是:将容器编排系统抽象封装进来。这样做的好处是:


  • 不需要去重复造容器编排的轮子

  • 可以将各种优秀的容器编排工具集成进来

  • 可以利用编排工具所支持的各种优秀的容器技术解决方案比如rocket、garden、openVZ等等集成进来,而不一定只是docker。


下面我们具体来看下magnum 是如何抽象封装,先看一张官方的magnum软件架构图:


640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy


  • Bay:magnum用Bay来抽象容器编排工具,到L版发布的时候,支持的Bay类型有:kubernetes(k8s)、docker swarm、mesos。


  • Baymodel:容器规格。对于nova来说有flavor,自然对于容器来说,也有它自己的规格。



其它的比如Node、Pod、Service、RC这几个都是k8s的概念,到后面介绍k8s的时候再介绍。同openstack得其他服务一样,magnum也是通过一个API服务来接受请求,再转发到后端得conductor处理,conductor去调用不同得后端Bay驱动来跟不同的容器编排工具的得API做交互。除此之外,magnum使用openstack的keystone来提供一个异步的API来管理应用容器和一个完整的多租户实现,这也是magnum有别于docker或者kubernetes的地方。



在编排管理工具的选型上,到L版为止支持的Bay类型有docker swarm、mesos、kubernetes。magnum集成度最高的是kubernetes,实现了一层和kubernetes对应的交互API,目前magnum默认的Bay类型是kubernetes(官方推荐),先看下Docker swarm和mesos。



  • Docker swarm:swarm虽然也是对docker做了一层抽象封装,但是它的抽象还是有点过于简单,不适合于复杂的应用场景。它更多是可能是替代Docker客户端,因为docker客户端还不支持跨主机操作。


  • mesos:

    1、如果站在magnum上面来说,我们知道mesos是一个非常优秀的框架调度系统,虽然mesos也可以调度docker容器,但是它也还是以docker为控制粒度,缺少了对docker的抽象封装,不适合在运行大量的容器集群中做管理,而且在kubernetes的roadmap中会将mesos作为调度插件接入kubernetes,换句话说就是把kubernetes这个框架运行在mesos之上,或者说把mesos作为kubernetes的调度框架。我觉得这才是kubernetes和mesos最好的结合,因此这里我没想明白magnum为什么要把mesos集成到magnum这里面进来。我个人觉得在sahara这个项目中可以考虑怎么去更好的集成mesos,可以给Hadoop社区提供一个yarn之外的选择。

    2、如果单纯站在mesos上面来说,目前有一个比较好的应用管理解决方案:mesos+marathon,marathon是一个基于mesos的应用管理框架,前身是Chronos,主要还是focus在数据中心,因此marathon主要运用在运行Hadoop、Strom、Spark、kafaka等等数据处理框架为主的IDC中心,当然它也可以管理普通的web应用。在大数据和云计算的结合方面,目前sahara这个项目一直在做这件事,它可以考虑将marathon集成进来。



回到我们最初谈到的openstack要奔着垄断去的,它不会给IT厂商去做如何选择的“机会”。在google的kubernetes一出来的时候,立马一统容器管理的江上,openstack又岂会放过,这也是为什么magnum会对kubernetes做深度集成的原因。



接下来我们看下magnum创建一个kubernetes的简单的过程:



  • 创建Baymodel


  • 创建kubernetes Bay


  • 使用kubernetes的pod、service、rc模版来创建应用。



这些模版是kubernetes原生的模版。因此magnum要做得事情很少,基本又回归到kubernetes自身得使用上面来了。回过头来看magnum的控制粒度,把容器编排管理工具作为控制粒度,把容器应有的特性封装交给容器编排管理工具来做,这样就不会影响到一个优秀得容器集群管理工具得价值。对于openstack来说管理变得简单了,接下来让我们重点来介绍下kubernetes。


2、kubernetes项目介绍


kubernetes能干什么?首先kubernetes是google基于Borg开源的一个容器编排系统,Borg是google内部一直在使用的一个集群管理工具,实际上,容器技术的核心功能cgroup最早就是由google的工程师提交给Linux内核,google内部也一直在使用容器技术,Borg能够处理google每天成千上万个应用得任务处理,充分证明Borg系统是“靠谱的”大规模应用管理系统,google已经将Borg进行升级,代号Omega。同样百度内部也开发了一个号称可以媲美Borg的集群管理系统Matrix,并且拿到了百度内部最高奖(100万美金)。还有facebook的Corona、twitter的Aurora,可以想像一个好的集群管理系统有多重要,这也是我们t2cloud云平台2.0的目标。正是因为基于Borg得基因,因此kubernetes一开始就是为管理大规模的应用而生得,只不过kubernetes是专门针对大规模容器集群做管理得。那么它肯定有一套非常完美的对象抽象,否则怎么管理大规模的容器。此外,kubernetes还是跨主机容器化应用管理的系统,实现了包括部署、高可用管理和应用弹性伸缩在内的一系列基础功能,并封装成为一套精简的RESTful API对外提供服务,除了mesos已经可以作为kubernetes的调度服务之外,剑桥大学计算机实验室开源的一款最新的集群调度平台Firmament也正在跟kubernetes集成,Firmament目前还在alpha阶段。接下来我们来看下kubernetes是如何针对复杂的应用在管理上去抽象封装容器集群,先看kubernetes官方的架构图:


640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy


  • pod:kubernetes调度的最小单元,kubernetes不对单一的容器进行调度,相反,它将一些强耦合的应用组件容器捆绑在一起进行调度,这么做有两个好处:1、对于强耦合应用,比如说某个应用带了一个db服务,两个服务之间互相访问的方式变简单了,一个容器服务可以直接访问另一个容器服务指定的目录,一个容器可以直接通过localhost访问另一个容器,不需要更复杂的访问方式。2、可以简化调度系统,尤其是在大规模容器集群中,管理的粒度变大了,就相当于“放权”之后管理者要做的事就少了,那么调度者本身就能够大大的提高调度效率。


  • rc:全称replication controller,这个抽象是kubernetes用来保证应用可靠性而设计的,它被设计用来保证集群中pod的副本数,并且保证这些副本的期望状态与当前的状态一样。熟悉Cloud Foundry得人都知道,Cloud Foundry使用一个独立的组件HM9000来做统一监控管理,因此各个组件要不断的将信息发送给HM9000来监控处理,包括openstack的ceilometer监控也是,因此容易造成性能瓶颈。因此,kubernetes就设计了一个非常轻量化的对象来处理监控,每一个pod都可以自己定义一个rc,而一个rc只负责监控它所选择的pod,针对不同的pod状态有不同的处理策略,非常的精简高效。


  • label:label的设计用来管理kubernetes中运行的大量的pod、rc等等对象的运行实例。它是一个键/值对,结构非常简单,就是一个key和value均是string类型的map结构(go语言语法)。它通过lable selector来做lable管理的,比如我们使用的pod模版中有("name":"nginx")("name":"wordpress")这类的label,集群中运行很多这类模版创建的实例。那么我就可以通过lable去查看当前集群中所有name为nginx的pod实例。这只是一个简单的应用,实际应用中还可以将lable运用在复杂应用的分层纬度中去做分层管理,比如有一个非常大的应用,需要很多的pod组成,那么你就可以通过底层、中间件、上层这三种lable来区分每个pod所属的层次机构,因此lable非常适用在构建微服务架构为主的应用中做为微服务架构下应用的微服务的分类管理。lable可以随着实例的创建绑定,也可以动态的增/减,同一个pod中key是唯一的,value可以变。在创建pod或者rc等等实例的模版中可以自行指定label,而对于使用者来说,可以通过label selector来选择指定的lable。


  • service:这个是kubernetes设计用来代理pod请求的,为什么?因为pod的ip不是固定的,因此就需要一个有固定IP的服务来代理pod的路由,service通过label selector来选择它所要代理的pod的label。很多人可能就会想,那直接在Node节点跑一个Agent不就搞定了,很多分布式架构都会有这样的设计,kubernetes也有,但是kubernetes设计service还有一层考虑就是你可以更人性化的去管理你的应用,虽然service的后台实现机制也是要依赖Node节点的kube-proxy代理服务,但是把service固定住,那么后台的应用pod你可以随时更换而不需要再修改代理规则,对于使用者来说,你只感知到service就行了,完全屏蔽掉后台实现。service还可以为pod做负载均衡,当rc控制了多个pod的时候,service可以将流量分发到各个pod节点上。



上面几个概念是kubernetes对大规模集群管理做的一些对象抽象,从控制粒度为应用到稳定性保证到大规模分类管理到负载均衡,可以让你很轻松的去做一个大规模的容器集群管理。接下来点下kubernetes的软件架构,从上面的图可以看出,首先,kubernetes采用的是现在主流的分布式架构,因此就有主从的概念。主控节点上面运行:kube-api、kube-scheduler、kube-controller-manager服务,从节点上面运行:kube-proxy,docker服务,整个集群使用etcd作为后端存储系统和服务发现。主控节点上面的几个服务主要是用来做对象控制、调度和管理用的,而从节点上面除了正常的docker服务之外还运行了一个kube-proxy服务用来做service的代理,kube-proxy使用etcd的一个非常重要的watch机制来watch etcd上面的service来更新从节点所在的主机上面的iptables规则。



对于kubernetes软件实现层面的东西,我这里不做过多的文章,感兴趣可以去阅读源代码,go语言的代码还是很好阅读。前面都是一直在说如何去管理容器这件事,但是我们是否想过会有管理容器这件事,换句话说就是容器值得我们去管理,接下来我们来聊聊使用以Docker为主的容器技术来开发会带来哪些好处。传统的互联网应用开发流程如下:



  • 从代码库拉取代码


  • 本地环境安装依赖(高级点的可以直接配置一个依赖脚步执行一下就OK)


  • 提交代码仓库触发CI,做CI测试


  • 测试人员测试


  • 运维人员发布应用



理想很丰满,现实很骨感,简单的几个环节就可能会出现各种各样的问题,比如开发、测试和生产环境不一致导致的问题,版本升级带来的依赖问题等等。当然了,软件没有什么解决不了的问题,最终肯定都会有解决的办法,但至于“解决方法”所付出的代价可能就值得我们商榷了。那如果使用Docker来开发,它又有什么特点,先看一个使用Docker来开发的流程图:


640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy


使用Docker开发可以有如下好处:


  • 持续部署与测试 Docker消除了开发、测试、生产环境的差异性,保证了应用生命周期的环境一致性和标准化,你还可以像git工具一样去对Docker镜像做版本控制。现在主流的配置管理工具:Chef、Puppet、Ansible、Saltstack等等也都支持Docker。开发者在开发阶段编写好Dockerfile执行本地开发,提交完整镜像到镜像库,测试人员拉取镜像测试完提交到发布镜像库,运维人员从发布镜像库发布镜像,一旦出现故障还可以快速回滚,大大简化了持续集成、测试和发布的过程。

  • 跨平台 Java有句名言叫“一处编译,到处运行”,同样,Docker也有一句名言“一处构建,到处运行”。Docker镜像可以运行在任何运行Docker引擎的宿主机上,目前,Docker只支持运行Linux发行版本,运行Docker引擎的除了支持Linux发行版外,还支持window nano server。

  • 资源利用率高 Docker只是一个进程级别的系统开销,相比Hyper-V、KVM、Xen等等硬件仿真级别的虚拟化技术而言,在对宿主机资源利用率方面,Docker可以高出一节。当然了,正式因为它是容器技术,只是提供了在进程级别的隔离,隔离性方面肯定比不上虚拟化技术,这就要考虑到实际的应用场景的隔离级别了。

    这些只是我个人觉得Docker可以带来的好处,更多的功能还等着我们去挖掘。kubernetes的管理思想和Docker的特性,结合微服务架构的思想,可以很轻松的构建复杂的大型应用,当然了,对于一个复杂的大型应用离不开另外两大块:存储和网络。这是两个比较大的内容,需要下次专门来分享,这里我可以简单的点一下这两块内容。

  • 存储:kubernetes的存储针对pod而言,支持的存储类型有:emptyDir(Node节点的一个目录)、hostPath(共享Node文件系统路径的一种机制。这个机制对于同一个节点的pod数据不会丢失,但是pod节点发生跨主机迁移,那么数据就会丢失,因此不推荐使用)、nfs(就是网络文件系统,nfs的性能问题一直都是一个瓶颈)、rbd(ceph块存储,ceph是我们t2cloud云平台现在在使用的分布式存储解决方案,理所当然的我们也是推荐使用ceph作为kubernetes的存储解决方案)像其他的还有Glusterfs、iscsi、gitRepo等等可以参考官网。下次可以给大家分享下我们云平台现在的ceph解决方案。

  • 网络:Docker自身的网络模型决定了它只能在同一台宿主机上面通信,因此Docker生态圈出了很多Docker的网络解决方案,比如:Weave、Flannel、Pipework、SocketPlane,Docker自己也发布了libnetwork来解决网络问题。kubernetes本身也可以算是Docker网络的一种解决方案,前面有提到过kubernetes为每一个pod分配一个ip,这就是它的“单pod单IP模型”,通过这个IP地址,可以在一个扁平化的网络地址空间里面跨网络与其他物理机、虚拟机或者容器进行通信,这个扁平网络是由某种IaaS或者网络工具OVS(OpenVSwich)、Socketplance来保证。


三、What:openstack完整的容器技术平台


openstack可以通过magnum项目来提供一个深度的容器解决方案,结合openstack的ironic项目提供的裸机计算能力,那么openstack最终展现出来的就是一个完整的计算方案:虚拟机、容器、裸机。(只能说目前是完整的,未来以OGE、SLURM为主的网格计算和以Unikernel为主的无核技术说不定会有一个比较好的方案)。在通过openstack去使用容器技术或者说docker的角度来看,你还可以使用openstack的应用目录服务murano来使用容器技术,使用murano模版来配置docker镜像或者配置部署kubernetes。最low的,你可以直接在openstack的VM中安装docker服务即可。此外,社区还有一个跟openstack部署相关的关于docker的项目:Kolla,这个项目主要的目的是使用docker快速的部署升级openstack服务,我个人对这个项目保持谨慎的态度。




转自:http://mp.weixin.qq.com/s?__biz=MjM5MzM3NjM4MA==&mid=401909586&idx=3&sn=15fe2e134ac883305087d19f4f16baf5&scene=2&srcid=1113gfUOHCjpwfvkoum3eWEa&from=timeline&isappinstalled=0#rd