本文要点
- 袜子商店应用始于一个简单的演示应用,之后发现它十分有用,最终演化成一个完全容器化的、云原生参照应用。
- 该应用混合使用了 Go、Java、Spring 以及 Node.js。它拥有完整的持续集成和发布管道,最终会发布到 AWS 上 Kubernetes 集群的准生产环境中。
- 其中的 API 使用了 Open API 的规范。并且使用了一个名为 Dredd 的工具,用其获得 swagger 规范并且对在容器化的服务上的 API 进行验证。
- 袜子商店可以使用独立 Docker、Docker Swarm、Kubernetes、Mesos/Marathon(或 DC/OS)、Hashicorp 的 Nomad 以及 AWS ECS 进行部署。
- 在合并两个服务成为单个服务时会遇到远超预期的麻烦。因此建议,在完全理清服务之前,尽量推迟对服务的拆分。
微服务、容器和编排框架是一个不断变化的领域。每周都有新的工具、服务或产品出现,同时伴随着新的概念、技术和流行语。为了达到在构建应用时“云端优先”的新兴思想,就诞生了云原生(Cloud Native)一词。然而,试图确定云原生究竟意味着什么将是徒劳的,因为它所试图定义的领域正不断变化着。我们看到最近的一个动向就是云原生计算基金会(Cloud Native Computing Foundation)的成立。它归属于 Linux 基金会,是一个专注于常用技术和开源软件的非营利性组织。
这看上去正朝着正确的方向发展,但还是没有能帮我们定义云原生应用到底是什么。我们可以说出一些技术,如容器、编排框架,和一些最佳实践,如短小、可扩展、灵活,但拥有一个具体的参照往往会更有帮助。这正是我们所一直在构建的。
这就是袜子商店应用,一个真实、完全容器化、采用微服务架构的云原生应用。
该项目一开始是作为DockerCon 的一个小型演示应用而诞生的,用于展示由 Weave Works 开发的一些新服务。作为一家致力于为微服务和基于容器的应用构建产品和工具的公司,他们需要一个真实的应用来演示他们的服务。在两周内,我们构建了一个大量使用微服务的应用,其中投入了各种技术、编程语言和数据存储。
初次运行之后,我们看到了持续维护该项目的好处。它既可以作为容器和微服务集中工具的测试平台,同时可以作为云原生系统的参照应用,这会非常有用。在接下来的几个月中,我们致力于将此演示应用转换为可以部署到生产的应用。我们对每个服务进行了彻底改进、按需替换数据存储、合并高耦合的服务、并添加日志和监控等标准功能。我们还建立了完整的持续集成和交付管道,最终会发布到 AWS 上 Kubernetes 集群的准生产环境中。
微服务
云原生应用必须足够灵活。我们需要快速而独立地部署,从而让我们在正确的时间做出正确的决定和变化。这能使组织架构变得敏捷。组织内部应该预期并鼓励变化而不是极力规避变化。云原生应用注重服务的独立性。系统的每一部分都不应该相互依赖,以避免造成级联故障。最后,云原生应用应该是技术无关的。为系统的一个部分选择编程语言,或者为特定数据集选型关系型数据库,不应对系统的其他部分造成影响。
显然,这些不是我们可以通过独立应用架构来实现的。虽然不是所有情况下都必要,但是云原生应用还是应该构建在微服务之上。在袜子商店应用中,我们积极地在应用中使用“微服务”的理念。
这给了我们诸多好处:我们能够利用多种持久化技术,即在不同的服务使用不同的数据存储。我们也可以为每个服务自由地选择语言。但真正的好处在于开发的速度。由于这是一个开源社区项目,短期内有很多开发人员参与。通过对服务进行适当的隔离,大家可以很容易地融入社区并快速修复 bug 或在某一服务中添加功能,而无需了解整个架构。
过分微服务化
有观点认为,一开始就使用微服务架构比转换现有的独立应用更加困难。其中一个原因是,在一个全新的项目中,服务之间的边界并不总那么清晰。如果你的服务沿着错误的边界进行划分,最终服务间的交互就会过多,而且这可能难以纠正。在我们袜子商店应用早期开发中就遇到这个问题。由于我们激进地对服务进行了划分,我们创建了一个登录服务和一个顾客服务。在我们的后续开发中,就发现它们之间的耦合度太高,他们应该是一个服务,而将它们合并成单个服务的过程又比预期设想的要更复杂。所以建议,在完全理清服务之前,尽量推迟对服务的拆分。
容器
微服务的广泛应用,在很大程度上是由于一些新兴技术使我们可以更容易地将应用分割成小而独立的部分。具体地说,就是容器技术。它为我们提供了轻量化的包装和工具。
除了越来越多地采用微服务外,容器也是将应用从本地转移到云端的关键。无论是在容器中运行的应用本身,还是应用运行所在的基础架构,已经运行在容器上十多年的 Google Cloud 就是一个例子。容器是构成云的一砖一瓦,也是云原生应用的重要组成部分。
在袜子商店应用中,我们在各个部分都采用了容器。我们不光在 docker 容器上运行我们的服务,更研究了如何在集成和部署管道中利用容器的优势。
一个例子就在我们的构建过程中。我们希望拥有一致、可重复的构建版本,但是我们不希望在服务的镜像中包含不必要的工具使其变得臃肿。为了满足这个需求,我们创建了单独的镜像来构建和运行我们的服务。构建的镜像包含必要的工具,并在任何环境中提供了一致的可重复的生成文件。然后,我们将构建的二进制文件(或 jar 文件)复制到实际运行服务的最小部署镜像中。(示例)
我们利用容器优势的另一个方面是在测试中,这在微服务领域是有明显不同的。我们的服务规模相当合理,因此可以轻松地测试内部功能。然而,我们的服务有更多的外部依赖,这为测试带来了一些棘手的问题。
我们测试的一个重点是我们的服务API。因为这些是我们服务间相互通讯的契约。我们使用Open API 规范(即 Swagger )记录了我们所有的 API,该 API 规范具有诸多的工具。我们使用了一个名为 Dredd 的工具,它使用我们的 Swagger 规范,并在我们容器化的服务上对 API 进行验证。当我们将其引入到持续集成管道中时,我们能对所有服务的 API 进行持续地验证。所有这些都会在容器中运行,这为我们的操作带来了可重复性,并且这个过程与运行的平台无关。
我们创建了一个测试用的 Docker 镜像,其中包含了我们的测试框架和 Dredd 工具。这个容器读入 API(Swagger)规范,并针对我们的真实服务进行 API 调用,对 API 规范进行完整的验证。我们测试框架的生命周期是短暂的,每个测试案例都会自己创建并删除独立的环境,并且这个过程与运行环境无关。
编排
构建云原生应用的第三个支柱是编排(orchestration)。一旦我们创建、测试并部署完单个服务,接下来的困难就是管理我们的各个容器,以保持一个稳定而又灵活的运行环境。一旦你有多个容器,手动编排就变得难以管理,我们需要将其自动化。任何应用的主要部分包括运行服务的容器、服务器、存储和网络。从这组初始元素中,我们就有了一个理想的状况:运行应用、服务的发现、容错、资源的有效利用。理想情况下,这一切都应该在没有任何手动干预的情况下完成。
幸运的是,有许多工具和平台想要为我们管理这些。在袜子商店应用中,我们决定在尽可能多的编排平台上部署我们的应用,而不是选择某个特定的平台进行部署。毕竟,作为一个参照应用,它不应该与某个特定的平台绑定,而作为一个真正的“云原生”应用,它应该在任何编排平台上都可以正常工作。这种方式的另一个好处是可以让我们评估和比较不同的工具。在撰写本文时,袜子商店应用已经可以部署在独立 Docker、Docker Swarm、Kubernetes、Mesos/Marathon(或 DC/OS)、Hashicorp 的 Nomad 和 AWS ECS 上。可以查看对应的文档。
在大多数情况下,应用在这些平台上“恰好可以正常工作”。我们只需要根据每个工具的语法调整配置文件就可以实现切换。由于我们所有的组件都是容器化的,部署就变得直截了当。主要需要关注的是网络。我们使用了WeaveNet 插件来满足我们的容器网络和DNS 需求。在某些情况下这恰好可以满足需求,但更多情况下这会与工具内置的现存DNS 或网络组件产生冲突。容器网络接口将是未来的发展方向,但是目前它仍处于早期阶段,还不能与所有工具完全集成。
回顾云原生
云原生应用有三个主要支柱:微服务、容器和动态编排。虽然其中经常涉及其他技术,但构建云原生架构应用总会伴随着关注这三个方面。同时它们也是互补的技术。正如我们在袜子商店应用中看到的那样,容器技术使构建、测试和部署微服务变得更加容易。添加了编排平台更使我们能够自信地大规模运行我们的应用。如果我们要手动管理每个服务的部署、重启、扩展和调度,我们很快就会变得不堪重负,这样就会使云原生应用所带来的好处不足以弥补维持应用运行所需的额外工作。
对于构建云原生应用其他的重要部分包括连续交付管道、全面监控和日志以及追踪,所有这些都在袜子商店应用中有所使用。
袜子商店应用的下一步发展
既然现在该应用处于稳定状态,并且我们已经进行了必要的自动化和测试,接下来一个有趣的用例就是替换某些工具、语言、技术,来看看这会带来什么样意外的问题,以及这个过程是否能顺利进行。微服务架构常提及的优点之一,我认为也是云原生应用的目标,就是模块化。由于我们的应用的各种部件和基础设施之间的低耦合,所以可以方便地使用等价的组件替换系统的任何部分。
一个有趣的例子就是我的一个同事使用.NET 重新编写了我们的一个服务。目前在Linux 上的.NET Core 还相对粗糙,除了由于这个因素所带来编写服务的一些挑战之外,已经可以成功地将我们原来用Java 编写的订单服务与.NET 版本无缝切换。
作为一个稍稍极端的例子,我想尝试着替换实际的容器运行时,如使用rkt 来替代当前的Docker。这将大大有助于展示我们在“云原生”上的发展,并验证开放容器计划。
袜子商店应用的目标是成为一个云原生应用的参照,也可用作相关技术、模式和工具的测试平台。它是一个完全由社区拥有和驱动的项目,建议大家可以浏览一下代码、对应用进行测试、使用它来测试任何工具和新技术,并通过PR 贡献自己的代码。
关于作者
Ian Crosby是一位经验丰富的软件开发人员、拥护者和倡导者。他起步于军事防御系统的开发,并一直以来致力于发挥自己的能力。目前他在阿姆斯特丹的 Container Solutions 担任高级工程师,他协助各企业进入新的云原生领域,同时与合作伙伴一起开发用于实现云端原生的工具。
查看英文原文: Introducing Socks Shop: A Cloud Native Reference Application
评论