已经准备好向容器迁移了吗?若是你正考虑从现有非容器化的系统上将服务迁移到基于容器的环境中,那么你必定想知道该如何实现它。有什么正确的方法?有没有最好的方法?或者说,有没有某种直接迁移过程(lift-and-shift process)能够适用于全部的应用程序?数据库
一般来说,上述问题都有确定的答案。虽然因各公司的具体状况不一样,迁移到容器和微服务的具体细节会各有差别,可是对于实现应用程序从传统基础设施到容器环境的无缝迁移来讲,仍是有一些普适性原则和最佳实践经验值得你们遵循。网络
这篇博文将简要介绍成功将传统应用程序迁移到容器的指导原则。架构
在处于项目迁移的最初规划阶段,关于容器化,最须要注意的是容器系统架构是基于(或应该基于)微服务的。那么,微服务是什么?微服务
实际上,界定什么是微服务、什么不是微服务,这其间的标准是有些模糊的。这种状况实际上是一种必然,由于不一样的设计容器化应用程序的方法(咱们稍后会提到),正是基于不一样的定义微服务的方法。设计
从整体上来讲,微服务能够描述为一个基本的、功能分离的服务,它由应用程序的其余部分调用。咱们能够把从数据库中检索数据的服务看做是一个微服务,既能够将数据发送到存储设备,也能够处理用户输入。对象
例如,在线上商店中,访问库存数据库是由一个微服务处理,客户的购物车由一个微服务更新,交易再由一个微服务完成,而且还有一个微服务处理信用卡的受权,而这些微服务都是独立的。图片
而对于同一家店,能够由多个微服务工做,一个微服务处理全部的数据库访问(库存、客户和销售),一个微服务处理购物车和交易,而第三个微服务用作运输物流。这种特定的微服务结构,在很大程度上是一种设计选择,它取决于系统总体架构。资源
不过,在开始构建容器化应用程序以前,还须要着留意一下你当前的架构。宏观上,非容器化的应用程序能够大致分为两类:单体架构和SOA架构(服务导向架构)。当前架构不一样,进行容器化重构的方法就不一样,所以咱们先将它们区分开来,再讨论设计选择以及总体的重构策略。部署
大多数传统设计的应用程序都是单体架构。它们可能由单个包含了支持的库、服务以及配置文件的程序,或者少许带支持资源的程序组成。然而,在这两种状况下,大部分甚至所有的核心功能都包含在一个或几个二进制文件中,其中服务就包含于这些在二进制文件定义的应用程序边界内进行操做和通讯的功能中。桌面级的应用程序传统上讲是单体的,大多数基于网络的应用程序也是如此。it
在桌面或局域网环境中,单体架构一般是十分有效的。它的安装和更新至关容易,而且单体的设计可以轻松地监控组件,并且桌面/LAN的使用通常不会对应用程序的资源形成太大的压力。然而,在云或互联网的环境中,单体应用程序可能相对过于庞大、笨拙、缓慢,它们不只难以更新,且不可以处理大量的流量。另外,它们也不适用持续交付以及大多数构成DevOps的实践。
若是想重构容器的单体架构应用,那可能须要在概念层面上进行全盘的从新设计。即使应用程序的架构已经至关清晰地定义了其内部服务,而且保证了它的离散性,实际拆分红微服务时可能还须要对这些服务的边界以及它们彼此通讯的方式进行大规模的更改。对于大多数的单体应用程序,许多服务都须要从新定义,甚至须要从头开始定义。
有一些大型的非容器应用程序可能已经具备了基于服务的架构。例如,销售点的应用程序可能包含了独立的程序用来处理销售、库存、客户记录、订单、运输、差别、税收、应收帐款以及应付帐款。每个模块都是一个单独的程序,具备明确的应用程序边界,并且这种跨边界的模块间通讯和基于容器的应用程序十分类似。
若是有进行细分的须要,这种架构(假设它是使人满意的)能够做为进一步分解成微服务的基础。进一步分解能够是基于现有的模块分解成更小的服务,也能够是基于抽象的广义服务(好比访问单个数据库或打印收据的微服务),或者二者都是。另外一方面,若是现有模块已是小容量、功能分散且组织良好的,那么只须要进行极少的修改就能够将其迁移到容器中。
在这一点上,应该弄清楚的是,将单体应用程序分解成微服务一般是一个复杂而极具挑战的工做。就像以前说的那样,首先是根据微服务从新定义架构。这里的从新定义以及实际细分红微服务自己的过程一般称为分解(decomposition)。关于分解有一些基本的模式。在不少状况下,了解这些模式的基础和基本性质比选择哪一种模式更重要,而在实际生产中,根据系统的功能要求,将单体应用程序分解成微服务时经常涉及到多种模式。
用例是指用户在执行任务时一般会采起的一组操做。用户既能够是实际的人,能够是应用程序的另外一部分,也能够是外部的应用程序。用例的关键要素是它是与任务相关联的一组可定义的动做。在线上商店的例子中,一组客户操做(如选择和购买商品)就能够是一个用例,单纯的内部操做也能够是用例,例如在销售以后更新库存、客户信息以及交易数据库。
根据功能分解是分解的另外一种常见模式。例如,销售交易能够是一个由功能定义的单元,而信用受权能够做为由功能定义的另外一个服务。你能够根据诸如差别跟踪、运输和自动补货这些功能来定义功能域。功能分解和用例分解很是类似,不过它的定义更多的是由须要执行的行为决定而非执行的对象。
在多数状况下,根据资源定义特定的微服务无疑是最好的方案。例如,你能够定义一个单一的微服务来处理全部与具体某个数据库或一组数据库的交互,或者处理全部与持久存储器的交互。在许多方面,设备驱动程序是基于资源的微服务。若是经过某种相似于设备驱动程序的通用服务来和资源进行交互是有意义的,那么将该服务定义为微服务也可能有实际价值。
肯定了分解单体应用的总体模式后,就能够开始将其分解成微服务。你的最终目标应该是将整个应用程序缩成一组微服务层级的容器,它们和原始的单体应用同样,提供相同的一组服务(可以根据须要添加或改进功能),能够根据须要进行管理和部署,并且相比之下有更出色的速度、流量以及灵活性。
比较好的一点是,你并不须要一会儿把它拆散。能够将前面说的大型SOA架构做为中间阶段。你能够在开始的时候将单体应用程序拆成大型的基于服务的块,而后再将其细分红愈来愈小的服务,直到最终达到指望目标级别的微服务。而这里还有另外一种方案,你能够从定义明确的服务入手,先将这些服务拆分红基于容器的微服务,而后再以相似先前的方法,分几回拆分应用程序的其他部分。
不管采起哪一种方法,必定要牢记一点,那就是要明肯定义微服务,并且这些定义在应用程序的总体功能和架构上都应该是有实际意义的。只要你遵循了这些原则,相信你的迁移工做就会成功。