传统企业应用容器化的痛点、坑和解决之道
作者:互联网
刘春阳 分布式实验室
本次分享将讲解容器化技术对传统企业的价值;传统企业在应用容器化技术改造核心应用如CRM、BOSS等等,中遇到的问题以及应对措施。
大家好!我是来自于天云软件的刘春阳,我主要是负责我们公司容器化以及平台化产品的规划和设计。今天我主要跟大家分享一下在平台性的产品,特别是针对企业平台性的产品设计过程当中,可能会面临什么样的需求,面临什么样的问题。同时包括我们自己在面对这些问题时,采取的一些技术选型和思考。
我们先对这个标题做个语法断句。企业,应用容器化的,痛点、坑、和解决之道。开宗明义,我们是针对企业的。在企业这个背景下,构建平台性产品,就必须面对权利相关的东西,平台上多业务融合的东西。就像上一位讲师说的,在HOST模式情况下,怎么考虑端口的问题,就必须要考虑。下面我正式开始分享一下我们在这方面的思考。
这是我今天讲的内容,首先是技术背景和行业特性的介绍。基于这个背景,分析一下要做一款企业级的平台性产品的时候,需求来自于哪些方面,以及有一些什么样的原则。最后我们是我们的产品在设计过程当中的技术方面的选择和我们的思考。
第一个是技术背景。应该说这几年,云计算这个领域可以说是精彩纷呈,基本上每年都有1-2个技术的热点,云计算、大数据、容器。从去年开始容器上升到一个非常高的热点了,在这方面做研究的,新的产品出来非常快。从我这边来看,容器不光是Docker,我认为容器主要是两个内容,一个是镜像一个是运行时RUNTIME。
我第一次看到Docker提出的build, ship, run口号时,一下就想到了10几年前,Java当时提供的build once,run anywhere一次构建,处处运行。这么多年过去了,Java也证明个这个口号,也成为了第一大语言。Docker能不能做到build、ship、run,我们还得拭目以待。目前大家对Image认可程度比较高,整个业界对这方面的关注度和争议性相对也小一点。Image解决什么问题?在我看来一个应用从研发分包到分发到运行起来,Image在运行之前做一个界面,定义了一套标准。有了这个标准之后,运行前和运行后两边的人就可以很融洽的合作了。
另一方面,支撑Image能Run的就是Runtime。Docker Engine是目前用的是最多的。当然还有Rkt、LXC等等都在做。目前Runtime主要支撑如何让一个应用运行起来。一个程序的运行,要有CPU、内存、带宽、存储。Docker Runtime就是支撑这个,让这个事情更加顺畅。Runtime部署在服务器的每个节点上,它有一定的实效性。相比与Image,它是累积的。一个企业进行技术选型的时候,Runtime这个是可变的,因为它是不可见的。而Runtime相比Engine是可见的。你的程序、业务逻辑成天累月的积累到Image中,如果那天想要把它翻过去,换一个是非常大的成本。技术选型要考虑这样的因素。
这页PPT的左边这三个Kubernetes、Mesosphere、Docker之前关系很融洽,现在已经有一些摩擦了。现在的业务系统越来越复杂,特别是微服务化后,光靠一个Docker Engine Runtime,程序是跑不起来。几百个程序一起协作才能完成的一件事,必须要有调度,必须要有编排。因此Docker就往上做。Mesosphere原来就是做调度,做编排的。它即缺少底层Runtime,又缺少对应用的支持,所以它既往上做又往下做。Kubernetes从诞生之初,目标就是支持应用的运行。所以从一开始,它就内建了很多应用运行时的特性。技术选型过程之中,我们在综合考虑了以后,在容器支撑应用这儿主要选了Kubernetes。因为它可以更好的支撑应用。至于它不能解决的一些问题,特别是放在整IT的环境下,一些支撑性的功能和基础,我们选择了很多技术,对它进行补充。
下面我们看一下行业背景。2015年的时候,浙江移动DCOS平台上线,承载了浙江移动CRM业务容器化。在当年的双十一大促中表现非常好。在电信行业影响还是挺不错的。证明了容器在解决运营商的一些典型业务的时候,它是有这个优势的。
第二个是今年开始,中国移动启动了容器平台规范的制定。让容器这种技术能够尽快的规范起来,而且让这个技术尽快推进下去。
第三个中国移动除了制定规范,针对容器技术在其它业务上,还没有被验证过的,就开始做一些试点项目,验证其可行性。包括CRM、BOSS、BOMC等等。这里面CRM已经验证过的。CRM是属于交互性的,大家都可以看得到,它有一些典型的互联网的属性,比如说秒杀活动、团购活动。短时间内可以有巨大的负载。但是BOSS是不一样的,它是长期稳定运行,它也有些周期性,但是总体是长期稳定运行。一个BOSS程序跑起来可以使用几百个G内存、二三十核。在这种情况下Docker还能不能工作?BOMC是电信行业里面的管理型软件。BOMC本身能不能被容器化,BOMC能不能纳入Docker的特性,为其他的平台提供更好的服务,比如说公共的服务,并考虑未来不同的调度编排平台之间操作及迁移的问题。综合来说,容器在电信领域在以后会有一个非常大的应用。
回过头来我们再看一下,在这个行业里面,它的特殊性在哪里?简单来说,分为三块,一个是管理者主要就是我们的运营商企业,然后是应用提供商,然后是资源提供商,这三个是分离的。在互联网公司和其他的公司,大部分时个这三者可能是合一的。管理方对于资源提供方,应用提供方都有要求。对应用提供方的要求是业务要稳定、特性开发能敏捷,要能快,尽快适应管理者的需求。你是CRM提供商,一个特性能不能10分钟上线,或者几天就上线,在大负载、大流量的情况下,能不能稳定持续运行。管理者对资源提供的要求,你能不能少用点资源,能高效,能快速响应。业务提供才对资源提供者也有要求,秒杀来了,能不能一下子扩充,能不能动态给我提供资源,怎么让我自动或者是主动获取到这些资源。
虽然角色只有三个,但是一般来说都是非常多的厂家在参与的。运营商需要一个规范的标准平台,把这三个拉到上面去,在平台上满足大家的需求。
我们现在来看一下容器技术能给这三者关系带来什么样的一些改变?
第一个,容器镜像封装了应用在运行过程当中的依赖包也好,程序逻辑也好。这样应用它就可以用标准的协议交付第三方。应用开发商开发完了就可以交给资源提供者,平台只需要把它运行起来。大家之间不存在角色模糊或者边界相互有重叠的情况。
第二个,资源提供者可以无差别的对待资源需求。以前CRM上线了,一定要单独的资源。因为我要配一些特殊的东西,我的东西跟别的东西可能有冲突,不隔离没有办法放在一起用。单独只运行一个应用就存在资源浪费的问题。现在有了镜像,有了容器技术。就想船上放货柜,货柜有大小之分,但是没有本质区分。这时候可以混合编排,混合部署,一个设备上可以部署很多业务,这样可以提高业务的部署密度和资源的使用率。同时,因为有了这个,就为我们构建统一的平台提供了可行性。
第三个,是研发流程和上线流程就可以做到自动化了,因为这些都是标准的,都是可编程的,可以通过程序的方式来做了。
第四个,是应用模式化。我们开发程序的都知道,Java有20多个设计模式。实际上程序本身在部署运行过程当中也是有模式可循的,不是一点共通性都没有。比如典型的Web应用,就可以分为接入层、业务逻辑层、数据持久层。在典型应用中发现模式,模式被发现之后,在构建的平台上,你的应用以后就可以遵循这样的规范,共享这样的能力。最近这几年微服务比较流行,可以更加细粒度控制程序的架构和控制程序的交付方式,它也更适合使用容器的技术。
最后,因为有了前面的这些技术的改变,我们就可以构建标准化、自动化、可编程华响应非常快的,整个业务开发、交付、上线、运营整个的流程。
当然,构建一个容器平台是面临很多的挑战的。
第一,是所有平台化产品都会面临的问题。平台化要定标准。目前来说,容器的标准相对统一(Image、Runtime),但是容器管理平台的标准至少有三家(Kubernetes、Docker Swarm、Mesos)在做,谁能占上风,目前也没有一个绝对的,新的产品和技术可能也会冒出来。标准不统一,导致大家在使用过程当中,技术选型的时候会有挑战。
第二,容器的技术涉及到资源,涉及到应用内部结构,所以它具有一定的侵入性。不像是虚拟机,交付完成后,在虚所机内部怎么搞平台就不管了。容器要关心这个问题,否则就没有办法做模式化了,不做模式化的话,平台的很多东西都没有办法构建了。
第三,大量传统应用需要改造。运营商市场有几百,上千个应用。这些应用估计都是几百上千亿的投资,不可能这批应用都不用了,全部改成容器。而且容器也不是银弹可以解决所有的问题。传统应用的改造适合什么样的技术,怎么改变,这就是我们非常大的挑战。这些挑战在我们产品技术选型时,能多多少少都会涉及一些。
综合上面的一些分析,我们认为这三个角色的基本的需求,可能就是这样的。对于管理者、运营商来说,需要一个多租户、分权分域、多应用,对使用者安全的平台。在平台上所做的操作也好,所产生的一些事情也好,可以做到审计、追溯。最好做到提前预判、预警。程序的架构,包括技术方案应该具有一定的可演进性,不能说隔几个月就发现你的技术要革命性的推翻。一定要有演进和延续性。
作为资源提供者,首先要支持异构资源,不能只跑在戴尔服务器或者别人的服务器,存储只能选某个牌子。要做到同种资源要做同一化处理,异种资源要相互兼容。资源使用最好能高效,能达到90%这就是非常厉害的了。最后对所有的资源要进行监管和监控。监管和监控的数据,也可以输出来满足管理者关于审计、分析需求。
作为应用提供者来说,首先你能提供可靠的容器,这个容器不能三天两头就出问题。对于有状态的应用、无状态的应用,包括一些特殊应用,要有足够的兼容性,要能容纳、支持它们。对应用配置元数据的管理,平台能提供相对统一的方式方法。我的应用能通过编排的方式在你的平台正常运行。我的东西托管给你了,你要负责运行的状态,以及出了问题,你能提供我手段分析、发现并最终解决问题。比如说你把你的程序跑到某一个平台上,出了问题,平台不管,然后得你自己想办法解决。这样的话,你肯定不愿意用。至少能让用户访问它的日志和内部的数据,平台得提供相应的功能和手段。但是因为有一些安全性和权限相关的控制,你也不能说无限制开放。平台上面是业务混合部署,上面可能有很多人在操作,很多业务的应用,权限开放太大,万一操作不慎出了问题也是很麻烦的。既要管,又要放,这就是矛盾的地方。
总体来说,我们需要一个桥梁,这个桥梁既能连接应用和资源,也能连接老的应用模式和新的应用模式,同时把所有参与者容纳在上面,这个桥梁就是容器平台。
我们构建平台和构建产品的时候,以及技术选型时有一些原则。产品构建时,第一要紧贴用户需求,我们的技术和功能设计出来肯定要解决用户的问题。做一个东西,这个东西有什么场景在使用,可能在什么时候?我们要有一些预见性,也要贴近实际。
第二要有可扩展,也不能说跟客户要求的一模一样,这个就不是产品了,这个就是一个项目。产品要解决共性问题,要有可复制性。我们需要提取公共的部分,把他们的需求作为我们的产品功能。
最后一个是实用。
技术选取也有三个原则。第一是可控,选择的技术要有一定的前瞻性,它即不是处在非常萌芽的状态,因为萌芽状态需要探索,变化太大。我们自己本身也做预研性探索。但产品中使用技术,一定得是可控的,已经摸索熟练的。不能说出了问题没有解决办法。
第二技术可复用,任何技术的使用选择都是有投资的,投资下去以后,我希望利用率越高越好,在不同的场景下可使用的情况越多越好。
第三技术可演进,明天可以增加,后天还可以再增加。一年过去了,回过头发现,这个技术跟之前有了一个本质性的变化。但是这个技术是一点一点迭代的,不一是革命性一夜就蹦出来。
基于上面的分析,下面我讲一下面对管理者、应用提供者、资源提供者他们的需求,我们的产品构建以及我们的技术选择。
管理者的需求最主要有两块,一个是权限,一个是安全。我们对容器仓库要做一个很好的权限方面的管理,我们要支持公共仓库,我也得能支持私有仓库。私有仓库就是某个业务专用的,或者是某个部门也好,对别人不开放,但是拥有者有权限访问。包括公共仓库也要支持多租户的,是有可访问范围的控制。这个平台是多个业务在上面运行的,大家要有隔离性。然后是RBAC细力度访问控制。
安全这块合规检查我们选择了clair。安全这个事没有大小之分。镜像做好以后,一定要做一个合规性检查,是不是满足通用的安全管理规范。
容器应用上线以后一定要有隔离性,我们主要说的是网络隔离性,通过网络的技术,让不同的应用之间做到物理层面的一些隔离。总归放到安全这个大话题之下。
关于租户以及权利,基于Keystone我们开发了SAS的服务。用户、组织机构、角色以及权限控制,都会放在SAS上。我们产品中其它所有服务都要接入这个体系,服务本身有什么样的访问权限,你的人员在访问系统的时候,能在那个子系统里面执行什么样的操作,都是需要受SAS服务控制的。为什么选Keystone呢?第一我们对Keystone研究比较多,第二Keystone是从OpenStack来的,天生可以直接接入OpenStack。OpenStack在企业用户的部署慢慢会越来越多,我们希望有一套整体的解决方案解决这个问题。不管你是普通的物理设备的,还是虚拟化管理的OpenStack,还是以后的容器,我们用一套权限体系统一纳归到一起来。
镜像管理,我们使用了VMware Habor开源组件。私有仓库是我们自己做的,Habor提供给我们的是多仓库镜像同步。
这是涉及到网络这块,大家做过IaaS的估计都看到了Neutron。我们把Neutron嫁接到了Project,容器网络、容器安全组都归结到Neutron特性上。通常我们实施过程当中,主机都挂在管理网络,主要做主机之间的互动,作为管理层的内网。第二个是存储网,容器本身也要写数据,我们会有专门的存储网。生产网是一组,不同的容器,不同的业务,甚至不同的用户,可以放在不同的生产网络里面。他们可以使用vlan, vxlan等等技术进行二次隔离。就算你知道我容器的密码你进去了,但是通过网络***的方式访问它也是非常困难的。包括容器本身我们有一些QOS的限制,带宽、可访问端口我们都会有限制。
这页镜像管理子系统。我们把镜像扫描加入到镜像构建流程中,镜像构建以后要做安全扫描,扫描完以后告诉你是不是合规的。报告已经扫出来了。镜像进入到镜像管理子系统以后,镜像本身就会有一个安全评级和扫描报告。如果所有的东西都没有问题就可以到上线。镜像有多种方式进入,你可以Push你的镜像,你可以上传你的镜像。镜像在生成运行态变成容器的时候,我们也要进行访问控制,只能暴露部分端口。容器本身还有一些QOS策略,是1M的还是10M的带宽。一般来说,业务不是放在一个网里就完事了,甚至有的时候一个业务本身要放到好多的网里,之间也是有网络隔离的,这些都是在运营商应用体系里面常规的要求。
上面是管理者的需求,侧重权限和安全。对于应用提供者来说,他们对平台有什么需求?一个应用开发到上线到你的平台首先有一个过程,容器化。如果是一个新的程序,非常好,直接可以按容器的方式来做。写编排文件就可以直接了。如果是老应用,要先有容器化的过程。这个过程大致可以分为拆分、改造、合并三个阶段。拆分的时候要分析老应用,它原来是单体应用,或者是个很复杂的应用,那各个模块有什么样的调用关系,每个模块的职责是否单一?层次结构是否清晰,各层之间界限是不是清楚的,他们相互之间有什么样的依赖,分析完之后就知道怎么分解了。
把它分解成很多小服务,这时候就需要为每个服务做镜像改造。还可以跟研发代码过程联系起来,做持续集成。可能的话,把应用改成无状态的。比如原来有一些Session,会话之类的数据,是不是可以把它迁到别的地方?有的应用不能这么改。它本身就是产生状态,产生数据的。这时候就要考虑,它的数据怎么存储。比如说能不能约定数据共享存储。如果可行,能不能把应用的数据写到S3之类的分布式存储里面。如果应用只能写文件系统,应用能不能使数据存储目录是动态的,如果可以动态就好办了。平台可以提供存储能力,应用只需要集成存储能力,就可以记数据和可执行逻辑分离。最后,一个应用的改造要看场景,具体应用有很多细节的情况,不一而足,需要单独分析。
当应用改造完以后,手里就有一堆小服务,调用关系也是非常清楚的时候,你就要合并了。通过编排的方式把它们再组合到一起。A应用怎么发现B应用,就存在服务发现的问题,一个应用里面可能会有很多运行实体,这时候就有一个单一访问的问题,是不是要考虑负载均衡。如果可以的话,业务是不是可以不用再维护开发某些通用共性的组件了,如数据库、消息处理等等。由平台来提供,应用只管用就可以了。现在互联网上提供很多SaaS服务就是解决这方面的问题。
总的来说,我们最终把应用分成了4个概念,容器,主要解决是打包和运行时依赖的问题。POD解决多进程协作问题。有的应用没有办法放到两个容器里,这时候我只能放到多进程一起跑,包括容器的网络,IP的问题,存储的问题都在POD里面解决。服务就是微服务的概念,微服务有同构性、可拓展性,很多微服务就可以构成一个大的应用。
应用最终就是两个阶段,运行前和运行中。运行前要做编排和初始的配置,存储的计划。运行中,应用提供的服务怎么让别人访问到,负载怎么调度起来,资源状态调整的问题,应用出了问题如何分析定位、解决以后如何升级。运行期占应用整个生命周期最长的,这才是平台最重点需要关注和解决的地方。
应用初始主要是配置问题,有一些应用,有一些初始配置。比如应用研发中有两个环节,一个测试环节,一个开发环节。在两个阶段,应用都需要往数据库里面写数据。那如何发现数据库呢?可以利用两套DNS,这样应用迁移到新环境时不需要配置变更。但需要管理DNS。也可以做成初始配置,不同环境使用不同的配置。我们重点解决的是应用里面静态的配置问题,以及应用元数据的问题。这里我们复用了OpenStack Metadata服务,并做了增强改造。可以兼容Kubernetes ConfigMag格式。配置服务里面存储的元数据既可以用到编排文件里面去,也可以应用到容器环境变量里面去,也可以在业务运行起来之后通过我们的公共的服务API就可以访问容器里面的信息。这个API会告诉访问者,你是谁,你属于哪个应用,你属于哪个用户,你属于什么环境,配置的内容是什么……这些信息应用可以用来做自身判断。这是关于配置方面的。
这一页是存储这块的。我们选择使用Cinder。在我们的平台上,用户根据业务需求的不同可以选择不同的设备。可以选择像NFS,如果只是存储大量冷数据。也可以选择块设备,如果业务需要有大量的存储IO。把应用的存储的信息放到配置文件里面去。Kubernetes运行的时候,就可以把存储块挂到相应的位置上。如果不是主机的本地硬盘,直接通过存储网写过去就可以使用了。这样业务的数据就可以写到外面来了。容器里面写数据是挺危险的事。
这一页是关于动态资源调整这块,容器能提供给我们的主要是CPU和内存。一个应用在运行过程,仅靠这两个指标并不一定能做出准确的判断。比如说网络应用,链接数可能是很重要的指标,但是放入通过容器Docker是拿不到的。有一些应用,压根跟用户不打交道,自发性的。我们曾经有一个运营商的应用,这个应用本身是做网元采集的,需要采集几千个网元。关于资源调度考虑的不仅仅是几个指标,要靠一个很复杂的算法。一些因子如还有多少网元没有采,单个采集任务的消耗量是多少,现在有多少并发采集,有没有线性采集的。还有些网元有特殊性,比如说12点之前不把数据采集来就没有了。这些通过一个通用的CPU+内存是解决不了的。所以,在设计时,我们的平台提供了扩展的接口。一方面,应用可以实现我们规定的接口。平台通过这个接口可以拿到链接数这种标准的数据。我们拿到这些数据,也可以通过我们下面说的动态资源调整API,把数据回馈给应用。应用通过自身的逻辑算法来确定是否要动态的调整资源。当然,基础的基于CPU和内存负载动态的调整做为基本功能,平台也是支持的。
服务发现我们提供了三种一个是Kubernetes的Service,还有Neutron LBaaS,最后我们做了一个HWLB的扩展,应用要放到公网,或者直接面对终端用户,从可靠性,性能等方面要考虑。
日志这块主要是三个,容器Console日志,从持续性上,从清晰度上可能会乱。我们就有一个日志目录,应用持载并写日志,平台能严格保证日志的持续性和文件的结构性。最终通过我们底层的平台处理完以后,用户什么时候想要,我们就给。并且保证你原来的目录结构和原来的时序都可以保障。平台本身也提供了查询,但是不一定满足,特别复杂的分析。我们也提供了下载功能和对外输出。
资源提供者这块,主要是四块,一块是监控,各种各样指标的收集。第二就是高效,响应速度要快,要资源立马能给,使用率要高,CPU、内存使用率,对资源的消耗要高。第三审计和分析,不仅对常见的东西做出告警。最好能做到异常发现。第四异构,企业里面有很多固定资产,必然面临异构的问题。我们写了很多技术选型和方案,下面都像个倒树的分支,要解决异构性的问题。最终是多种资源混合管理,同种资源一致化。
资源管理监控,我们用的是Ceilometer,我们存储后端使用的是HBase。我们对存储后端和API接入方式都进行了大量的扩充。可以说除了Ceilometer这个名子,已经差别很大的。主要解决了性能和稳定性的问题。监控分析子系统,分析数据的结果有几个用途,一个就是产生报表,最重要的是实时分析负载,这个分析结果会影响我们调度系统,关于容器调度的结果。
多个进程的容器怎么处理?我们碰到这么一个案例,两个进程必须得跑在一个主机上。程序是非常重量级的,非常不好改。我们对Kubernetes做了一些增强,我们加了一个IPC调度。运行过程当中,A程序声明依赖于XXX命名空间,B程序声明能提供XXX命名空间。在调度时,如果一个容器上已经有了一个XXX的消费者的时候,就不会往上面做调度了。如果还没有XXX提供者,就先pending A程序的调度。
容器无差别调度的时候,有一些容器业务要求IO非常高,会把一些机器压死。我们用了资源分区的方式,对主机做了很多标签。这个容器希望什么标签,就往这个容器调度什么。容器不喜欢什么标签,就不要往这个容器上进行调度。通过亲全性、反亲合性的组合使用。以及主机标签的设置和自动发现,来让资源需求和提供达到最佳的适配。
还有过一个故障,程序总体运行是正常的。但是仔细观察,发现有一些业务的抖动。后来才发现是程序会崩溃掉。平台对服务有自恢复机制,一死就拉起来了。所以总体上看,没有反馈出来程序的问题。总体看起来不错,实际上内部是有问题的。我们通过平台上的pod_time和service_pod_avg_up_time这两个指标最后发现。然后通过日志进行分析,才最终定位了崩溃的原因。
最后,这一页,我们用了很多技术,从技术架构上就做出了这么一个东西,我们能够对容器进行统一的管理和调度,并且共享了很多公共的技术,这个架构还可以继续往下延续。
这是我们做出来的产品,我们的宣传册也有相应的介绍。我们产品的目标就是最新的技术更好支撑应用的运行以及应用的运维。让应用的运行和维护更简单和可靠。我主要介绍的就这么多!谢谢大家。
标签:容器,痛点,平台,企业应用,应用,解决之道,可以,我们,运行 来源: https://blog.51cto.com/u_15127630/2802388