数人云

数人云

数人云官网
用户手册

用户手册

数人云用户手册
Mesos中文文档

Mesos中文文档

开源, 欢迎大家修改优化

三分天下,分久必合:IBM的Kubernetes on Mesos探索之路

宁静胡同 发表了文章 • 0 个评论 • 286 次浏览 • 2016-11-10 14:54 • 来自相关话题

今天是数人云容器三国演义Meetup嘉宾演讲实录第四弹。说完了各家容器技术的实战,那么最后来看容器技术的融合——IBM正在探索的一条道路。

我叫马达,名字很好记,挂的title是IBM软件架构师,但我更喜欢下面这个角色: kube-mesos社区负责人;我在Mesos和Kubernetes两个社区都有不同的贡献。国内我是较早一批进入Mesos社区的,2014年开始通过meetup认识了很多技术圈的朋友,后来由于公司的需要就转到了Kubernetes,目前在team里主要做的是Kubernetes on Mesos。
 
很多人对Kuberneteson Mesos有疑问,说这两个东西放在一起到底有没有价值。前段时间有人在微信群里问我是不是为了集成而集成,搞一个噱头,大家一起去玩这个事情。这方面我会讲一下,以及Kuberneteson Mesos现在已经有将近一年没有人维护了,所以现在我们接手以后有很多事情要做,包括后面的很多功能要完善。

kube-mesos历史
 
Kubernetes on Mesos,现在我一般是叫kube-mesos。Kubernetes on Mesos这个项目最早从2014年开始,从Kubernetes刚开始的时候,Mesosphere就投入精力把它们做一个集成。后来Mesosphere出了自己的DC/OS,就不再投入资源了。2015年的时候版本跟得很紧,从0.3一直到0.7十几个release,到了2016年最后一个版本release是0.7.2,到今年的1月份就很少release了。9月,IBM开始接手,因为IBM整个产品都是基于这个Kuberneteson Mesos为基础的。这时IBM把它重新定义成一个孵化器的项目,把它从Kubernetes Github里面拆出来,放到Kubernetes孵化项目里面。






9月,当我们跑Kuberneteson Mesos这个项目的时候也是得到了很大的支持,现在的Sponsor是Google的Tim,他主要会帮我们一起去review Kubernetes on Mesos后面的roadmap,以及什么时候升级为Kuberentes的顶级项目。现在有一个叫Champion的角色类,Champion这个角色来自红帽的David,他会和我们做一些daily的review,看一下process和一些BUG。这是我们现在在Github上的一个ID,所以现在我主要负责Kubernetes后面的一些roadmap,也希望大家一起去共享这个项目,因为后面有很多非常有意思的项目,不仅要改Kuberntes、Mesos,还有我们一些新的想法。下面是Github的地址 (https://github.com/kubernetes- ... work/ ),到Github可以找到相关的资料。

为什么kube-mesos?






为什么要做这样一个项目,把两个社区或者两个比较复杂的东西放在一起。大家看一个环境的时候,现在讨论最多的是容器,但真正到一个数据中心或者企业环境,你会发现其中会有各种各样的workload,Kubernetes on Mesos只是其中的一部分。在作业管理和应用管理这一层的话,比如跑大数据会希望用Spark;跑管理容器相关的时候,可以跑一些Kubernetes 、Marathon这样的功能。但这时候是分开的,不同的workload使用不同的框架。再往下一层的时候,这些workload,是可以把资源共享、可以把资源重新抽象出来。

这就是Mesos最开始提的事情,把资源重新抽象出来,抽象出一个资源池,有CPU、有memory。这也是为什么Mesos在描述自己的时候,它会说抽象出一个资源池,在Google的Omega文章里面,它也会提把Mesos定义为第二代调度的策略,两级的调度出来scheduling。Omega这个事,Google还没有实现,所以现在也无人提。

真正说容器、说Docker的时候,最早它只是一个运行环境,每一台机器上一个Docker agent,然后把机器提起来,负责一些起停监控等。我们把资源管理用Mesos抽象出来,上层的应用管理可以放Kubernetes,也可以放Marathon、Spark。一些用户已经搭建了环境,底层是Mesos,上面的容器化是跑Kubernetes,大数据跑Spark。Hadoop那些的话,我们当时是在测试Myriad项目的一些功能,有许多问题和经验,有机会可以聊一下。






容器基本都在PaaS这一层,IaaS那一层Openstack搞定所有的事情。Paas这一层抽象出来,就是是Mesos上面加Kubernetes,包括上面真正的运行环境加Docker。各个厂商当你做一个完整的solution,统一用户的管理、统一的界面,都是差不多的。做整个流程时,你不希望用户还去在意下面是跑Mesos还是Kubernetes,于是对外最后就把它抽象成业务的一个逻辑和一个业务的描述。






IBM从1992年的时候开始做自己的产品叫LSF,就是说在九几年的时候像PDS、SGE,早期的HPC, 网络计算基本上都属于这一期的。大家都比较像,workload的管理和资源管理都放在一起了。但等到2003年的时候,资源管理那一层,IBM在做新产品的时候资源管理层又做了一遍,而且是有这样的需求,一些大的银行用户里面LSF和Symphony两个是需要同时跑在一起的,而且由于它们业务上的问题,白天的时候大部分资源给Symphony这个产品,晚上的时候有一部分资源要给LSF,即另外一个产品。
 
中间资源的切换,如果是原来的话,只能去写脚本,把这个cluster一些agent重新提起来放在那边,但是下面如果把这个资源这层重新抽象出来的话,我们内部产品叫EGO,其实跟Mesos非常像,这也是为什么IBM在Mesos有很大的投入。包括我们这边有很多高级调度策略,像刚才说按时间的调度,包括一些资源的分配和资源的共享。
 
从2003年的时候,IBM就开始做这样相应的事情,资源管理是一层,上面的workload pattern是一层。放眼整个开源社区,我们发现Kubernetes对容器的管理这一方面做得更好一点,所以最后选的还是Kuberneteson Mesos整体的架构。当2006年我们在做DCOS类似Paas平台这样一个产品的时候,最终定出来的方案就是说Kubernetes on Mesos。可以看到整个产品的架构从零几年开始做,而且基本验证了至少现在是一个正确的方向。
 
待解决问题






Kuberneteson Mesos现在将近有一年没有再发布新的版本了,目前有很多问题。第一个,Kubernetes on Mesos这个项目到年底、明年年初最主要做这个项目就是要把整个refactor一下,最主要的原因是现在的Kuberneteson Mesos对Kubernetes的代码依赖非常严重。它集成的时候是把Kubernetes里面很多组件拿过来,在外面再包一下,它是代码级别的改造。我在9月份刚开始接受那个项目的时候,经常会有Kubernetes主干的人告诉我,我们这块有interface变了,你要赶紧去看一下,要不然可能就编译不过,问题是它的改动基本都是内部的interface,其实对我外部的像RESTful API这些东西是不需要变的。所以在这块最主要做的是要把它分离出来,跟Mesos、Kubernetes集成的这些interface和这些接口,我们都希望通过它的RESTful API来做。
 
这部分还有一个更大的topic,11月份的KubeCon与Google在讨论这个事情,Google前两天也有人在做——希望Kubernetes可以提供一种资源管理的功能,无论是它本身提供还是它提供资源管理这一层,希望Spark可以利用这样的一个功能,而不是说Spark再去写,希望做这样的集成。我们也是希望Kubernetes可以更友好的去支持资源管理这一层。基于之前的那些经验,我们会在社区里推动它,至少它对resource manager的支持,不仅仅是对Mesos的支持。因为我知道Horon work也在做Kubernetes on Yarn,就是说这个Yarn也是资源管理这一层,Yarn、Mesos包括我们内部的一些资源管理EGO, 很多都是属于空层这一层,所以Kubernetes把它定位成一个container管理的软件,下面是可以把它完全抽象出来,让它更好的接受资源管理这个东西。
 
就代码级别来看的话,其实Swarm对资源管理层支持得更好,因为它默认自己是需要有资源管理这一层的,它把自身Swarm和内部这个调度都重新写成了一个resources manager资源管理。虽然它没有Mesos强,但是跟Mesos是一样的,所以它很容易就接到Mesos里面去。但Kubernetes现在是不用做这样的事情,它把整个全都揉到一起,所以这在后续的KuberCon,我们也需要更多人去讨论,是希望它能把这个东西得抽象出来,而不是说我们自己再去搞这样的东西。
 
revocable resources在Mesos里面基本上是资源的借入借出。现在的revocable resources,Mesos只支持超频(Oversubscription),这个功能现在只是超频这个部分,但现在在跟Mesos的社区讨论的时候,我们希望做这种资源的共享和资源的抢占。所谓资源的共享,举一个例子,我们在跟用户去做大数据和long running service两个同时在跑的一个环境里面的时候,对于大数据的机器是预留下来的,Mesos里面用它的动态预留或者静态预留,应该是这部分的机器留在那儿了,因为这部分机器是相对来说比较好的,无论是网络还是存储。大数据跑起来经常会有一些数据的迁移,所以它的网络经常会被压得比较满,再把一些优先级别比较高的应用放在上面网络性能会比较差一点。但大数据的workload又不是时时的占满,经常会有一些空闲,所以也希望它预留下来的这一部分是可以借出去,借给Kubernetes一部分,Kubernetes在上面可以跑,比如跑一些测试,一些build,就跑这些其实优先级并没有那么高的应用,那么从大数据的资源池借来部分resource基本就变成了revocable resources。

但是现在Kubernetes并不支持这件事情,它并没有去描述哪些作业是可以跑在上面、哪些是不能跑在上面。因为借来这个resource也会被高优先级的资源抢占掉,有可能是被杀掉,所以像一些数据库、一些比较重要的Service是不能跑在上面的,因为你会跑一些低优先级的作业,这样只是说有更多的资源可以用。
 
当上面去跑两个framework的时候,你跑Kubernetes和Spark,你会发现它俩之间是需要互相访问一些数据的,有的时候是运行结果,有一些是中间的数据。我们希望可以用地址去寻址,但是Kubernetes的DNS基本上在Spark里面又可以跑,所以你这个时候最希望的是什么?Kubernetes的DNS跟Web的DNS可以通了,可以互相访问。这不光是DNS的事情,包括下面Spark的作业,因为我们在做propose的时候,Spark其实跑在Mesos上了,无论你的Spark master是通过Kubernetes把它拉起来还是自己手动提起来,至少作业的那部分是重头,作业是希望它们可以互相访问的,所以除了DNS可以互通,底层的network也是需要互通的。
 
与Mesos集成这部分是跟resource相关的,因为在Kubernetes里边现在有太多自己的namespace和Quota。Mesos还有一套,有自己的role和 Quota。现在社区里面在做支持一个framework注册多个role,用多个role的身份注册到Mesos上面,还在做层级的role,就像一个树状结构。因为这块有一些需求是这样的,在做部门的时候, Mesos做下层资源管理时,大部分时间你是按部门的层级下来的。现在有很多人在做了,最后就变成部门一下划线,子部门一,然后再下划线,以这种形式做成一个role,但是这种更多的是做成一个tree,而且每个树状结构彼此之间是要再做一层调度的,再做一层DNS的算法调度。

无论如何,现在Mesos还不支持那么多,但是现在Kubernetes自己有一套,Mesos自己也有一套,做起来会比较麻烦,你会发现Mesos给你分配了,有可能Kubernetes限制一下,你就分不出去了;或者说Kubernetes你感觉可以分了,但是你到那边去又调不出来,所以这两个是需要统一的。但统一有一个问题,Kubernetes做这件事情的时候,它并没有认为这些事情应该是需要resourcemanager或者cloud provide参与的,这个事情也是需要在社区propose,它的Quota和namespace需要参考下面的resourcemanager资源分配的那一层。
 
Kubernetes在做scheduler,其实这只是一个特例的case,特例的case是需要有一些加强的,包括Mesos。Kuberneteson Mesos,Kubernetes本身可以有service affinity,包括它自己可以去选择node selector等等功能,但是这些信息Mesos是不知道的,因为Mesos发offer的时候,它只管自己的事,比如说我有两个framework,可能那个资源换过来以后能达到更好的效果,但Mesos不知道这事,所以Mesos这块本身需要加强,Kubernetes需要哪些resource,Mesos应该知道的。分出来了以后,Kubernetes也有一层的调度,如何来更好的做这样的事情。最终会变成Mesos要两层的调度:第一层,Mesos做一层,然后资源调度尽量的分出,尽量大家都匹配好;第二层,再交给Kubernetes去做这样的调度。






图中标红的这部分,现在去下这个包,装下来的时候,你会看到,这个东西它改了,scheduler它改了,它还有一个executor,这个executor下面还有一个minion进程,然后再去起这两个子进程。而Kubernetes也改了,它用下面Kubernetespackage的包来做,不用那个command了,它重新改了command。唯一没改的就是API和proxy。但是当refactor以后,我们希望这两个地方都不要改了,我们真正release的时候只有一个scheduler去做这个资源的交互。只有executor来做这样的事情,其它的事情还是希望走它原来的逻辑来做。
 
这其中对Kubernetes本身是有一些变化的,是需要跟Kubernetes去做这样的事情,因为只有单独这个项目想把它做得那么流畅的话,不太现实。最主要的原因是Kubernetes现在自己并没有完全的去接受,并没有完全去把这个东西做成一个插件。虽然它的scheduler已经把它放到plugin里面,但它现在做得也并不是特别好。在后续的工作里面,借着子社区的建设,我们也会逐渐希望Kubernetes把这个底层的资源调度做得更好,而不是像现在这样所有都攒在一起。Kubernetes在资源管理这一层,资源管理像Mesosresource manager这样的一层,它如果两边都做,不见得能做得那么好。

我们现在做Kubernetes、做上层的时候,更在意的是它的功能。Kubernetes在announce一个新版本的时候,1.4去测10万还是几万请求压力时,它强调的一是请求不停,service不停,它并没有强调资源的调度是否OK。那个只是service的一部分,因为如果在上面加一个Spark、加一个其它的大数据上的东西,Mesos也有问题,Mesos短作业做得特不是别好,性能有时候上不来,你需要把scheduler inverval调得非常低,比如调到五百毫秒以内才可以去用一用,社区也有提这个事。






现在我们在做revocable resource时也有问题,比如Kubernetes跟其它的framework去交互,集成的时候Mesos下面走executor,现在所有的Kubernetes都在一起的,你如果去借了资源的话,你有可能revocable resource和regular resource都放在同一个Kubernetes上跑。但是Mesos为了能够完全清理所有的东西,它杀的时候直接把这东西全杀了,把executor下面所有的东西都杀掉了。当去杀这个revocable resource的时候,你会发现下面有可能顺带的把那些你不想杀的东西都杀掉了,把regular resource杀掉了。

现在我还没有最终的解决方案,办法之一是起两个Kubernetes。但是Kubernetes设计的时候,它希望你一个节点去起一个东西,不要起那么多。revocable resource这块到底该如何做大家可以一起讨论一下,因为Mesos有自己的一套策略,Kubernetes也有自己的策略。我们也在跟Mesos社区提这个事情,要提供一个机制去杀task,如果task执行不了,再去杀executor。但是这个项目貌似并没有特别高的量级,我们也在想办法要么去改Mesos、要么去改Kubernetes,让它把这块做得更好。毕竟如果误杀,整个功能就没有特别大的意义了。其实作业上经常会有混合的形式。
 
现在Kubernetes有这么多namespace,该怎么办?Mesos一直想做multiple role,从去年年底、今年年初design document就已经出来了,但是一直没做。它的功能是把Kubernetes作为一个frameworks,它可以role1、role2、role3这三个role注册到Mesos里面,Mesos里面会根据它自己现有DRF相对三个role来分配资源。往上对应的话,有可能role1就对应namespace1,role2就对应amespace2,role3是amespace3,这样跟Kubernetes就可能对得起来。比如它的Quota是管理文件这些事情,它的资源可以跟Mesos的Quota,上面这两个可以通起来的。






这也是我们一直在想做的事情,Mesos和Kuberentes的统一资源管理,希望它把multiplerole做出来。最后你会发现web interface主要是从Kubernetes进来,比如创建一个interface,Kubernetes里面会有一个interface,下面底层是紧接着Mesos带着一个role,所以所有资源的管理都可以穿得起来。但是现在是变成这样了,Kubernetes是以一个role分到Mesos上面,然后在里面自己再去做。这样其实相当于把资源管理分开了,Kubernetes自己管一层,Mesos自己再管一层,最好还是希望Mesos可以去把整个所有的资源管理都管到一块去。
 







后面是一些细节,一个是scheduler enhancement,因为一旦引入了两级调度,如果还是跟原来一样其实没有任何意义,像K8S service这些事情现在都做得不是很好。Kuberneteson Mesos里面会有很多像like,像constraint,比较像Marathon的一些概念在里边,这并不是一个很好的事情,Kubernetes本身就应该有Kubernetes自己的东西在里面。另一个像对资源的管理和这些Policy,像它动态预留或者静态预留的一些资源,包括它对Quoto的管理,现在也是希望Kubernetes可以去完全支持,而不是自己再来一套。
 
最后,这是需要跟Mesos一起去work的,一旦有了Service,一旦有了node selector,、希望Mesos能够知道这件事情,然后在做调度的时候也考虑这件事情,而不是盲目的分,分完了半天不能用,再还回去,因为想用那个节点有可能别人已经用了。并不是所有人都按套路出牌,说没有这个level就不用了,这个事情需要Mesos来统一控制的。这也是为什么希望有一个资源管理层,可以控制所有的resource。
 
网络这一层,当你去架到大数据架到longrunning framework以后,像DNS、network连接,底层是要把它打通的。否则有很多case无法运行,比如一些Spark的数据要连到K8S里面,它永远是通过K8S ingress resource这些东西往上push。
 
kube-mesos时间表






这是一个大概的时间表,在10月底或者11月初,希望Kuberneteson Mesos在新的code branch可以release版本,延续它之前的版本叫0.7。这个版本大概会留半年到一年。到2016年底、2017年初的时候,计划把refactor这个事情做完,我们现在最主要的事情避免这个项目对Kubernetes本身代码级别的依赖太强,希望通过interface、API搞定这件事情。到2017年的时候,刚才提到的一些主要的feature,像revocable resource以及前期的资源调度,会把它们加进去。

在2017年一季度应该会有一个0.9的release。在2017年最主要做的事情是production,production不是跑两个测试就是production,IBM有一个基于Kubernetes on Mesos的产品,基于产品也会做system test,做一种longivity test,大概一百台机器跑一个月,所以会以产品的形式来release。当它们都做完了以后,我们才会说Kubernetes on Mesos1.0可以上production。那个时候如果大家有兴趣的话可以去试一下,有很多的公司也想把两个不同的workload、公司内部所有的资源统一在一起,上面运行不同的workload。
 
希望大家多到社区贡献,刚开始是有很多讨论都可以把它involve进来,因为到后面项目比较多的时候有可能有一些miss。谢谢大家! 查看全部

今天是数人云容器三国演义Meetup嘉宾演讲实录第四弹。说完了各家容器技术的实战,那么最后来看容器技术的融合——IBM正在探索的一条道路。



我叫马达,名字很好记,挂的title是IBM软件架构师,但我更喜欢下面这个角色: kube-mesos社区负责人;我在Mesos和Kubernetes两个社区都有不同的贡献。国内我是较早一批进入Mesos社区的,2014年开始通过meetup认识了很多技术圈的朋友,后来由于公司的需要就转到了Kubernetes,目前在team里主要做的是Kubernetes on Mesos。
 
很多人对Kuberneteson Mesos有疑问,说这两个东西放在一起到底有没有价值。前段时间有人在微信群里问我是不是为了集成而集成,搞一个噱头,大家一起去玩这个事情。这方面我会讲一下,以及Kuberneteson Mesos现在已经有将近一年没有人维护了,所以现在我们接手以后有很多事情要做,包括后面的很多功能要完善。

kube-mesos历史
 
Kubernetes on Mesos,现在我一般是叫kube-mesos。Kubernetes on Mesos这个项目最早从2014年开始,从Kubernetes刚开始的时候,Mesosphere就投入精力把它们做一个集成。后来Mesosphere出了自己的DC/OS,就不再投入资源了。2015年的时候版本跟得很紧,从0.3一直到0.7十几个release,到了2016年最后一个版本release是0.7.2,到今年的1月份就很少release了。9月,IBM开始接手,因为IBM整个产品都是基于这个Kuberneteson Mesos为基础的。这时IBM把它重新定义成一个孵化器的项目,把它从Kubernetes Github里面拆出来,放到Kubernetes孵化项目里面。

Mesos_Meetup0002.jpg


9月,当我们跑Kuberneteson Mesos这个项目的时候也是得到了很大的支持,现在的Sponsor是Google的Tim,他主要会帮我们一起去review Kubernetes on Mesos后面的roadmap,以及什么时候升级为Kuberentes的顶级项目。现在有一个叫Champion的角色类,Champion这个角色来自红帽的David,他会和我们做一些daily的review,看一下process和一些BUG。这是我们现在在Github上的一个ID,所以现在我主要负责Kubernetes后面的一些roadmap,也希望大家一起去共享这个项目,因为后面有很多非常有意思的项目,不仅要改Kuberntes、Mesos,还有我们一些新的想法。下面是Github的地址 (https://github.com/kubernetes- ... work/ ),到Github可以找到相关的资料。

为什么kube-mesos?

Mesos_Meetup0003.jpg


为什么要做这样一个项目,把两个社区或者两个比较复杂的东西放在一起。大家看一个环境的时候,现在讨论最多的是容器,但真正到一个数据中心或者企业环境,你会发现其中会有各种各样的workload,Kubernetes on Mesos只是其中的一部分。在作业管理和应用管理这一层的话,比如跑大数据会希望用Spark;跑管理容器相关的时候,可以跑一些Kubernetes 、Marathon这样的功能。但这时候是分开的,不同的workload使用不同的框架。再往下一层的时候,这些workload,是可以把资源共享、可以把资源重新抽象出来。

这就是Mesos最开始提的事情,把资源重新抽象出来,抽象出一个资源池,有CPU、有memory。这也是为什么Mesos在描述自己的时候,它会说抽象出一个资源池,在Google的Omega文章里面,它也会提把Mesos定义为第二代调度的策略,两级的调度出来scheduling。Omega这个事,Google还没有实现,所以现在也无人提。

真正说容器、说Docker的时候,最早它只是一个运行环境,每一台机器上一个Docker agent,然后把机器提起来,负责一些起停监控等。我们把资源管理用Mesos抽象出来,上层的应用管理可以放Kubernetes,也可以放Marathon、Spark。一些用户已经搭建了环境,底层是Mesos,上面的容器化是跑Kubernetes,大数据跑Spark。Hadoop那些的话,我们当时是在测试Myriad项目的一些功能,有许多问题和经验,有机会可以聊一下。

Mesos_Meetup0004.jpg


容器基本都在PaaS这一层,IaaS那一层Openstack搞定所有的事情。Paas这一层抽象出来,就是是Mesos上面加Kubernetes,包括上面真正的运行环境加Docker。各个厂商当你做一个完整的solution,统一用户的管理、统一的界面,都是差不多的。做整个流程时,你不希望用户还去在意下面是跑Mesos还是Kubernetes,于是对外最后就把它抽象成业务的一个逻辑和一个业务的描述。

Mesos_Meetup0005.jpg


IBM从1992年的时候开始做自己的产品叫LSF,就是说在九几年的时候像PDS、SGE,早期的HPC, 网络计算基本上都属于这一期的。大家都比较像,workload的管理和资源管理都放在一起了。但等到2003年的时候,资源管理那一层,IBM在做新产品的时候资源管理层又做了一遍,而且是有这样的需求,一些大的银行用户里面LSF和Symphony两个是需要同时跑在一起的,而且由于它们业务上的问题,白天的时候大部分资源给Symphony这个产品,晚上的时候有一部分资源要给LSF,即另外一个产品。
 
中间资源的切换,如果是原来的话,只能去写脚本,把这个cluster一些agent重新提起来放在那边,但是下面如果把这个资源这层重新抽象出来的话,我们内部产品叫EGO,其实跟Mesos非常像,这也是为什么IBM在Mesos有很大的投入。包括我们这边有很多高级调度策略,像刚才说按时间的调度,包括一些资源的分配和资源的共享。
 
从2003年的时候,IBM就开始做这样相应的事情,资源管理是一层,上面的workload pattern是一层。放眼整个开源社区,我们发现Kubernetes对容器的管理这一方面做得更好一点,所以最后选的还是Kuberneteson Mesos整体的架构。当2006年我们在做DCOS类似Paas平台这样一个产品的时候,最终定出来的方案就是说Kubernetes on Mesos。可以看到整个产品的架构从零几年开始做,而且基本验证了至少现在是一个正确的方向。
 
待解决问题

Mesos_Meetup0006.jpg


Kuberneteson Mesos现在将近有一年没有再发布新的版本了,目前有很多问题。第一个,Kubernetes on Mesos这个项目到年底、明年年初最主要做这个项目就是要把整个refactor一下,最主要的原因是现在的Kuberneteson Mesos对Kubernetes的代码依赖非常严重。它集成的时候是把Kubernetes里面很多组件拿过来,在外面再包一下,它是代码级别的改造。我在9月份刚开始接受那个项目的时候,经常会有Kubernetes主干的人告诉我,我们这块有interface变了,你要赶紧去看一下,要不然可能就编译不过,问题是它的改动基本都是内部的interface,其实对我外部的像RESTful API这些东西是不需要变的。所以在这块最主要做的是要把它分离出来,跟Mesos、Kubernetes集成的这些interface和这些接口,我们都希望通过它的RESTful API来做。
 
这部分还有一个更大的topic,11月份的KubeCon与Google在讨论这个事情,Google前两天也有人在做——希望Kubernetes可以提供一种资源管理的功能,无论是它本身提供还是它提供资源管理这一层,希望Spark可以利用这样的一个功能,而不是说Spark再去写,希望做这样的集成。我们也是希望Kubernetes可以更友好的去支持资源管理这一层。基于之前的那些经验,我们会在社区里推动它,至少它对resource manager的支持,不仅仅是对Mesos的支持。因为我知道Horon work也在做Kubernetes on Yarn,就是说这个Yarn也是资源管理这一层,Yarn、Mesos包括我们内部的一些资源管理EGO, 很多都是属于空层这一层,所以Kubernetes把它定位成一个container管理的软件,下面是可以把它完全抽象出来,让它更好的接受资源管理这个东西。
 
就代码级别来看的话,其实Swarm对资源管理层支持得更好,因为它默认自己是需要有资源管理这一层的,它把自身Swarm和内部这个调度都重新写成了一个resources manager资源管理。虽然它没有Mesos强,但是跟Mesos是一样的,所以它很容易就接到Mesos里面去。但Kubernetes现在是不用做这样的事情,它把整个全都揉到一起,所以这在后续的KuberCon,我们也需要更多人去讨论,是希望它能把这个东西得抽象出来,而不是说我们自己再去搞这样的东西。
 
revocable resources在Mesos里面基本上是资源的借入借出。现在的revocable resources,Mesos只支持超频(Oversubscription),这个功能现在只是超频这个部分,但现在在跟Mesos的社区讨论的时候,我们希望做这种资源的共享和资源的抢占。所谓资源的共享,举一个例子,我们在跟用户去做大数据和long running service两个同时在跑的一个环境里面的时候,对于大数据的机器是预留下来的,Mesos里面用它的动态预留或者静态预留,应该是这部分的机器留在那儿了,因为这部分机器是相对来说比较好的,无论是网络还是存储。大数据跑起来经常会有一些数据的迁移,所以它的网络经常会被压得比较满,再把一些优先级别比较高的应用放在上面网络性能会比较差一点。但大数据的workload又不是时时的占满,经常会有一些空闲,所以也希望它预留下来的这一部分是可以借出去,借给Kubernetes一部分,Kubernetes在上面可以跑,比如跑一些测试,一些build,就跑这些其实优先级并没有那么高的应用,那么从大数据的资源池借来部分resource基本就变成了revocable resources。

但是现在Kubernetes并不支持这件事情,它并没有去描述哪些作业是可以跑在上面、哪些是不能跑在上面。因为借来这个resource也会被高优先级的资源抢占掉,有可能是被杀掉,所以像一些数据库、一些比较重要的Service是不能跑在上面的,因为你会跑一些低优先级的作业,这样只是说有更多的资源可以用。
 
当上面去跑两个framework的时候,你跑Kubernetes和Spark,你会发现它俩之间是需要互相访问一些数据的,有的时候是运行结果,有一些是中间的数据。我们希望可以用地址去寻址,但是Kubernetes的DNS基本上在Spark里面又可以跑,所以你这个时候最希望的是什么?Kubernetes的DNS跟Web的DNS可以通了,可以互相访问。这不光是DNS的事情,包括下面Spark的作业,因为我们在做propose的时候,Spark其实跑在Mesos上了,无论你的Spark master是通过Kubernetes把它拉起来还是自己手动提起来,至少作业的那部分是重头,作业是希望它们可以互相访问的,所以除了DNS可以互通,底层的network也是需要互通的。
 
与Mesos集成这部分是跟resource相关的,因为在Kubernetes里边现在有太多自己的namespace和Quota。Mesos还有一套,有自己的role和 Quota。现在社区里面在做支持一个framework注册多个role,用多个role的身份注册到Mesos上面,还在做层级的role,就像一个树状结构。因为这块有一些需求是这样的,在做部门的时候, Mesos做下层资源管理时,大部分时间你是按部门的层级下来的。现在有很多人在做了,最后就变成部门一下划线,子部门一,然后再下划线,以这种形式做成一个role,但是这种更多的是做成一个tree,而且每个树状结构彼此之间是要再做一层调度的,再做一层DNS的算法调度。

无论如何,现在Mesos还不支持那么多,但是现在Kubernetes自己有一套,Mesos自己也有一套,做起来会比较麻烦,你会发现Mesos给你分配了,有可能Kubernetes限制一下,你就分不出去了;或者说Kubernetes你感觉可以分了,但是你到那边去又调不出来,所以这两个是需要统一的。但统一有一个问题,Kubernetes做这件事情的时候,它并没有认为这些事情应该是需要resourcemanager或者cloud provide参与的,这个事情也是需要在社区propose,它的Quota和namespace需要参考下面的resourcemanager资源分配的那一层。
 
Kubernetes在做scheduler,其实这只是一个特例的case,特例的case是需要有一些加强的,包括Mesos。Kuberneteson Mesos,Kubernetes本身可以有service affinity,包括它自己可以去选择node selector等等功能,但是这些信息Mesos是不知道的,因为Mesos发offer的时候,它只管自己的事,比如说我有两个framework,可能那个资源换过来以后能达到更好的效果,但Mesos不知道这事,所以Mesos这块本身需要加强,Kubernetes需要哪些resource,Mesos应该知道的。分出来了以后,Kubernetes也有一层的调度,如何来更好的做这样的事情。最终会变成Mesos要两层的调度:第一层,Mesos做一层,然后资源调度尽量的分出,尽量大家都匹配好;第二层,再交给Kubernetes去做这样的调度。

Mesos_Meetup0007.jpg


图中标红的这部分,现在去下这个包,装下来的时候,你会看到,这个东西它改了,scheduler它改了,它还有一个executor,这个executor下面还有一个minion进程,然后再去起这两个子进程。而Kubernetes也改了,它用下面Kubernetespackage的包来做,不用那个command了,它重新改了command。唯一没改的就是API和proxy。但是当refactor以后,我们希望这两个地方都不要改了,我们真正release的时候只有一个scheduler去做这个资源的交互。只有executor来做这样的事情,其它的事情还是希望走它原来的逻辑来做。
 
这其中对Kubernetes本身是有一些变化的,是需要跟Kubernetes去做这样的事情,因为只有单独这个项目想把它做得那么流畅的话,不太现实。最主要的原因是Kubernetes现在自己并没有完全的去接受,并没有完全去把这个东西做成一个插件。虽然它的scheduler已经把它放到plugin里面,但它现在做得也并不是特别好。在后续的工作里面,借着子社区的建设,我们也会逐渐希望Kubernetes把这个底层的资源调度做得更好,而不是像现在这样所有都攒在一起。Kubernetes在资源管理这一层,资源管理像Mesosresource manager这样的一层,它如果两边都做,不见得能做得那么好。

我们现在做Kubernetes、做上层的时候,更在意的是它的功能。Kubernetes在announce一个新版本的时候,1.4去测10万还是几万请求压力时,它强调的一是请求不停,service不停,它并没有强调资源的调度是否OK。那个只是service的一部分,因为如果在上面加一个Spark、加一个其它的大数据上的东西,Mesos也有问题,Mesos短作业做得特不是别好,性能有时候上不来,你需要把scheduler inverval调得非常低,比如调到五百毫秒以内才可以去用一用,社区也有提这个事。

Mesos_Meetup0008.jpg


现在我们在做revocable resource时也有问题,比如Kubernetes跟其它的framework去交互,集成的时候Mesos下面走executor,现在所有的Kubernetes都在一起的,你如果去借了资源的话,你有可能revocable resource和regular resource都放在同一个Kubernetes上跑。但是Mesos为了能够完全清理所有的东西,它杀的时候直接把这东西全杀了,把executor下面所有的东西都杀掉了。当去杀这个revocable resource的时候,你会发现下面有可能顺带的把那些你不想杀的东西都杀掉了,把regular resource杀掉了。

现在我还没有最终的解决方案,办法之一是起两个Kubernetes。但是Kubernetes设计的时候,它希望你一个节点去起一个东西,不要起那么多。revocable resource这块到底该如何做大家可以一起讨论一下,因为Mesos有自己的一套策略,Kubernetes也有自己的策略。我们也在跟Mesos社区提这个事情,要提供一个机制去杀task,如果task执行不了,再去杀executor。但是这个项目貌似并没有特别高的量级,我们也在想办法要么去改Mesos、要么去改Kubernetes,让它把这块做得更好。毕竟如果误杀,整个功能就没有特别大的意义了。其实作业上经常会有混合的形式。
 
现在Kubernetes有这么多namespace,该怎么办?Mesos一直想做multiple role,从去年年底、今年年初design document就已经出来了,但是一直没做。它的功能是把Kubernetes作为一个frameworks,它可以role1、role2、role3这三个role注册到Mesos里面,Mesos里面会根据它自己现有DRF相对三个role来分配资源。往上对应的话,有可能role1就对应namespace1,role2就对应amespace2,role3是amespace3,这样跟Kubernetes就可能对得起来。比如它的Quota是管理文件这些事情,它的资源可以跟Mesos的Quota,上面这两个可以通起来的。

Mesos_Meetup0009.jpg


这也是我们一直在想做的事情,Mesos和Kuberentes的统一资源管理,希望它把multiplerole做出来。最后你会发现web interface主要是从Kubernetes进来,比如创建一个interface,Kubernetes里面会有一个interface,下面底层是紧接着Mesos带着一个role,所以所有资源的管理都可以穿得起来。但是现在是变成这样了,Kubernetes是以一个role分到Mesos上面,然后在里面自己再去做。这样其实相当于把资源管理分开了,Kubernetes自己管一层,Mesos自己再管一层,最好还是希望Mesos可以去把整个所有的资源管理都管到一块去。
 


Mesos_Meetup0010.jpg


后面是一些细节,一个是scheduler enhancement,因为一旦引入了两级调度,如果还是跟原来一样其实没有任何意义,像K8S service这些事情现在都做得不是很好。Kuberneteson Mesos里面会有很多像like,像constraint,比较像Marathon的一些概念在里边,这并不是一个很好的事情,Kubernetes本身就应该有Kubernetes自己的东西在里面。另一个像对资源的管理和这些Policy,像它动态预留或者静态预留的一些资源,包括它对Quoto的管理,现在也是希望Kubernetes可以去完全支持,而不是自己再来一套。
 
最后,这是需要跟Mesos一起去work的,一旦有了Service,一旦有了node selector,、希望Mesos能够知道这件事情,然后在做调度的时候也考虑这件事情,而不是盲目的分,分完了半天不能用,再还回去,因为想用那个节点有可能别人已经用了。并不是所有人都按套路出牌,说没有这个level就不用了,这个事情需要Mesos来统一控制的。这也是为什么希望有一个资源管理层,可以控制所有的resource。
 
网络这一层,当你去架到大数据架到longrunning framework以后,像DNS、network连接,底层是要把它打通的。否则有很多case无法运行,比如一些Spark的数据要连到K8S里面,它永远是通过K8S ingress resource这些东西往上push。
 
kube-mesos时间表

Mesos_Meetup0011.jpg


这是一个大概的时间表,在10月底或者11月初,希望Kuberneteson Mesos在新的code branch可以release版本,延续它之前的版本叫0.7。这个版本大概会留半年到一年。到2016年底、2017年初的时候,计划把refactor这个事情做完,我们现在最主要的事情避免这个项目对Kubernetes本身代码级别的依赖太强,希望通过interface、API搞定这件事情。到2017年的时候,刚才提到的一些主要的feature,像revocable resource以及前期的资源调度,会把它们加进去。

在2017年一季度应该会有一个0.9的release。在2017年最主要做的事情是production,production不是跑两个测试就是production,IBM有一个基于Kubernetes on Mesos的产品,基于产品也会做system test,做一种longivity test,大概一百台机器跑一个月,所以会以产品的形式来release。当它们都做完了以后,我们才会说Kubernetes on Mesos1.0可以上production。那个时候如果大家有兴趣的话可以去试一下,有很多的公司也想把两个不同的workload、公司内部所有的资源统一在一起,上面运行不同的workload。
 
希望大家多到社区贡献,刚开始是有很多讨论都可以把它involve进来,因为到后面项目比较多的时候有可能有一些miss。谢谢大家!

服务发现bamboo部署在多台slave后,每个bamboo都能发现所有的服务,如何针对发现特定的服务而不是所有服务

yuntui 回复了问题 • 3 人关注 • 2 个回复 • 489 次浏览 • 2016-10-21 21:37 • 来自相关话题

Marathon如何跑docker container -d

xds2000 回复了问题 • 2 人关注 • 1 个回复 • 339 次浏览 • 2016-10-17 16:42 • 来自相关话题

数人云CTO解读Docker 1.12和金融业容器化

宁静胡同 发表了文章 • 0 个评论 • 586 次浏览 • 2016-08-03 10:24 • 来自相关话题

7月29日数人云在上海举办金融沙龙,邀请上交所和近二十家来自银行、保险、证券的IT技术专家一同探讨容器技术在金融业中的最佳实践。数人云CTO肖德时在会上将传统金融行业通过容器可以解决的四大问题做了逐一解读。


以下是演讲实录:

容器技术基本上是2013年出来的,2014年开始在中国传播。在2016年,大家可以感觉到Docker技术的发展加速,在生产环境中也有很多的成功案例。在DockerCon 2016上我们发现,Docker已经从原来的一个工具变成一个真正的生态圈,Docker已经具备整套的解决方案,同时上下游生态也已经非常完备。这都在告诉大家,你能想到的、和你需要的一些最佳实践,Docker基本上都能提供。目前,基本上是大公司在不断的追求Docker的技术,因为小公司用Docker技术解决问题产生的收益比还比较不明显,而大公司原来冗余的架构通过使用Docker确实可以产生效益,所以一些传统企业对Docker会比较关注。

容器技术发展加速

最新的资料显示,现在是应用Docker技术的比较好的时机。全球雇员超过500人的公司中73%已使用Docker技术。国内的很多公司也都在关注这项技术,尤其是金融行业,因为金融业的IT发展的比较成熟,他们对新技术比较关注,Docker已经有很多生产应用在里面产生。
 







用Docker能干什么是大家比较关心的问题。第一个比较常见的场景是DevOps,DevOps实际上就是提高生产力。原来,开发能做运维的事,运维能做开发的事。但实际上从真实的场景里,术业有专攻,在创业公司可以这么干,但传统公司做不了。Docker可以帮助企业进行业务的转型,提供标准的接口,这样开发提供标准运维能知道,运维提供标准开发也能知道。传统企业的开发流程不像创业公司,一个人要干很多事,传统企业强调的是标准化,是业务的转型,而在原有的老的制度下很难实现这种标准,用Docker技术可以加快转型。

第二个场景,云化。2016年云计算开始了新的增长,云计算发展到了新的技术点,老的虚拟化技术已经不能满足企业对动态资源和快速响应的需求,不能起到资源复用的作用。Docker可以应用在物理机上,也可以应用在虚拟机上,可以快速构建应用管理平台,或者构建IaaS、PaaS,或者service都可以。原来部门做不了,因为没有技术栈的改变,仍然要用老设施,那些老设施都是为大企业设计的。但是Docker出来的时候就是为开发者服务的,它是一个工具,一个人也可以做一个私有云。从这个点来看,在云端的转变这个场景里Docker是目前比较推荐的技术栈,它能够快速构建应用管理平台,可以有很好的基础。

另外,用了Docker一定要无状态,这只是表象,以前的应用架构和原来的状态是不是就一定不能满足现在的需求?不是的,原来的单体仍然可以用,为什么要做微服务?因为业务里有多个Function,其中有一个Function是特别热的,这时候怎么能抽出来?最简单的办法就是重构,因为想把它抽出来,抽出来以后,如果没有一些工具怎么做后面的工作?这都是限制问题。Docker公司提供的方案就是用Docker把它包裹一下,成为一个标准的小组件,然后利用分布式的概念,把它scale out,scale out以后再进行后面的工作。在现代的应用中,用了云,资源更容易获得,所以客户想快速地创造一些环境,这些环境里面的资源利用率解决了,但是应用的复杂度仍然存在。如何动态的分配,就是刚才上交所介绍的一些治理的方法。在Modern APP之上会面临一些问题,但是如何快速响应,这个情况是需要一些工具的,这些工具我们认为Docker是可以做到。
 







大背景,之前IOE的架构存在,不是说不好,从技术层面来讲,我并不认为IOE有什么不好,只是我加了一些策略做这件事,它比较拥堵,但不代表它不好。还有“十三五”规划,自主可控的要求,这些背景让企业对开源工具的需求变得会越来越多,数人云这种开源公司也是应势而生,我们给企业提供的解决方案就是自主可控,把开源、透明的技术交给客户。

在2015年,当时去跟客户说我们上一个Docker,人家说你的Docker和VM比有什么好处?VM用的多好,为什么要上Docker?当时我们是无言以对的,因为安全性,还有各种生态圈的工具链也不成熟。但是慢慢的,我们在做这件事的时候发现,其实这是需要和企业一起成长,我们也总结一些步骤。

金融行业拥抱容器四大步
 






总结一下我们想解决的问题,首先,Docker能不能解决快速发布的问题,实际上用Docker以后,管理起来是更复杂的。所以才会有数人云这种PaaS的存在,把复杂的东西用计算机的方式管理,因为用个人的方式是没法管理那么多资源的和实例的;二是原来多套环境相互隔离,客户需要的是多套环境多租户的分发,真正的隔离,因为是内部系统,对于隔离的要求还是可以分级的。环境的快速搭建涉及编排,怎么把DB分成两个,上面分成多个,然后都能访问DB,还有如何将手工操作变成自动的;三是大版本升级回滚,很难做这种升级回滚,怎么去做;四是各种设备,有的CPU,有的是VM,有的在物理机上,这么多设备怎么统一的管理起来。这是我们现实的一些场景,我们怎么解决这些问题是我今天想和大家一起探讨的问题。
 







第一个问题是快速部署,还有缓慢的升级,基本上就是用容器和微服务解。微服务是一个框架,如果把现有的服务拆成微服务,一定是一个统一的架构,那这个架构里面一定是包含这样的元素:首先,一定要有一个API网关的Server,微服务里面的API网关不涉及Nginx,因为Nginx没法动态的改配置,得手动去改,这是满足不了需求的,因为底下的应用无数,所以上面一定要构建自己的API网关,这个网关可以解决所有的问题,要不然下面每个API的服务,它的服务请求SLA都是可以经过网关控制的,这也是新型微服务架构里面经常不被人提起的,被忽略的地方。但是这是非常重要的一点,因为底下的服务特别多。发到集群里,怎么管控这些服务的质量,就是API的请求,出错怎么办,怎么来控制?这些都要通过API网关来控制,所以这个一定要去注意一下。
 







另外是几个大块的认证,如果你的内部认证没有统一的认证,就没法做标准化的双向通行,而且API网关也没有办法给下面的应用下发东西,因为没法认证。还有Configuration server一定要加上,Service Discovery单纯靠容器解决不了,需要PaaS的容器平台解决。做端口、应用的发现,方便其他应用访问它。还有监控、报警,然后就是常规的日志分析,这就是常规的需求。这些需求里面最特殊的就是容器,因为很多个要做逐一监控,没有一个平台是不行的。对日志也是一样,每个容器起来以后就死掉了,怎么知道这个容器是应用呢?一般都是要通过容器的ID来标识,然后收集回来。

还有一个API网关里面最大的特点,快速的熔断,什么意思呢?就是底下的服务很可能出问题。微服务架构里都打散,上面挂一个Nginx,如果业务量大了,如何快速关闭某个API呢?没有可编程的接口是做不到的。但是要采取微服务解决,这个架构的的组织形式就是这样。微服务里面承载的这些组件特别复杂,需要一个标准的组件来封装起来,这个封装组件的方式用Docker是比较合适的。微服务的架构确实可以解决这个问题,因为每个组件的升级很快,如果把整个组件升级一下,还有一些其他的东西,会很麻烦。我们会想到能给一个这样的架构,微服务架构里面统一管理服务。
 







环境之间的隔离,Docker做的目录级别的隔离已经完全可以满足需求了,原来为什么做不到这点?是因为手工的操作特别多,用别的方法隔离也是没有问题的。但是我们觉得,原来的架构里面,CICD的架构已经很成熟了,能不能把它自动化?因为完全可以用Docker来交付整个环境,手工部署没有问题。我们再往前走一步,怎么走?Jenkins可以调一个集群系统,然后分发集群,刚才说的微服务发到这里面,然后快速的部署。这是一个自动化的过程。这里面涉及到一个问题,原来咱们经常会听到的是持续构建,也就是把原码先构建成镜像,然后镜像再发到集群里面,这个操作觉得很顺,但实际上这里面真正的挑战在于,因为每个业务组件的依赖,还有他们之间的配置怎么抽离出来,这都是需要比以前更复杂的。所以,用容器确实解决了持续集成的一部分问题,但它对你的技术要求会越来越高。原来是手工做,而现在需要自动化。对于基础人员的架构改造,其实是抽象层更高一点,对大家的要求也会更高一点。
 







大版本升级不可回滚。大版本的升级困难点在哪儿?原来都是单体服务根本没法拆,动又不能动,刚才说了微服务基本上能够解决它。第二个情况是每个版本的版本控制怎么解决?基本上配置中心可以把配置做出来,然后建仓库,做版本控制。要做这个最好是滚动更新,也就是在不停机的情况下,一点点把业务迁到新的应用上面,然后将老的流量在处理完业务之后慢慢的退掉,这是一种办法。服务的时候,原来指向老的服务进程,自动地切到新的服务进程里面,这样产生流量尽快切到新的服务里面,所以这是需要服务发现的。
 







我们这边会构建一个集群,我们用的ZooKeeper去保证调度器,在正常运行的情况下,我们给Marathon发指令,让它把应用一个一个更新。起一个服务,保证老服务不停机,这时再把域名切换,进来的新流量就到新的应用里面了,老的应用在没有流量的时候自动退出,保证用户访问的时候没有宕机的感觉。这是集群环境里面做升级的常见案例。
 







还有各种异构设备,硬件资源利用率比较低,解法是数人云的应用集群。它是容器的集群,我们的系统会运行在独立的环境里远程控制集群系统,保证系统里面运行的只有容器,然后有相应的Agent来管理应用的服务。
 







这张图比较清晰一点,数人云本身就是微服务的架构,这里面针对的情况,大家都知道Nginx性能是最好的,我们可能在这上面写一个新的API网关对接整个系统,这套系统是数人云系统架构里面的一部分。我们业务管理用Marathon调度器会进行升级,因为Mesos本身是集群管理的调度。对于这些组件,比如镜像,我们采用的方式是跟VMware合作的一个开源项目叫Harbor镜像管理仓库,这是我们和他们一起合作开发的软件。持续集成我们和Jenkins做集成,通过自动配置能够把我们这个小本下发给Jenkins,然后和它构建镜像。监控报警,大家会觉得容器的监控报警不好做,容器目前为止基本上都是接口,现在新的容器把日志和报警,所谓的报警的实现都要按照流程的方式提供API接口,只要接上就收走日志,在本地不落盘。日志也是一样,它现在提供plugin方式和日志系统对接,不用担心落到盘里面收上来是不是把硬盘撑爆,现在都可以配的。这里对于我们现在新加的网络模块,就容器发展到现在其实对于网络都是成熟的,大家都在用host模式去管,虽然容器很轻,但并不比VM先进到哪里去,只是说它更轻量一些。客户希望VM有的东西它也有,这块最后也提供了这种对于IP的管理。所以也是刚刚在上的一种新的成熟架构,也就是说一容器一IP,现在是刚刚才开始支持,这是我们最新配套的。

容器圈新方向预览
 







讲完这些方案之后,今天会有些容器圈的新东西给大家讲讲。

首先是Docker1.12,昨天它正式发布了,这是一个新版本的发布,最重要的发布。这个发布先是内置了自己的工具,再就是对网络的增强,达到了更容易商用的阶段。第二个是我们现在用的Mesos,也发布了1.0,可以给大家介绍一下特性。
 







Docker1.12它有一个重要的特点,一般在集群系统里面,因为容器是很碎的,用户希望知道这个服务到底是run还是不run,原来的方式是Docker run的时候把端口打开,然后通过一个脚本去查。这等于是第三方去做,现在提供的功能是可以在构建镜像的时候就把Healthcheck打开,通过Docker Daemon的内容给这台主机上运行的容器定期的检查,通过Docker知道这个容器是不是健康的。当然这个功能并不是为咱们准备的,是为自己内置的Swarm编排工具做准备的,因为Docker公司做集群管理的工具也在想这个事情。还有一个情况是咱们最常用的CentOS系列,原来对于安全Docker公司一直在回避,它现在默认把这个组件打开了,打开以后跑出来更安全。Linux可以打标签、做监控,但是这个东西因为刚出来,所以只是一个信号,也就是Docker越来越安全了,原来是做不到,现在是越来越方便了,可以做到这样。Docker内置了一个IPVS,干什么用?就是想替代HaProxy提供IP给网络里面。这是比较新的技术,目前我们认为处于实验阶段,它利用IPVS的模块来提供网络的接口,只是一个信号,目前是没有采用这种方案的,因为太新了,还要测试。最后是内置Swarm的组件,这是很轻量的编排工具,也就是说装几台机器,必须要组成一个网,怎么去做?可以用Swarm做这个事。这个网IP怎么做,用IPVS,这就是最新的Docker的发展,非常快。
 







目前为止,一容器一IP技术理论已经落地。每台机器要装一个小的路由器,然后小路由器给你的容器。这个路由器可以想象成家里的无线路由器,因为是个屋子,一台主机里面都有屋子,任何终端设备都可以向路由器调IP,这个IP是假的都可以。当然Docker里面现在有了网络的插件,就相当于类似有了一个驱动,就可以找路由器要一个IP,实现了路由器有IP。大家注意到这个IP和底下的IP不一样,他们之间通过IPtable 做包头的转换,通过转换就可以双向通信了。但是这里面192.168的网段和10网段的管控,如果只做一次转发,那就控制不了这些IP之间的东西,我们用的方案把这些规则都记录在一个键值库里面,这样的好处在于,可以控制这个IP和这个IP的通信,把它记录下来就可以了,如果删掉,默认不让它通信也是可以的。虽然一台主机有三台服务器,但是他们之间是否能通信是你可以控制的,这样更安全。也就是说,用户有一个应用,这个应用是1.1和0.9,放在这两个容器上,然后1.10是另外一个APP,不希望他们之间互相通信就可以通过IPtable写进去,然后把他们隔开,他们通信的时候,一看规则没有就把他们删掉了,路由器就不会给它分。

还有一个情况,都是容器里面的IP,那外网的IP之间能不能通信?因为内网有一个路由器,路由器给它分了一个IP,也想给容器分一个同样网段的IP,需要一个网关来转换为可用的IP,转换给它,就是改包头改完包头转进去。它请求的时候再转出去,两个路由器之间再转一下,是这样的过程。它有一个缺点,就是主机的数量不能太大,毕竟是虚拟的IP网络,主机的数量不是容器的数量,基本上在200台左右是一个推荐的方式。
 







性能对比,跟主机、物理机再和calico的解决方案对比,基本上会在1024、2048、4096这块,如果用普通的overlay方案性能就很低,目前Docker overlay自己的原生方案性能就很低,但是它在提升,因为它刚刚出来。上面这套方案,因为calico的方案只是在包的包头上做了篡改,欺骗主机转发数据包,所以它的性能和host主机之间,有时候从数据表里面看到它传输的效率,吞吐量比host还快,但是这个数有假像,因为改了包头,但是基本上可以肯定,和原生的host的网卡里面性能是差不多的,是这样的情况。
 






最后说Mesos现在新产品,就是1.0技术开源的组件,1.0以后,我们基本上就会有新的HTTP API,原来的API都是Google的协议,现在有新的HTTP API更方便数人云和它做深度整合,我们也希望不断的前进,给客户提供更好的产品。第二个情况,大家现在遇到的情况,那就是Docker有各种各样的bug,这个问题没有很好的解决办法,因为Docker公司的产品是开源的,它的商业产品也到不了中国。Mesos解决了这个问题,Mesos拥有给Twitter、苹果等都部署过几万台的节点的经验。他发现安装Docker Daemon以后,Docker是很不稳定的,尤其在大规模集群方面很不稳定,所以他们推荐另外一个方式,就是用原生的容器框架解包镜像。客户在本地用Docker,但是把镜像发给我,我用另外的方式把这种镜像给起起来,用户是透明的,就认为它是Docker room,但它不用了Docker Daemon,因为把Docker Daemon关掉以后容器就死掉了,但是把Docker Daemon去掉以后,容器还要通过原生的方式运行起来,这就满足了企业的各种需求,这是新的技术点。还有云原生APP架构里面,对于网络需要一个标准,现在提供了一个类似的架构,Mesos提供了这个标准。另外就是支持GPU。还有Mesos在和微软合作,开始接管Windows的一些信息,这也是比较大的亮点。这个生态圈还是比较活跃的,这也是数人云关注和考虑的。 查看全部
7月29日数人云在上海举办金融沙龙,邀请上交所和近二十家来自银行、保险、证券的IT技术专家一同探讨容器技术在金融业中的最佳实践。数人云CTO肖德时在会上将传统金融行业通过容器可以解决的四大问题做了逐一解读。


以下是演讲实录:

容器技术基本上是2013年出来的,2014年开始在中国传播。在2016年,大家可以感觉到Docker技术的发展加速,在生产环境中也有很多的成功案例。在DockerCon 2016上我们发现,Docker已经从原来的一个工具变成一个真正的生态圈,Docker已经具备整套的解决方案,同时上下游生态也已经非常完备。这都在告诉大家,你能想到的、和你需要的一些最佳实践,Docker基本上都能提供。目前,基本上是大公司在不断的追求Docker的技术,因为小公司用Docker技术解决问题产生的收益比还比较不明显,而大公司原来冗余的架构通过使用Docker确实可以产生效益,所以一些传统企业对Docker会比较关注。

容器技术发展加速

最新的资料显示,现在是应用Docker技术的比较好的时机。全球雇员超过500人的公司中73%已使用Docker技术。国内的很多公司也都在关注这项技术,尤其是金融行业,因为金融业的IT发展的比较成熟,他们对新技术比较关注,Docker已经有很多生产应用在里面产生。
 


1.png


用Docker能干什么是大家比较关心的问题。第一个比较常见的场景是DevOps,DevOps实际上就是提高生产力。原来,开发能做运维的事,运维能做开发的事。但实际上从真实的场景里,术业有专攻,在创业公司可以这么干,但传统公司做不了。Docker可以帮助企业进行业务的转型,提供标准的接口,这样开发提供标准运维能知道,运维提供标准开发也能知道。传统企业的开发流程不像创业公司,一个人要干很多事,传统企业强调的是标准化,是业务的转型,而在原有的老的制度下很难实现这种标准,用Docker技术可以加快转型。

第二个场景,云化。2016年云计算开始了新的增长,云计算发展到了新的技术点,老的虚拟化技术已经不能满足企业对动态资源和快速响应的需求,不能起到资源复用的作用。Docker可以应用在物理机上,也可以应用在虚拟机上,可以快速构建应用管理平台,或者构建IaaS、PaaS,或者service都可以。原来部门做不了,因为没有技术栈的改变,仍然要用老设施,那些老设施都是为大企业设计的。但是Docker出来的时候就是为开发者服务的,它是一个工具,一个人也可以做一个私有云。从这个点来看,在云端的转变这个场景里Docker是目前比较推荐的技术栈,它能够快速构建应用管理平台,可以有很好的基础。

另外,用了Docker一定要无状态,这只是表象,以前的应用架构和原来的状态是不是就一定不能满足现在的需求?不是的,原来的单体仍然可以用,为什么要做微服务?因为业务里有多个Function,其中有一个Function是特别热的,这时候怎么能抽出来?最简单的办法就是重构,因为想把它抽出来,抽出来以后,如果没有一些工具怎么做后面的工作?这都是限制问题。Docker公司提供的方案就是用Docker把它包裹一下,成为一个标准的小组件,然后利用分布式的概念,把它scale out,scale out以后再进行后面的工作。在现代的应用中,用了云,资源更容易获得,所以客户想快速地创造一些环境,这些环境里面的资源利用率解决了,但是应用的复杂度仍然存在。如何动态的分配,就是刚才上交所介绍的一些治理的方法。在Modern APP之上会面临一些问题,但是如何快速响应,这个情况是需要一些工具的,这些工具我们认为Docker是可以做到。
 


2.png


大背景,之前IOE的架构存在,不是说不好,从技术层面来讲,我并不认为IOE有什么不好,只是我加了一些策略做这件事,它比较拥堵,但不代表它不好。还有“十三五”规划,自主可控的要求,这些背景让企业对开源工具的需求变得会越来越多,数人云这种开源公司也是应势而生,我们给企业提供的解决方案就是自主可控,把开源、透明的技术交给客户。

在2015年,当时去跟客户说我们上一个Docker,人家说你的Docker和VM比有什么好处?VM用的多好,为什么要上Docker?当时我们是无言以对的,因为安全性,还有各种生态圈的工具链也不成熟。但是慢慢的,我们在做这件事的时候发现,其实这是需要和企业一起成长,我们也总结一些步骤。

金融行业拥抱容器四大步
 

3.png


总结一下我们想解决的问题,首先,Docker能不能解决快速发布的问题,实际上用Docker以后,管理起来是更复杂的。所以才会有数人云这种PaaS的存在,把复杂的东西用计算机的方式管理,因为用个人的方式是没法管理那么多资源的和实例的;二是原来多套环境相互隔离,客户需要的是多套环境多租户的分发,真正的隔离,因为是内部系统,对于隔离的要求还是可以分级的。环境的快速搭建涉及编排,怎么把DB分成两个,上面分成多个,然后都能访问DB,还有如何将手工操作变成自动的;三是大版本升级回滚,很难做这种升级回滚,怎么去做;四是各种设备,有的CPU,有的是VM,有的在物理机上,这么多设备怎么统一的管理起来。这是我们现实的一些场景,我们怎么解决这些问题是我今天想和大家一起探讨的问题。
 


4.png


第一个问题是快速部署,还有缓慢的升级,基本上就是用容器和微服务解。微服务是一个框架,如果把现有的服务拆成微服务,一定是一个统一的架构,那这个架构里面一定是包含这样的元素:首先,一定要有一个API网关的Server,微服务里面的API网关不涉及Nginx,因为Nginx没法动态的改配置,得手动去改,这是满足不了需求的,因为底下的应用无数,所以上面一定要构建自己的API网关,这个网关可以解决所有的问题,要不然下面每个API的服务,它的服务请求SLA都是可以经过网关控制的,这也是新型微服务架构里面经常不被人提起的,被忽略的地方。但是这是非常重要的一点,因为底下的服务特别多。发到集群里,怎么管控这些服务的质量,就是API的请求,出错怎么办,怎么来控制?这些都要通过API网关来控制,所以这个一定要去注意一下。
 


5.png


另外是几个大块的认证,如果你的内部认证没有统一的认证,就没法做标准化的双向通行,而且API网关也没有办法给下面的应用下发东西,因为没法认证。还有Configuration server一定要加上,Service Discovery单纯靠容器解决不了,需要PaaS的容器平台解决。做端口、应用的发现,方便其他应用访问它。还有监控、报警,然后就是常规的日志分析,这就是常规的需求。这些需求里面最特殊的就是容器,因为很多个要做逐一监控,没有一个平台是不行的。对日志也是一样,每个容器起来以后就死掉了,怎么知道这个容器是应用呢?一般都是要通过容器的ID来标识,然后收集回来。

还有一个API网关里面最大的特点,快速的熔断,什么意思呢?就是底下的服务很可能出问题。微服务架构里都打散,上面挂一个Nginx,如果业务量大了,如何快速关闭某个API呢?没有可编程的接口是做不到的。但是要采取微服务解决,这个架构的的组织形式就是这样。微服务里面承载的这些组件特别复杂,需要一个标准的组件来封装起来,这个封装组件的方式用Docker是比较合适的。微服务的架构确实可以解决这个问题,因为每个组件的升级很快,如果把整个组件升级一下,还有一些其他的东西,会很麻烦。我们会想到能给一个这样的架构,微服务架构里面统一管理服务。
 


6.png


环境之间的隔离,Docker做的目录级别的隔离已经完全可以满足需求了,原来为什么做不到这点?是因为手工的操作特别多,用别的方法隔离也是没有问题的。但是我们觉得,原来的架构里面,CICD的架构已经很成熟了,能不能把它自动化?因为完全可以用Docker来交付整个环境,手工部署没有问题。我们再往前走一步,怎么走?Jenkins可以调一个集群系统,然后分发集群,刚才说的微服务发到这里面,然后快速的部署。这是一个自动化的过程。这里面涉及到一个问题,原来咱们经常会听到的是持续构建,也就是把原码先构建成镜像,然后镜像再发到集群里面,这个操作觉得很顺,但实际上这里面真正的挑战在于,因为每个业务组件的依赖,还有他们之间的配置怎么抽离出来,这都是需要比以前更复杂的。所以,用容器确实解决了持续集成的一部分问题,但它对你的技术要求会越来越高。原来是手工做,而现在需要自动化。对于基础人员的架构改造,其实是抽象层更高一点,对大家的要求也会更高一点。
 


7.png


大版本升级不可回滚。大版本的升级困难点在哪儿?原来都是单体服务根本没法拆,动又不能动,刚才说了微服务基本上能够解决它。第二个情况是每个版本的版本控制怎么解决?基本上配置中心可以把配置做出来,然后建仓库,做版本控制。要做这个最好是滚动更新,也就是在不停机的情况下,一点点把业务迁到新的应用上面,然后将老的流量在处理完业务之后慢慢的退掉,这是一种办法。服务的时候,原来指向老的服务进程,自动地切到新的服务进程里面,这样产生流量尽快切到新的服务里面,所以这是需要服务发现的。
 


8.png


我们这边会构建一个集群,我们用的ZooKeeper去保证调度器,在正常运行的情况下,我们给Marathon发指令,让它把应用一个一个更新。起一个服务,保证老服务不停机,这时再把域名切换,进来的新流量就到新的应用里面了,老的应用在没有流量的时候自动退出,保证用户访问的时候没有宕机的感觉。这是集群环境里面做升级的常见案例。
 


9.png


还有各种异构设备,硬件资源利用率比较低,解法是数人云的应用集群。它是容器的集群,我们的系统会运行在独立的环境里远程控制集群系统,保证系统里面运行的只有容器,然后有相应的Agent来管理应用的服务。
 


10.png


这张图比较清晰一点,数人云本身就是微服务的架构,这里面针对的情况,大家都知道Nginx性能是最好的,我们可能在这上面写一个新的API网关对接整个系统,这套系统是数人云系统架构里面的一部分。我们业务管理用Marathon调度器会进行升级,因为Mesos本身是集群管理的调度。对于这些组件,比如镜像,我们采用的方式是跟VMware合作的一个开源项目叫Harbor镜像管理仓库,这是我们和他们一起合作开发的软件。持续集成我们和Jenkins做集成,通过自动配置能够把我们这个小本下发给Jenkins,然后和它构建镜像。监控报警,大家会觉得容器的监控报警不好做,容器目前为止基本上都是接口,现在新的容器把日志和报警,所谓的报警的实现都要按照流程的方式提供API接口,只要接上就收走日志,在本地不落盘。日志也是一样,它现在提供plugin方式和日志系统对接,不用担心落到盘里面收上来是不是把硬盘撑爆,现在都可以配的。这里对于我们现在新加的网络模块,就容器发展到现在其实对于网络都是成熟的,大家都在用host模式去管,虽然容器很轻,但并不比VM先进到哪里去,只是说它更轻量一些。客户希望VM有的东西它也有,这块最后也提供了这种对于IP的管理。所以也是刚刚在上的一种新的成熟架构,也就是说一容器一IP,现在是刚刚才开始支持,这是我们最新配套的。

容器圈新方向预览
 


17.png


讲完这些方案之后,今天会有些容器圈的新东西给大家讲讲。

首先是Docker1.12,昨天它正式发布了,这是一个新版本的发布,最重要的发布。这个发布先是内置了自己的工具,再就是对网络的增强,达到了更容易商用的阶段。第二个是我们现在用的Mesos,也发布了1.0,可以给大家介绍一下特性。
 


18.png


Docker1.12它有一个重要的特点,一般在集群系统里面,因为容器是很碎的,用户希望知道这个服务到底是run还是不run,原来的方式是Docker run的时候把端口打开,然后通过一个脚本去查。这等于是第三方去做,现在提供的功能是可以在构建镜像的时候就把Healthcheck打开,通过Docker Daemon的内容给这台主机上运行的容器定期的检查,通过Docker知道这个容器是不是健康的。当然这个功能并不是为咱们准备的,是为自己内置的Swarm编排工具做准备的,因为Docker公司做集群管理的工具也在想这个事情。还有一个情况是咱们最常用的CentOS系列,原来对于安全Docker公司一直在回避,它现在默认把这个组件打开了,打开以后跑出来更安全。Linux可以打标签、做监控,但是这个东西因为刚出来,所以只是一个信号,也就是Docker越来越安全了,原来是做不到,现在是越来越方便了,可以做到这样。Docker内置了一个IPVS,干什么用?就是想替代HaProxy提供IP给网络里面。这是比较新的技术,目前我们认为处于实验阶段,它利用IPVS的模块来提供网络的接口,只是一个信号,目前是没有采用这种方案的,因为太新了,还要测试。最后是内置Swarm的组件,这是很轻量的编排工具,也就是说装几台机器,必须要组成一个网,怎么去做?可以用Swarm做这个事。这个网IP怎么做,用IPVS,这就是最新的Docker的发展,非常快。
 


19.png


目前为止,一容器一IP技术理论已经落地。每台机器要装一个小的路由器,然后小路由器给你的容器。这个路由器可以想象成家里的无线路由器,因为是个屋子,一台主机里面都有屋子,任何终端设备都可以向路由器调IP,这个IP是假的都可以。当然Docker里面现在有了网络的插件,就相当于类似有了一个驱动,就可以找路由器要一个IP,实现了路由器有IP。大家注意到这个IP和底下的IP不一样,他们之间通过IPtable 做包头的转换,通过转换就可以双向通信了。但是这里面192.168的网段和10网段的管控,如果只做一次转发,那就控制不了这些IP之间的东西,我们用的方案把这些规则都记录在一个键值库里面,这样的好处在于,可以控制这个IP和这个IP的通信,把它记录下来就可以了,如果删掉,默认不让它通信也是可以的。虽然一台主机有三台服务器,但是他们之间是否能通信是你可以控制的,这样更安全。也就是说,用户有一个应用,这个应用是1.1和0.9,放在这两个容器上,然后1.10是另外一个APP,不希望他们之间互相通信就可以通过IPtable写进去,然后把他们隔开,他们通信的时候,一看规则没有就把他们删掉了,路由器就不会给它分。

还有一个情况,都是容器里面的IP,那外网的IP之间能不能通信?因为内网有一个路由器,路由器给它分了一个IP,也想给容器分一个同样网段的IP,需要一个网关来转换为可用的IP,转换给它,就是改包头改完包头转进去。它请求的时候再转出去,两个路由器之间再转一下,是这样的过程。它有一个缺点,就是主机的数量不能太大,毕竟是虚拟的IP网络,主机的数量不是容器的数量,基本上在200台左右是一个推荐的方式。
 


20.png


性能对比,跟主机、物理机再和calico的解决方案对比,基本上会在1024、2048、4096这块,如果用普通的overlay方案性能就很低,目前Docker overlay自己的原生方案性能就很低,但是它在提升,因为它刚刚出来。上面这套方案,因为calico的方案只是在包的包头上做了篡改,欺骗主机转发数据包,所以它的性能和host主机之间,有时候从数据表里面看到它传输的效率,吞吐量比host还快,但是这个数有假像,因为改了包头,但是基本上可以肯定,和原生的host的网卡里面性能是差不多的,是这样的情况。
 

21.png


最后说Mesos现在新产品,就是1.0技术开源的组件,1.0以后,我们基本上就会有新的HTTP API,原来的API都是Google的协议,现在有新的HTTP API更方便数人云和它做深度整合,我们也希望不断的前进,给客户提供更好的产品。第二个情况,大家现在遇到的情况,那就是Docker有各种各样的bug,这个问题没有很好的解决办法,因为Docker公司的产品是开源的,它的商业产品也到不了中国。Mesos解决了这个问题,Mesos拥有给Twitter、苹果等都部署过几万台的节点的经验。他发现安装Docker Daemon以后,Docker是很不稳定的,尤其在大规模集群方面很不稳定,所以他们推荐另外一个方式,就是用原生的容器框架解包镜像。客户在本地用Docker,但是把镜像发给我,我用另外的方式把这种镜像给起起来,用户是透明的,就认为它是Docker room,但它不用了Docker Daemon,因为把Docker Daemon关掉以后容器就死掉了,但是把Docker Daemon去掉以后,容器还要通过原生的方式运行起来,这就满足了企业的各种需求,这是新的技术点。还有云原生APP架构里面,对于网络需要一个标准,现在提供了一个类似的架构,Mesos提供了这个标准。另外就是支持GPU。还有Mesos在和微软合作,开始接管Windows的一些信息,这也是比较大的亮点。这个生态圈还是比较活跃的,这也是数人云关注和考虑的。

攻克微服务的最大难关:用户数据

宁静胡同 发表了文章 • 0 个评论 • 578 次浏览 • 2016-07-27 11:19 • 来自相关话题

今天数人云与大家分享的文章将探讨微服务架构的创建与开发工作当中最为困难的部分——用户数据。

只有我们摆脱自己的依赖时微服务才能起作用,换言之,存在于单一数据库上的多任务进程并不是真正的微服务。使用Spring Boot/Dropwizard/Docker并不代表大家所构建的就是微服务。再次强调,大家需要着眼于所处业务领域,而我们的数据才是实现微服务的关键所在。


考虑到我们正在着手尝试建立微服务架构,因此其中最重要的目标就是保证团队有能力以影响最低的方式通过不同速度对系统中的不同组件进行分别处理。因此,我们希望整个团队拥有自主性,能够找到最理想的实施手段并运行自己的服务,同时自由地根据业务需要做出快速变更。如果我们的团队能够满足这些既定要求,那么系统架构也将对应发生变化,即真正向微服务时代迈进。


为了实现这种自主性,我们需要“摆脱依赖性”,但这项目标显然是说着容易做起来难。我曾见证过无数从业者将微服务概念简单理解为“每项微服务都应该拥有并控制自己的数据库,且任意两项服务不应共享同一套数据库”。这样的理解非常合理,因为只要严格遵循上述要求,我们就不会遭遇由跨服务共享数据库所带来的读/写模式、数据模型冲突以及协调挑战等等。然而,单一数据库的实现方式也确实拥有诸多安全与便利性优势:ACID事务、着眼点单一、易于理解、单点管理等等。那么在构建微服务时,我们该如何顺利将单一数据库拆分成多套规模较小的数据库?


下面让我们共同找出答案。首先,对于一家有意构建微服务的“企业”,我们需要明确以下几个问题:


• 立足怎样的业务领域?现实情况又是如何?

• 事务边界在哪里?

• 微服务应当如何在不同边界之间实现通信?

• 我们将数据库剥离出来会造成怎样的影响?


立足怎样的业务领域?


这个问题往往受到人们的忽视,但必须承认微服务实践在互联网企业与传统企业当中往往存在着巨大差异(而这种忽视也是造成项目失败的主要原因之一)。


在构建微服务架构以及确定相关数据使用理由(例如用于生产/消费等)之前,我们首先要对数据的含义拥有清晰而正确的认识。举例一个团购网站,在我们将信息存储在与“预订”相关的数据库并把其进一步迁移至微服务之前,我们先要理解“预订是什么”。就像在HR领域一样,大家可能还需要了解“帐户”、“员工”以及“索赔”等相关定义。


为了实现这一目标,我们需要立足于现实回答更多关于理解的问题。例如,“书是什么?”虽然这个例子非常简单,但却能够很好地反映实际工作中的概念理解过程。因此,思考书的定义,而后为其设计合适的数据模型。


书是由不同分页所构成吗?报纸算不算书籍?因为其同样拥有分页结构。那么书籍是否拥有硬质封面?或者代表的是每天定期出版的各种刊物?如果我本人撰写了一部书籍,出版商可能只会在作者名下列出单一条目。但如果某家书店在出售五本由我撰写的书籍,那么这些书是彼此不同还是同一本书的多份副本?我们该如何表示这种关系?如果书籍内容过长,被拆分成了多个分卷又该如何处理?每部分是否也应算是独立的书籍?又或者全部分卷加起来才算一本书?众多细小部分组合起来应该如何处理?由此组成的整体算不算是书籍?又或者每个部分都属于书籍?最后再提出一种比较复杂的假设,我出版了一本书,书店中摆着大量同样内容的印本,而每种印本又分为多个分卷。在这种情况下,我们该如何定义“书”的概念?


现实情况是,并不存在这样确切的定义。“书是什么”这个问题没有一个绝对的概念,因此我们在回答之前需要了解“谁在提问以及上下文背景是什么。”换言之,即如今的上下文为王概念。我们人类能够快速(甚至是无意识地)解决这种认识模糊性问题,因为我们头脑中存在着上下文背景,其中涵盖环境与问题本身。但计算机显然缺乏这种认知基础。我们需要在构建软件与建立数据模型时,为其指定相关上下文。用书的概念可以让这样的理解过程变得更为明确。我们所处的业务领域(或者说企业指向)拥有其帐户、客户、预订、索赔等事务,其概念显示更加复杂且易产生冲突/模糊性。因此,我们需要为其设定明确的边界。


那么新的问题来了,我们该如何绘制这些边界?为了实现对所在领域的建模,我们需要对实体、值对象以及聚合等概念设定上下文。换言之,我们借此建立并完善整套代表所在业务领域的模型,该模型包含上下文中关于边界的各项定义。这种明确的边界最终将成为我们的微服务,或者作为微服务的边界内组件,抑或二者兼有。无论如何,微服务的核心在于边界,DDD(即业务驱动型设计)亦是如此。

 





我们的数据模型(即希望如何表现物理数据存储中的概念——注意其中的明确区别)受到业务领域模型的驱动,而非前者驱动后者。在设定了边界之后,我们将能够识别模型当中“正确”与不正确的部分。这些边界同时也能够实现一定程度的自主性。为上下文“A”指定一个与上下文“B”不同的“书籍”定义(例如将上下文‘A’设定为一项搜索服务,负责搜索标题被指定为‘书’的条目; 而上下文‘B’则为检查服务,负责根据书籍总量(即标题加副本)处理事务)。


在这里,大家可能会提出质疑:“等等,Netflix、Twitter或者领英并没有给出过任何关于业务驱动设计的说明。为什么我要遵循所谓DDD原则?”下面一起来看原因:


 “人们都希望复制Netflix,但却只能复制到其表象。他们复制到的只是结果,而并非过程”——Netflix公司前任首席云架构师Adrian Cockcroft


迈向微服务的旅程就是这么一段……旅程。每一家企业都拥有自己需要克服的坎坷与艰辛。其中并不存在任何固定或者便捷的规则,而只有权衡与取舍。复制某家企业的成功作法并不足以帮助我们同样顺利地完成这一流程/旅程,其甚至可能根本无法奏效。另外,也正是这样的思路才让我们的企业无法成为Netflix。事实上,我一直认为无论Netflix的领域复杂性有多么可怕,其仍然无法与传统企业面临的难题相提并论。搜索并显示影片、发布推文、更新领英动态等等绝对要比保障索赔处理系统简单得多。这些互联网企业之所以能够快速迎接微服务,是因为其需要出色的产品上市速度并应对批量/规模化负载(向Twitter发布一条推文非常简单,但面向5亿用户发布推文并显示内容则非常复杂)。如今的企业将不得不同时面临来自领域与规模两个层面的复杂性挑战。因此,我们在这段转型旅程当中必须在领域、规模以及组织变更之间做出权衡。每家企业都面临着不同的难题,而这也必须成为我们的关注重点。


事务边界是什么?


重新回到我们的主要议题上来。我们需要利用业务驱动设计等手段帮助自身理解用于实现系统的模型,同时在单一上下文当中围绕这些模型绘制边界。因此,我们需要将客户、帐户、预订等事务视为被绑定至不同上下文的不同事物,但最终亦需要立足于同一架构对这些相关概念进行分发,并在发生变更时调和这些模型所受到的具体影响。我们需要将这些情况全部纳入考量,但首先确立事务边界无疑是最为重要的前提。


遗憾的是,作为开发者的我们似乎仍然在以完全错误的方式进行分布式系统构建:我们仍然遵循着单一、孤立的关系型ACID数据库思路作为指导方针。我们还忽略了异步且可靠性较低的网络环境可能带来的风险。要知道,编写框架这类工作并不要求从业者对网络(包括RPC框架——数据库抽象方案亦严重忽略了网络因素)有多么了解,这意味着多数人都倾向于或者只知道如何利用点到点同步调用一切(包括REST、SOAP以及对象序列化RPC库等其它CORBA)。我们构建的系统没有考虑到授权与自主间的平衡,而且最终往往只能依靠覆盖众多独立服务的两段式提交方式解决数据分发问题。或者,我们彻底忽略了以上各项要求。由此建立起的系统扩展性极差且相当脆弱——即使我们非要将其称为SOA、微服务乃至迷你服务等等,其仍然不具备此类架构真正需要拥有的特性与优势。


那么我们到底该如何理解事务边界?我将其理解为业务常量当中最小的基本单位。无论大家是利用数据库的ACID属性以实现这种基础性,抑或是选择二段式提交,其实都无关紧要。真正的重点在于,我们希望尽可能缩小这些事务边界(在理想状态下,应该是单一事务对应单一对象),从而确保其可扩展能力。当我们建立自己的业务领域模型时,使用DDD技术以明确实体、值对象与聚合。在此上下文当中,聚合代表的是那些包含其它实体/值对象的对象,负责执行不变量(单一有界上下文当中可包含多组聚合)。


举例来说,让我们设定以下几种用例:


• “允许客户搜索航班信息。”

• “允许客户在特定航班中选择座位。”

• “允许客户预订航班。”


我们在这里可以设置三种有界上下文:搜索、预订与票务(当然,我们也可以设置更多相关上下文,包括支付、忠诚度、待机、升舱等,但这里我们就只强调这三种)。搜索负责显示特定路线以及与给定时间相符的航班选项。预订则负责利用客户信息建立预订流程(包括姓名、地址、会员编号等)、座位偏好以及支付信息。票务将负责与航空公司沟通并完成机票签发。在各有界上下文当中,我们都需要确定事务边界以执行约束/恒量。我们不需要在有界上下文当中考虑基本事务(亦称为原子事务,我们将在下一章节中对此进行详尽说明)。


那么我们要如何在建模时允许考虑最小事务边界(在本示例中,其应被简化为航班预订流程)?也许设置一套“航班”聚合是不错的作法,其中可以囊括时间、日期、路线以及客户、机型以及预订等实体条目?听起来很有搞头,其中单一航班拥有具体的机型、座位、客户与预订条目。航班聚合负责在预订创建过程中追踪机型及座位等信息。在这种情况下,我们可以选择在数据库当中建立一套数据模型(这是一种标准的关系模型,其中包含约束与外键等),或者在源代码中生成一套对象模型(继承/组合),下面我们看看具体作法会带来怎样的变数。

 







在利用预订、机型以及航班等信息创建一条预订时,其中是否真的存在恒量?换言之,如果我们向航班聚合当中新增一种机型信息,那么我们是否真的应当将客户与预订包含在该事务当中?答案恐怕是否定的。我们在这里需要考虑的是如何利用可组合数据模型建立聚合。然而,这样的事务边界太过庞大。如果我们面对着大量航班、座位与预订信息的变更,则可能出现众多事务冲突。而且这种作法显然不具备可扩展性(而且一次航班计划变更就会带来大量订单失败,从而造成糟糕的客户体验)。


那么我们显然需要把事务边界设定得更小一点。


也许预订、可选座位以及航班三者自有拥有自己的独立聚合。一条预订当中可包含客户信息、偏好以及可能的支付信息。可用座位聚合则包含有机型与内部配置。航班聚合由日程安排与路线构成,等我们能够在不影响航班规划以及机型/可用座位等事务的前提下,随时调整预订内容。从领域的角度来看,我们希望实现这样的效果。我们不需要在机型/航班/预订之间实现100%的严格一致,而是希望确保管理员能够正确记录航班规划变更、供应商正确提供机型配置并由客户正确完成预订。那么我们该如何完成在航班中“选择特定座位”这样的操作?


预订过程中,我们可能需要调用可用座位聚合并要求其在飞机上保留一个座位。这一座位保留操作可能作为单一事务(例如保留座位23A)实现,同时返回一个保留ID。我们可以将该保留ID分配给对应预订,而后将该分配有座位的预订提交为“保留”点。其中的每个环节(包括保留座位与接受预订)都作为独立事务存在,且可在无需任何二段式提交或者二段式锁定的前提下独立进行。


需要注意的是,这里使用“保留”是一种业务要求。我们在这里并不进行实际座位分配,而只是保留该座位。此要求可能需要通过模型迭代对其进行约束,这是因为该用例的初始作用描述可能只是“允许客户选择某个座位”。开发人员可能会对其做出不同理解,例如“从剩余的座位中挑选并分配给客户,而后将该座位从清单中移除,避免其被重复出售”。这将会给我们的事务模型增加额外的负担,因为其中的业务并没有被真正作为恒定量处理。此业务在处理预订操作时表现良好,但却无法解决座位分配与航班超额销售等问题。

 






通过以上实例,大家应该已经清楚了为什么我们需要为单一聚合提供尽可能小、尽可能简单且最为基本的事务边界。不过事情到这里还没结束,因为我们现在需要解决新的问题,即如何将这些高度独立的事务整合起来。其中涉及多种不同数据成分(即我们创建了一条预订与座位保留设置,但其尚未被真正纳入登机牌/出票流程)。


微服务该如何在不同边界间完成通信?


我们希望保有真正的恒定业务量。在DDD的帮助下,我们可以选择将这些恒定量建模为聚合,并强制要求每一聚合对应一项事务。有时候我们可能需要在单一事务当中更新多种聚合(中专单一或者多套数据库),但此类场景算是意外情况。我们还需要在不同聚合之间保持一定程度的一致性(并最终在不同边界上下文间保持这种一致性),那么这一点要如何实现?


首先需要强调的是,分布式系统非常难以打理。事实上,几乎没人能够在毫无挫折的前提下在有限的时间内建立起一套分布式系统(可能出现的问题包括故障、不确定原因造成的性能缓慢或者服务停机、系统中出现非同步时间边界等),那么我们为什么非要使用这样一种系统?我们能否将其整合在跨越自身领域的一致性模型当中?在必要事务边界之间使用不同数据与领域组成部分,并在之后的特定时间点上重新实现一致性——这样的思路又是否可行?


正如之前所提到,我们一直在强调微服务的自主权价值。我们需要有能力对其它系统进行独立变更(具体包括可用性、协议与格式等形式)。这将把时间元素解耦出来,确保任意服务之间的对象在任意时间段内皆可实现这种自主性优势。


如前所述,在不同事务边界与有界上下文之间使用事件以完成一致性通信。事件属于恒定结构,用于捕捉特定时间点中应当被广播给受众的重要点。受众则接收自己感兴趣的事件并根据该数据制定决策、存储该数据、存储该数据的部分衍生信息、根据所制定决策更新部分自有数据等等。


继续以之前提到的航班预订为例,在通过ACID类事务进行预订信息存储时,我们要如何最终完成出票?


在这里,之前提到的票务有界上下文要发挥作用了。预订有界上下文将会发布一条类似于“新预订创建”之类的事件,而票务有界上下文则消息此事件并随后与后端(可能是传统)出票系统进行交互。其中显然要涉及某种集成与数据转换,我们可以利用Apache Camel来实现。另外,这一流程还带来了其它几个问题。我们该如何向数据库写入并立足于基本层面向设备发布一条队列/消息?另外,如果我们在不同事件之间进行了多次请求,结果会如何?再有,为每项服务指定单一配套数据库,效果又会有何时不同?


在理解情况下,我们的聚合将直接使用命令与领域事件(作为最优作法,即全部操作皆作为命令执行,而任何响应都作为事件响应存在),并能够更为明确地将内部使用的事件与有界上下文进行映射。


我们可以直接将事件(即新预订创建事件)发布至消息收发队列,而后由监听方从队列中进行消费,并将其插入至数据库当中——不使用XA/2PC事务,而是直接插入数据库自身。我们可以将该事件插入至某个既作为数据库又作为消息发布-订阅主题(在本示例中可能代表偏好航线)的特定事件。或者,我们也可以继续使用ACID数据库并将变更以数据流方式提交至数据库,而后由Apache Kafka等持久性复制日志系统利用某种事件处理器/流处理器进行事件处理。无论选择哪种方式,我们的最终目标是通过恒定时间事件点实现不同边界间的通信。

 






这种作法能够实现以下几大关键优势:


• 避免使用成本高昂甚至可能无法实现的跨边界事务模型。

• 我们可以对自身系统进行变更,而无需影响到系统其它组件的执行进程(包括计时与可用性)。

• 我们可以决定与外界间的同步节奏,从而在不占用过多资源的前提下保持一定程度的同步性。

• 我们可以将数据存储在自有数据库内,同时为自己的服务选择最合适的配套技术方案。

• 我们可以在闲暇时段对自身模式/数据库做出变更。

• 我们将拥有更出色的可扩展性、容错性以及灵活性。

• 我们需要高度关注CAP定理以及用于实现存储/队列机制的各项技术。


但必须承认,这种作法也会带来以下弊端:


• 其复杂程度更高。

• 更难于调试。

• 由于在查看事件时可能存在延迟,因此我们无法假设其它系统知晓实时情况(利用其它方案可能同样无法实现实时反馈,但这种作法的延迟性更为明显)。

• 更加难以操作。

• 我们需要高度关注CAP定理以及用于实现存储/队列机制的各项技术。


我在优势与弊端当中都列出了“高度关注CAP……”这一条,因为尽管其对于大家而言可能是一种负担,但却有着必须这样做的理由!只有做到这一点,我们才能够时刻确保分布式数据系统当中不同形式数据的一致性与并发性!单纯认为“我们的数据库符合ACID”已经不足以说明问题(特别是ACID数据库很可能默认存在一致性薄弱的问题)。


这种方案中涉及的另一项有趣概念名为“命令查询间隔责任”,这意味着我们要将实际模型与写入模型拆分成多个独立服务。请注意,之前提到过互联网企业往往无需面对复杂的领域模型,这一点已经通过其编写的简单模型得到了充分证明(例如可以将一条推文插入至一份分布式日志当中)。


然而,他们的读取模型却由于规模极大而复杂到丧心病狂。CQRS能够帮助互联网厂商解决这些问题。在另一方面,传统企业的写入模型则往往更加复杂,而读取模型则由于只涉及普通的选择查询与DTO对象而显得比较简单。CQRS是一种强大的拆分手段,能够在边界设置妥当后执行评估,同时在不同聚合与有界上下文之间完成数据变更。


那么,如果一项服务只具有一套数据库且不同其它服务分享该数据库,结果又会如何?在这种情况下,我们的受众可能会订阅事件流并将主聚合所使用的数据插入到一套共享数据库当中。这种“共享式数据库”的实际效果非常理想。请注意,具体实现方式并无规则,而只是做出权衡。在本示例当中,我们可以让多项服务共同围绕同一数据库起效,而且由于我们的团队拥有全部进程,所以无需在自主权方面做出妥协。因此,如果下次有人提到“微服务就应该拥有自己的数据库,而且不与其它服务共享该数据库”,大家可以云淡风清地回应“差不多吧”。


如果我们将之前章节中的概念推向逻辑极端,会造成怎样的结果?如果我们利用事件/流处理一切,同时又想保证事件间永远一致,该怎么办?如果我们将数据库/缓存/索引仅仅视为过往日志/事件流的一种持久性物化视力,而当前状态则属于全部事件的顺序集合,结果又会怎样?


最后,我们再来补充一些此种事件间通信方案所能带来的实际收益:


• 现在大家能够将自己的数据库视为一种记录的“当前状态”,而非实际记录。

• 大家可以引入新型应用并重读以往事件,从而检查其行为“会发生哪些变化”。

• 大家可以完善审计记录而无需承担任何成本。

• 大家可以引入新的应用程序版本并通过重播事件的方式完成详尽测试。

• 大家可以更轻松地在新数据库中重播事件,从而明确数据库版本控制/升级/模式的变更理由。

• 大家可以迁移至其它全新数据库技术(即现有关系型数据库已经无法满足需求,这时我们可能需要切换至其它特定数据库/索引机制)。

 







当我们在aa.com或者united.com网站上预订某次航班时,就能看到各项概念的起效过程。在选定某个座位时,该座位实际并没有被真正分配给我们,而只是得到了保留。在预订航班时,我们也还没有真正完成出票。使用过这类服务的朋友都知道,我们稍后会通过邮件或者短信得到出票确认。那么大家有没有经历过航班变化而导致实际座位与预订不符的情况?或者是已经登机完成,却发现由于超量出票而不得不站到终点?这就是事务边界、最终一致性、补偿事务乃至事故带来的真实案例。


故事带来的启示


这个故事带来的启示在于,数据、数据集成、数据边界、企业使用模式、分布式系统理论以及计时机制等等都属于微服务中的重要组成部分(因为微服务实际上就是一套分布式系统)。我发现很多朋友对于这项技术还存在着严重误解(例如‘我用了Spring Boot,所以我建立的是微服务’、‘我需要解决服务发现与云端的负载均衡问题,而后才能实现微服务’乃至‘我必须为每项微服务提供一套对应的数据库’等等),并为微服务制定了一大堆无用的“规则”。别担心,众多大型厂商已经介入并开始销售各类相关产品,所以其它问题都将很快得到解决——只留下最困难的部分,数据。
  查看全部
今天数人云与大家分享的文章将探讨微服务架构的创建与开发工作当中最为困难的部分——用户数据。

只有我们摆脱自己的依赖时微服务才能起作用,换言之,存在于单一数据库上的多任务进程并不是真正的微服务。使用Spring Boot/Dropwizard/Docker并不代表大家所构建的就是微服务。再次强调,大家需要着眼于所处业务领域,而我们的数据才是实现微服务的关键所在。


考虑到我们正在着手尝试建立微服务架构,因此其中最重要的目标就是保证团队有能力以影响最低的方式通过不同速度对系统中的不同组件进行分别处理。因此,我们希望整个团队拥有自主性,能够找到最理想的实施手段并运行自己的服务,同时自由地根据业务需要做出快速变更。如果我们的团队能够满足这些既定要求,那么系统架构也将对应发生变化,即真正向微服务时代迈进。


为了实现这种自主性,我们需要“摆脱依赖性”,但这项目标显然是说着容易做起来难。我曾见证过无数从业者将微服务概念简单理解为“每项微服务都应该拥有并控制自己的数据库,且任意两项服务不应共享同一套数据库”。这样的理解非常合理,因为只要严格遵循上述要求,我们就不会遭遇由跨服务共享数据库所带来的读/写模式、数据模型冲突以及协调挑战等等。然而,单一数据库的实现方式也确实拥有诸多安全与便利性优势:ACID事务、着眼点单一、易于理解、单点管理等等。那么在构建微服务时,我们该如何顺利将单一数据库拆分成多套规模较小的数据库?


下面让我们共同找出答案。首先,对于一家有意构建微服务的“企业”,我们需要明确以下几个问题:


• 立足怎样的业务领域?现实情况又是如何?

• 事务边界在哪里?

• 微服务应当如何在不同边界之间实现通信?

• 我们将数据库剥离出来会造成怎样的影响?


立足怎样的业务领域?


这个问题往往受到人们的忽视,但必须承认微服务实践在互联网企业与传统企业当中往往存在着巨大差异(而这种忽视也是造成项目失败的主要原因之一)。


在构建微服务架构以及确定相关数据使用理由(例如用于生产/消费等)之前,我们首先要对数据的含义拥有清晰而正确的认识。举例一个团购网站,在我们将信息存储在与“预订”相关的数据库并把其进一步迁移至微服务之前,我们先要理解“预订是什么”。就像在HR领域一样,大家可能还需要了解“帐户”、“员工”以及“索赔”等相关定义。


为了实现这一目标,我们需要立足于现实回答更多关于理解的问题。例如,“书是什么?”虽然这个例子非常简单,但却能够很好地反映实际工作中的概念理解过程。因此,思考书的定义,而后为其设计合适的数据模型。


书是由不同分页所构成吗?报纸算不算书籍?因为其同样拥有分页结构。那么书籍是否拥有硬质封面?或者代表的是每天定期出版的各种刊物?如果我本人撰写了一部书籍,出版商可能只会在作者名下列出单一条目。但如果某家书店在出售五本由我撰写的书籍,那么这些书是彼此不同还是同一本书的多份副本?我们该如何表示这种关系?如果书籍内容过长,被拆分成了多个分卷又该如何处理?每部分是否也应算是独立的书籍?又或者全部分卷加起来才算一本书?众多细小部分组合起来应该如何处理?由此组成的整体算不算是书籍?又或者每个部分都属于书籍?最后再提出一种比较复杂的假设,我出版了一本书,书店中摆着大量同样内容的印本,而每种印本又分为多个分卷。在这种情况下,我们该如何定义“书”的概念?


现实情况是,并不存在这样确切的定义。“书是什么”这个问题没有一个绝对的概念,因此我们在回答之前需要了解“谁在提问以及上下文背景是什么。”换言之,即如今的上下文为王概念。我们人类能够快速(甚至是无意识地)解决这种认识模糊性问题,因为我们头脑中存在着上下文背景,其中涵盖环境与问题本身。但计算机显然缺乏这种认知基础。我们需要在构建软件与建立数据模型时,为其指定相关上下文。用书的概念可以让这样的理解过程变得更为明确。我们所处的业务领域(或者说企业指向)拥有其帐户、客户、预订、索赔等事务,其概念显示更加复杂且易产生冲突/模糊性。因此,我们需要为其设定明确的边界。


那么新的问题来了,我们该如何绘制这些边界?为了实现对所在领域的建模,我们需要对实体、值对象以及聚合等概念设定上下文。换言之,我们借此建立并完善整套代表所在业务领域的模型,该模型包含上下文中关于边界的各项定义。这种明确的边界最终将成为我们的微服务,或者作为微服务的边界内组件,抑或二者兼有。无论如何,微服务的核心在于边界,DDD(即业务驱动型设计)亦是如此。

 
1.png


我们的数据模型(即希望如何表现物理数据存储中的概念——注意其中的明确区别)受到业务领域模型的驱动,而非前者驱动后者。在设定了边界之后,我们将能够识别模型当中“正确”与不正确的部分。这些边界同时也能够实现一定程度的自主性。为上下文“A”指定一个与上下文“B”不同的“书籍”定义(例如将上下文‘A’设定为一项搜索服务,负责搜索标题被指定为‘书’的条目; 而上下文‘B’则为检查服务,负责根据书籍总量(即标题加副本)处理事务)。


在这里,大家可能会提出质疑:“等等,Netflix、Twitter或者领英并没有给出过任何关于业务驱动设计的说明。为什么我要遵循所谓DDD原则?”下面一起来看原因:


 “人们都希望复制Netflix,但却只能复制到其表象。他们复制到的只是结果,而并非过程”——Netflix公司前任首席云架构师Adrian Cockcroft


迈向微服务的旅程就是这么一段……旅程。每一家企业都拥有自己需要克服的坎坷与艰辛。其中并不存在任何固定或者便捷的规则,而只有权衡与取舍。复制某家企业的成功作法并不足以帮助我们同样顺利地完成这一流程/旅程,其甚至可能根本无法奏效。另外,也正是这样的思路才让我们的企业无法成为Netflix。事实上,我一直认为无论Netflix的领域复杂性有多么可怕,其仍然无法与传统企业面临的难题相提并论。搜索并显示影片、发布推文、更新领英动态等等绝对要比保障索赔处理系统简单得多。这些互联网企业之所以能够快速迎接微服务,是因为其需要出色的产品上市速度并应对批量/规模化负载(向Twitter发布一条推文非常简单,但面向5亿用户发布推文并显示内容则非常复杂)。如今的企业将不得不同时面临来自领域与规模两个层面的复杂性挑战。因此,我们在这段转型旅程当中必须在领域、规模以及组织变更之间做出权衡。每家企业都面临着不同的难题,而这也必须成为我们的关注重点。


事务边界是什么?


重新回到我们的主要议题上来。我们需要利用业务驱动设计等手段帮助自身理解用于实现系统的模型,同时在单一上下文当中围绕这些模型绘制边界。因此,我们需要将客户、帐户、预订等事务视为被绑定至不同上下文的不同事物,但最终亦需要立足于同一架构对这些相关概念进行分发,并在发生变更时调和这些模型所受到的具体影响。我们需要将这些情况全部纳入考量,但首先确立事务边界无疑是最为重要的前提。


遗憾的是,作为开发者的我们似乎仍然在以完全错误的方式进行分布式系统构建:我们仍然遵循着单一、孤立的关系型ACID数据库思路作为指导方针。我们还忽略了异步且可靠性较低的网络环境可能带来的风险。要知道,编写框架这类工作并不要求从业者对网络(包括RPC框架——数据库抽象方案亦严重忽略了网络因素)有多么了解,这意味着多数人都倾向于或者只知道如何利用点到点同步调用一切(包括REST、SOAP以及对象序列化RPC库等其它CORBA)。我们构建的系统没有考虑到授权与自主间的平衡,而且最终往往只能依靠覆盖众多独立服务的两段式提交方式解决数据分发问题。或者,我们彻底忽略了以上各项要求。由此建立起的系统扩展性极差且相当脆弱——即使我们非要将其称为SOA、微服务乃至迷你服务等等,其仍然不具备此类架构真正需要拥有的特性与优势。


那么我们到底该如何理解事务边界?我将其理解为业务常量当中最小的基本单位。无论大家是利用数据库的ACID属性以实现这种基础性,抑或是选择二段式提交,其实都无关紧要。真正的重点在于,我们希望尽可能缩小这些事务边界(在理想状态下,应该是单一事务对应单一对象),从而确保其可扩展能力。当我们建立自己的业务领域模型时,使用DDD技术以明确实体、值对象与聚合。在此上下文当中,聚合代表的是那些包含其它实体/值对象的对象,负责执行不变量(单一有界上下文当中可包含多组聚合)。


举例来说,让我们设定以下几种用例:


• “允许客户搜索航班信息。”

• “允许客户在特定航班中选择座位。”

• “允许客户预订航班。”


我们在这里可以设置三种有界上下文:搜索、预订与票务(当然,我们也可以设置更多相关上下文,包括支付、忠诚度、待机、升舱等,但这里我们就只强调这三种)。搜索负责显示特定路线以及与给定时间相符的航班选项。预订则负责利用客户信息建立预订流程(包括姓名、地址、会员编号等)、座位偏好以及支付信息。票务将负责与航空公司沟通并完成机票签发。在各有界上下文当中,我们都需要确定事务边界以执行约束/恒量。我们不需要在有界上下文当中考虑基本事务(亦称为原子事务,我们将在下一章节中对此进行详尽说明)。


那么我们要如何在建模时允许考虑最小事务边界(在本示例中,其应被简化为航班预订流程)?也许设置一套“航班”聚合是不错的作法,其中可以囊括时间、日期、路线以及客户、机型以及预订等实体条目?听起来很有搞头,其中单一航班拥有具体的机型、座位、客户与预订条目。航班聚合负责在预订创建过程中追踪机型及座位等信息。在这种情况下,我们可以选择在数据库当中建立一套数据模型(这是一种标准的关系模型,其中包含约束与外键等),或者在源代码中生成一套对象模型(继承/组合),下面我们看看具体作法会带来怎样的变数。

 

2.png



在利用预订、机型以及航班等信息创建一条预订时,其中是否真的存在恒量?换言之,如果我们向航班聚合当中新增一种机型信息,那么我们是否真的应当将客户与预订包含在该事务当中?答案恐怕是否定的。我们在这里需要考虑的是如何利用可组合数据模型建立聚合。然而,这样的事务边界太过庞大。如果我们面对着大量航班、座位与预订信息的变更,则可能出现众多事务冲突。而且这种作法显然不具备可扩展性(而且一次航班计划变更就会带来大量订单失败,从而造成糟糕的客户体验)。


那么我们显然需要把事务边界设定得更小一点。


也许预订、可选座位以及航班三者自有拥有自己的独立聚合。一条预订当中可包含客户信息、偏好以及可能的支付信息。可用座位聚合则包含有机型与内部配置。航班聚合由日程安排与路线构成,等我们能够在不影响航班规划以及机型/可用座位等事务的前提下,随时调整预订内容。从领域的角度来看,我们希望实现这样的效果。我们不需要在机型/航班/预订之间实现100%的严格一致,而是希望确保管理员能够正确记录航班规划变更、供应商正确提供机型配置并由客户正确完成预订。那么我们该如何完成在航班中“选择特定座位”这样的操作?


预订过程中,我们可能需要调用可用座位聚合并要求其在飞机上保留一个座位。这一座位保留操作可能作为单一事务(例如保留座位23A)实现,同时返回一个保留ID。我们可以将该保留ID分配给对应预订,而后将该分配有座位的预订提交为“保留”点。其中的每个环节(包括保留座位与接受预订)都作为独立事务存在,且可在无需任何二段式提交或者二段式锁定的前提下独立进行。


需要注意的是,这里使用“保留”是一种业务要求。我们在这里并不进行实际座位分配,而只是保留该座位。此要求可能需要通过模型迭代对其进行约束,这是因为该用例的初始作用描述可能只是“允许客户选择某个座位”。开发人员可能会对其做出不同理解,例如“从剩余的座位中挑选并分配给客户,而后将该座位从清单中移除,避免其被重复出售”。这将会给我们的事务模型增加额外的负担,因为其中的业务并没有被真正作为恒定量处理。此业务在处理预订操作时表现良好,但却无法解决座位分配与航班超额销售等问题。

 
3.png



通过以上实例,大家应该已经清楚了为什么我们需要为单一聚合提供尽可能小、尽可能简单且最为基本的事务边界。不过事情到这里还没结束,因为我们现在需要解决新的问题,即如何将这些高度独立的事务整合起来。其中涉及多种不同数据成分(即我们创建了一条预订与座位保留设置,但其尚未被真正纳入登机牌/出票流程)。


微服务该如何在不同边界间完成通信?


我们希望保有真正的恒定业务量。在DDD的帮助下,我们可以选择将这些恒定量建模为聚合,并强制要求每一聚合对应一项事务。有时候我们可能需要在单一事务当中更新多种聚合(中专单一或者多套数据库),但此类场景算是意外情况。我们还需要在不同聚合之间保持一定程度的一致性(并最终在不同边界上下文间保持这种一致性),那么这一点要如何实现?


首先需要强调的是,分布式系统非常难以打理。事实上,几乎没人能够在毫无挫折的前提下在有限的时间内建立起一套分布式系统(可能出现的问题包括故障、不确定原因造成的性能缓慢或者服务停机、系统中出现非同步时间边界等),那么我们为什么非要使用这样一种系统?我们能否将其整合在跨越自身领域的一致性模型当中?在必要事务边界之间使用不同数据与领域组成部分,并在之后的特定时间点上重新实现一致性——这样的思路又是否可行?


正如之前所提到,我们一直在强调微服务的自主权价值。我们需要有能力对其它系统进行独立变更(具体包括可用性、协议与格式等形式)。这将把时间元素解耦出来,确保任意服务之间的对象在任意时间段内皆可实现这种自主性优势。


如前所述,在不同事务边界与有界上下文之间使用事件以完成一致性通信。事件属于恒定结构,用于捕捉特定时间点中应当被广播给受众的重要点。受众则接收自己感兴趣的事件并根据该数据制定决策、存储该数据、存储该数据的部分衍生信息、根据所制定决策更新部分自有数据等等。


继续以之前提到的航班预订为例,在通过ACID类事务进行预订信息存储时,我们要如何最终完成出票?


在这里,之前提到的票务有界上下文要发挥作用了。预订有界上下文将会发布一条类似于“新预订创建”之类的事件,而票务有界上下文则消息此事件并随后与后端(可能是传统)出票系统进行交互。其中显然要涉及某种集成与数据转换,我们可以利用Apache Camel来实现。另外,这一流程还带来了其它几个问题。我们该如何向数据库写入并立足于基本层面向设备发布一条队列/消息?另外,如果我们在不同事件之间进行了多次请求,结果会如何?再有,为每项服务指定单一配套数据库,效果又会有何时不同?


在理解情况下,我们的聚合将直接使用命令与领域事件(作为最优作法,即全部操作皆作为命令执行,而任何响应都作为事件响应存在),并能够更为明确地将内部使用的事件与有界上下文进行映射。


我们可以直接将事件(即新预订创建事件)发布至消息收发队列,而后由监听方从队列中进行消费,并将其插入至数据库当中——不使用XA/2PC事务,而是直接插入数据库自身。我们可以将该事件插入至某个既作为数据库又作为消息发布-订阅主题(在本示例中可能代表偏好航线)的特定事件。或者,我们也可以继续使用ACID数据库并将变更以数据流方式提交至数据库,而后由Apache Kafka等持久性复制日志系统利用某种事件处理器/流处理器进行事件处理。无论选择哪种方式,我们的最终目标是通过恒定时间事件点实现不同边界间的通信。

 
4.png



这种作法能够实现以下几大关键优势:


• 避免使用成本高昂甚至可能无法实现的跨边界事务模型。

• 我们可以对自身系统进行变更,而无需影响到系统其它组件的执行进程(包括计时与可用性)。

• 我们可以决定与外界间的同步节奏,从而在不占用过多资源的前提下保持一定程度的同步性。

• 我们可以将数据存储在自有数据库内,同时为自己的服务选择最合适的配套技术方案。

• 我们可以在闲暇时段对自身模式/数据库做出变更。

• 我们将拥有更出色的可扩展性、容错性以及灵活性。

• 我们需要高度关注CAP定理以及用于实现存储/队列机制的各项技术。


但必须承认,这种作法也会带来以下弊端:


• 其复杂程度更高。

• 更难于调试。

• 由于在查看事件时可能存在延迟,因此我们无法假设其它系统知晓实时情况(利用其它方案可能同样无法实现实时反馈,但这种作法的延迟性更为明显)。

• 更加难以操作。

• 我们需要高度关注CAP定理以及用于实现存储/队列机制的各项技术。


我在优势与弊端当中都列出了“高度关注CAP……”这一条,因为尽管其对于大家而言可能是一种负担,但却有着必须这样做的理由!只有做到这一点,我们才能够时刻确保分布式数据系统当中不同形式数据的一致性与并发性!单纯认为“我们的数据库符合ACID”已经不足以说明问题(特别是ACID数据库很可能默认存在一致性薄弱的问题)。


这种方案中涉及的另一项有趣概念名为“命令查询间隔责任”,这意味着我们要将实际模型与写入模型拆分成多个独立服务。请注意,之前提到过互联网企业往往无需面对复杂的领域模型,这一点已经通过其编写的简单模型得到了充分证明(例如可以将一条推文插入至一份分布式日志当中)。


然而,他们的读取模型却由于规模极大而复杂到丧心病狂。CQRS能够帮助互联网厂商解决这些问题。在另一方面,传统企业的写入模型则往往更加复杂,而读取模型则由于只涉及普通的选择查询与DTO对象而显得比较简单。CQRS是一种强大的拆分手段,能够在边界设置妥当后执行评估,同时在不同聚合与有界上下文之间完成数据变更。


那么,如果一项服务只具有一套数据库且不同其它服务分享该数据库,结果又会如何?在这种情况下,我们的受众可能会订阅事件流并将主聚合所使用的数据插入到一套共享数据库当中。这种“共享式数据库”的实际效果非常理想。请注意,具体实现方式并无规则,而只是做出权衡。在本示例当中,我们可以让多项服务共同围绕同一数据库起效,而且由于我们的团队拥有全部进程,所以无需在自主权方面做出妥协。因此,如果下次有人提到“微服务就应该拥有自己的数据库,而且不与其它服务共享该数据库”,大家可以云淡风清地回应“差不多吧”。


如果我们将之前章节中的概念推向逻辑极端,会造成怎样的结果?如果我们利用事件/流处理一切,同时又想保证事件间永远一致,该怎么办?如果我们将数据库/缓存/索引仅仅视为过往日志/事件流的一种持久性物化视力,而当前状态则属于全部事件的顺序集合,结果又会怎样?


最后,我们再来补充一些此种事件间通信方案所能带来的实际收益:


• 现在大家能够将自己的数据库视为一种记录的“当前状态”,而非实际记录。

• 大家可以引入新型应用并重读以往事件,从而检查其行为“会发生哪些变化”。

• 大家可以完善审计记录而无需承担任何成本。

• 大家可以引入新的应用程序版本并通过重播事件的方式完成详尽测试。

• 大家可以更轻松地在新数据库中重播事件,从而明确数据库版本控制/升级/模式的变更理由。

• 大家可以迁移至其它全新数据库技术(即现有关系型数据库已经无法满足需求,这时我们可能需要切换至其它特定数据库/索引机制)。

 

5.png



当我们在aa.com或者united.com网站上预订某次航班时,就能看到各项概念的起效过程。在选定某个座位时,该座位实际并没有被真正分配给我们,而只是得到了保留。在预订航班时,我们也还没有真正完成出票。使用过这类服务的朋友都知道,我们稍后会通过邮件或者短信得到出票确认。那么大家有没有经历过航班变化而导致实际座位与预订不符的情况?或者是已经登机完成,却发现由于超量出票而不得不站到终点?这就是事务边界、最终一致性、补偿事务乃至事故带来的真实案例。


故事带来的启示


这个故事带来的启示在于,数据、数据集成、数据边界、企业使用模式、分布式系统理论以及计时机制等等都属于微服务中的重要组成部分(因为微服务实际上就是一套分布式系统)。我发现很多朋友对于这项技术还存在着严重误解(例如‘我用了Spring Boot,所以我建立的是微服务’、‘我需要解决服务发现与云端的负载均衡问题,而后才能实现微服务’乃至‘我必须为每项微服务提供一套对应的数据库’等等),并为微服务制定了一大堆无用的“规则”。别担心,众多大型厂商已经介入并开始销售各类相关产品,所以其它问题都将很快得到解决——只留下最困难的部分,数据。
 

代码篇 | Docker1.12+Swarm构建动态微服务应用

宁静胡同 发表了文章 • 0 个评论 • 597 次浏览 • 2016-07-21 12:00 • 来自相关话题

这次数人云与大家分享的文章里,主要介绍了Docker Swarm如何凭借革新对整体场景进一步加以简化。事实上,如今我们已经可以轻松且直观地构建起一套Docker Swarm集群,快来一起体验一下吧:)


下面先来看看各项具体的更新内容:

 我们在之前提到过一个示例,即一款由前端与多项后端服务共同构成的微服务应用。其中前端为Traefik HTTP代理,负责将各项请求路由至后端服务。而后端则非常简单,是一套基于Go的HTTP Web服务器,负责返回其运行所在的容器ID。





新的Docker Swarm不再需要为应用容器设置独立的HTTP代理。如上图所示的原有架构现在被精简为下图所示的形式:








移动部件更少了——赞!


另外,我们还为后端服务内置了负载均衡机制。我们甚至能够立足于集群内的任一节点访问这些服务。Docker Swarm还集成有一种内置网状路由机制,用于将各请求路由至适合的后端容器当中。

面对这些新功能,有些朋友可能认为Docker Swarm集群的设置过程会比原本更为复杂。事实上,整个流程反而更加简单。


仍然半信半疑?下面一起来看。

没错,这次我们仍然使用Raspberry Pi集群。我使用的是Docker 1.12内部版本,并将其安装在Raspberry Pi上。当Docker 1.12推出正式版后,我们会对内容做出针对性更新。


下面看看当前配置:
root@pi6 $ docker version
Client:
Version: 1.12.0-rc1
API version: 1.24
Go version: go1.6.2
Git commit: 1f136c1-unsupported
Built: Wed Jun 15 15:35:51 2016
OS/Arch: linux/arm

Server:
Version: 1.12.0-rc1
API version: 1.24
Go version: go1.6.2
Git commit: 1f136c1-unsupported
Built: Wed Jun 15 15:35:51 2016
OS/Arch: linux/arm
 
很好,Docker 1.12 RC1已经准备就绪。下面启动各项必要服务。


首先看看我们能否在Docker CLI中找到隐藏的各项新功能。
root@pi6 $ docker
Usage: docker [OPTIONS] COMMAND [arg...]
docker [ --help | -v | --version ]

A self-sufficient runtime for containers.
...
service Manage Docker services
...
stats Display a live stream of container(s) resource usage statistics
...
swarm Manage Docker Swarm
...
update Update configuration of one or more containers

Run 'docker COMMAND --help' for more information on a command.
我直接去掉了其中与上代版本完全一致的部分,而只留了不同之处。


现在我们可以使用docker swarm命令了。


查询其具体作用:
root@pi6 $ docker swarm
Usage: docker swarm COMMAND
Manage Docker Swarm
Options:
--help Print usage
Commands:
init Initialize a Swarm.
join Join a Swarm as a node and/or manager.
update update the Swarm.
leave Leave a Swarm.
inspect Inspect the Swarm
Run 'docker swarm COMMAND --help' for more information on a command.
就是说其用于“初始化一套Swarm”。看起来正是我们需要的。首先启动该命令。
root@pi6 $ docker swarm init
Swarm initialized: current node (1njlvzi9rk2syv3xojw217o0g) is now a manager.
现在我们的Swarm管理节点已经开始运行,接下来为集群添加更多节点。


前往集群中的另一节点并执行:
root@pi1 $ docker swarm join pi6:2377
This node joined a Swarm as a worker.
使用上述命令,我们在刚刚创建的初始Swarm集群中声明了应当加入该Swarm管理节点的各个新节点。Docker Swarm会在后台执行相关操作。


举例来说,其会为不同集群节点设置经过加密的彼此通信通道。我们不再需要自行管理TLS证书。


每位曾经设置过Docker Swarm集群的朋友,都会意识到新的流程有多么简单。

不过到这儿还没有结束。


Swarm管理节点中的一条“docker info”带来了一些有趣的提示。我仍然删去其中不必要的部分:
root@pi6 $ docker info
...
Swarm: active
NodeID: 1njlvzi9rk2syv3xojw217o0g
IsManager: Yes
Managers: 1
Nodes: 2
CACertHash: sha256:de4e2bff3b63700aad01df97bbe0397f131aabed5fabb7732283f044472323fc
...
Kernel Version: 4.4.10-hypriotos-v7+
Operating System: Raspbian GNU/Linux 8 (jessie)
OSType: linux
Architecture: armv7l
CPUs: 4
Total Memory: 925.4 MiB
Name: pi6
...
如大家所见,我们现在已经在“docker info”输出结果中有了新的“Swarm”部分,其告诉我们当前节点属于一套Swarm管理节点,且该集群由两个集群节点构成。


在第二个节点上,其输出结果与管理节点稍有不同:
Swarm: active
NodeID: 3fmwt4taurwxczr2icboojz8g
IsManager: No
到这里,我们已经拥有了一套有趣但仍然空空如也的Swarm集群。


我们还需要了解Docker 1.12中的service这项全新抽象定义。大家可能在前面的输出结果中注意到了docker service命令。所谓docker service,是指运行在容器当中且负责为外部世界提供运行在Swarm集群内的“service”的软件片段。

这样的一项服务可以由单一或者多套容器构成。在后一种情况下,我们可以确保服务拥有高可用性及/或负载均衡能力。

下面使用之前创建的“whoami”镜像建立这样一项服务。
root@pi6 $ docker service create --name whoami -p 80:8000 hypriot/rpi-whoami
buy0q65lw7nshm76kvy5imxk3
在“docker swarm ls”命令的帮助下,我们可以检查这项新服务的状态。
root@pi6 $ docker service ls
ID NAME SCALE IMAGE COMMAND
buy0q65lw7ns whoami 1 hypriot/rpi-whoami
下面检查我们是否能够通过curl命令向eth0网络接口发送l http命令,从而请求目录页面。
root@pi6 $ curl http://192.168.178.24
I'm 1b6df814c654
一切顺利,鼓掌!


有些朋友可能注意到,“docker swarm ls”命令的标题行中存在“SCALE”部分,这似乎意味着我们可以对服务进行扩展。
root@pi6 $ docker service scale whoami=5
whoami scaled to 5
那就来实际验证一下吧:
root@pi6 $ docker service ls
ID NAME SCALE IMAGE COMMAND
buy0q65lw7ns whoami 5 hypriot/rpi-whoami

root@pi6 $ for i in {1..5}; do curl http://192.168.178.24; done
I'm 8db1657e8517
I'm e1863a2be88d
I'm 1b6df814c654
I'm 8db1657e8517
I'm e1863a2be88d
非常简单。


但这种方式与原有Swarm其实差不多,只不过在使用感受上更便捷也更快速。请注意,我们使用的是Raspberry Pi而非强大的服务器,所以要对性能拥有较为保守的估计。


下面从单一Docker引擎的角度来看看目前的运行状态:
root@pi6 $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1863a2be88d hypriot/rpi-whoami:latest "/http" 2 minutes ago Up 2 minutes 8000/tcp whoami.4.0lg12zndbal72exqe08r9wvpg
8db1657e8517 hypriot/rpi-whoami:latest "/http" 2 minutes ago Up 2 minutes 8000/tcp whoami.5.5z6mvsrdy73m5w24icgsqc8i2
1b6df814c654 hypriot/rpi-whoami:latest "/http" 8 minutes ago Up 8 minutes 8000/tcp whoami.1.bg4qlpiye6h6uxyf8cmkwuh52
如大家所见,已经启动的容器有5套,其中3套驻留于“pi6”中。


下面看看是否能够找到其它容器:
root@pi1 docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db411a119c0a hypriot/rpi-whoami:latest "/http" 6 minutes ago Up 6 minutes 8000/tcp whoami.2.2tf7yhmx9haol7e2b7xib2emj
0a4bf32fa9c4 hypriot/rpi-whoami:latest "/http" 6 minutes ago Up 6 minutes 8000/tcp whoami.3.2r6mm091c2ybr0f9jz4qaxw9k
那么如果我们将这套Swarm集群驻留在“pi1”上,结果又会如何?
root@pi1 docker swarm leave
Node left the default swarm.
下面看看另一节点上的运行情况:docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58620e3d533c hypriot/rpi-whoami:latest "/http" 46 seconds ago Up 43 seconds 8000/tcp whoami.2.cgc4e2ixulc2f3ehr4laoursg
acc9b523f434 hypriot/rpi-whoami:latest "/http" 46 seconds ago Up 43 seconds 8000/tcp whoami.3.67bhlo3nwgehthi3bg5bfdzue
e1863a2be88d hypriot/rpi-whoami:latest "/http" 8 minutes ago Up 8 minutes 8000/tcp whoami.4.0lg12zndbal72exqe08r9wvpg
8db1657e8517 hypriot/rpi-whoami:latest "/http" 8 minutes ago Up 8 minutes 8000/tcp whoami.5.5z6mvsrdy73m5w24icgsqc8i2
1b6df814c654 hypriot/rpi-whoami:latest "/http" 15 minutes ago Up 14 minutes 8000/tcp whoami.1.bg4qlpiye6h6uxyf8cmkwuh52
这里的情况相当于“pi1”节点发生故障,此时“pi1”中运行的全部容器都会被自动迁移至另一集群节点。这项机制在实际生产当中无疑非常重要。


那么下面我们回顾一下之前了解到的信息:


我们创建了一款小型动态微服务应用,完全由Docker构成。Docker Swarm现在被整合至Docker-Engine当中,而不再以独立软件形式存在。在多数情况下,这能够为应用后端服务建立起独立的代理机制。不再需要使用nginx、HAProxy或者Traefik。

尽管活动部件数量有所减少,但我们现在反而拥有了内置的高可用性与负载均衡功能。我非常期待未来Docker Swarm正式版本中会带来哪些新的惊喜,又如何与Docker Compose进行协作。 查看全部

这次数人云与大家分享的文章里,主要介绍了Docker Swarm如何凭借革新对整体场景进一步加以简化。事实上,如今我们已经可以轻松且直观地构建起一套Docker Swarm集群,快来一起体验一下吧:)


下面先来看看各项具体的更新内容:

 我们在之前提到过一个示例,即一款由前端与多项后端服务共同构成的微服务应用。其中前端为Traefik HTTP代理,负责将各项请求路由至后端服务。而后端则非常简单,是一套基于Go的HTTP Web服务器,负责返回其运行所在的容器ID。

1.jpg

新的Docker Swarm不再需要为应用容器设置独立的HTTP代理。如上图所示的原有架构现在被精简为下图所示的形式:


2.jpg



移动部件更少了——赞!


另外,我们还为后端服务内置了负载均衡机制。我们甚至能够立足于集群内的任一节点访问这些服务。Docker Swarm还集成有一种内置网状路由机制,用于将各请求路由至适合的后端容器当中。

面对这些新功能,有些朋友可能认为Docker Swarm集群的设置过程会比原本更为复杂。事实上,整个流程反而更加简单。


仍然半信半疑?下面一起来看。

没错,这次我们仍然使用Raspberry Pi集群。我使用的是Docker 1.12内部版本,并将其安装在Raspberry Pi上。当Docker 1.12推出正式版后,我们会对内容做出针对性更新。


下面看看当前配置:
root@pi6 $ docker version
Client:
Version: 1.12.0-rc1
API version: 1.24
Go version: go1.6.2
Git commit: 1f136c1-unsupported
Built: Wed Jun 15 15:35:51 2016
OS/Arch: linux/arm

Server:
Version: 1.12.0-rc1
API version: 1.24
Go version: go1.6.2
Git commit: 1f136c1-unsupported
Built: Wed Jun 15 15:35:51 2016
OS/Arch: linux/arm

 
很好,Docker 1.12 RC1已经准备就绪。下面启动各项必要服务。


首先看看我们能否在Docker CLI中找到隐藏的各项新功能。
root@pi6 $ docker
Usage: docker [OPTIONS] COMMAND [arg...]
docker [ --help | -v | --version ]

A self-sufficient runtime for containers.
...
service Manage Docker services
...
stats Display a live stream of container(s) resource usage statistics
...
swarm Manage Docker Swarm
...
update Update configuration of one or more containers

Run 'docker COMMAND --help' for more information on a command.

我直接去掉了其中与上代版本完全一致的部分,而只留了不同之处。


现在我们可以使用docker swarm命令了。


查询其具体作用:
root@pi6 $ docker swarm
Usage: docker swarm COMMAND
Manage Docker Swarm
Options:
--help Print usage
Commands:
init Initialize a Swarm.
join Join a Swarm as a node and/or manager.
update update the Swarm.
leave Leave a Swarm.
inspect Inspect the Swarm
Run 'docker swarm COMMAND --help' for more information on a command.

就是说其用于“初始化一套Swarm”。看起来正是我们需要的。首先启动该命令。
root@pi6 $ docker swarm init
Swarm initialized: current node (1njlvzi9rk2syv3xojw217o0g) is now a manager.

现在我们的Swarm管理节点已经开始运行,接下来为集群添加更多节点。


前往集群中的另一节点并执行:
root@pi1 $ docker swarm join pi6:2377
This node joined a Swarm as a worker.

使用上述命令,我们在刚刚创建的初始Swarm集群中声明了应当加入该Swarm管理节点的各个新节点。Docker Swarm会在后台执行相关操作。


举例来说,其会为不同集群节点设置经过加密的彼此通信通道。我们不再需要自行管理TLS证书。


每位曾经设置过Docker Swarm集群的朋友,都会意识到新的流程有多么简单。

不过到这儿还没有结束。


Swarm管理节点中的一条“docker info”带来了一些有趣的提示。我仍然删去其中不必要的部分:
root@pi6 $ docker info
...
Swarm: active
NodeID: 1njlvzi9rk2syv3xojw217o0g
IsManager: Yes
Managers: 1
Nodes: 2
CACertHash: sha256:de4e2bff3b63700aad01df97bbe0397f131aabed5fabb7732283f044472323fc
...
Kernel Version: 4.4.10-hypriotos-v7+
Operating System: Raspbian GNU/Linux 8 (jessie)
OSType: linux
Architecture: armv7l
CPUs: 4
Total Memory: 925.4 MiB
Name: pi6
...

如大家所见,我们现在已经在“docker info”输出结果中有了新的“Swarm”部分,其告诉我们当前节点属于一套Swarm管理节点,且该集群由两个集群节点构成。


在第二个节点上,其输出结果与管理节点稍有不同:
Swarm: active
NodeID: 3fmwt4taurwxczr2icboojz8g
IsManager: No

到这里,我们已经拥有了一套有趣但仍然空空如也的Swarm集群。


我们还需要了解Docker 1.12中的service这项全新抽象定义。大家可能在前面的输出结果中注意到了docker service命令。所谓docker service,是指运行在容器当中且负责为外部世界提供运行在Swarm集群内的“service”的软件片段。

这样的一项服务可以由单一或者多套容器构成。在后一种情况下,我们可以确保服务拥有高可用性及/或负载均衡能力。

下面使用之前创建的“whoami”镜像建立这样一项服务。
root@pi6 $ docker service create --name whoami -p 80:8000 hypriot/rpi-whoami
buy0q65lw7nshm76kvy5imxk3

在“docker swarm ls”命令的帮助下,我们可以检查这项新服务的状态。
root@pi6 $ docker service ls
ID NAME SCALE IMAGE COMMAND
buy0q65lw7ns whoami 1 hypriot/rpi-whoami

下面检查我们是否能够通过curl命令向eth0网络接口发送l http命令,从而请求目录页面。
root@pi6 $ curl http://192.168.178.24
I'm 1b6df814c654

一切顺利,鼓掌!


有些朋友可能注意到,“docker swarm ls”命令的标题行中存在“SCALE”部分,这似乎意味着我们可以对服务进行扩展。
root@pi6 $ docker service scale whoami=5
whoami scaled to 5

那就来实际验证一下吧:
root@pi6 $ docker service ls
ID NAME SCALE IMAGE COMMAND
buy0q65lw7ns whoami 5 hypriot/rpi-whoami

root@pi6 $ for i in {1..5}; do curl http://192.168.178.24; done
I'm 8db1657e8517
I'm e1863a2be88d
I'm 1b6df814c654
I'm 8db1657e8517
I'm e1863a2be88d

非常简单。


但这种方式与原有Swarm其实差不多,只不过在使用感受上更便捷也更快速。请注意,我们使用的是Raspberry Pi而非强大的服务器,所以要对性能拥有较为保守的估计。


下面从单一Docker引擎的角度来看看目前的运行状态:
root@pi6 $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1863a2be88d hypriot/rpi-whoami:latest "/http" 2 minutes ago Up 2 minutes 8000/tcp whoami.4.0lg12zndbal72exqe08r9wvpg
8db1657e8517 hypriot/rpi-whoami:latest "/http" 2 minutes ago Up 2 minutes 8000/tcp whoami.5.5z6mvsrdy73m5w24icgsqc8i2
1b6df814c654 hypriot/rpi-whoami:latest "/http" 8 minutes ago Up 8 minutes 8000/tcp whoami.1.bg4qlpiye6h6uxyf8cmkwuh52

如大家所见,已经启动的容器有5套,其中3套驻留于“pi6”中。


下面看看是否能够找到其它容器:
root@pi1 docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db411a119c0a hypriot/rpi-whoami:latest "/http" 6 minutes ago Up 6 minutes 8000/tcp whoami.2.2tf7yhmx9haol7e2b7xib2emj
0a4bf32fa9c4 hypriot/rpi-whoami:latest "/http" 6 minutes ago Up 6 minutes 8000/tcp whoami.3.2r6mm091c2ybr0f9jz4qaxw9k

那么如果我们将这套Swarm集群驻留在“pi1”上,结果又会如何?
root@pi1 docker swarm leave
Node left the default swarm.

下面看看另一节点上的运行情况:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58620e3d533c hypriot/rpi-whoami:latest "/http" 46 seconds ago Up 43 seconds 8000/tcp whoami.2.cgc4e2ixulc2f3ehr4laoursg
acc9b523f434 hypriot/rpi-whoami:latest "/http" 46 seconds ago Up 43 seconds 8000/tcp whoami.3.67bhlo3nwgehthi3bg5bfdzue
e1863a2be88d hypriot/rpi-whoami:latest "/http" 8 minutes ago Up 8 minutes 8000/tcp whoami.4.0lg12zndbal72exqe08r9wvpg
8db1657e8517 hypriot/rpi-whoami:latest "/http" 8 minutes ago Up 8 minutes 8000/tcp whoami.5.5z6mvsrdy73m5w24icgsqc8i2
1b6df814c654 hypriot/rpi-whoami:latest "/http" 15 minutes ago Up 14 minutes 8000/tcp whoami.1.bg4qlpiye6h6uxyf8cmkwuh52

这里的情况相当于“pi1”节点发生故障,此时“pi1”中运行的全部容器都会被自动迁移至另一集群节点。这项机制在实际生产当中无疑非常重要。


那么下面我们回顾一下之前了解到的信息:


我们创建了一款小型动态微服务应用,完全由Docker构成。Docker Swarm现在被整合至Docker-Engine当中,而不再以独立软件形式存在。在多数情况下,这能够为应用后端服务建立起独立的代理机制。不再需要使用nginx、HAProxy或者Traefik。

尽管活动部件数量有所减少,但我们现在反而拥有了内置的高可用性与负载均衡功能。我非常期待未来Docker Swarm正式版本中会带来哪些新的惊喜,又如何与Docker Compose进行协作。

实录分享 | 应用容器env化实战

宁静胡同 发表了文章 • 0 个评论 • 823 次浏览 • 2016-07-21 11:53 • 来自相关话题

本文是数人云工程师志浩在DockOne微信群分享的实录,与大家聊一聊应用容器在配置管理中遇到的问题以及解决方法。
随着Docker技术的火热发展, Docker在代码构建发布中扮演着越来越重要的角色。Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到流行的Linux机器上。Docker非常适用于如下场景:
应用容器的自动化打包和发布;
 
自动化测试和持续集成、发布。

这次主要和大家聊聊应用容器在配置管理中遇到的问题。首先是介绍现有容器常用的配置文件加载方式,接下来重点介绍数人云组件在自动化打包和发布遇到的问题和解决方法。


现有的主要Docker加载配置的方式


首先简单介绍下现有容器的加载配置文件的方式。

挂载宿主机配置文件的方式

通过docker run -v 参数将宿主机上的配置文件挂载到容器指定目录中如:docker run -v /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf --name myredis redis redis-server /usr/local/etc/redis/redis.conf


这种方式对于单实例应用比较方便。

下载配置中心文件的方式

这种方法首先需要建立配置中心,例如用Nginx等Web服务组件,提前将配置文件放在指定目录,在Dokcerfile entrypoint中拉取配置中心文件的脚本,之后容器启动就自动拉取配置中心的配置。

通过环境变量传入到容器中

通过docker run -e 参数将将环境变量传入到容器如:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.6

应用容器的自动化打包和发布中遇到的问题


数人云组件采用微服务架构,将服务拆分,分别采用相对独立的服务对各方面进行管理,彼此之间使用统一的接口来进行交流,架构变得复杂,但优势非常明显。为了保证高可用,这些容器一般都运行在多个VM上,服务实例前是一层诸如HAPROXY的负载均衡器,它们负责在各个实例间分发请求。数人云分测试、演示、生产三种环境进行持续集成、发布,同时数人云组件通过Docker+Mesos+Marathon进行应用容器的封装下发和管理。首先说下我们容器发布遇到的问题——配置文件多,如何进行统一的管理?

我们由于采用微服务架构,就产生了各个模块的配置,导致配置文件过多;其次数人云的三套环境,如MySQL等基础组件IP、Port等配置不同,导致配置成倍增加;最后采用高可用架构,也造成了配置文件的增多。 下面是数人云Mesos系统架构流程图:









Marathon、Jenkins作为Framework注册在mesos-master上,动态调度mesos-slave资源。

Marathon负责应用的发布

Jenkins负责代码打包、镜像构建

Mesos Framework截图如下:









若单纯-v的挂载方式需提前将配置文件放在mesos-slave所在的宿主机上,新加slave时也需进行相同的操作,且当配置文件需要更新时,需更新每台mesos-slave宿主机上的配置文件,这显然不够灵活,所以我们刚开始采用应用容器启动下载配置中心文件的方式。

早期的配置中心,如下图所示:









此时存在的问题有:

因为是多种环境,虽然把这些配置都在Configserver上集中配置,但是需要手动修改这些配置。手动修改容易出错,例如Dev更新了一个服务,可能过了一周才会更新到生产环境。那个时候再去修改生产就很容易出错,导致无法运行。

如果配置发生了Bug需要回滚,手动修改也是不合适的。

我们进行了改进,引进Jenkins后工作流程如下图:









我们用Jenkins把它们整体串起来,我们的第一个工作是把所有的配置文件抽象化,各种环境的文件抽象出来一个模板,放在GitLab上。它的数据是放在数据库里面,这样组合起来是一个完整的配置文件。各个环境的值是不一样的。 我们的运维平台触发Jenkins,Jenkins去调度我们的ConfigCenter API,它传入两个参数,一个是需要更新的环境,另一个是更新哪个服务。之后API去做对比,从数据库去读现有的配置文件的模板Tag,再去读新模板的Tag进行对比。

如果这个文件需要更新,把它从数据库拉过来,数据做匹配,渲染成我们最终的配置文件,再传到Gitlab上。剩下的通过Jenkins 触发 Configserver去调Gitlab下载最新的配置文件到Configserver服务器,Jenkins再去调用Marathon去重启服务,服务就会成功更新配置文件。 这很好解决了配置文件对应文件,但还是存在以下一些问题:

配置格式不统一,配置有env 、congfig.js 、.yaml 、.xml 等配置文件,各种配置文件需要在应用容器发布前进行替换,当新增配置文件项时,需重新编写模版,替换匹配内容较为繁琐。

Marathon发布应用采用了配置文件的方式,在Marathon界面看不到配置文件的内容,需后台查看,增加了运维复杂度。

后来我们对应用进行env化改造,统一配置文件格式,且配置通过变量传递给Marathon,使得所有配置在Marathon界面上可见 。

以下是具体的工作,我们对开发进行了规约。


产品模块GitHub目录规约结构


除了代码和产品开发的一些文件外,还需要规约一下目录结构:








在GitHub中更新env文件,这个由开发提供维护,里面有对应env文件如下图:








改进后具体的流程图如下:







以上主要对配置文件进行env化,减少配置替换复杂度,将配置存在于Marathon发布脚本中。

更新后产生的marathon applist:









单个应用容器配置:









采用env化有助于配置文件的统一维护和管理,新版Marathon很好的支持了应用的更新和回滚,除去了容器启动对静态配置文件的依赖,使应用容器更新发布、回滚更加方便。从界面上可以看到所有容器配置信息,使排错管理也变得方便。

线下数人云企业版组件采用和线上相同的镜像和env变量,通过API获取对应版本的envfile和Docker镜像,之后将所有配置文件抽离到一个配置文件中,实施的同事只需修改这张配置文件,从而省去修改其他配置文件的步骤,使得实施过程更加简单。

以上就是数人云组件配置管理碰到的问题,以及env化解决方式,欢迎大家提出宝贵意见。


Q&A


Q:请问MySQL数据库怎么随Docker迁移?备份和恢复有什么好的建议吗?

A:MySQL现在是固定主机主从同步,没有对MySQL做迁移,我们的数据现在备份是定时全备份,正在尝试使用MariaDB集群Galera Cluster ,但还没有上生产,当然有共享存储的话就最好不过啦。

Q:请问配置文件的话生产环境和开发环境怎么区分?

A:生产环境和测试环境都是隔离的,配置文件配置不同的参数即可。

Q:请问对类似Java应用jdbc、spring.xml等配置文件如何管理?

A:XML配置通过sed替换传入的环境变量。

Q:生产上配置项变更怎么操作?

A:生产配置的值需要修改时 ,在configcenter页面中修改,再触发Jenkins更新配置文件的job, 生产新的配置文件 ,再调用marathon API 更新task进行更新。

Q:业务的配置是和环境配置放在一起的么?

A:是的,都是通过envfile进行统一的。

Q:请问你们对环境变量是采用什么样的管理方法?有相应的命名规范吗?环境变量多了,会出现管理方面的问题吧。

A:环境变量键值由开发维护,运维需要提前了解新增环境变量,目前在配置中心里维护,容器环境变量变量命名规范很重要,我们目前采用服务名+需连接的组件名+属性 进行命名的,且环境变量全部大写。 查看全部
本文是数人云工程师志浩在DockOne微信群分享的实录,与大家聊一聊应用容器在配置管理中遇到的问题以及解决方法。
随着Docker技术的火热发展, Docker在代码构建发布中扮演着越来越重要的角色。Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到流行的Linux机器上。Docker非常适用于如下场景:
  • 应用容器的自动化打包和发布;

 
  • 自动化测试和持续集成、发布。


这次主要和大家聊聊应用容器在配置管理中遇到的问题。首先是介绍现有容器常用的配置文件加载方式,接下来重点介绍数人云组件在自动化打包和发布遇到的问题和解决方法。


现有的主要Docker加载配置的方式


首先简单介绍下现有容器的加载配置文件的方式。

挂载宿主机配置文件的方式

通过docker run -v 参数将宿主机上的配置文件挂载到容器指定目录中如:
docker run -v /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf --name myredis redis redis-server /usr/local/etc/redis/redis.conf


这种方式对于单实例应用比较方便。

下载配置中心文件的方式

这种方法首先需要建立配置中心,例如用Nginx等Web服务组件,提前将配置文件放在指定目录,在Dokcerfile entrypoint中拉取配置中心文件的脚本,之后容器启动就自动拉取配置中心的配置。

通过环境变量传入到容器中

通过docker run -e 参数将将环境变量传入到容器如:
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.6


应用容器的自动化打包和发布中遇到的问题


数人云组件采用微服务架构,将服务拆分,分别采用相对独立的服务对各方面进行管理,彼此之间使用统一的接口来进行交流,架构变得复杂,但优势非常明显。为了保证高可用,这些容器一般都运行在多个VM上,服务实例前是一层诸如HAPROXY的负载均衡器,它们负责在各个实例间分发请求。数人云分测试、演示、生产三种环境进行持续集成、发布,同时数人云组件通过Docker+Mesos+Marathon进行应用容器的封装下发和管理。首先说下我们容器发布遇到的问题——配置文件多,如何进行统一的管理?

我们由于采用微服务架构,就产生了各个模块的配置,导致配置文件过多;其次数人云的三套环境,如MySQL等基础组件IP、Port等配置不同,导致配置成倍增加;最后采用高可用架构,也造成了配置文件的增多。 下面是数人云Mesos系统架构流程图:


1.png




Marathon、Jenkins作为Framework注册在mesos-master上,动态调度mesos-slave资源。

Marathon负责应用的发布

Jenkins负责代码打包、镜像构建

Mesos Framework截图如下:


2.png




若单纯-v的挂载方式需提前将配置文件放在mesos-slave所在的宿主机上,新加slave时也需进行相同的操作,且当配置文件需要更新时,需更新每台mesos-slave宿主机上的配置文件,这显然不够灵活,所以我们刚开始采用应用容器启动下载配置中心文件的方式。

早期的配置中心,如下图所示:


3.png




此时存在的问题有:

因为是多种环境,虽然把这些配置都在Configserver上集中配置,但是需要手动修改这些配置。手动修改容易出错,例如Dev更新了一个服务,可能过了一周才会更新到生产环境。那个时候再去修改生产就很容易出错,导致无法运行。

如果配置发生了Bug需要回滚,手动修改也是不合适的。

我们进行了改进,引进Jenkins后工作流程如下图:



4.png



我们用Jenkins把它们整体串起来,我们的第一个工作是把所有的配置文件抽象化,各种环境的文件抽象出来一个模板,放在GitLab上。它的数据是放在数据库里面,这样组合起来是一个完整的配置文件。各个环境的值是不一样的。 我们的运维平台触发Jenkins,Jenkins去调度我们的ConfigCenter API,它传入两个参数,一个是需要更新的环境,另一个是更新哪个服务。之后API去做对比,从数据库去读现有的配置文件的模板Tag,再去读新模板的Tag进行对比。

如果这个文件需要更新,把它从数据库拉过来,数据做匹配,渲染成我们最终的配置文件,再传到Gitlab上。剩下的通过Jenkins 触发 Configserver去调Gitlab下载最新的配置文件到Configserver服务器,Jenkins再去调用Marathon去重启服务,服务就会成功更新配置文件。 这很好解决了配置文件对应文件,但还是存在以下一些问题:

配置格式不统一,配置有env 、congfig.js 、.yaml 、.xml 等配置文件,各种配置文件需要在应用容器发布前进行替换,当新增配置文件项时,需重新编写模版,替换匹配内容较为繁琐。

Marathon发布应用采用了配置文件的方式,在Marathon界面看不到配置文件的内容,需后台查看,增加了运维复杂度。

后来我们对应用进行env化改造,统一配置文件格式,且配置通过变量传递给Marathon,使得所有配置在Marathon界面上可见 。

以下是具体的工作,我们对开发进行了规约。


产品模块GitHub目录规约结构


除了代码和产品开发的一些文件外,还需要规约一下目录结构:


9.png



在GitHub中更新env文件,这个由开发提供维护,里面有对应env文件如下图:


5.png



改进后具体的流程图如下:

6.png



以上主要对配置文件进行env化,减少配置替换复杂度,将配置存在于Marathon发布脚本中。

更新后产生的marathon applist:



7.png



单个应用容器配置:


8.png




采用env化有助于配置文件的统一维护和管理,新版Marathon很好的支持了应用的更新和回滚,除去了容器启动对静态配置文件的依赖,使应用容器更新发布、回滚更加方便。从界面上可以看到所有容器配置信息,使排错管理也变得方便。

线下数人云企业版组件采用和线上相同的镜像和env变量,通过API获取对应版本的envfile和Docker镜像,之后将所有配置文件抽离到一个配置文件中,实施的同事只需修改这张配置文件,从而省去修改其他配置文件的步骤,使得实施过程更加简单。

以上就是数人云组件配置管理碰到的问题,以及env化解决方式,欢迎大家提出宝贵意见。


Q&A


Q:请问MySQL数据库怎么随Docker迁移?备份和恢复有什么好的建议吗?

A:MySQL现在是固定主机主从同步,没有对MySQL做迁移,我们的数据现在备份是定时全备份,正在尝试使用MariaDB集群Galera Cluster ,但还没有上生产,当然有共享存储的话就最好不过啦。

Q:请问配置文件的话生产环境和开发环境怎么区分?

A:生产环境和测试环境都是隔离的,配置文件配置不同的参数即可。

Q:请问对类似Java应用jdbc、spring.xml等配置文件如何管理?

A:XML配置通过sed替换传入的环境变量。

Q:生产上配置项变更怎么操作?

A:生产配置的值需要修改时 ,在configcenter页面中修改,再触发Jenkins更新配置文件的job, 生产新的配置文件 ,再调用marathon API 更新task进行更新。

Q:业务的配置是和环境配置放在一起的么?

A:是的,都是通过envfile进行统一的。

Q:请问你们对环境变量是采用什么样的管理方法?有相应的命名规范吗?环境变量多了,会出现管理方面的问题吧。

A:环境变量键值由开发维护,运维需要提前了解新增环境变量,目前在配置中心里维护,容器环境变量变量命名规范很重要,我们目前采用服务名+需连接的组件名+属性 进行命名的,且环境变量全部大写。

响应银监会十三五规划之拥抱容器系列(一):微服务化

宁静胡同 发表了文章 • 0 个评论 • 360 次浏览 • 2016-07-21 11:50 • 来自相关话题

中国银监会7月15日就《中国银行业信息科技“十三五”发展规划监管指导意见(征求意见稿)》(以下简称指导意见)公开征求意见。从提升信息科技治理水平,深化科技创新,推进互联网、大数据、云计算新技术应用等方面入手,指出健全产品研发管理机制,加强信息安全管理,提升信息科技风险管理水平,推进科技开发协作等方面重点工作任务。

指导意见同时指出,银行业应该适应互联网环境下计算资源弹性变化和快速部署等需求,开展云计算架构规划,制定云计算应用策略。探索构建私有云平台,采用成熟度高、开放性强的计算虚拟化、容器虚拟化、分布式存储、网络虚拟化等技术,建立资源池,形成资源弹性供给、灵活调度和动态计量的私有云平台。探索建立银行业金融公共服务行业云,构建私有云与行业云相结合的混合云应用。同步开展应用架构规划,构建与云计算基础设施相适应的应用架构,自主设计或推动应用开发商实施应用架构改造,并降低应用与基础架构的耦合度。稳步实施架构迁移,到“十三五”末期,面向互联网场景的主要信息系统尽可能迁移至云计算架构平台。

银行业拥抱云计算已经是必然趋势,而容器则是其中的关键技术。数人云推出了传统金融业Docker实践系列组图与文章,将一一为大家展现传统金融业的转型过程中的技术细节与实践心得,欢迎大家持续关注。







数人金融容器云

作为基于Docker的最轻量级PaaS平台,数人金融容器云致力于打造金融领域专属的云原生应用平台,实现秒级启停,帮助客户及时响应高并发等新型业务需求;同时,借助容器技术,使应用的交付变得标准,极大地消除技术部署的局限性,提高客户产品的交付及运维效率;数人金融容器云平台自身具备高可用能力,以最大程度保证对工作集群不间断管控,工作集群内的各组件也具备高可用特性,进一步保障了客户的容器化应用安全、可靠、稳定运行;提供从主机网络到应用容器实例的多级实时监控和告警机制,极大降低了金融IT运维风险。

目前,数人云在金融领域已有多家合作客户,帮助金融客户在互联网+时代下构建开放业务新形态,从平台转型、产品创新、服务交付等层面推进金融业信息化变革,激发创新活力。


  查看全部
中国银监会7月15日就《中国银行业信息科技“十三五”发展规划监管指导意见(征求意见稿)》(以下简称指导意见)公开征求意见。从提升信息科技治理水平,深化科技创新,推进互联网、大数据、云计算新技术应用等方面入手,指出健全产品研发管理机制,加强信息安全管理,提升信息科技风险管理水平,推进科技开发协作等方面重点工作任务。

指导意见同时指出,银行业应该适应互联网环境下计算资源弹性变化和快速部署等需求,开展云计算架构规划,制定云计算应用策略。探索构建私有云平台,采用成熟度高、开放性强的计算虚拟化、容器虚拟化、分布式存储、网络虚拟化等技术,建立资源池,形成资源弹性供给、灵活调度和动态计量的私有云平台。探索建立银行业金融公共服务行业云,构建私有云与行业云相结合的混合云应用。同步开展应用架构规划,构建与云计算基础设施相适应的应用架构,自主设计或推动应用开发商实施应用架构改造,并降低应用与基础架构的耦合度。稳步实施架构迁移,到“十三五”末期,面向互联网场景的主要信息系统尽可能迁移至云计算架构平台。

银行业拥抱云计算已经是必然趋势,而容器则是其中的关键技术。数人云推出了传统金融业Docker实践系列组图与文章,将一一为大家展现传统金融业的转型过程中的技术细节与实践心得,欢迎大家持续关注。


654082800374343878.png


数人金融容器云

作为基于Docker的最轻量级PaaS平台,数人金融容器云致力于打造金融领域专属的云原生应用平台,实现秒级启停,帮助客户及时响应高并发等新型业务需求;同时,借助容器技术,使应用的交付变得标准,极大地消除技术部署的局限性,提高客户产品的交付及运维效率;数人金融容器云平台自身具备高可用能力,以最大程度保证对工作集群不间断管控,工作集群内的各组件也具备高可用特性,进一步保障了客户的容器化应用安全、可靠、稳定运行;提供从主机网络到应用容器实例的多级实时监控和告警机制,极大降低了金融IT运维风险。

目前,数人云在金融领域已有多家合作客户,帮助金融客户在互联网+时代下构建开放业务新形态,从平台转型、产品创新、服务交付等层面推进金融业信息化变革,激发创新活力。


 

Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包

宁静胡同 发表了文章 • 0 个评论 • 715 次浏览 • 2016-07-13 15:10 • 来自相关话题

在本文中数人云将带大家了解如何利用Docker Compose创建一套分布式应用捆绑包,并将其作为Docker Stack在Docker Swarm Mode中进行部署。


Docker 1.12的首套候选发行版于三周之前公布,而近期又有更多新功能计划被添加至该版本当中。


下面首先来看各项新的功能特性:
内置编排机制:通常来讲,应用利用一个Docker Compose文件进行定义。此定义由多个被部署在不同主机上的容器共同构成。这种作法除了能够避免单点故障(简称SPOF)之外,也能够让应用具备弹性。目前包括Docker Swarm、Kubernetes以及Mesos在内的多种编排框架都允许大家对此类应用进行编排。不过现在我们又有了新的选择——Docker Engine如今迎来了内置编排机制。更多细节内容将在后文中进行说明。Service:现在大家可以利用docker service create 命令轻松创建一项复制且分布式的负载均衡服务。该应用可实现“理想状态”,例如运行三套Couchbase容器,并具备自我修复能力。Docker引擎能够确保必要容器数量始终运行于集群当中。如果某容器发生故障,那么另一容器将旋即启动。如果某台节点发生故障,则该节点上的容器会在另一节点上启动。稍后我们将详细说明其作用。零配置安全性: Docker 1.12采用相互验证TLS,能够对swarm当中各节点间的通信内容进行验证、授权与加密。更多详尽内容将在后文中进行讨论。

Docker Stack与分布式应用捆绑包:分布式应用捆绑包,或者简称DAB,是一种多服务可分发镜像格式。在后文中我们会进一步讨论。


截至目前,大家已经可以选定一个Dockerfile,并利用docker build命令由此创建镜像。使用docker run命令则可启动容器。这条命令亦能够轻松同时启动多套容器。另外,大家也可以使用Docker Compose文件并利用docker-compose scale命令对容器进行规模扩展。









镜像属于单一容器的一种便携式格式。而Docker 1.12当中新推出的分布式应用捆绑包,或者简称DAB,则属于一种新的概念,其专门面向多套容器的迁移需求。每个捆绑包都可作为stack在运行时中进行部署。









感兴趣的朋友可以前往docker.com/dab了解更多与DAB相关的内容。为了简单起见,在这里我们利用类比来进行说明:


kerfile -> 镜像 -> 容器

Docker Compose -> 分布式应用捆绑包 -> Docker Stack

下面我们使用一个Docker Compose文件来创建DAB,并将其作为Docker Stack加以部署。


需要强调的是,这项实验性功能仅存在于1.12-RC2版本当中。


利用Docker Compose创建一个分布式应用捆绑包


Docker Compose CLI添加了一条新的bundle命令。下面来看其具体说明:docker-compose bundle --help
Generate a Docker bundle from the Compose file.

Local images will be pushed to a Docker registry, and remote images
will be pulled to fetch an image digest.

Usage: bundle [options]

Options:
-o, --output PATH Path to write the bundle file to.
Defaults to "<project name>.dsb".
现在,让我们选取一条Docker Compose定义并以此为基础创建DAB。以下为我们的Docker Compose定义内容:version: "2"
services:
db:
container_name: "db"
image: arungupta/oreilly-couchbase:latest
ports:
- 8091:8091
- 8092:8092
- 8093:8093
- 11210:11210
web:
image: arungupta/oreilly-wildfly:latest
depends_on:
- db
environment:
- COUCHBASE_URI=db
ports:
- 8080:8080

此Compose文件会启动WildFly与Couchbase服务器。其中WildFly服务器中已经预部署了一款Java EE应用,且接入Couchbase服务器并允许利用REST API执行CRUD操作。该文件的源代码来自:github.com/arun-gupta/oreilly-docker-book/blob/master/hello-javaee/docker-compose.yml。利用它生成一个应用捆绑包:docker-compose bundle
WARNING: Unsupported key 'depends_on' in services.web - ignoring
WARNING: Unsupported key 'container_name' in services.db - ignoring
Wrote bundle to hellojavaee.dsb


depends_on只负责创建两项服务之间的依赖性,并以特定顺序对二者进行启动。这能确保Docker容器首先启动,而运行在其中的应用则需要更长时间才能启动完成。因此,此属性只在一定程度上解决了这一问题。


container_name能够为该容器提供一个特定名称。对特定容器名称的依赖性为紧密耦合,且不允许我们对该容器进行规模伸缩。因此这里我们暂时忽略这两条警告。此命令会利用Compose项目名(也就是其目录名称)生成一个文件。因此在本示例中,生成的文件名为hellojavaee.dsb。此文件的扩展名在RC3中则为.dab。此生成的应用捆绑包内容如下所示:{
"services": {
"db": {
"Image": "arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c",
"Networks": [
"default"
],
"Ports": [
{
"Port": 8091,
"Protocol": "tcp"
},
{
"Port": 8092,
"Protocol": "tcp"
},
{
"Port": 8093,
"Protocol": "tcp"
},
{
"Port": 11210,
"Protocol": "tcp"
}
]
},
"web": {
"Env": [
"COUCHBASE_URI=db"
],
"Image": "arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914",
"Networks": [
"default"
],
"Ports": [
{
"Port": 8080,
"Protocol": "tcp"
}
]
}
},
"version": "0.1"
}


此文件为包含在应用内的各项服务提供完整的描述。当然,未来我们应该可以使用其它容器格式,例如Rkt或者VM等形式。不过就目前来讲,其还仅支持Docker这一种格式。


在Docker中进行Swarm Mode初始化


正如之前所提到,目前“理想状态”由Docker Swarm负责保持。而其现在已经被纳入Docker Engine当中。在本篇文章中,我们使用新增的一条命令,即docker swarm:docker swarm --help

Usage: docker swarm COMMAND

Manage Docker Swarm

Options:
--help Print usage

Commands:
init Initialize a Swarm
join Join a Swarm as a node and/or manager
update Update the Swarm
leave Leave a Swarm
inspect Inspect the Swarm

Run 'docker swarm COMMAND --help' for more information on a command.
在Docker Engine中对一个Swarm节点(作为工作节点)进行初始化:docker swarm init
Swarm initialized: current node (ek9p1k8r8ox7iiua5c247skci) is now a manager.

关于该节点的更多细节信息可利用docker swarm inspect命令进行查看。docker swarm inspect
[
{
"ID": "1rcvu7m9mv2c8hiaijr7an9zk",
"Version": {
"Index": 1895
},
"CreatedAt": "2016-07-01T23:52:38.074748177Z",
"UpdatedAt": "2016-07-02T04:54:32.79093117Z",
"Spec": {
"Name": "default",
"AcceptancePolicy":{
"Policies": [
{
"Role": "worker",
"Autoaccept": true
},
{
"Role": "manager",
"Autoaccept":false
}
]
},
"Orchestration": {
"TaskHistoryRetentionLimit":10
},
"Raft": {
"SnapshotInterval": 10000,
"LogEntriesForSlowFollowers":500,
"HeartbeatTick":1,
"ElectionTick":3
},
"Dispatcher": {
"HeartbeatPeriod": 5000000000
},
"CAConfig": {
"NodeCertExpiry": 7776000000000000
}
}
}
]
从输出结果中可以看到,该节点只属于工作节点而非管理节点。如果在单节点集群当中,这样的设置并无不妥。不过在多节点集群当中,则应至少存在一个管理节点。


部署Docker Stack


利用docker deploy命令创建一个stack:docker deploy -f hellojavaee.dsb hellojavaee
Loading bundle from hellojavaee.dsb
Creating network hellojavaee_default
Creating service hellojavaee_db
Creating service hellojavaee_web
下面来看各服务列表:docker service ls
ID NAME REPLICAS IMAGE COMMAND
2g8kmrimztes hellojavaee_web 1/1 arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914
46xhlb15cc60 hellojavaee_db 1/1 arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c

在输出结果中,我们可以看到正在运行的两项服务,分别为WildFly与Couchbase。 Service概念同样新增于Docker 1.12版本,其负责为我们提供“理想状态”,而具体实现则由Docker Engine负责。使用docker ps命令显示当前正在运行的容器列表:CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
622756277f40 arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c "/entrypoint.sh /opt/" 3 seconds ago Up 1 seconds 8091-8093/tcp, 11207/tcp, 11210-11211/tcp, 18091-18092/tcp hellojavaee_db.1.19enwdt6i5m853m5675tx3z29
abf8703ed713 arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914 "/opt/jboss/wildfly/b" 3 seconds ago Up 1 seconds 8080/tcp hellojavaee_web.1.70piloz6j4zt06co8htzisgyl

WildFly容器会在Couchbase容器启动并运行之前先行启动。这意味着Java EE应用会尝试接入Couchbase服务器但发生失败。因此,该应用将永远无法成功完成引导。


自我修复Docker Service


Docker Service负责保持应用的“理想状态”。在本示例中,我们的理想状态是确保特定服务有且只有一套容器与之对应且持续运行。如果我们移除该容器,而非服务,则该服务会自动重启容器。使用以下命令移除容器:docker rm -f abf8703ed713

请注意,这里之所以要使用-f,是因为该容器已经处于运行状态。Docker 1.12自我修复机制会介入并自动重启此容器。现在再次打开运行容器列表:CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db483ac27e41 arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914 "/opt/jboss/wildfly/b" 1 seconds ago Up Less than a second 8080/tcp hellojavaee_web.1.ddvwdmojjysf46d4n3x4g8uv4
622756277f40 arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c "/entrypoint.sh /opt/" 26 seconds ago Up 25 seconds 8091-8093/tcp, 11207/tcp, 11210-11211/tcp, 18091-18092/tcp hellojavaee_db.1.19enwdt6i5m853m5675tx3z29
结果显示新容器已经启动完成。检查WildFly服务:docker service inspect hellojavaee_web
[
{
"ID": "54otfi6dc9bis7z6gc6ubynwc",
"Version": {
"Index": 328
},
"CreatedAt": "2016-07-02T01:36:35.735767569Z",
"UpdatedAt": "2016-07-02T01:36:35.739240775Z",
"Spec": {
"Name": "hellojavaee_web",
"Labels": {
"com.docker.stack.namespace": "hellojavaee"
},
"TaskTemplate": {
"ContainerSpec": {
"Image": "arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914",
"Env": [
"COUCHBASE_URI=db"
]
}
},
"Mode": {
"Replicated": {
"Replicas": 1
}
},
"Networks": [
{
"Target": "epw57lz7txtfchmbf6u0cimis",
"Aliases": [
"web"
]
}
],
"EndpointSpec": {
"Mode": "vip",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 8080
}
]
}
},
"Endpoint": {
"Spec": {},
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 8080,
"PublishedPort": 30004
}
],
"VirtualIPs": [
{
"NetworkID": "9lpz688ir3pzexubkcb828ikg",
"Addr": "10.255.0.5/16"
},
{
"NetworkID": "epw57lz7txtfchmbf6u0cimis",
"Addr": "10.0.0.4/24"
}
]
}
}
]




Swarm会将随机端口分配给该服务,我们也可以利用docker service update命令进行手动更新。在本示例中,容器的端口8080被映射至主机上的端口30004。



进行应用验证


下面检查该应用是否已经成功部署:curl http://localhost:30004/books/resources/book
[{"books":0}]


为该应用添加新的book:curl -v \
> -H "Content-Type: application/json" \
> -X POST -d '{
> "isbn": "978-1-4919-1889-0",
> "name": "Minecraft Modding with Forge",
> "cost": 29.99
> }' \
> http://localhost:30004/books/resources/book
* Trying ::1...
* Connected to localhost (::1) port 30004 (#0)
> POST /books/resources/book HTTP/1.1
> Host: localhost:30004
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 92
>
* upload completely sent off: 92 out of 92 bytes
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Powered-By: Undertow/1
< Server: WildFly/10
< Content-Type: application/octet-stream
< Content-Length: 88
< Date: Sat, 02 Jul 2016 01:39:49 GMT
<
* Connection #0 to host localhost left intact
{"name":"Minecraft Mhttp://localhost:30004/books/r ... ot%3B}



再次验证该book:curl http://localhost:30004/books/resources/book
[{"books":{"name":"Minecraft Modding with Forge","cost":29.99,"id":"1","isbn":"978-1-4919-1889-0"}}, {"books":1}]
欲了解更多与此Java应用相关的信息,请访问github.com/arun-gupta/oreilly-docker-book/tree/master/hello-javaee。 查看全部
在本文中数人云将带大家了解如何利用Docker Compose创建一套分布式应用捆绑包,并将其作为Docker Stack在Docker Swarm Mode中进行部署。


Docker 1.12的首套候选发行版于三周之前公布,而近期又有更多新功能计划被添加至该版本当中。


下面首先来看各项新的功能特性:
  • 内置编排机制:通常来讲,应用利用一个Docker Compose文件进行定义。此定义由多个被部署在不同主机上的容器共同构成。这种作法除了能够避免单点故障(简称SPOF)之外,也能够让应用具备弹性。目前包括Docker Swarm、Kubernetes以及Mesos在内的多种编排框架都允许大家对此类应用进行编排。不过现在我们又有了新的选择——Docker Engine如今迎来了内置编排机制。更多细节内容将在后文中进行说明。
  • Service:现在大家可以利用docker service create 命令轻松创建一项复制且分布式的负载均衡服务。该应用可实现“理想状态”,例如运行三套Couchbase容器,并具备自我修复能力。Docker引擎能够确保必要容器数量始终运行于集群当中。如果某容器发生故障,那么另一容器将旋即启动。如果某台节点发生故障,则该节点上的容器会在另一节点上启动。稍后我们将详细说明其作用。
  • 零配置安全性: Docker 1.12采用相互验证TLS,能够对swarm当中各节点间的通信内容进行验证、授权与加密。更多详尽内容将在后文中进行讨论。


Docker Stack与分布式应用捆绑包:分布式应用捆绑包,或者简称DAB,是一种多服务可分发镜像格式。在后文中我们会进一步讨论。


截至目前,大家已经可以选定一个Dockerfile,并利用docker build命令由此创建镜像。使用docker run命令则可启动容器。这条命令亦能够轻松同时启动多套容器。另外,大家也可以使用Docker Compose文件并利用docker-compose scale命令对容器进行规模扩展。



1.png



镜像属于单一容器的一种便携式格式。而Docker 1.12当中新推出的分布式应用捆绑包,或者简称DAB,则属于一种新的概念,其专门面向多套容器的迁移需求。每个捆绑包都可作为stack在运行时中进行部署。


2.png




感兴趣的朋友可以前往docker.com/dab了解更多与DAB相关的内容。为了简单起见,在这里我们利用类比来进行说明:


kerfile -> 镜像 -> 容器

Docker Compose -> 分布式应用捆绑包 -> Docker Stack

下面我们使用一个Docker Compose文件来创建DAB,并将其作为Docker Stack加以部署。


需要强调的是,这项实验性功能仅存在于1.12-RC2版本当中。


利用Docker Compose创建一个分布式应用捆绑包


Docker Compose CLI添加了一条新的bundle命令。下面来看其具体说明:
docker-compose bundle --help
Generate a Docker bundle from the Compose file.

Local images will be pushed to a Docker registry, and remote images
will be pulled to fetch an image digest.

Usage: bundle [options]

Options:
-o, --output PATH Path to write the bundle file to.
Defaults to "<project name>.dsb".

现在,让我们选取一条Docker Compose定义并以此为基础创建DAB。以下为我们的Docker Compose定义内容:
version: "2"
services:
db:
container_name: "db"
image: arungupta/oreilly-couchbase:latest
ports:
- 8091:8091
- 8092:8092
- 8093:8093
- 11210:11210
web:
image: arungupta/oreilly-wildfly:latest
depends_on:
- db
environment:
- COUCHBASE_URI=db
ports:
- 8080:8080


此Compose文件会启动WildFly与Couchbase服务器。其中WildFly服务器中已经预部署了一款Java EE应用,且接入Couchbase服务器并允许利用REST API执行CRUD操作。该文件的源代码来自:github.com/arun-gupta/oreilly-docker-book/blob/master/hello-javaee/docker-compose.yml。利用它生成一个应用捆绑包:
docker-compose bundle
WARNING: Unsupported key 'depends_on' in services.web - ignoring
WARNING: Unsupported key 'container_name' in services.db - ignoring
Wrote bundle to hellojavaee.dsb


depends_on只负责创建两项服务之间的依赖性,并以特定顺序对二者进行启动。这能确保Docker容器首先启动,而运行在其中的应用则需要更长时间才能启动完成。因此,此属性只在一定程度上解决了这一问题。


container_name能够为该容器提供一个特定名称。对特定容器名称的依赖性为紧密耦合,且不允许我们对该容器进行规模伸缩。因此这里我们暂时忽略这两条警告。此命令会利用Compose项目名(也就是其目录名称)生成一个文件。因此在本示例中,生成的文件名为hellojavaee.dsb。此文件的扩展名在RC3中则为.dab。此生成的应用捆绑包内容如下所示:
{
"services": {
"db": {
"Image": "arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c",
"Networks": [
"default"
],
"Ports": [
{
"Port": 8091,
"Protocol": "tcp"
},
{
"Port": 8092,
"Protocol": "tcp"
},
{
"Port": 8093,
"Protocol": "tcp"
},
{
"Port": 11210,
"Protocol": "tcp"
}
]
},
"web": {
"Env": [
"COUCHBASE_URI=db"
],
"Image": "arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914",
"Networks": [
"default"
],
"Ports": [
{
"Port": 8080,
"Protocol": "tcp"
}
]
}
},
"version": "0.1"
}


此文件为包含在应用内的各项服务提供完整的描述。当然,未来我们应该可以使用其它容器格式,例如Rkt或者VM等形式。不过就目前来讲,其还仅支持Docker这一种格式。


在Docker中进行Swarm Mode初始化


正如之前所提到,目前“理想状态”由Docker Swarm负责保持。而其现在已经被纳入Docker Engine当中。在本篇文章中,我们使用新增的一条命令,即docker swarm:
docker swarm --help

Usage: docker swarm COMMAND

Manage Docker Swarm

Options:
--help Print usage

Commands:
init Initialize a Swarm
join Join a Swarm as a node and/or manager
update Update the Swarm
leave Leave a Swarm
inspect Inspect the Swarm

Run 'docker swarm COMMAND --help' for more information on a command.

在Docker Engine中对一个Swarm节点(作为工作节点)进行初始化:
docker swarm init
Swarm initialized: current node (ek9p1k8r8ox7iiua5c247skci) is now a manager.


关于该节点的更多细节信息可利用docker swarm inspect命令进行查看。
docker swarm inspect
[
{
"ID": "1rcvu7m9mv2c8hiaijr7an9zk",
"Version": {
"Index": 1895
},
"CreatedAt": "2016-07-01T23:52:38.074748177Z",
"UpdatedAt": "2016-07-02T04:54:32.79093117Z",
"Spec": {
"Name": "default",
"AcceptancePolicy":{
"Policies": [
{
"Role": "worker",
"Autoaccept": true
},
{
"Role": "manager",
"Autoaccept":false
}
]
},
"Orchestration": {
"TaskHistoryRetentionLimit":10
},
"Raft": {
"SnapshotInterval": 10000,
"LogEntriesForSlowFollowers":500,
"HeartbeatTick":1,
"ElectionTick":3
},
"Dispatcher": {
"HeartbeatPeriod": 5000000000
},
"CAConfig": {
"NodeCertExpiry": 7776000000000000
}
}
}
]

从输出结果中可以看到,该节点只属于工作节点而非管理节点。如果在单节点集群当中,这样的设置并无不妥。不过在多节点集群当中,则应至少存在一个管理节点。


部署Docker Stack


利用docker deploy命令创建一个stack:
docker deploy -f hellojavaee.dsb hellojavaee
Loading bundle from hellojavaee.dsb
Creating network hellojavaee_default
Creating service hellojavaee_db
Creating service hellojavaee_web

下面来看各服务列表:
docker service ls
ID NAME REPLICAS IMAGE COMMAND
2g8kmrimztes hellojavaee_web 1/1 arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914
46xhlb15cc60 hellojavaee_db 1/1 arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c


在输出结果中,我们可以看到正在运行的两项服务,分别为WildFly与Couchbase。 Service概念同样新增于Docker 1.12版本,其负责为我们提供“理想状态”,而具体实现则由Docker Engine负责。使用docker ps命令显示当前正在运行的容器列表:
CONTAINER ID        IMAGE                                                                                                 COMMAND                  CREATED             STATUS              PORTS                                                        NAMES
622756277f40 arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c "/entrypoint.sh /opt/" 3 seconds ago Up 1 seconds 8091-8093/tcp, 11207/tcp, 11210-11211/tcp, 18091-18092/tcp hellojavaee_db.1.19enwdt6i5m853m5675tx3z29
abf8703ed713 arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914 "/opt/jboss/wildfly/b" 3 seconds ago Up 1 seconds 8080/tcp hellojavaee_web.1.70piloz6j4zt06co8htzisgyl


WildFly容器会在Couchbase容器启动并运行之前先行启动。这意味着Java EE应用会尝试接入Couchbase服务器但发生失败。因此,该应用将永远无法成功完成引导。


自我修复Docker Service


Docker Service负责保持应用的“理想状态”。在本示例中,我们的理想状态是确保特定服务有且只有一套容器与之对应且持续运行。如果我们移除该容器,而非服务,则该服务会自动重启容器。使用以下命令移除容器:
docker rm -f abf8703ed713


请注意,这里之所以要使用-f,是因为该容器已经处于运行状态。Docker 1.12自我修复机制会介入并自动重启此容器。现在再次打开运行容器列表:
CONTAINER ID        IMAGE                                                                                                 COMMAND                  CREATED             STATUS                  PORTS                                                        NAMES
db483ac27e41 arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914 "/opt/jboss/wildfly/b" 1 seconds ago Up Less than a second 8080/tcp hellojavaee_web.1.ddvwdmojjysf46d4n3x4g8uv4
622756277f40 arungupta/oreilly-couchbase@sha256:f150fcb9fca5392075c96f1baffc7f893858ba763f3c05cf0908ef2613cbf34c "/entrypoint.sh /opt/" 26 seconds ago Up 25 seconds 8091-8093/tcp, 11207/tcp, 11210-11211/tcp, 18091-18092/tcp hellojavaee_db.1.19enwdt6i5m853m5675tx3z29

结果显示新容器已经启动完成。检查WildFly服务:
docker service inspect hellojavaee_web
[
{
"ID": "54otfi6dc9bis7z6gc6ubynwc",
"Version": {
"Index": 328
},
"CreatedAt": "2016-07-02T01:36:35.735767569Z",
"UpdatedAt": "2016-07-02T01:36:35.739240775Z",
"Spec": {
"Name": "hellojavaee_web",
"Labels": {
"com.docker.stack.namespace": "hellojavaee"
},
"TaskTemplate": {
"ContainerSpec": {
"Image": "arungupta/oreilly-wildfly@sha256:d567ade7bb82ba8f15a85df0c6d692d85c15ec5a78d8826dfba92756babcb914",
"Env": [
"COUCHBASE_URI=db"
]
}
},
"Mode": {
"Replicated": {
"Replicas": 1
}
},
"Networks": [
{
"Target": "epw57lz7txtfchmbf6u0cimis",
"Aliases": [
"web"
]
}
],
"EndpointSpec": {
"Mode": "vip",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 8080
}
]
}
},
"Endpoint": {
"Spec": {},
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 8080,
"PublishedPort": 30004
}
],
"VirtualIPs": [
{
"NetworkID": "9lpz688ir3pzexubkcb828ikg",
"Addr": "10.255.0.5/16"
},
{
"NetworkID": "epw57lz7txtfchmbf6u0cimis",
"Addr": "10.0.0.4/24"
}
]
}
}
]




Swarm会将随机端口分配给该服务,我们也可以利用docker service update命令进行手动更新。在本示例中,容器的端口8080被映射至主机上的端口30004。



进行应用验证


下面检查该应用是否已经成功部署:
curl http://localhost:30004/books/resources/book
[{"books":0}]


为该应用添加新的book:
curl -v \
> -H "Content-Type: application/json" \
> -X POST -d '{
> "isbn": "978-1-4919-1889-0",
> "name": "Minecraft Modding with Forge",
> "cost": 29.99
> }' \
> http://localhost:30004/books/resources/book
* Trying ::1...
* Connected to localhost (::1) port 30004 (#0)
> POST /books/resources/book HTTP/1.1
> Host: localhost:30004
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 92
>
* upload completely sent off: 92 out of 92 bytes
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Powered-By: Undertow/1
< Server: WildFly/10
< Content-Type: application/octet-stream
< Content-Length: 88
< Date: Sat, 02 Jul 2016 01:39:49 GMT
<
* Connection #0 to host localhost left intact
{"name":"Minecraft Mhttp://localhost:30004/books/r ... ot%3B}




再次验证该book:
curl http://localhost:30004/books/resources/book
[{"books":{"name":"Minecraft Modding with Forge","cost":29.99,"id":"1","isbn":"978-1-4919-1889-0"}}, {"books":1}]

欲了解更多与此Java应用相关的信息,请访问github.com/arun-gupta/oreilly-docker-book/tree/master/hello-javaee。

中国开源云联盟容器工作组第一次会议召开

宁静胡同 发表了文章 • 0 个评论 • 416 次浏览 • 2016-07-08 16:24 • 来自相关话题

7月7日,中国开源云联盟WG11容器工作组第一次会议在京召开,会议的主题为“容器技术与标准交流会”。此次会议由中国电子技术标准化研究院主办,参与方包括中国开源云联盟容器工作组组长单位数人云,副组长单位CNTV,以及Hyper,去哪儿网,VMware,Intel,中国移动。







中国开源云联盟容器工作组第一次会议召开


会议上,参会单位首先围绕容器生态圈展开了讨论,数人云CTO肖德时和Hyper CTO王旭对容器生态圈以及容器发展趋势进行了分享,吕晓旭分享了去哪儿网使用Mesos+Docker技术在集群、日志收集等场景下的应用情况;张海宁分享了VMware针对容器研究情况,包括容器和虚拟化技术融合的研究以及纯容器数据中心的研究情况;杨剑浩分享了中国移动研究院容器技术在CRM等方面的应用情况;何钦钦分享了CNTV使用容器技术实现快速交付和资源回收的应用案例。此外,参会专家还针对容器在应用情况面临的问题和遇到的挑战展开了讨论。最后,中国电子技术标准化研究院高级工程师陈志峰介绍了我国云计算综合标准化指南、标准体系框架以及云计算标准化白皮书情况,为实现容器领域开展标准化工作提供借鉴。

后续容器工作组将开展我国容器应用和标准化白皮书的编制工作,白皮书编制工作的开展将有利于推动容器技术在国内的落地,并为建立符合中国本地化特征的容器标准奠定基础。


相关背景


中国开源云联盟由Intel、新浪网、中标软件和上海交大于2012年8月共同发起创立,是中国最早专注于OpenStack的专业联盟。作为领先的云计算创新技术实践者,数人云一直致力于推动开源技术的发展,并荣膺联盟挂靠中国电子技术标准化研究院后的首批成员单位。目前,联盟下设工作组工作范围从OpenStack逐渐向开源云计算生态圈的其他技术方向延伸,涉及我国云计算领域较热点的发展趋势,如混合云研究、千节点部署、Ceph开源技术、桌面云技术、容器技术等;同时,部分技术方向已开始探索标准化工作,开展开源标准研究,以及与国家标准、国际标准的配套方式的研究。


5月31日,中国开源云联盟2016年第一次理事会在京召开,会上中国开源云联盟Mesos工作组正式成立,为更好地推进容器及相关技术在中国的落地与实践,Mesos工作组现已正式更名为容器工作组。中国开源云联盟容器工作组旨在推动容器技术在国内的落地,提升容器技术在开源社区的贡献比例,并建立顺应国际技术发展趋势、符合中国本地化特征的容器标准体系。


关于数人云


数人云创始团队来自谷歌、红帽和惠普,在今年3月初公司完成A轮融资,由云启资本领投,思科、策源以及唯猎跟投。作为领先的云计算创新技术实践者,数人云致力于打造最轻量化的PaaS平台,将应用弹性做到极致。基于Docker + Mesos,数人云实现一站式的微服务架构集群系统,最大化地帮助客户实现应用业务在云端的快速部署,解决从客户到云资源的最后一公里。 查看全部
7月7日,中国开源云联盟WG11容器工作组第一次会议在京召开,会议的主题为“容器技术与标准交流会”。此次会议由中国电子技术标准化研究院主办,参与方包括中国开源云联盟容器工作组组长单位数人云,副组长单位CNTV,以及Hyper,去哪儿网,VMware,Intel,中国移动。


685425922798165313.jpg11_.jpg


中国开源云联盟容器工作组第一次会议召开


会议上,参会单位首先围绕容器生态圈展开了讨论,数人云CTO肖德时和Hyper CTO王旭对容器生态圈以及容器发展趋势进行了分享,吕晓旭分享了去哪儿网使用Mesos+Docker技术在集群、日志收集等场景下的应用情况;张海宁分享了VMware针对容器研究情况,包括容器和虚拟化技术融合的研究以及纯容器数据中心的研究情况;杨剑浩分享了中国移动研究院容器技术在CRM等方面的应用情况;何钦钦分享了CNTV使用容器技术实现快速交付和资源回收的应用案例。此外,参会专家还针对容器在应用情况面临的问题和遇到的挑战展开了讨论。最后,中国电子技术标准化研究院高级工程师陈志峰介绍了我国云计算综合标准化指南、标准体系框架以及云计算标准化白皮书情况,为实现容器领域开展标准化工作提供借鉴。

后续容器工作组将开展我国容器应用和标准化白皮书的编制工作,白皮书编制工作的开展将有利于推动容器技术在国内的落地,并为建立符合中国本地化特征的容器标准奠定基础。


相关背景


中国开源云联盟由Intel、新浪网、中标软件和上海交大于2012年8月共同发起创立,是中国最早专注于OpenStack的专业联盟。作为领先的云计算创新技术实践者,数人云一直致力于推动开源技术的发展,并荣膺联盟挂靠中国电子技术标准化研究院后的首批成员单位。目前,联盟下设工作组工作范围从OpenStack逐渐向开源云计算生态圈的其他技术方向延伸,涉及我国云计算领域较热点的发展趋势,如混合云研究、千节点部署、Ceph开源技术、桌面云技术、容器技术等;同时,部分技术方向已开始探索标准化工作,开展开源标准研究,以及与国家标准、国际标准的配套方式的研究。


5月31日,中国开源云联盟2016年第一次理事会在京召开,会上中国开源云联盟Mesos工作组正式成立,为更好地推进容器及相关技术在中国的落地与实践,Mesos工作组现已正式更名为容器工作组。中国开源云联盟容器工作组旨在推动容器技术在国内的落地,提升容器技术在开源社区的贡献比例,并建立顺应国际技术发展趋势、符合中国本地化特征的容器标准体系。


关于数人云


数人云创始团队来自谷歌、红帽和惠普,在今年3月初公司完成A轮融资,由云启资本领投,思科、策源以及唯猎跟投。作为领先的云计算创新技术实践者,数人云致力于打造最轻量化的PaaS平台,将应用弹性做到极致。基于Docker + Mesos,数人云实现一站式的微服务架构集群系统,最大化地帮助客户实现应用业务在云端的快速部署,解决从客户到云资源的最后一公里。