怎么评估企业能否上云?
如果不具备上云条件,如何才能具备条件?
如果条件也具备,那么怎么做才算是上云?我的企业是否需要上云?
笔者希望大家读完本文后,能够对以上问题的认识有较大帮助。
云计算平台一般主流的分为Iaas层(基础设施即服务)、Paas层(平台即服务)和Saas层(软件即服务),当然随着云计算的发展,目前又出现了Caas(容器即服务)、Faas(函数即服务)等,Caas和Faas其实可以划到paas层中,本文对caas和Faas不做重点讨论,在讲到Paas层时是包含Caas和Faas的,由于faas的特殊性,文末会对这块有专门的简介。
另外,无论是公有云、私有云、专有域、混合云都是可以分为Iaas、Paas和Saas的。对于需要自主研发或者采购第三方系统的企业而言,一般使用的重点都在Iaas层和Paas层,Saas层使用的比较少,本文重点介绍的也是Iaas层和Paas层。
Iaas层,在这里包含计算资源、存储资源、网络资源和安全资源。云计算的基础是虚拟化,虚拟化中大家接触最早的就是VMware为大家提供的虚拟机,这其实就属于Iaas层的计算资源的虚拟化。
存储资源,这里主要指的是存储的虚拟化,物理资源能够组成一个资源池,资源池可以横向扩展(理论上无限扩容),并且能同时提供块存储、文件存储和对象存储能力(目前市场上的商用产品不是所有的都能同时提供以上三种能力,这个需要根据业务需求具体评估优先级来选型产品)。
网络资源,主要是指网络服务能力的虚拟化,主要包括虚拟路由器,虚拟交换机,虚拟负载均衡,虚拟dns等,并且虚拟机创建出来以后要能够自动获取ip和mac地址,而不用像使用VMware创建完虚拟机之后还要手动的修改ip和mac地址。
安全资源,主要是指虚拟防火墙(4-7层),安全组等能力。除此之外,iaas层平台还应该能提供虚拟机(包含自身数据)的本集群cdp能力以及同城跨机房的cdp能力,以及虚拟机的同城跨机房的热迁移。
Paas层,在这里主要涉及应用开发框架、中间件、权限管理、代码管理、测试质量、环境初始化、CI/CD等。
开发框架,目前各大主流语言针对应用部署在云环境都有一些较好的开发框架,例如基于java语言的spring boot和spring cloud以及阿里巴巴的dubbo,蚂蚁金服的sofa等,尤其是最近sofa的开源,对给用户多提供了一种金融级开发框架的选择。
中间件,主要包括消息中间件、缓存中间件、数据库中间件、web应用中间件、事务中间件等。消息中间件主要包括kafka、active mq、rocket mq、rabbit mq等,这些消息中间件的选择也需要根据根据具体的应用场景以及本公司是否有相应的技术支持能力来选型,例如规模较小的公司并且没有消息总线的需求,那么选取active mq无论在部署难度还是维护难度上都比kafka容易很多;如果是规模较大的公司,有消息总线需求,并且还有消息回放的需求,研发人员能力较强,那么就比较适合使用kafka;如果还需要基于消息系统实现分布式事务的功能,那么比较推荐使用阿里巴巴开源的rocket mq。缓存中间件主要包括redis、memcache等,这块目前redis已经成为事实的主流了,市面上存在的memcache也是各个公司二次开发过的。数据库中间件这块目前开源领域的cobar、sharding-jdbc、mycat都是目前市面上使用较多的组件,选取思路也是类似消息中间件的选取方式。Web中间件在互联网领域基本被nginx和tomcat占据了80%的份额,部分传统行业还有使用apache和weblogic的。事务中间件目前使用的比较多的是TCC或者基于TCC改的代码实现。
权限管理,主要是指sso以及权限树的管理。
代码管理这块需要在公司内部统一规范的主干与分支代码管理方式,这个需要结合公司的具体情况来落地。
对于测试团队,在paas平台上除了需要做功能测试之外,还要重点关注非功能性测试,尤其在云环境下非功能性测试尤为重要,这块会在后面详述。
环境初始化,是指操作系统安装好以后,需要根据机器的服务对象和类型,对例如主机名,网络参数,内核参数,基础软件,补丁进行初始化,这里有个取巧的方式就是做成统一的模板,由iaas平台负责生成,然后创建出来后,再对一些个性化的参数进行自动化调整。
CI/CD是paas平台的核心功能,是应用能够达到paas层上云的基础,目前这块各个公司基本都开始使用了或者开始做了,这里就涉及和paas层对接的问题,这个问题开发能力比较强的团队而言可能对接起来问题不大,对于以采购为主的企业,可能需要和厂家谈好明确的需求。
对真正的Iaas平台而言,计算、存储、网络、安全资源都应该是可以全自动创建,并配置可用,无需人工参与进行参数或者配置的调整。
在真正的paas平台上,各种类型的中间件应该可以自助创建,开发框架可以便捷的调用创建出来的中间件,开发代码提交到代码仓库后,可以用CI进行集成测试,然后按照迭代计划测试人员进行测试,最后使用CD或者半CD的方式进行部署,整个流程应该都在paas平台体内进行而不应出现体外部分,任何体外的参与都可能导致错误的发生以及效率的降低,从而对整体带来负面的影响。
只有在iaas和paas层都做好了(包括两者的联动),才能真正实现应用的快速部署、快速迭代、按需弹性扩容和缩容而不影响用户体验。
说到这里,再来看下这段的题目,“分层的云”,再想想企业上云?您是不是也认为需要清楚您的企业应用上云是要到iaas层,还是paas层?有了这个认识,也可以避免被号称提供云服务的厂商忽悠。
首先明确一个前提,本文所述上云主要是指应用程序的云化改造,涉及Iaas及Paas层的工作,目的是使应用程序能够实现快速部署、快速迭代、按需弹性扩容和缩容而尽量小的对用户体验造成影响,达到此目标即可以认为应用程序上了Paas层的云,而不仅仅是把应用部署在Iaas层上就算完事。接下来我们详细讨论下应用上云最佳实践的必要条件。主要包括:资源自动化、代码可控、CI/CD、监控、状态管理、服务拆分、思维认知。
这里的资源自动化包括Iaas层和Paas层的资源自动化。
在实际场景下Iaas层面的资源自动化比较重要的有计算资源自动化、存储资源自动化,网络资源和安全资源目前还很难完全自动化,半自动化也是可以接受的。
计算资源自动化要求的是资源申请以后创建出的虚拟机自动分配好ip地址、mac地址和主机名,而不要像现在一样要手动的去设置ip地址、mac地址和主机名,这些动作是低效并且易出错的,不能带来价值,同时计算资源的创建需要有api的支持,以便实现代码层面对计算资源自动创建的管理。
存储资源自动化是指在创建计算资源时主要设定相应的存储资源或者用api在创建计算资源时通过设置参数就可以直接使用,减少传统存储中创建存储,存储与主机关联这样的步骤。
网络资源中主要涉及路由器、交换机、负载均衡,在实际应用中,交换机和路由器在系统建设初期一般都是初始化一次就可以的,后面调整的不多,调整较多的是负载均衡。负载均衡这里涉及两块,一块是新应用上线需要vip,另一块是应用缩容和扩容需要自动挂载到已有的vip上,这就要求负载均衡这块也要有相应的api接口,提供给自动化团队调用。
安全模块在云环境下主要是指安全组,这块和负载均衡需求差不多,一是新应用上需要创建新的安全组,二是应用扩容后新扩容的主机需要加入安全组中。
由此,一个一键建站(iaas层)的实际落地方式就呼之欲出了,先初始化虚拟路由器、交换机和安全组,然后根据应用模块数量创建计算资源(包含了存储资源),然后创建vip并绑定后端计算资源,然后将创建好的资源插入到cmdb系统,整个过程可以通过编程调用api实现,需要创建的资源可以放在一个json文件里或者yaml文件里,笔者建议用后者,层次更清晰。
有些人看到代码可控一条会觉得很疑惑,为什么应用上云要做到代码可控?有些人甚至觉得应用上云和代码可控没有什么关系。
凡是有这个疑惑的读者我认为是正常的,因为他们可能是被提供iaas方案的厂商洗脑了了,或者是没有从本质上搞清楚应用要上的是iaas层还是paas层,为了给没有从头阅读本文的读者带来不必要的误解,这里再次强调,本文重点讨论的是应用上paas层。
如果说用户仅仅是想把自己的应用程序从本地迁移到iaas平台上(包括公有云或者私有云)部署,仅仅相当于更换了应用程序运行的底座,没有对应用程序有任何影响,不需要应用程序做改造,那么从这个层面看确实不需要代码可控。
如果要做到使应用程序能够实现快速部署、快速迭代、按需弹性扩容和缩容而尽量小的对用户体验造成影响。那么这里要面对的问题就来了,快速弹性扩容需要涉及底层计算资源的增加、应用的自动化部署、应用的监控、扩容的应用自动挂载到vip上以及用户登录状态的管理。
思考一下,如何能在一个平台体内全自动化完成以上操作?不改动应用代码可以做到吗?在快速弹性扩容这个场景下,有几点是需要设计代码改造:
一是应用的自动化部署,这里需要应用程序能够适配paas平台的CI/CD工具,这里就可能涉及文件路径的标准化,配置文件与程序的分离,程序包管理,应用程序开关改造,如果是使用docker化部署,还要写应用程序的dockerfile文件等,具体细节在后面的CI/CD部分会详解;
二是应用的监控,在云环境下,需要时刻了解应用的状态,以便手动或者动态的进行缩容和扩容操作,如果代码不可控就没有了解应用状态的接口。
三是自动挂载,应用进行弹性缩容和扩容后,需要自动挂载到vip才能对外提供服务,这里就涉及应用主动向vip服务自动注册挂载的动作,这里同样是以代码可控为前提的。
CI/CD现在在传统行业使用的也很多了,其实主要还是在CI部分,CD这块还需要人工参与。很多公司不敢完全自动化CD主要是缺少四方面的能力:
一是应用的健康检查能力,CD自动化需要时刻关注新上或者变更应用的服务是否正常,如果缺乏这方面的能力就如同闭眼开车;
二是灰度发布能力,通过灰度的方式可以将新版本通过引流进行预热;
三是与监控系统联动的熔断或者回滚机制,即如果监控发现新上或者变更的应用出现问题,应该能够快速熔断路由到这个节点的访问并选择进行回滚;
四是应用间的强依赖,如果A应用依赖B应用,那么如果B应用做变更不可用,A应用是一定会受到影响的。要解决这个问题,那么B应用要进行灰度发布,同时A应用在对B应用有感知能力,当对B1进行变更时,A的请求被路由到B2,当对B2进行变更时,再将A的请求路由到B1。
接下来讨论下为什么应用上云也要CI/CD,其实原因很简单,在快速扩容的场景中,基础资源快速弹出以后,应用程序要部署在上面才能提供服务,快速扩容就必须自动化,人工操作是不能忍受的。
这里其实在实际应用中又涉及两种场景,一种是将服务部署在虚拟机或者物理机上的,另一种是将应用服务直接部署在容器平台上。
这两者其实内在逻辑差别不大,都是通过jenkins来做CI/CD,但是有一点是有区别的,由于传统行业标准化(软件安装路径不统一,操作系统版本不一致,应用启动用户不统一,内核参数不一致等)做的不到位,在第一种场景下往往需要结合ansible之类的工具在协助来屏蔽差异,但是在新上系统越来越多的情况下维护ansible也是一项痛苦的工作。对于第二种场景使用容器的方式,由于在开发阶段到上线阶段基本就是维护一个dockerfile(也就是有些环境变量会有不同),所以对于运维同学而言工作量小了很多,而且由于镜像屏蔽了底层差异,因此能避免出现很多基础环境不同导致的问题。
监控是个老生常谈的问题,从传统的集中式系统就开始讲监控,一直讲到云化应用和微服务的监控。从目前的主流视角看,应用包括物理资源监控、操作系统监控、数据库监控、中间件监控、应用监控、业务监控。
随着IT技术的发展,一是各个监控层次里的组件的监控项增多(例如数据库指标增加、中间件的种类增加),二是从原先的注重每个模块的监控开始转变为从用户视角注重整个业务体验(响应时间/吞吐量/成功率等)的监控,三是在分布式和微服务架构下,还需要监控每个方法的耗时以及对每次请求的全链路跟踪。
监控在实际使用中,需要关注误报的问题,报警参数调整问题,不同业务报警特征的问题,层级依赖造成的报警收敛问题(底层的交换机故障,依赖这个底层交换机的物理机、虚拟机、应用程序都会引发报警),报警的处理响应机制(这里比较建议使用on call的机制,相比于每个负责几个应用系统的方式,on call的方式一方面对大家的应急能力有更好的锻炼,另一方面也能使大家对所有的应用都熟悉)。
在分布式架构和微服务场景下,监控就显得更加重要了,相比于传统的烟囱式架构,完成一项业务流程需要涉及多个组件,而且这些组件又可能是新增或者有发生扩容的。那么当一笔业务发生问题的时候,需要快速定位是哪个节点出了问题,这就需要分布式链路跟踪上场了。
在云的场景下,监控就是眼睛,在应用进行上线、变更和弹性扩容的时候需要实时感知应用的健康状态,主要包括可用率(正常情况这个指标需要是100%)、响应时间等,以便采取相应的措施来保证不影响用户体验。云更多讲究是资源池的概念,池里面可能有资源出了问题,但是对外暴露出来的服务要是好的。云环境下,应用变更(包括版本更新和扩容)的正确姿势应该是一边做变更,一边看监控大盘,看每个动作对当前应用可用率的影响,看着监控做变更是一种好习惯。
另外多说一句,最近AIOps也很火爆,笔者也重点调研了市面上AIOps中监控的一些成果,总的来看这块还是处于起步阶段,只有一些大厂由于有数据的积累以及强大的ai能力,在AI监控方面做出了一些场景。
在互联网领域有一句话叫做,“以无状态为荣,以有状态为耻”,但是目前在传统企业应用还是以有状态应用为主。应用的状态是阻止应用弹性伸缩以及用户端高可用体验的拦路虎,这里所说的状态信息,更多的是指原先记录在会话session中的信息和定时任务执行的状态信息。目前常见的情况是用户的session信息存储在java中间件所在主机的内存里,需要依赖前端负载均衡设备通过设置基于源地址哈希来保证同一个用户请求能够发送到同一台后端服务器上从而在保证状态。
一是基于源地址哈希容易导致的问题就是由于每个请求的在线时间不同负载很容易不均衡;
二是在进行版本迭代升级的时候,这个节点上如果有状态信息就会被清除,给用户的感受就是被踢出登录了或者访问的信息消失了。
如果要做无状态的改造,有两种思路,一种是通过在业务逻辑上的优化,真正的去掉原来记录在session的中的信息,这种方式改造的很完全,但是难度大,并且适用范围比较小;另外一种方式就是将原来由各个业务节点保存的session信息,集中地保存在session服务上,这样就变相的去掉了业务的状态信息,请求到达的时候,就可以从session服务中获取session信息,实现了业务逻辑与session保存的解耦,从而可以使业务模块能够快速的弹性扩容和缩容。同时session服务一般都是分布式部署,自身提供了良好的高可用机制以及分布式部署特性,在多机房或者多云环境下可以部署在多机房或者多云,从而保证session数据的安全可靠。同时认证模块如果使用token的方式,那么可以将用户的session id放在token里面,从而解决认证和session id安全两方面的问题。做了应用程序的状态管理工作后,在进行应用弹性缩容和扩容的时候,由于状态信息是统一管理的,不落在具体的java容器中才能够提供良好的用户体验。
云环境下,为了对应用程序进行快速迭代和随时的容量变化,那么就需要对应用程序进行拆分或者进行微服务的改造。
一是可以使每个团队专注自己模块的开发与测试而不会被挂起;
二是在进行版本迭代的时候只做本模块的变更不会对其他模块造成影响(除非是本模块被其他模块强依赖,对于这种情况前面也提到了应对方式);
三是在弹性扩容时可以做到最小单元的扩容,而不用对不相关的应用扩容(单体应用会存在这个问题),从而节约资源,加速扩容速度。
再说下在传统行业进行服务拆分的思路:
首先是对自研的非核心系统进行拆分,这样做一方面可以让开发同学练练手,探索服务拆分的方式并有体感的感受;另一方面由于是针对非核心系统进行拆分,就是真出了问题也不会造成重大影响。
其次是对自研的准核心系统拆分,有了前面的经验,在进行这步工作的时候就要求稳,由于是准核心系统,还要考虑拆分失败的应急方案(例如原来的单体应用对于这个功能留一个后门,当拆分的服务有问题时,切换使用这个后门接入),并且在对准核心系统拆分的时候要一个模块一个模块的来,一个稳定了以后再做另外一个,不要求快!
再下来是对自研核心系统拆分,这部分要进行充分的评估,定制出一个稳定的步骤和排期,对于某些没有十足把握的功能或者模块,也可以不拆分,待后续技术能力达到匹配的程度后再继续拆分。
最后对于采购的系统,基本上不用考虑拆分了,一是外购系统升级都是厂商统一发版,你就算让厂商拆了也没用;二是一般情况下厂商也不会去给用户满足这种个性化的需求。
在我司应用进行云化改造的过程中,笔者深深的感受到同事对应用上云的理解确实不尽人意。
一是原来管vmware虚拟机的同事会觉得创建vmware虚拟机挂载磁盘以及手动改ip和mac地址是天经地义的事,对目前创建虚机后自动挂载磁盘并且自动分配ip和mac地址觉得方便了很多(其实笔者内心想的是,后者这样才应该是天经地义的吧……);
二是很多同事认为应用程序部署在虚拟机上就算是上云了,这是典型的iaas层思维或者是与受部分无良厂商的误导分不开的;
三是在推广容器部署应用的过程中,有开发同事还是把容器等同于虚拟机看待,甚至直接找到负责管理k8s的同事,说给他两个容器他自己去部署应用…..笔者当时也是苦笑不得。因为这件事,我们还专门组织了一次专题培训,为开发的同事宣讲虚拟机与容器的区别,当然我们讲的区别更多的在面向开发人员的方面,这次宣讲后效果还不错,没有再出现过之前的“乌龙”事件。
各家企业现在都在做云平台,尤其是传统行业可能缺乏这方面的专家,因此很容易被一些无良厂商忽悠,从而对一些概念造成错误的理解和认知,因此在进行应用云化改造的过程中,一定要纠正大家一些不恰当的认知。
对于传统企业应用上云的改造思路其实我在前文中也略微提到过一些,这里做一个系统的梳理:遵循“自建为主,由外向内,由轻向重,先新后旧”的思路进行。
这里做一个说明,自建为主就是要做到代码可控,由外向内就是先对外围非核心系统(例如T 1的系统)改造再逐步到内部核心系统,由轻向重就是先对原来结构就没有那么复杂的系统改造,再对结构复杂的单体应用改造,先新后旧就是对于新上的系统可以优先考虑直接按照应用上云的要求去开发,对于旧的系统逐步改造。除此之外,对于任何一个要上云的应用,都必须提供健康检查接口,这也是一个必须的准入条件。
第一步是目标选择,大家在实际工作中,应该会感觉的有些人对新技术不敏感,不愿意尝试,有些人对新技术比较敏感,愿意去拥抱新技术。在对应用云化改造这块也是一样的,那么我们在计划做改造的时候就从对新技术敏感的开发同学入手,去和他进行交流,看看他手上目前是否有适合做云化改造,并且他也有精力投入的,经过筛选我们选定了一位开发同学和他手上目前的一个项目,为了后续表述方便,这位同学称为凯凯,他的这个项目称为R项目。
第二步是选择实施平台,这里需要解释下,目前我司有两套基础设施都可以实现应用云化改造,一套是基于传统虚拟机加自动化部署,一套是新上的k8s平台,经过评估我们选则在k8s平台上进行。一方面是传统虚拟机方式在应用部署后还不能自动挂载到原来的vip上,而k8s平台是可以的;另一方面是容器化是未来的一个方向,我们也想让开发开始去适应容器部署的方式,因此选择了使用k8s这个平台。
第三步是引导开发同事如何使用容器部署应用。由于笔者之前都是使用git对代码进行管理,而我司目前还是使用svn。笔者窃以为git比svn好用很多,因此也是利用这次机会对于要在k8s部署的应用,要求使用git仓库。接下来就是要指导开发同学如何写dockerfile了,这个过程其实对于有开发经验的人来说并不复杂,只需要讲下语法结构,再看个例子,基本上大家都会比葫芦画瓢的搞出来。最后看下凯凯的R这个项目的git结构,这里我隐去了一些内部信息:
Dockerfile里内部信息太多了,如果都隐去基本也看不到什么了,所以这里就不上图了,如果对这块有不是很了解的,可以和笔者线下交流。
第四步提供健康检查能力并上线。提供了健康检查方式后,经过测试验证没有问题就可以上线了,上线后在后台该服务的详情如下:
凯凯的R这个应用由于天生就是无状态的,所以在这个项目改造过程中并没有涉及状态管理的服务的改造,在下一个改造项目中我们会选择一个有状态的服务,并且将服务状态从剥离出来由单独的状态管理服务来进行管理。
这篇应用上云的建设思路洋洋洒洒写了很多,有些地方可能也没有写清楚,并且未必适合所有的场景,有些情况还要具体问题具体分析,还请大家见谅。
总之,要做应用上云需要先理清楚目标是上Iaas层还是paas层,上不同的层对应用的要求不同,能达到的效果也不同;另外就是一定要有对云平台比较熟悉的人来主导,不要被厂商的一面之词所混淆。
联系客服