| 作者:ThoughtWorks总监咨询师 熊节

    随着云计算逐渐成为主流的计算环境,我们提出这样一个问题:在云原生(Cloud Native)的环境下,软件开发应该是怎样的?在其他领域,我们看到云计算带来了弹性、标准化和更高的效率。当云成为软件开发团队的缺省环境,哪些实践能帮助他们兑现云计算的价值?各个组织、各个团队采用的软件开发方法论和流程各有不同,我们尝试找出一个最佳实践的最小集合:如果缺少其中的任一实践,就会在一定程度上妨碍团队享受云计算能带来的价值。
    从这个角度出发,我们识别出了下面这个列表:
    image.png
    脚手架
    开发一个应用,采用什么基础框架、代码目录结构怎么安排、引入哪些测试工具、使用什么构建工具、遵循什么构建流程,这些问题在典型的应用类型(例如“Java微服务”或者“React前端应用”)下都有成熟的答案。大多数情况下,新的项目不应该从头新建这一套结构:一来是为了节省工作量,二来更重要的是应该尽量复用已有的最佳实践。建议的做法是使用标准的脚手架,例如JHipster或者其他基于Yeoman的生成器可以提供较为通用的脚手架,IT组织也可以设计自己的标准脚手架。

    自包含应用
    应用程序应该尽可能少依赖周边环境。对周边环境依赖越少,因为环境差异而带来的工作量和错误就会越少。以Java应用为例,基于Spring Boot的独立应用,就比依赖Tomcat甚至WebSphere应用服务器的应用更具自包含性,环境的配置和管理都会容易得多。其他例如npm、rvm等工具都意图让应用程序更具自包含性。

    统一构建
    每一次构建,不论是由开发者自行发起的,还是在持续集成环境执行的构建,都应该尽量、最好是完全一致。为了达到这种效果,不仅构建工具和构建流程本身统一,执行构建的外部环境也应该统一。最好的方式是把构建放在虚拟机或容器里进行,而不是在彼此不同的计算机上执行。为了避免个人电脑计算资源的局限,构建最好是在云上进行。

    镜像化
    为了保证构建的外部环境完全统一,执行构建的不应该是各自不同的计算机,而应该是虚拟机或容器。因此运行应用程序的机器应该被镜像化。Vagrant之类的工具提供了很好的版本化管理虚拟机镜像的能力,但VMWare和VirtualBox等虚拟机在性能上和资源占用上都并不鼓励频繁启停的使用方式,Docker等容器技术可能是更好的选择。构建产物也应该是可执行的容器镜像。

    基础设施即代码
    为了保证构建的外部环境完全统一,获得运行环境的过程应该完全自动化,不应该允许任何手动修改运行环境的情况。如果运行环境是不可变的,那么就可以随时抛弃并重建。因此环境的配置应该以代码形式记录并自动化,并且还能顺便得到环境可以版本管理、可以自动化测试等好处。

    构建产物仓库
    构建成功的产物应该被放入统一的仓库,并分版本管理。这样做的目的是按照《持续交付》的理念,整个构建发布流程中使用用同一个构建产物;并且统一且分版本管理的构建产物可以在组织内复用。Nexus可以用于管理各种构建产物,包括容器镜像。

    弹性运行环境
    运行应用程序的环境,不论是用于执行测试、还是用于试用、培训、用户验收测试、乃至生产,都应该是弹性的:需要时可以立即开通,不需要时可以理解销毁。对于生产系统,运行环境的弹性使系统可以随负载水平扩展,使各种路由技术成为可能;对于开发、测试、预发布等场景,运行环境的弹性使环境开通和使用变得简单且不会出错。

    服务质量透明
    诸如高吞吐量、高可用性、高安全性、双机热备等服务质量,由运维或数据库的专家配置好,在生产环境提供给应用程序使用时,只暴露IP地址和端口(甚至只有端口)。对于应用开发者而言,服务质量是透明的,不会感觉到生产环境与开发环境依赖的外部服务有任何差别。

    诊断信息服务
    当构建和运行都在容器中乃至云上发生,并且容器是为应用程序专门定制的,调试诊断必然不能像在本地开发机器一样直接。需要借助完善的日志、监控等方式(例如基于Splunk或ELK的方案)的来提供应用程序的诊断信息。诊断信息服务不仅作用于生产环境,测试、开发、构建等各个环境也使用同样的方式获得诊断信息。