本章将涵盖的内容:
- 理解什么是平台,以及我们为什么需要它
- 在 Kubernetes 之上构建一个平台
- 介绍一个"可运行骨架"(walking skeleton)应用
平台工程 在技术行业中并不是一个新术语,但在云原生领域以及 Kubernetes 的语境下,它相对较新。
当我在 2020 年开始写这本书时,云原生社区里还没有广泛使用这个术语。然而,到 2023 年撰写本书时,平台工程已成为云原生和 Kubernetes 社区中的热门话题。
本书旨在带领读者探索:什么是平台,以及为什么要用 Kubernetes,尤其是以 Kubernetes API 为核心,来构建一个平台,从而帮助内部团队更高效地交付软件。
要理解平台工程为何会在行业中成为趋势,首先需要理解云原生和 Kubernetes 生态系统。
由于本书假设你已经熟悉 Kubernetes、容器以及云原生应用,因此我们会重点描述在 Kubernetes 和云服务商之上构建、运行这些应用时将面临的挑战。
我们会采用面向开发者的方式展开,这意味着大多数主题都将与开发者的日常工作紧密相关,并探讨云原生领域的各种工具与框架会如何影响他们。
每个软件开发团队的最终目标,都是为客户交付新功能以及修复缺陷或安全问题。
新功能和更稳定的应用,可以直接转化为竞争优势和客户满意度。
为了更高效地交付软件,开发团队必须能够使用他们完成工作所需的工具。
而平台及平台工程团队的主要目标,就是让开发人员更高效地交付软件。
这不仅需要技术层面的新方法,还需要一种文化转变------将开发团队视为我们所构建平台的内部客户。
在本书的各个章节中,我们会使用一个简单的应用(由多个服务组成)作为示例,通过云原生领域的开源工具构建一个平台,来支持负责构建、发布和管理这个应用的团队。
1.1 什么是平台?我为什么需要一个平台?
平台是一组服务的集合,用来帮助企业让其软件运行在客户(无论是内部客户还是外部客户)面前。
平台的目标是成为一个"一站式"服务,让团队能够获得所有所需工具,从而高效生产并持续交付业务价值。
随着平台的普及和对加快开发周期需求的增长,平台已经从单纯提供计算资源,逐渐向上延伸,提供越来越多的服务。
平台并不是新事物,云平台也不是。
AWS、Google、Microsoft、阿里巴巴、IBM 等云服务商多年来一直在为我们提供平台。
这些云服务商提供了大量工具,帮助团队以按需付费的方式构建、运行和监控关键业务应用。
从业务敏捷性的角度看,这些云平台的出现,根本性地改变了团队使用服务时的预期:
- 企业和团队可以快速启动项目,构建可在全球范围扩展的应用,而无需大规模的初始投入;
- 如果应用没人用,每个月的账单不会很高;
- 反之,如果应用大受欢迎,就必须做好月底收到高额账单的准备------使用的资源越多(存储、网络流量、服务等),费用就越高。
此外,还有一个需要考虑的方面:
如果你过度依赖云服务商提供的工具,想要迁移到其他服务商会变得更困难,因为整个组织已经习惯了该云平台的工具、工作流和服务。
跨平台迁移应用将会是一件痛苦的事。
在接下来的部分,我们会介绍云平台的现状,以及本书中会探讨的平台类型。
在我们的行业中,总会发生这样的事情:原本用来描述具体工具和实践的术语,会被营销团队过度使用,最终变成流行词(buzzword)。
因此,我们必须先为本书设定上下文,避免产生混淆。
1.1.1 云服务与领域特定需求
为了理解行业现状以及未来的发展方向,我们可以将云服务划分为不同层次。
下面的图展示了云服务商提供的一些服务类别,从底层的基础设施服务(按需提供硬件),到高层的应用服务(开发者可以直接与机器学习模型交互,而无需关心这些模型运行在哪里)。
如图 1.1 所示,这些层次从底部的低层计算资源,一直向上到应用级和行业特定的服务。

类别越高,你需要为该服务支付的费用就越多,因为这些服务通常会为你处理所有底层层级和运营成本。
例如,假设你在云服务商提供的托管服务中创建了一个新的高可用 PostgreSQL 数据库。
图 1.2 展示了一个关系型数据库(如 PostgreSQL)的示例。

在这种情况下,服务成本不仅包括运行所需的数据库软件成本和管理费用,还包括数据库运行所在的操作系统以及运行所需的硬件成本。
由于你可能希望在应用程序高负载时监控数据库性能并获取相关指标,云服务商还会为该服务接入所有可用的监控工具。
接下来就需要你来权衡:
是值得花钱让云服务商替我们做出所有这些决策,还是应该组建一个具备足够知识的内部团队,在本地运行并运维这些软硬件?
有时,资金并不是问题,你可能还需要应对公司或行业的政策与监管要求。在这种情况下,你是否能在云服务商的环境中运行业务负载并托管数据,就需要谨慎评估。
1.1.2 作为一个组织,你的职责
跟上所有可用服务、库、框架和工具的最新动态,本身就是一份全职工作。
运营和维护企业运行应用程序所需的各种软硬件,需要配备合适的团队。归根结底,如果你的组织在软件交付实践方面不是一个规模大且成熟的组织,或者自行管理软硬件堆栈并不能为你带来竞争优势,那么选择云服务商通常是更合理的做法。
即便如此,每家公司和每位开发人员仍然需要去评估现有服务,选择将使用哪些服务,以及如何将这些服务组合起来以构建新功能。
在每个组织中,通常会有云架构师(可能是某一云服务商的专家,或是本地部署的专家)来定义如何以及使用哪些服务来构建核心应用。
企业也常会借助云服务商的咨询服务,获取特定用例和最佳实践方面的建议与指导。
云服务商可能会推荐用于构建应用的工具和工作流,但每个组织都需要经历一个学习曲线,并在将这些工具应用于解决自身特定挑战的过程中逐渐成熟。
引入云服务商的专家始终是一个好主意,因为他们能带来以往经验积累的知识,从而为经验不足的团队节省时间。
在本书中,我们将重点关注组织特定的平台 ,而不是云服务商提供的那种"开箱即用"的通用云平台。
我们还会关注能够在组织自有硬件上、本地部署环境中运行的平台。这对于那些无法运行在公有云上的受监管行业尤其重要。
这就要求我们对可以应用在云服务商之外的工具、标准和工作流有更广泛的视野。
从多个云服务商消费服务的情况也越来越常见,这可能是因为你的公司收购或被另一家使用不同云服务商的公司收购,最终形成多云共存的局面,此时需要为不同云服务商制定统一的策略。
在某些受监管行业,组织甚至被要求在不同的云服务商(包括本地部署)之间运行业务负载,以确保在某个云服务商整体宕机的情况下,系统仍然具有韧性。
我们将探讨的平台类型,是在前面提到的"客户行为层"之上进一步扩展的------加入公司特定的服务、公司特定的标准,以及支持开发团队构建复杂系统的开发者体验。
无论我们消费的是云服务、第三方服务还是内部服务,组织都必须在这些服务之上构建新的层,以解决特定的业务挑战(如图 1.3 所示)。

这些额外的层,大多数时候是把现有的服务、数据和事件源"粘合"在一起,以解决业务所面临的特定挑战,或为客户实现新的功能。
很常见的做法是依赖第三方服务提供商来获得更多业务相关的工具,例如行业专用的或通用的 CRM(客户关系管理)系统,比如 Salesforce。
对于客户来说,平台、云服务商以及服务运行在哪里完全无关紧要。
在公司内部,对于开发团队而言,平台是帮助他们完成工作的赋能工具。平台不是一成不变的,它的主要目标是帮助组织不断改进,并持续为客户交付高质量的软件。
无论你的公司身处哪个行业,也无论是否选择使用云服务商,你公司为了向客户交付新功能而组合使用的工具与工作流,都可以被称为你的平台。
从技术角度看,平台的核心就是系统集成、最佳实践,以及可组合的服务------我们可以将这些服务组合起来构建更复杂的系统。
本书将探讨让平台成功的标准实践、工具和行为,并介绍如何构建你自己的云原生平台,无论它是运行在一个或多个云服务商上,还是运行在本地部署环境中。
我们会以云服务商为参考,对比它们提供的服务与工具,并学习如何通过开源工具,在多云环境或本地部署中实现类似的效果。
但在深入研究具体工具之前,首先要了解我们可以从云服务商那里获得什么样的体验。
1.1.3 使用云平台
所有云服务商的一个共同点是:它们都采用 API 优先 (API-first) 的方式提供服务。
这意味着,要访问它们的任何服务,都会向用户提供一个 API,以便请求和与该服务交互。
这些 API 会暴露该服务的所有功能,例如可以创建哪些资源、支持哪些配置参数、希望资源在哪个区域(Region)运行等。
另一个重要方面是,这些 API 必须有一个团队来负责和维护------包括确定 API 如何使用、如何演进,以及明确 API 不负责的范围。
我们可以通过分析 API 来了解一个云服务商的能力,因为通常每个服务都会对应一个 API。
在服务正式发布之前,常会有处于 Beta 或 Alpha 阶段的服务,仅通过 API 提供给早期用户试用、测试,并反馈意见。
虽然同一家云服务商的各项服务在结构、格式、风格上通常类似,但在不同云服务商之间,并没有统一的标准来规定服务应该如何暴露,以及必须支持哪些功能。
直接手动编写复杂的 API 请求来调用云服务既复杂又容易出错。
因此,云服务商普遍会提供 SDK(软件开发工具包) 来简化开发者的工作,这些 SDK 会封装 API,并提供多种编程语言版本。
这样,开发者只需在应用中引入依赖(即云服务商 SDK 库),就可以以编程方式连接并使用云服务商的服务。
不过,这也带来了应用代码与云服务商之间的强耦合,有时为了升级这些依赖,我们甚至需要发布新的应用版本。
与 API 一样,SDK 也没有统一标准,每个 SDK 都深受所支持的编程语言生态的最佳实践和工具的影响。
有些情况下,SDK 可能与该语言生态中流行的框架或工具不兼容,例如数据库驱动版本与云服务商不匹配,或者云服务商暂不支持某些语言与生态。
在这种情况下,虽然可以直接调用 API,但难度较大,而且通常不被推荐,因为这意味着你需要自己维护所有与云服务商交互的代码。
云服务商还会提供 CLI(命令行工具) ,方便运维团队和部分开发者使用。
CLI 是可以下载、安装并直接在操作系统终端中运行的二进制工具,它们直接与云服务商 API 交互,但不像 SDK 那样要求你编写应用程序来调用服务。
CLI 在持续集成(CI)和自动化流水线中尤其有用,例如在运行集成测试时按需创建资源。
图 1.4 展示了应用程序和自动化流程(如 CI/CD 流水线和集成测试)如何使用不同的工具来消费相同的 API------这些工具由云服务商设计,用来简化使用场景。
图中还展示了 Dashboard(控制台) 组件,它通常运行在云服务商内部,提供所有已创建服务和资源的可视化访问界面。

最后,由于云服务提供商所提供的服务数量众多,且这些服务之间相互关联,因此他们通常会提供仪表板(dashboard)和用户界面,让用户能够访问并与所有提供的服务进行交互。这些仪表板还会提供报表、计费以及其他一些通过 CLI(命令行接口)或直接调用 API 很难直观呈现的功能。借助这些仪表板,用户可以访问大多数由服务提供的标准功能,并能够实时查看云服务提供商内部正在创建的资源。
正如前面提到的,仪表板、CLI 和 SDK 都要求你的团队去学习大量云服务商特有的流程、工具以及命名体系。由于每家云服务商提供的服务种类繁多,因此不难理解,为何要找到能同时精通多个云服务商平台的专家会是一件非常有挑战的事。
鉴于这是一本以 Kubernetes 为核心的书,我想展示一下云服务提供商在创建 Kubernetes 集群时所提供的使用体验,以此演示 Google Cloud Platform 所暴露的仪表板、CLI 和 API。虽然有些云服务商的体验优于其他,但总体上来说,你在所有主要云服务商上都能实现相同的功能。
1.1.4 GCP 仪表板、CLI 与 API
请看图 1.5 中的 Google Kubernetes Engine 仪表板,用它来创建新的 Kubernetes 集群。一旦你点击 Create a New Cluster(创建新集群) 按钮,系统就会呈现一个表单,要求你填写一些必要的字段,例如集群名称。

云服务提供商在设置合理的默认值方面做得非常出色,这样在创建所需资源之前,你不必填写 200 个参数。填写完所有必填字段后,表单会在底部提供一个快捷方式,只需点击 Create(创建) 按钮就能启动资源的创建流程。
有趣的是,在这种情况下,Google Cloud Platform 会向你显示已配置资源的 每小时预估费用。这体现了一个差别:有些平台只是在为技术团队提供功能,而另一些平台则提供了完整的服务,既满足技术团队的需求,又清晰说明这些决策会如何影响整个业务。你甚至可以调整参数,观察成本的变化(通常是往上走的)。

如图 1.6 所示,在 Create(创建) 按钮旁边,你可以看到 REST 选项。云服务提供商会帮你生成一个 REST 请求,用于调用他们的 API 来创建你在表单中配置的资源。这样就非常方便------如果你不想花几个小时去翻阅 API 文档,寻找请求所需的 payload(载荷) 结构和属性,这个功能就能帮你省下不少时间;见图 1.7。

最后,命令行(CLI)选项,即使用云提供商的 CLI(此处为 gcloud),同样会根据你在表单中配置的内容生成所需的所有参数,如图 1.8 所示。

注意图 1.8 中的横向滚动条;这个命令可能会变得非常复杂。Google Cloud Platform 的用户体验团队在简化团队设置所有这些参数方面做得非常出色,他们依靠了合理的默认值。这些方法在预期行为上没有差异,但你需要注意,当你使用云提供商的仪表板时,你的账户凭证是来自当前会话的。如果你从云提供商网络之外构造请求或使用 CLI,你必须先通过云提供商进行身份验证,然后才能发出请求或执行创建资源的命令。需要特别注意的是,这些交互在不同云提供商之间会有所不同。你不能指望在 AWS 或 Azure 中命令、仪表板交互或安全机制的工作方式与 GCP 相同,无论是用于验证 CLI 还是 REST 请求。
1.1.5 云提供商为什么能运作?
有人可能会认为,仪表板、CLI、API 和 SDK 是我们从云提供商获取的主要工具,但更大的问题是:我们如何将这些工具结合起来交付软件?如果你分析全球各地组织为什么信任 AWS、Google Cloud Platform 和 Microsoft Azure,你很可能会发现,通过采用 API 优先的方法,并提供仪表板、CLI、SDK 以及众多服务,这些平台为团队提供了三个定义现代平台的主要特性(图 1.9):
- API(契约) :无论使用哪种工具,平台必须公开一组 API,使团队能够消费或配置完成工作所需的资源。这些 API 由平台工程团队负责维护和演进。
- 通向生产的黄金路径:平台对团队将变更部署到生产环境的工作流程进行编码和自动化,使实际客户/用户能够访问这些变更。
- 可视性:通过查看云提供商的仪表板,组织可以随时监控资源使用情况、各项服务费用、处理事件,并全面了解组织的软件交付情况。

这些关键特性是通过一种竞争性的"按需付费"模式提供的,这种模式高度依赖需求(流量),在全球范围内(并非针对所有服务)生效,从而使组织能够将所有运营和基础设施成本外包出去。
尽管云提供商在技术栈中提供的服务越来越高层次(提供高层服务,而不仅仅是提供硬件和应用基础设施,例如数据库),你的团队仍然需要学习如何将这些服务组合在一起,以解决业务挑战。
这就是为什么 Kubernetes 和 CNCF 生态体系 (Cloud-Native Computing Foundation,www.cncf.io/)成为关键学习领域------...
1.2 构建在 Kubernetes 之上的平台
我们已经简要讨论了平台的概念,以及云提供商如何引领方向,定义这些平台能为组织和负责交付软件的开发团队提供哪些能力。但这如何映射到 Kubernetes 呢?Kubernetes 本身不是一个平台吗?
Kubernetes 的设计初衷是为云原生应用提供声明式管理系统。它定义了一套构建模块,使我们能够运行和部署工作负载。如今,每个主要云提供商都提供 Kubernetes 托管服务,这让我们可以通过标准化方式打包(容器化)并在不同云提供商之间部署工作负载。
由于 Kubernetes 自带工具和生态体系(CNCF 生态体系,landscape.cncf.io/),你可以创建与云无关的工作流程来构建、运行和监控应用。但学习 Kubernetes 只是起点,因为 Kubernetes 提供的构建模块非常底层,需要组合使用来构建工具和系统,以解决更具体的场景。将这些低层构建模块组合成更复杂的工具,以解决特定挑战,是一种自然的进化步骤。
虽然 Kubernetes 提供了 API(Kubernetes APIs)、CLI(kubectl)和仪表板(Kubernetes Dashboard,kubernetes.io/docs/tasks/...),但它本身并不是一个平台。Kubernetes 是一个元平台 ,或者说是一个用于构建平台的平台,因为它提供了构建具体平台所需的所有构建模块,这些平台能够解决特定领域的挑战。
图 1.10 展示了 Kubernetes 的工具和组件如何映射到我们之前讨论的平台和云提供商概念。

Kubernetes 是可扩展的,这也是本书将探讨如何使用 Kubernetes API、工具或内部机制的具体项目来解决通用挑战的原因,例如持续集成、持续交付、云资源配置、监控与可观测性,以及开发者体验等。
1.2.1 Kubernetes 采用之旅
无论平台团队选择哪种工具,我们都必须将所有复杂性以及为让这些工具协同工作而编写的"胶水代码"抽象出来,让使用这些工具的团队无需关心这些细节。记住,应用开发团队、测试团队、运维团队等关注点和优先级各不相同。在 Kubernetes 采用过程中,我们必须意识到,并非所有使用这些工具的团队都是 Kubernetes 专家。
通过自定义扩展来扩展 Kubernetes,是使其适应组织特定挑战的一种方式。请记住,无论你在 Kubernetes 集群中编写或安装什么工具,运维团队都需要在生产环境中运行这些工具,并确保其可扩展性和持续运行。每新增一个工具或扩展,都需要对使用团队进行培训,让他们理解这些工具的工作原理以及设计目标。很容易出现这样的情况:你选择了 10 个不同的工具,它们需要被集成,并且需要编写大量胶水代码。平台团队总是在权衡编写胶水代码、为特定场景重写更合适的解决方案,或者扩展现有工具之间的利弊。我强烈建议你熟悉 CNCF 生态体系中的工具(landscape.cncf.io),以避免走向每个工具都为你的组织量身定制的方向,因为这意味着长期需要内部维护所有这些工具。
抽象复杂性是构建平台的关键部分。与团队达成清晰的契约,明确平台能为他们提供什么,是平台工程成功的关键。这些契约通常以 API 形式对外提供,团队可以通过编程、仪表板或自动化方式进行交互。
图 1.11 展示了典型的 Kubernetes 采用之旅,以平台工程为目标。这个旅程从将 Kubernetes 作为运行工作负载的目标平台开始,接着研究和选择工具(通常来自 CNCF 生态体系)。当初始工具选定后,平台开始成型,需要一定投入来配置并使这些工具适应团队使用。最终,所有配置和选择的工具可以被隐藏在更友好的平台 API 背后,让最终用户专注于自己的工作流程,而无需理解构成平台的每一个工具和胶水代码的细节。

在经历这一旅程后,我们可以将平台定义为:将知识编码起来,以便为开发团队提供所有必要工作流程的方式。用于实现这些工作流程的运维知识以及工具选择决策,都被封装在以平台 API 形式体现的契约背后。这些 API 可以调用 Kubernetes API 提供声明式方法,但这并非必须。有些平台甚至隐藏了其底层使用了 Kubernetes,这同样可以降低与平台交互的团队的认知负担。
虽然我试图从非常高层次介绍平台的概念,但我更倾向于将正式定义交给云原生领域负责定义并更新术语的工作组。我强烈建议你查看 CNCF 关于平台的白皮书中 App Delivery TAG - Platform Working Group (tag-app-delivery.cncf.io/whitepapers...),他们致力于定义平台的概念。
在撰写本书时,他们的定义如下:"云原生计算平台是根据平台用户需求定义和呈现的一整套集成功能。它是一个跨领域的层,确保在获取和整合典型功能及服务时,为广泛的应用和使用场景提供一致的体验。一个优秀的平台为其功能和服务(如 Web 门户、项目模板和自助 API)的使用与管理提供一致的用户体验。"
在本书中,我们将通过构建示例平台的方式展开这一旅程,探索可用的云原生工具,并观察它们如何提供不同的平台能力。但这些工具在哪里可以找到?这些工具能协同工作吗?我们如何在不同选项间进行选择?接下来,让我们快速了解 CNCF 生态体系。
1.2.2 CNCF 生态体系拼图
紧跟云提供商的服务更新几乎是一份全职工作,每个云提供商都会举办年度大会和一些小型活动来发布最新动态。在 Kubernetes 和云原生领域,你也会遇到同样的情况。CNCF 生态体系在不断扩展和演进。如图 1.12 所示,这个生态体系规模庞大,初看时非常难以理解。

与云提供商提供的服务相比,一个显著的区别在于 CNCF 中的每个项目都必须遵循公开的、社区驱动的成熟度模型,才能获得"毕业"状态。每个项目的成熟之路独立于任何云提供商,而你,无论是个人还是组织,都可以影响项目的发展方向或推进速度。
尽管云提供商已经定义了云的形态,但如今大多数云提供商都参与了 CNCF 项目,推动这些开源倡议的成功。他们正在开发可跨云提供商使用的工具,消除壁垒,并在开放环境中推动创新,而不是仅在各自云的闭门环境中进行。图 1.13 展示了 Kubernetes 如何促使云原生创新生态在云提供商之外蓬勃发展。云提供商并未停止推出新的、更专业化的服务,但在过去五年中,我们已经看到一种趋势:云提供商与软件厂商之间的协作增强,共同在开放环境中开发新工具和推动创新。

大多数 CNCF 托管项目的一个共同特点是,它们都与 Kubernetes 协作,通过扩展 Kubernetes 来解决更贴近开发团队的高层次挑战。CNCF 已经发展到一个阶段:越来越多的工具被创建出来,以简化开发工具和工作流程。有趣的是,这些工具大多不仅面向开发者,它们还支持运维团队和系统集成商,将不同项目整合在一起,并为 Kubernetes 原生的开发者体验定义新的方式。开发团队无需担心日常工作流程所需的工具和集成。CNCF 生态体系中社区的成熟度提升,以及推动简化开发团队与工具交互的努力,催生了围绕平台工程的讨论。下一节将探讨这些讨论、为什么平台无法直接购买,以及本书将如何探索这一庞大生态体系。
1.3 平台工程
就像云提供商有内部团队来定义将提供哪些新服务、这些服务如何扩展,以及需要向客户暴露哪些工具和 API 一样,组织也能从内部平台工程团队中获益。这些团队通过决定最合适的工具选择,帮助开发团队解决软件交付问题并加快流程。
一个常见趋势是设立专门的 平台工程团队 来定义这些 API 并做出平台范围的决策。平台团队与开发团队、运维团队以及云提供商专家协作,实现满足应用团队工作流需求的工具。除了设立专门的团队外,《Team Topologies》(teamtopologies.com/)一书倡导的一个关键文化转变是:将平台本身视为内部产品,将开发团队视为客户。这虽然并非新概念,但它促使平台团队关注内部开发团队在使用平台工具时的满意度。
图 1.14 展示了应用开发团队(App Dev Teams)如何专注于使用其偏好的工具开发新功能,而平台团队则创建通向生产的"黄金路径"(Golden Paths),确保这些团队所产出的工作能够验证功能并将变更交付给组织的客户或最终用户。

平台与开发团队之间的这种关系能够产生协同效应,专注于改进整个组织的软件交付实践。通过创建"黄金路径",平台不仅仅关注日常开发任务,还旨在自动化开发团队所做变更如何触达组织的最终客户/消费者。
通过为整个流程增加可视性,你可以帮助整个组织理解并观察团队如何开发新功能,以及这些功能何时能提供给最终用户。这对于业务决策、市场营销以及整体规划都非常有价值。
1.3.1 为什么我不能直接购买一个平台?
不幸的是,你无法购买一个现成的平台来满足组织的所有需求。如前所述,你可以购买一个或多个云提供商的服务,但你的内部团队仍需弄清楚哪些服务需要组合,以及如何组合才能解决特定问题。弄清楚哪些工具和服务符合组织需求与合规要求,并将这些决策封装在团队可以自助使用的接口背后,这通常是无法直接购买的。
针对这种情况,有一些工具试图通过提供一套开箱即用的工作流程,或提供一套高度意见化的工具组合,来减少平台团队的"胶水工作"。这类工具中,重度使用并扩展 Kubernetes 的包括 Red Hat OpenShift (www.redhat.com/en/technolo...)和 VMware Tanzu (tanzu.vmware.com/tanzu)。这些工具对首席技术官(CTO)和架构师非常有吸引力,因为它们涵盖了大多数需要解决的问题,如 CI/CD、运维、开发工具和框架。
根据我的经验,虽然这些工具在许多场景中很有帮助,但平台团队仍需要在所选工具上保持灵活性,以适应现有实践。归根结底,即便购买了这些工具,团队仍需花时间学习,这也是为什么 Red Hat OpenShift 和 VMware Tanzu 通常配套提供咨询服务,这也是需要纳入成本的因素。对于中大型组织而言,采用和调整这些意见化的现成工具,可能需要对团队已经熟知的工作流程和实践进行变更。对于较小或不成熟的组织,这些工具可以通过减少团队在新项目启动时面临的选择数量,节省大量时间,但其工具和服务成本可能对年轻组织而言过高。
图 1.15 展示了平台团队选择不同工具时,旅程如何发生变化。这些 Kubernetes 发行版(如 OpenShift、Tanzu 等)可能会限制平台团队的选择数量,但它们也可以节省时间,并提供培训和咨询等服务,团队可以依赖这些服务。

无论你是否已经是这些工具的用户,你仍然需要在这些工具之上构建平台。如果你的团队可以使用 Red Hat OpenShift 或 VMware Tanzu,我强烈建议你熟悉它们支持的工具及其设计选择和决策。与现有工具保持一致,并与其架构师沟通,可能会帮助你找到在这些工具之上构建平台层的捷径。
需要注意的是:这些工具可以被视作 Kubernetes 发行版。这里的"发行版"类似于 Linux 发行版,这意味着未来会出现越来越多的发行版,针对不同的挑战和使用场景。例如,面向物联网和边缘计算的 K0s 和 MicroK8s 就是另一些例子。在采用任何这些发行版时,请确保它们与组织目标保持一致。
为了保持本书尽可能实用,我们将在下一节中使用一个简单应用作为我们的实践旅程。我们不会为通用场景构建一个泛用平台,而是构建一个示例平台,以展示前几节讨论的概念。拥有一个可运行、可实验和可修改的具体示例,将帮助你将讨论的主题映射到日常业务挑战中。下一节介绍的应用强调了在大多数业务领域中创建、构建和维护分布式应用所面临的挑战。因此,我们将构建的示例平台应当能够映射到你在业务领域中可能遇到的挑战。
1.4 对"行走骨架"(walking skeleton)的需求
在 Kubernetes 生态中,要交付一个简单的概念验证(PoC),通常需要整合至少 10 个以上的项目或框架。这项工作可能涉及将项目打包到 Kubernetes 可运行的容器中,并将流量路由到每个服务提供的 REST 端点。如果你希望尝试新项目,验证它们是否适合你的生态系统,可以构建 PoC 来验证你对该新项目/框架的理解,以及它如何为你和团队节省时间。
在本书中,我创建了一个简单的 "行走骨架"(walking skeleton) 。这个云原生应用不仅仅是一个 PoC,还可以让你探索不同架构模式的应用,同时测试不同工具和框架如何集成,而无需修改实验项目。我选择使用"walking skeleton"这个术语,而不是 PoC 或演示应用,因为它更准确地反映了本节介绍的应用的意图。
这个 walking skeleton 的主要目的是从架构角度展示如何解决非常具体的挑战,应用所需的需求,以及交付实践的思路。你应该能够将示例云原生应用中解决这些挑战的方法映射到你的具体领域中。挑战不可能完全相同,但我希望强调每个解决方案背后的原则,以及指导你决策的方法。
通过这个 walking skeleton,你还能确定所需的最小可行产品(MVP),并快速部署到生产环境中进行改进。将 walking skeleton 部署到生产环境,可以让你获得关于其他服务和基础设施需求的宝贵见解,也能帮助团队理解与这些项目协作所需的条件,以及可能出现问题的环节和方式。
用于构建 walking skeleton 的技术栈并不重要,更重要的是理解各部分如何组合,以及哪些工具和实践可以使每个服务(或一组服务)背后的团队安全高效地发展。
1.4.1 构建 Conference 应用
在本书中,你将使用 Conference 应用。该应用可以部署在不同环境中,为不同活动提供服务。它依赖容器、Kubernetes,以及可以在主要云提供商和本地 Kubernetes 安装中运行的工具。
图 1.16 展示了该应用主页的界面。

Conference 应用允许用户管理会议活动,它提供了一个基础的首页、一个议程页面(Agenda),在该页面中会列出所有已批准的演讲,以及一个征稿表单(Call for Proposals),供潜在演讲者提交他们的演讲提案。该应用还允许会议组织者执行管理任务,例如审核提交的提案并进行批准或拒绝(见图 1.17)。

该应用由一组具有不同职责的服务组成。图 1.18 展示了应用的主要组件,也就是你所控制的部分------换句话说,就是你和你的团队将会修改和交付的服务。

团队创建了这些服务,以实现一个基础的 walking skeleton,其功能展示了业务价值。以下是每个服务的简要说明:
- Frontend(前端服务) :该服务是用户访问应用的主要入口。因此,它托管了一个 NextJS 应用(包括 HTML、JavaScript 和 CSS 文件),供客户端浏览器下载。客户端应用会与后端服务交互,后端服务接收浏览器的请求并将每个请求路由到一个或多个后端服务。
- Agenda 服务:该服务负责列出所有已获批准的会议演讲。在会议期间,该服务需要高度可用,因为参会者会在一天中多次访问此服务,以在不同议程环节之间切换。
- Call for Proposals(C4P,征稿服务) :该服务包含处理征稿场景(简称 C4P)的逻辑,用于会议筹办期间。该功能允许潜在演讲者提交演讲提案,由会议组织者审核并决定哪些提案纳入会议议程。
- Notifications 服务(通知服务) :该服务使会议组织者能够向参会者和演讲者发送通知。
图 1.19 展示了团队选择用于构建 walking skeleton 的 征稿流程,并验证他们对 Conference 应用如何工作的假设。通过端到端实现该用例,团队可以验证所选技术栈和架构假设的合理性。

在实现了征稿用例的基础功能后,团队可以决定接下来实现哪个用例。例如,会议组织者是否需要管理赞助商?演讲者是否需要专门的个人主页?由于基础构建模块已经到位,新增功能或服务应该相对简单。
在观察这些用例的实现方式时,你还需要考虑在实现新用例或引入变更时如何在团队间进行协调。为了提升协作,你需要具备可视性,并且理解应用的运行情况。
同时,你还需要考虑该云原生应用的运维方面。可以想象,应用会在某个时期开放征稿功能以让潜在演讲者提交提案,然后在会议临近时开放参会者注册页面,等等。
在本书中,我会鼓励你通过添加新服务和实现新用例进行实验。在第 2 章中,当你将应用部署到 Kubernetes 集群时,你将检查这些服务的配置方式、不同服务间的数据流以及如何扩展这些服务。
通过操作一个虚拟应用,你可以自由修改每个服务的内部结构,使用不同工具进行对比,甚至可以同时尝试每个服务的不同版本。每个服务都提供了将其部署到环境所需的全部资源。在第 3 章和第 4 章中,我们将深入探讨每个服务,了解如何构建和部署它们,使团队能够修改现有行为并创建和部署新版本。
在部署这个云原生 Conference 应用之前,有必要提一下将所有功能捆绑在单体应用中的主要差异。
那么,如果 Conference 应用采用单体架构会怎样呢?我们来简要讨论主要区别。
1.4.2 单体应用与分布式服务集的差异
理解单体应用与完全分布式服务集之间的差异,对于理解增加的复杂性为何值得付出努力至关重要。如果你仍在使用希望拆分为分布式架构的单体应用,本节将强调你会遇到的主要差异。
图 1.20 展示了一个实现前述相同用例的单体应用。在这种情况下,不同团队在不同功能上工作,但共享同一代码库。开发单体应用时,并不要求内部服务之间有强接口;将不同功能的逻辑分离到封装良好的模块中也是可选的。由于缺乏接口且功能重叠,团队在修改应用时需要复杂的协调策略,以确保功能不会冲突,并且变更能够正确合并到代码库中。

在功能上,它们是相同的,你可以实现相同数量的用例,但单体应用存在一些缺点,而你可能在使用单体应用时已经遇到过这些问题。以下几点强调了我们将在本书中使用的云原生应用的优势,以及与假想的单体实现方案相关的一些劣势:
- 服务可以独立演进,团队能够更快推进,代码库不再是瓶颈:在单体应用中,不同团队共享一个源代码仓库,整个项目只有一个持续集成流水线,速度缓慢,而且团队使用功能分支(feature branch)会导致复杂的合并问题。
- 应用可以针对不同场景进行差异化扩展:从可扩展性角度来看,每个服务可以根据其承载的负载进行独立扩展。而在单体应用中,如果只需要扩展单个功能,运维团队只能创建整个应用的新实例。对不同功能的精细化扩展控制可能成为你用例的重要差异化因素,但前提是你要做好充分调研。
- 云原生版本更复杂,因为它是分布式系统:它更好地利用了云基础设施的灵活性和特性,让运维团队可以使用工具管理复杂性和日常运维。在构建单体应用时,内部开发操作大型应用的机制更为常见。而在云原生环境中,云提供商和开源项目提供了大量工具,可用于运维和监控云原生应用。
- 支持多语言技术栈:每个服务可以使用不同的编程语言或框架构建。在单体应用中,开发者通常受限于旧版本库,因为升级或更换库通常需要大规模重构,并且必须测试整个应用以确保不出错。在云原生方法中,服务不必使用单一技术栈,这让团队在选择工具时更自主,从而在某些情况下加快交付速度。
- 单体应用是全有或全无:如果单体应用宕机,整个应用不可用,用户无法访问任何内容。而云原生版本即使部分服务宕机,用户仍可访问应用。示例 walking skeleton 展示了如何通过流行工具支持服务降级。使用 Kubernetes,可以监控服务并在服务异常时采取措施,平台将尝试自我修复应用。
- 每个会议事件需要单体应用的不同版本:处理不同事件时,每个会议可能需要稍有不同的单体版本,这会导致代码库分歧和整个项目的重复修改。大多数针对某次会议做的修改在活动结束后会丢失。云原生方法通过精细化服务实现可复用性,可以替换单个服务,避免整个应用重复。
虽然单体应用在开发和运维上更直接,但本书的重点是理解并降低构建分布式应用的复杂性。我们将通过采用合适的工具和实践,使团队更加独立和高效,同时提升应用的弹性和稳健性。
如果你目前正在使用单体应用,我希望本书能够帮助你比较不同方法,并介绍构建分布式应用所需的工具和实践。
1.4.3 我们的 walking skeleton 与平台构建
现在我们有了一个客户将使用的简单应用,我们可以专注于理解团队需要哪些工具来持续改进这些服务。本书涵盖的平台是为特定领域目的构建的,而非通用型平台。通过为特定场景创建 walking skeleton,我们可以模拟一个优化工具和工作流的平台,从而提升软件交付效率。我们的 walking skeleton 并非简单的 "Hello World" 应用,因此允许更多实验、构建复杂功能,并使用工具增强应用稳健性。
接下来,我们将踏上云原生之旅。首先,我们将了解分布式应用如何在 Kubernetes 上运行,Kubernetes 提供了哪些功能以及其面临的挑战。随后,我们将研究扩展 Kubernetes 基础功能的工具,帮助我们构建、部署和运行云原生应用。
在第 6 章中,在评估构建和交付分布式应用的挑战之后,我们将构建平台 walking skeleton,帮助团队在安全环境下创建新功能,与现有应用协作,而不会与其他团队产生冲突。一旦拥有平台 walking skeleton,我们将构建并提供更高层次的平台能力,让团队更高效,同时减少理解 Kubernetes 及本书所讨论工具复杂性的需求。
最后,在书的结尾,我们将探讨如何衡量所构建平台的好坏。与任何软件一样,我们需要衡量平台,以确保新引入的工具或变更能改善而非恶化现状。
这个旅程将推动我们做出关键决策,这些决策对于平台工程实践至关重要。以下是本旅程的主要里程碑(未涉及各章具体工具细节):
- 第 2 章:云原生应用挑战
在 Kubernetes 集群中部署 Conference 应用后,我们将分析在 Kubernetes 上运行云原生应用时最常见的挑战。你将从运行时角度检查应用,并尝试以不同方式"破坏"应用,观察其异常行为。 - 第 3 章:服务流水线------构建云原生应用
应用上线后,你和团队将修改应用服务以添加新功能或修复 Bug。本章介绍构建应用服务所需的流程,包括使用服务流水线生成部署到生产环境的新版本所需的工件。 - 第 4 章:环境流水线------部署云原生应用
了解如何打包和发布服务新版本后,需要明确策略将新版本推广到不同环境,以便在面对真实用户前进行测试和验证。本章介绍环境流水线概念,以及云原生社区流行的 GitOps 方法,用于跨环境配置和部署应用。 - 第 5 章:多云(应用)基础设施
应用不能孤立运行。应用服务需要数据库、消息中间件、身份服务等基础设施组件。本章重点介绍如何以多云和 Kubernetes 原生方式提供应用服务所需的组件。 - 第 6 章:在 Kubernetes 上构建平台
了解应用运行、构建、部署及其与云基础设施的连接后,我们将专注于将工具带来的复杂性抽象出来,让开发团队不被干扰,如配置云服务账户、构建流水线服务器或环境位置等。欢迎加入平台工程团队! - 第 7 章:平台能力 I------共享应用关注点
如何减少应用与运维团队之间的摩擦与依赖?如何进一步解耦应用逻辑与运行所需组件?本章介绍一系列平台能力,使应用开发者专注于编码,平台团队负责协调所有必要组件并提供简单标准的 API 供开发者使用。 - 第 8 章:平台能力 II------支持团队实验
拥有能够为团队提供环境的平台后,还能做什么?如果允许团队同时运行应用服务的多个版本,则新功能或修复可逐步发布。实验空间让组织更早发现问题,并降低每次发布的压力。本章介绍如何为云原生应用实现不同的发布策略。 - 第 9 章:衡量平台
平台的价值取决于其对组织带来的改进。我们需要衡量平台性能,以确保使用的工具帮助团队更快、更高效地交付软件。本章聚焦使用 DORA 指标评估组织的软件交付水平,并分析平台变更如何提高交付流水线吞吐量。
现在,你已经了解了接下来的内容,让我们开始部署云原生 Conference 应用吧。
总结
- (云)平台为团队提供了一整套服务,用于构建特定领域的应用。
- 平台通常提供三大核心功能:API、仪表盘和 SDK,让不同团队可以根据自己的工作流程选择合适的工具使用。
- 云平台采用按需付费模式,硬件和软件资源按使用量计费。技术栈越往上层,服务成本越高。
- Kubernetes 提供了构建平台的基础构件,使我们能够在不依赖底层云提供商的情况下构建平台,甚至可以在本地部署我们的平台。
- Cloud Native Computing Foundation(云原生计算基金会)推动并促进云原生领域开源项目之间的协作。跟踪这些社区动态几乎是一份全职工作。
- 在 Kubernetes 上进行平台工程(本书的重点)有助于管理复杂性,即帮助团队选择需要采用的工具和实践,从而更高效地交付运行在 Kubernetes 之上的软件。