VMware-Tanzu-DevSecOps-实践指南-全-
VMware Tanzu DevSecOps 实践指南(全)
原文:
annas-archive.org/md5/a084e86a83d965c74ef449f2db346567译者:飞龙
前言
以容器打包的微服务形式运行业务应用程序已成为当今的常态。根据云原生计算基金会在 2021 年进行的一项调查(www.cncf.io/reports/cncf-annual-survey-2021/),约 80%的应用程序都部署在 Kubernetes 上。然而,构建容器化应用程序和生产级 Kubernetes 平台是一些难以攻克的难题。此外,企业考虑到多云部署策略,这为不同的原因增加了更多的操作复杂性。在本书中,我们将学习 VMware Tanzu 产品组合中的不同工具如何协同解决在多云 Kubernetes 平台上构建、运行和管理现代应用的挑战。
我们将本书分为三个逻辑部分,符合应用开发生命周期。在第一部分中,我们将回顾帮助构建安全应用的不同工具。在这一部分中,我们还将展示如何将这些应用容器化并管理它们暴露的 API。在第二部分中,我们将深入探讨帮助大规模运行这些应用的工具。我们将涵盖帮助管理容器镜像和在多云环境中部署 Kubernetes 平台的工具。本节还介绍了如何通过供应链编排部署安全的生产路径。最后一部分将讲解如何管理大规模的 Kubernetes 部署。本节涵盖了监控、安全性和治理多云部署的统一视图。
本书的每一章都涵盖了现代应用生命周期中的一个方面,以及与该方面相关的 Tanzu 工具。这些章节首先描述了业务案例及其适用的挑战——工具背后的为什么。然后,它们提供了适用于工具的高层次细节——工具背后的什么。最后,它们讲解了如何开始使用这些工具——工具背后的如何。
到本书结束时,你将深入理解 Tanzu 平台及其能力,能够将 DevSecOps 实践应用于你的现代容器化应用。
本书适合人群
本书适合任何想了解 VMware Tanzu 的人。读者将了解该平台解决的不同安全性、操作性和开发人员生产力的挑战。本书的目的是从学习的角度深入理解这项技术。它还旨在帮助读者在不同工具上执行基本的 Day-1 和 Day-2 操作,获取实践经验。如果你是云或应用程序架构师,本书将帮助你理解这些工具所提供的各种功能,以决定如何或是否将其包含在你的解决方案中。如果你是开发人员或开发负责人,你将学习如何通过不同方式提高开发人员的生产力。如果你是安全官员,你将找到更好的方法来确保你的云原生应用程序和 Kubernetes 平台的安全性。最后,如果你是DevOps 工程师或云平台操作员,你将学会如何围绕这些产品进行各种操作。
本书适合有几年构建和运行现代应用程序经验的人阅读和理解。然而,具有 Kubernetes 经验将有助于更好地理解相关概念和挑战。此外,读者应该有一定的命令行接口(CLI)使用经验,以便跟随所有的实践指导。
本书涵盖的内容
第一章,理解迁移到云平台的必要性,为读者提供现代应用程序的背景和相关背景知识。
第二章,开发云原生应用程序,解释如何使用预定义的应用程序模板,包含所需的框架和模板代码,来开发安全的云原生应用程序。
第三章,使用构建服务构建安全的容器镜像,指导读者如何从应用程序代码或工件中,以完全自动化的方式构建安全的容器镜像。
第四章,为应用程序配置支持服务,详细说明如何构建流行的开源工具目录,以便将其安全的容器镜像作为应用程序后端服务使用。
第五章,定义和管理业务 API,讲述如何构建和管理安全的应用程序 API。
第六章,使用 Harbor 管理容器镜像,提供了如何使用私有容器镜像注册表存储和管理容器镜像的指导。
第七章,使用 Tanzu Kubernetes Grid 在云之间编排容器,详细讲解了多云 Kubernetes 平台的细节。
第八章,通过 Tanzu 应用平台提升开发者生产力,详细介绍了如何建立一个安全的应用供应链,以实现快速的生产路径。
第九章,使用 Tanzu Mission Control 管理和控制 Kubernetes 集群,教会读者如何在多云环境中集中管理部署的各种 Kubernetes 集群。
第十章,通过 VMware Aria 应用程序操作实现全栈可视化,演示了如何监控多云环境中部署的应用程序、它们的 Kubernetes 平台和基础设施。
第十一章,通过 Tanzu 服务网格实现安全的微服务间通信,探讨了如何在多云/多集群环境中,为部署在 Kubernetes 上的微服务建立安全的通信。
第十二章,综合应用,总结了技术领域的端到端概况,并对相关技术的未来发展进行了预测。
充分利用本书
本书的入门门槛非常低。任何具有应用程序开发和/或基础设施运维经验的人都可以使用本书学习 Tanzu 平台的相关内容。然而,读者如果对 Kubernetes 和容器化应用程序有所了解,将能从本书中获得更多收获。为了遵循书中的动手操作,读者还应熟悉 CLI 命令。
| 本书涵盖的 软件/硬件 | 操作系统 要求 | 
|---|---|
| Tanzu 应用加速器 | Windows, macOS 或 Linux | 
| Tanzu 构建服务 | |
| VMware 应用目录 | |
| VMware Tanzu 的 API 门户 | |
| Spring Cloud Gateway | |
| Harbor | |
| Tanzu Kubernetes Grid | |
| Tanzu 应用平台 | |
| Tanzu Mission Control | |
| VMware Aria 应用程序操作 | |
| Tanzu 服务网格 | 
本书中的逐步指导是在 macOS 系统上执行的。然而,大部分指令在 Linux 或 Windows 系统上也能无修改地工作。
如果您使用的是本书的数字版,我们建议您自己输入代码,或从本书的 GitHub 仓库访问代码(链接在下一节提供)。这样做可以帮助您避免因复制和粘贴代码而可能出现的错误。
本书中有一些地方使用了示例应用程序和 Kubernetes 配置。读者可以通过以下章节提供的 GitHub 仓库下载这些内容。
下载示例代码文件
你可以从 GitHub 下载本书的示例代码文件,网址为github.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu。如果代码有更新,它会在 GitHub 仓库中进行更新。
我们还有其他代码包,可以从我们丰富的书籍和视频目录中找到,访问github.com/PacktPublishing/。快来看看吧!
下载彩色图片
我们还提供了一份包含书中截图和图表的彩色 PDF 文件,你可以在此下载:packt.link/xL5cm。
使用的约定
本书中使用了多种文本约定。
文本中的代码:表示文本中的代码字、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 账号。例如:“从那里,你可以按照README.md中的说明,在线下运行应用程序并将其部署到 Kubernetes。”
一段代码会按照如下格式显示:
$ kubectl port-forward -n kubeapps svc/kubeapps 8080:80
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
当我们希望引起你对代码块中特定部分的注意时,相关的行或项会以粗体显示:
$ chmod +x gradlew && ./gradlew openApiGenerate  # (this will create a maven project in-place, use gradlew.bat on Windows)
...
$ mvn spring-boot:run
任何命令行输入或输出都会按如下方式书写:
kubectl apply -f ./accelerator-k8s-resource.yaml
粗体:表示一个新术语、重要词汇或在屏幕上看到的词汇。例如,菜单或对话框中的词汇会以粗体显示。比如:“在 TAP GUI 的创建页面上,我们点击选择按钮,位于Hello Fun 加速器下方。”
提示或重要说明
以这样的形式出现。
联系我们
我们欢迎读者的反馈。
customercare@packtpub.com并在邮件主题中注明书名。
勘误表:虽然我们已尽最大努力确保内容的准确性,但错误难免发生。如果你在本书中发现错误,我们将非常感激你向我们报告。请访问www.packtpub.com/support/errata并填写表格。
copyright@packt.com并附上链接到相关材料。
如果你有兴趣成为作者:如果你在某个主题方面有专业知识,并有兴趣写书或为书籍做贡献,请访问authors.packtpub.com。
分享你的想法
阅读完《DevSecOps in Practice with VMware Tanzu》后,我们非常希望听到你的反馈!请点击此处直接前往 Amazon 评论页面并分享你的想法。
你的评论对我们以及技术社区都非常重要,帮助我们确保提供优质的内容。
下载本书的免费 PDF 版本
感谢购买本书!
你喜欢在旅途中阅读,但又无法随身携带纸质书籍吗?
你的电子书购买是否与您选择的设备不兼容?
别担心,现在购买每本 Packt 图书,你都可以免费获得该书的无 DRM PDF 版本。
在任何地方、任何设备上都可以阅读。搜索、复制并将你最喜欢的技术书籍中的代码直接粘贴到你的应用程序中。
优惠不仅仅如此,你还可以独家获得折扣、新闻通讯,并且每天将有精彩的免费内容发送到你的邮箱
按照以下简单步骤即可享受优惠:
packt.link/free-ebook/9781803241340
- 
提交你的购买证明 
- 
就这些!我们会直接将你的免费 PDF 和其他福利发送到你的电子邮件 
第一部分 – 在 Tanzu 平台上构建云原生应用程序
本部分包含了不同的 Tanzu 工具的详细信息,这些工具对于提高开发者的生产力和软件供应链的安全性,在云原生应用程序开发中非常有用。
本书的这一部分包括以下章节:
- 
第一章,理解迁移到云平台的必要性 
- 
第二章,开发云原生应用程序 
- 
第三章,使用构建服务构建安全的容器镜像 
- 
第四章,为应用程序提供后端服务 
- 
第五章,定义和管理业务 API 
第一章:理解迁移到云平台的必要性
欢迎!如果您与在企业中大规模交付软件有任何关联,我们希望本书对您有所帮助。在本章中,我们将建立一个产品(如 VMware Tanzu)出现的背景。我们将通过回顾过去 20 年企业软件的发展历程,涵盖主要的里程碑、转折点和沿途出现的问题来进行阐述。
然后,在建立了必要的背景后,我们可以对 Tanzu 进行一个 10,000 英尺的概览,涵盖工具、好处和特性。最后,我们将为您提供成功的基础,介绍一些技术前提,确保您在参与本书中的任何实践内容之前已做好准备。
本章将涵盖以下内容:
- 
运行软件供应链的挑战 
- 
云计算和容器的出现 
- 
Kubernetes 
- 
以结果为导向的方法 
- 
VMware Tanzu 的必要性 
运行软件供应链的挑战
VMware Tanzu 是一个模块化的软件应用平台,能够原生运行于多个云平台,并且专注于提高开发者生产力、运营效率,以及默认的安全性等重要业务成果。如果您期待对 VMware Tanzu 进行详细的动手实践,本书不会让您失望。
然而,在深入了解平台的各个组件之前,了解一些历史和背景可能会有所帮助。如果您正在阅读这本书,那么很有可能您参与了软件的编码、设计、架构、运维、监控或管理。然而,您可能没有意识到,您正在参与一个供应链。
根据亚当·海斯在他的 Investopedia 文章《供应链:从原材料到订单履行》中所述,供应链“指的是一个网络,其中包括组织、人员、活动、信息和资源,这些都涉及到将产品或服务交付给消费者”。
当一款软件从开发者的工作站到达最终用户时,这就像是红牛和方便面从原料到生产设施,再到仓库,再到邻里超市的供应链过程。
每个供应链都有其独特的挑战,软件供应链也不例外。今天编写的大多数软件都由库和框架组成,包含数百万行开源软件,这些软件是由一些本质上匿名的人开发的,他们的动机并不完全明确。
大部分软件在从开源代码库到开发人员,再到源代码管理、构建打包、测试、预发布,最后进入生产环境的过程中会经历多次交接。此外,运行这些软件的基础设施通常也是开源的,全球的黑客社区不断寻找操作系统、网络协议实现和组成软件运行的公共工具中的漏洞。这个生态系统呈现出巨大的表面区域,容易发生各种问题。
关于软件供应链可能出现问题的实际案例,进一步阅读 2020 年 SolarWinds 事件或 2021 年 Log4Shell(CVE-2021-44228)漏洞的出现会很有帮助。作为 Tanzu 解决方案工程师,本书的作者亲眼目睹了软件供应链问题对金融、政府、电信、零售和娱乐等行业的影响。
云计算和容器的兴起
幸运的是,科技行业已经开始围绕一些关键技术形成共识,这些技术在解决一些问题方面取得了长足的进展。第一个就是通常所说的云计算。拥有大量技术资源的企业开始意识到,管理数据中心和基础设施并非其业务的主要焦点,这些任务可以由第三方公司更高效地完成,而这些公司将此作为其核心竞争力。
企业不再需要自建数据中心和管理硬件,而是可以租赁由专业团队管理和维护的技术基础设施,并且能够根据实时的业务需求灵活地扩大或缩小容量。这在多个层面上都是一次变革。这一变化的一个积极成果是互联网中易受攻击和过时软件的普遍提高。当漏洞暴露时,云服务提供商能够让正确的做法成为最简单的做法。例如,能够自动处理操作系统更新的托管数据库,以及默认情况下无法公开访问的对象存储。另一个成果是,随着基础设施管理被从开发者的工作职责中剥离,部署速度大幅提升。
随着云计算在企业软件世界中的普及,以及基础设施容量成为商品,这使得一些之前由于基础设施问题而被掩盖的隐患成为了焦点。开发人员可能在开发环境中运行得完美无缺,但一旦进入生产环境就会崩溃。这个问题变得如此普遍,以至于它诞生了一个编程幽默的子类别,叫做它在 我的机器上能运行。
另一个问题是未使用的容量。搭建新的服务器基础设施变得如此简单,以至于应用团队仅为了将大规模(且昂贵)服务器集群搭建起来,结果这些服务器大部分时间几乎处于空闲状态。
容器
这就引出了容器的主题。许多应用团队会争辩说,他们需要自己的服务器集群,因为他们有一套独特的依赖关系需要在这些服务器上安装,而这些依赖关系与其他可能共享这些服务器的应用所需的库和工具发生冲突。最终,是两个技术流派的有幸交汇解决了这个问题,使得依赖关系差异极大的应用能够在同一台服务器上并排运行,彼此甚至不会察觉到对方的存在。
容器运行时
第一个流派是 cgroups 和内核命名空间的概念。这些是内置于 Linux 内核中的抽象,为进程提供了保证,确保其可以获得一定的内存和处理器容量,并且提供了它自己的进程空间、网络栈和根文件系统等虚拟化环境。
容器打包与分发
第二个问题是通过 API 打包整个 Linux 根文件系统,包括其独特的依赖关系,能够高效存储,解包到任意服务器上,并在与其他进程的根文件系统隔离的环境中运行。
当容器技术结合起来时,开发者发现他们能够搭建一组服务器,并在这组服务器上安全地运行多个异构应用,从而更加高效地使用云基础设施。
然后,正如向云迁移暴露了一组新问题,这些问题最终导致了容器生态系统的演变一样,这些容器也带来了新的问题,我们将在接下来的关于 Kubernetes 的部分中讨论这些问题。
Kubernetes
当容器技术流行开来时,它们迅速得到了广泛应用,但它们并不是开发者们所希望的终极解决方案。服务器上的容器运行时通常需要在灵活性和安全性之间做出较大妥协。因为容器运行时需要与 Linux 内核紧密配合,用户通常需要提升权限才能运行容器。此外,运行容器的方式有很多种,其中一些与特定的云服务提供商紧密耦合。最后,虽然容器运行时让开发者能够启动他们的应用,但它们在对持久存储和网络等方面的支持上差异很大,通常需要手动配置和定制。
这些正是 Google 的 Joe Beda、Craig McLuckie 和 Brendan Burns 在构建 Kubernetes 时试图解决的问题。Kubernetes 不仅仅是一个在服务器上运行容器化应用程序的工具,它演变成了 Google 知名开发者倡导者 Kelsey Hightower 所称的“构建平台的平台”。与直接在服务器上运行容器相比,Kubernetes 提供了许多优势:
- 
它提供了一个灵活的声明式 API,用于描述正在运行的应用程序的期望状态——例如,9 个实例,每个使用 1GB 的内存和 500 毫核的 CPU,均匀分布在 3 个可用区。 
- 
它处理了跨弹性服务器群集运行实例的任务,并配备了所有必要的网络和资源管理。 
- 
它提供了一种声明式方式,将云服务商特定的网络和持久存储实现暴露给容器工作负载。 
- 
它提供了一个框架,用于管理自定义 API,从而使 Kubernetes 可以管理任何任意对象。 
- 
它配备了面向开发者的抽象工具,如 Deployments(部署)、Stateful Sets(有状态集)、Config Maps(配置映射)和 Secrets(密钥),这些工具处理了许多常见的用例。 
我们许多人曾认为,或许 Kubernetes 是能够最终解决所有问题的技术进步,但正如每次技术迭代一样,解决一组特定问题的方案往往会暴露出新一代的问题。
随着拥有大规模开发团队的公司开始使用 Kubernetes,这些问题变得越来越突出。以下是一些例子:
- 
技术蔓延逐渐成形,每个团队以不同的方式解决同样的问题。 
- 
各个团队拥有自己的运维工具和流程,导致很难在不同应用程序之间扩展操作。 
- 
强制执行最佳实践涉及同步的人工流程,导致开发人员的工作效率下降。 
- 
每个云服务提供商的 Kubernetes 版本略有不同,这使得多云和混合云部署变得困难。 
- 
Kubernetes 部署的许多核心组件——比如容器镜像——只是将现有问题带到了新的层面,让开发人员比以前更快速、更广泛地部署容易受攻击的软件,实际上使问题变得更严重。 
- 
整个团队不得不专门成立,只为管理开发工具,并试图在众多应用程序中强制执行某种一致性。 
- 
在单一的 Kubernetes 集群上运行多个不同的应用程序需要大量的运维工作和投入。 
可惜的是,Kubernetes 并不是我们希望的万灵药;它只是技术发展的又一次迭代,解决了一组问题,但不可避免地带来了新的一组问题。这就是 VMware Tanzu 团队登场的地方。
面向结果的方法
VMware 的 Tanzu 团队成立时,正值 Kubernetes 在企业中大展拳脚。凭借收购 Heptio,VMware 准备在该领域取得领导地位,Heptio 带来了深厚的 Kubernetes 知识和两位原始创造者。通过收购 Pivotal,VMware 还获得了精细的软件交付理念。Tanzu 团队继续交付一种深思熟虑且细致入微的基于 Kubernetes 的应用平台,专注于对客户来说重要的有意义的商业成果。
毫无疑问,许多成熟的 Tanzu 客户都面临着上一节提到的 Kubernetes 问题,但他们也关注一些关键成果,例如以下几点:
- 
最大化开发人员的速度、生产力和影响力 
- 
最大化运维效率 
- 
在数据中心和多个云提供商之间无缝操作 
- 
默认情况下使软件更安全 
这些是 Tanzu 为客户设定的成果,在这个过程中,他们也解决了许多人在使用 Kubernetes 时遇到的问题。
Tanzu 产品组合将采取以成果为驱动的方法,交付一个有明确意见的基于 Kubernetes 的云原生应用平台,优化运维效率、开发人员生产力、无缝的多云操作以及应用安全。这就是我们将在本书中讲解的平台。
VMware Tanzu 的需求
对于那些拥有大量开发足迹并正在考虑或积极使用 Kubernetes 的公司来说,面临着两种阻力。首先,他们在跨多个团队大规模运行 Kubernetes 时遇到了各种问题。这些问题在本章 Kubernetes 部分的结尾处有列出。其次,这些团队在面临着使用技术交付有意义成果的压力。这意味着开发人员需要以最小的摩擦发挥出全部潜力,而运维人员则需要能够通过一套统一的工具在多个团队中实现规模化。这就是前一节中提到的以成果为驱动的方法。VMware Tanzu 是一个专门面向解决软件团队两方面需求的工具组合。
该图展示了 VMware Tanzu 如何作为基于 Kubernetes 的软件平台的下一次迭代以及集成工具包,帮助软件开发、运维和安全工程师实现世界级成果:

图 1.1 – VMware Tanzu 的背景
现在我们已经确定了促使 VMware Tanzu 诞生的背景,接下来我们准备描述该产品本身。
VMware Tanzu 的功能、工具、益处和应用
这是一组结合了开源、专有和 软件即服务(SaaS)的服务,它们协同工作,帮助软件团队实现重要的成果。这些工具紧密集成,提供一个统一的工具集,专注于交付关键成果并大规模运行 Kubernetes。这些工具和应用程序可以分为三个大类。
构建和开发
这组工具帮助开发人员高效、可靠地开发和构建软件。包括 VMware Tanzu 应用加速器、VMware Tanzu 构建服务、VMware 应用目录 和 VMware Tanzu API 门户。
运行
这一组包含高效交付和持续运行应用程序的工具和应用程序。包括 Harbor、Tanzu Kubernetes Grid 和 Tanzu 应用平台。
管理
最后一组工具包含用于管理应用程序和平台本身的工具。包括 Tanzu Mission Control、VMware Aria 应用操作 和 Tanzu 服务网格。
前提条件
现在我们已经阐明了 VMware Tanzu 的原因和内容,接下来我们准备深入实际解决一些真实世界的问题。本书面向软件专业人士,假设你对一些工具和概念有所了解。如果你在这些领域中某些方面不太擅长,也不用担心,因为每一章都会一步步指导你。
Linux 控制台和工具
你可以使用 Windows 机器跟随本书中的大部分章节,但经验表明,如果你使用 Mac 或 Linux 工作站,操作会更加顺畅。对于 Windows 用户,有很多选择,包括虚拟机、双系统启动 Linux 或使用基于云的虚拟机。本书假设你能熟练操作文件系统、查找和查看文件,并使用 Vim 或 nano 等编辑器进行编辑。
Docker
本书重点讲解容器。与构建和运行容器的 API 交互的主要方式是使用 Docker CLI。你需要同时拥有 Docker 守护进程和 Docker CLI 来完成本书中的一些章节。假设你能熟练列出容器镜像并运行容器。
Kubernetes
Kubernetes 是 Tanzu 产品组合的核心。本书假设你能在本地或公共云服务商上搭建 Kubernetes 集群。还假设你熟悉 kubectl CLI 来与 Kubernetes 集群进行交互。最后,你应该能够阅读 YAML 格式的 Kubernetes 清单。
工作站要求和公共云资源
本书中讨论的某些工具可以在你的工作站上本地运行,而其他一些则更适合在公共云上使用。还有一些工具只需要一个网页浏览器和一个已存在的 Kubernetes 集群。
如果你想在本地运行 Tanzu Kubernetes Grid,强烈建议至少配置 32GB 的内存。你可能会发现其他工具,如 Tanzu 应用平台或 Harbor,在由公有云提供商提供的 Kubernetes 集群上运行效果最好。我强烈建议使用这些提供商的内建预算工具,以确保你不会产生意外账单。
现在你已经知道了所需的条件,我鼓励你找到一个感兴趣的话题并深入研究。所有 Packt 出版的书籍都以独立的章节组织,你可以按顺序从头到尾阅读,也可以直接跳到你感兴趣的主题。
总结
在本章中,我们简要介绍了企业软件的历史,以及其演变如何为 VMware Tanzu 的出现奠定基础。接着,我们对 Tanzu 产品本身进行了高层次的概述。最后,我们介绍了一些技术要求,帮助你在动手练习中取得成功。
在一切准备就绪后,你可以自由跳转到任何一个引起你兴趣的章节;它们都是独立的,可以单独阅读。或者,如果你按顺序进行,我们将从软件开发过程的开始讲起。VMware Tanzu 的应用加速器是一个用于快速构建新应用的工具,它内置了所有企业标准和已批准的库,为你提供了更统一的应用组合,防止软件团队重复过去的错误。无论你以何种方式阅读本书,我们希望你享受这些内容,并祝你在实践中取得巨大成功。
第二章:开发云原生应用
大型企业中常见的问题是技术的扩散。当开始一个新的开发项目时,通常会浪费大量的 day-0 时间来选择合适的技术,错误的决策可能会导致多年的运营问题。
本章将首先关注VMware Tanzu 的应用加速器,简称App Accelerator,这是一种解决新项目启动时 day-0 问题的工具。它允许开发者拉取已经预配置的应用模板,这些模板已经通过企业架构的审核,内置了所有企业的安全意见和保护措施,包含所有企业标准库,使用企业标准格式和布局,并允许配置常见属性(如 Git 仓库、数据库、API 模式等)。
接着,我们将介绍当前在企业中占据重要份额的几个开发框架:Spring Boot 和 .NET Core with Steeltoe。
在本章中,我们将覆盖以下主题:
- 
App Accelerator所解决的业务需求 
- 
技术要求 
- 
App Accelerator概述 
- 
开始使用 App Accelerator 
- 
App Accelerator的高级主题 
- 
使用App Accelerator进行 day-2 操作 
- 
Tanzu旗下的云原生开发框架 
App Accelerator所解决的业务需求
在我们正式开始产品安装之前,让我们花点时间思考一下企业应用程序开发者的工作生活。假设Cody是我们组织中的一名开发者。
今天,Cody 被指派启动一项新服务,预计将为公司带来可观的收入。如果我们让他列出一些可能妨碍他交付该服务的因素,可能会得到如下列表:
- 
为当前任务找到合适的应用框架 
- 
将必要的库导入到该框架中 
- 
导入所有企业要求的库 
- 
解决前两点中引入的任何版本不兼容问题 
- 
确认证所有企业安全标准在此项目中得到了遵守 
- 
使所有导入的库协同工作 
- 
研究并导入所有企业编码规范、项目结构、文档布局等 
- 
等待审查,确保所有标准都已被正确理解和实施 
作为一名软件开发者,也许你会理解 Cody 的一些担忧:

图 2.1 – 开发者 Cody
这对 Cody 来说是一个巨大的负担,对新加入项目的开发者来说更是如此。大部分工作每次创建新项目时都必须重复,这必然导致配置漂移,因为不同的开发者对标准的理解不同,并且在写下第一行有价值的代码之前,这需要大量的时间和精力投入。
现在,让我们把视角转向企业架构师的角色。我们叫她 Alana。她的任务是优化开发者的价值实现时间,确定技术方向,创建并执行一套平衡一致性和安全性与开发者生产力和满意度的标准。她面临着一份与 Cody 类似的障碍清单,这些障碍阻止她最大化开发者的表现:
- 
新开发者必须了解每个项目的独特性,才能开始提高生产力 
- 
手动检查每个组件,以确保遵守所有公司标准的过程会成为瓶颈 
- 
开发者忽略或无视他们不理解或选择不实施的标准 
- 
开发者使用过时且未打补丁的库 
- 
开发者使用未经审查和批准的技术和框架 
- 
由于 软件开发生命周期 (SDLC) 中的重复性、繁琐且容易出错的步骤,开发者的工作满意度下降 
- 
她几乎无法对整个组合做出任何假设,以便能够进行集中管理 
- 
跨项目的问题,如自动扫描、部署或备份,因组合的异质性而受到阻碍 
如果你更关注 Ops(运维)方面,也许 Alana 在这个可视化中提出的一些问题会引起你的共鸣:

图 2.2 – 我们的企业架构师 Alana
现在我们知道了为什么我们在这里,让我们深入探讨应用加速器的细节,并开始解决 Cody 和 Alana 的痛点。
技术要求
应用加速器是 Tanzu 应用平台 (TAP) 的一个子组件,详见 第八章,通过 Tanzu 应用平台提升开发者生产力。要开始使用应用加速器,我们首先需要安装一个 Kubernetes 集群,然后在其上安装 TAP。你可以自由选择任何你喜欢的 Kubernetes 发行版。如果你需要关于搭建集群的指导,本书附录提供了多个启动 Kubernetes 的选项。
一旦你有了一个运行中的 Kubernetes 集群,你需要稍微跳转到 第八章,通过 Tanzu 应用平台提升开发者生产力,在那里我们会介绍 TAP 的安装。那一章讲解了一个更复杂的端到端用例,而本章仅关注应用加速器组件。
根据你的 Kubernetes 集群,TAP GUI 可能位于本地地址,如 http://localhost:8081,或者可能是你设置的入口域名,如 http://tap-gui.example.com。
当你打开浏览器访问 TAP GUI 时,你应该会看到类似于以下截图的界面:

图 2.3 – Tanzu 应用平台 GUI 截图
当你点击左侧菜单栏中的 Create 链接时,你将看到默认的应用加速器,这些加速器随 TAP GUI 一起提供:

图 2.4 – 空的创建部分截图
恭喜!如果你已经看到这里,你已经准备好开始使用 App Accelerator 了!
App Accelerator 概述
App Accelerator 是 Alana 用来为 Cody 和他的同事们提供经过验证、批准、预配置的起点工具,支持他们选择自己喜欢的语言或框架。通过 App Accelerator,Alana 可以处理一些重复性、低价值的任务,如选择技术并确保其与其他应用程序和企业标准的互操作性和兼容性。这让 Cody 和他的开发同事可以将精力集中在交付具有业务价值的软件上。
App Accelerator 由多个 API 和接口组成,特别针对 Alana(架构师)或 Cody(开发者)这两种角色:

图 2.5 – App Accelerator 架构
Alana 从一个包含项目骨架的 Git 仓库开始。除了模板代码、预批准的库、以及标准化的文档和测试结构外,项目中还包含一个特别的 YAML 文件,按约定命名为 accelerator.yaml。这个文件包含了如何让模板应用的消费者(即 accelerator)自定义应用模板的细节。Alana 和 Cody 的 Kubernetes 集群中运行着一个 accelerator.apps.tanzu.vmware.com/v1alpha1 的控制器。Alana 部署了一个 accelerator 自定义资源的实例,控制器便知道了 Alana 的 Git 仓库,并使其对 Cody 可用:

图 2.6 – Accelerator CRDs
App Accelerator 向 Cody 展示了不同的视图。他打开了一个 UI,显示了所有可用的 accelerator 详情。Alana 提供了多种语言和框架,给开发者提供灵活性,可以根据需要使用合适的工具,而无需在选择库、确保兼容性和应对公司治理方面重新发明轮子。
Cody 可以通过标签搜索并预览各种加速器的内容。许多加速器会提示 Cody 输入某些信息,并根据输入定制项目。这是通过前述架构图中的模板引擎组件完成的。应用加速器提供了一套丰富的转换机制,使得像你想使用哪种数据库?这样的简单输入,能够生成复杂的配置选项和预先配置的库。其理念是尽可能将复杂性抽象化,以最大化重用性和开发者生产力。
现在我们已经理解了应用加速器的工作原理,接下来让我们开始安装自己的应用加速器。
开始使用应用加速器
如果你在本章开始时完成了技术要求部分的工作,你应该已经有了一个运行中的 Tanzu 应用平台实例,并准备开始探索应用加速器。
探索应用加速器
当我们安装应用加速器时,我们得到了一个开箱即用的加速器集合,帮助开发者快速启动企业级应用模板,如下所示:

图 2.7 – 已安装的应用加速器
你可以点击这些加速器中的选择按钮,跳转到一个页面,在那里你可以提供所需的任何参数,并探索项目模板和预览其文件。一旦选择了符合需求的加速器,你可以填写所需的参数,点击下一步和创建。此时,你将能够下载一个包含你下一个伟大应用初步框架的 ZIP 文件,其中集成了你公司的一切规范和最佳实践!
下载、配置和运行应用加速器
从 TAP GUI 中的 hello-fun-tanzu-devsecops 开始,并确保在 deploymentType 下选择了Kubernetes 部署和服务。然后,我们点击下一步 | 创建 | 下载 ZIP 文件。这将下载一个 ZIP 文件,你可以解压、在本地运行并部署到你的 Kubernetes 集群中。
使用你喜欢的压缩工具解压缩档案,然后在你喜欢的 IDE 中打开项目。从这里,你可以按照 README.md 中的说明在本地运行应用并将其部署到 Kubernetes。
一旦你熟悉了下载、配置和运行加速器,你就可以开始更高级的任务和话题了。
应用加速器的高级话题
假设你是前面提到的企业架构师或安全工程师,想要通过最新最优秀的技术为开发者同事们提供多种选择,同时在其中融入你所有关于技术持久性、最佳实践和安全性方面的辛勤经验。你将如何创建自己的应用加速器?接下来我们就来实现一个自定义的应用加速器。
我们首先登录 GitHub 并 fork 这本书的 GitHub 项目。访问github.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu,然后点击https://github.com/<your-username>/DevSecOps-in-Practice-with-VMware-Tanzu/tree/main/chapter-02/openapi-accelerator。
这个加速器接受一个 OpenAPI 3.0 规范作为输入。然后它会输出一个能够围绕该规范构建整个 API 框架的项目,并且有一个 SwaggerUI 前端供你测试。这样的做法算不算最佳实践?
一旦你 fork 了加速器项目,我们需要告诉在 Kubernetes 中运行的控制器,我们有另一个应用加速器,希望使其可用。让我们将加速器克隆到本地:
git clone https://github.com/<your-username>/DevSecOps-in-Practice-with-VMware-Tanzu.git
接下来,导航到项目并在文本编辑器中打开chapter-02/openapi-accelerator/accelerator-k8s-resource.yaml文件。修改spec.git.url(高亮部分)属性,使其指向你 fork 的项目,如下截图所示:

图 2.8 – accelerator-k8s-resource.yaml(将其指向你 fork 的 Git 仓库)
然后,你可以通过应用accelerator-k8s-resource.yaml,告诉 App Accelerator 控制器你新增的加速器:
kubectl apply -f ./accelerator-k8s-resource.yaml
现在,你应该能够返回到 TAP GUI 的创建页面,刷新页面,看到你的 OpenAPI 3.0 Spring Boot 加速器已经准备就绪:

图 2.9 – 自定义 OpenAPI 3.0 Spring Boot 加速器在 TAP GUI 中
从这里,你可以使用加速器生成一个 Spring Boot 项目,定制化你的 OpenApi 3.0 规范:
- 
点击加速器的选择按钮。 
- 
给它起个聪明的名字。 
- 
使用默认的(提供的)OpenApi 规范,或者粘贴你自己的一个。这里有一个不错的: raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-02/petstore.yaml:

图 2.10 – 插入自定义 API 规范后探索我们的加速器
- 
点击下一步、创建,然后下载 Zip 文件。 
- 
解压项目并进入该目录。 
- 
构建 Spring Boot 项目并运行应用程序: $ chmod +x gradlew && ./gradlew openApiGenerate # (this will create a maven project in-place, use gradlew.bat on Windows)...$ mvn spring-boot:run
- 
在浏览器中访问 http://localhost:8080:

图 2.11 – 我们的自定义 OpenAPI 3.0 API 在 Swagger UI 中
就这样!通过简单的下载,我们已经拥有了一个功能完备的 REST API 和 Swagger UI,准备好开始实现业务逻辑。我们可以立即开始交付价值,因为所有的企业治理、库和约定都从项目一开始就已经方便地集成进来了。
恭喜!如果你已经完成了这些步骤,你已经为你的开发人员提供了经过预审核、预验证的安全软件框架,允许他们跳过繁琐的行政工作,直接开始用软件交付真正的价值。
然而,软件始终在变化,一个上周最新、稳固的软件框架,本周可能已经变成了关键漏洞和暴露(CVE)。
现在让我们继续进行 Day-2 操作,看看如何保持我们的应用加速器更新和修补。
Day-2 操作与应用加速器
在软件开发中,将某个东西部署到生产环境通常是简单的部分。保持软件更新并进行修补,且尽量减少对用户的干扰,才是你大部分时间的工作内容。应用加速器是专为 Day 2 操作而设计的。
结果表明,我们的 OpenAPI 应用加速器中的组件版本已经过时了。让我们快速更新并修补我们的加速器。
首先,让我们找到本地的 openapi-accelerator 项目副本。在你喜欢的编辑器中打开 build.gradle。注意到 org.springframework.boot 和 org.openapi.generator 的依赖版本不是最新的,因此可能包含 bug 或者已知漏洞。注意 org.springframework.boot 的版本为 2.5.6,而 org.openapi.generator 的版本为 5.2.1:

图 2.12 – 我们的 build.gradle 文件,其中的 Spring Boot 和 OpenAPI Generator 版本过时
首先,让我们访问 start.spring.io 以查看最新的 Spring Boot 版本。在撰写时,它是 2.6.2:

图 2.13 – 从 start.spring.io 获取的最新 Spring Boot 版本
我们还可以从 plugins.gradle.org/plugin/org.openapi.generator 获取最新版本的 openapi 插件。如下面的截图所示,撰写时其版本为 5.3.1:

图 2.14 – org.openapi.generator 插件的最新发布版本(5.3.1)
现在我们已经获得了最新的版本号,让我们更新 build.gradle 文件:

图 2.15 – 在 build.gradle 中更新插件块以使用最新版本
然后,我们只需git-push更新后的加速器,几分钟后,我们可以在 UI 中查看并看到更新后的依赖关系。未来任何使用该加速器的人都将获得最新版本的openapi插件和 Spring Boot。
现在,是时候换个方向了。App Accelerator 可以帮助你在许多流行的开发框架中获得一个良好的开端,那么这些框架是什么呢?哪些框架更适合企业应用呢?下一节将介绍两种特别适合企业应用的开发框架。
Tanzu 旗下的云原生开发框架
如前几节和章节所提到的,Tanzu 产品组合并不是凭空出现的。它是多年来工作中深思熟虑的自然表达,帮助了世界上一些最大、最著名的公司培养其软件能力。这段经验的一个成果是学会了哪些开发框架能够最大化开发者的生产力,同时减少繁琐、单调和不良实践。
到目前为止,我们已经成功地部署、更新、下载并实现了一个基于应用程序加速器的简单 API。我们的示例使用了 Spring Boot。我们是如何选择 Spring Boot 作为 API 底层应用框架的呢?
Spring 框架和 Spring Boot
许多成功的 Tanzu 客户选择的框架是 Spring 框架。这一点得到了 Spring Initializr 在start.spring.io启动的数百万个应用程序的验证,以及像 Snyk JVM Ecosystem Report 2020 这样的企业调查,报告显示 60%的企业正在使用 Spring Boot(snyk.io/blog/spring-dominates-the-java-ecosystem-with-60-using-it-for-their-main-applications/)。
这里有一张截图,展示了 Spring 直接提供的一些功能:

图 2.16 – Spring 能做什么(spring.io)
Spring 框架在部署方式上非常灵活。Spring Boot 是一种运行 Spring 框架应用程序的有偏见的方式,使得它们能够自包含并直接运行。Spring Boot 为 Spring 框架开发者提供了一些非常有用的工具,以便运行自包含的应用程序,使其非常适合微服务。它还内置了合理的默认设置和适用于最常见场景的建议。Spring Boot 为你提供了以下功能:
- 
可供选择的几个最佳 Web 框架 
- 
独立可运行的应用程序,完美适合容器和 Kubernetes 
- 
用于常见用例的有偏见的起步器 
- 
在可能的情况下,自动配置所有库 
- 
现实生产中的功能,如度量和 Kubernetes 健康检查 
关于 Spring 框架和 Spring Boot 有整本书籍,所以我们无法在这一章中详尽讨论。相反,我会提供一些链接,供你进一步探索:
- 
Mark Heckler 的Spring Boot: Up and Running: www.oreilly.com/library/view/spring-boot-up/9781492076971/
- 
Spring 开发者快速入门: spring.io/quickstart
- 
Spring 指南和教程: spring.io/guides
- 
Josh Long 的一场美丽的 播客: soundcloud.com/a-bootiful-podcast
- 
SpringDeveloper YouTube 频道: www.youtube.com/user/SpringSourceDev
或许你在想,开源的 Spring 框架与 Tanzu 有什么关系? 很好的问题!其中,Tanzu 产品组合中的许多产品是开源 Spring 项目的企业版。它们包括以下内容:
- 
Spring Cloud Gateway ( spring.io/projects/spring-cloud-gateway)
- 
Spring Cloud Data Flow ( spring.io/projects/spring-cloud-dataflow)
- 
Spring Cloud ( spring.io/projects/spring-cloud)
还与云服务提供商合作,推出了端到端、垂直集成的 Spring 平台,例如 Azure Spring Cloud (tanzu.vmware.com/azure-spring-cloud)。
尽管 Spring 框架极为强大且内容丰富,但它主要面向 Java 开发者。如果你是一个拥有 Microsoft 技术栈背景的开发者呢?我们接下来会讨论这个问题。
Steeltoe 框架
当然,并不是每个企业软件公司都有职业 Java 开发者。目前支撑现代世界运行的数百万行代码是用 Microsoft .NET 技术栈编写的。Steeltoe是一套非常符合 Spring Boot 精神的库,它允许.NET 开发者可靠且高效地交付云原生微服务应用。如果你有兴趣最大化在.NET 上交付企业软件的开发者的生产力,我强烈建议你试试它:
old.dotnetfoundation.org/projects/steeltoe
就这样!通过 Spring 和 Steeltoe 项目,我们涵盖了将吸引绝大多数企业开发者的应用框架和工具集,使他们更高效、更少受到技术债务和错误决策的影响,最重要的是,他们对工作更有满足感,能够通过软件交付经济价值。
摘要
在持续追求最大化开发者生产力,或者作为技术领导者或架构师最大化团队生产力的过程中,我们需要确保第 0 天做对每一件事。在第 0 天做出的错误决策或开发失误,将会在多年后继续带来痛苦的后果。
避免这些代价高昂的第 0 天错误的最佳方法是从我们知道过去已经成功的起点开始,并以此作为未来开发的跳板。VMware Tanzu 的应用加速器、Spring Boot 和 Steeltoe 框架为这些起点提供了简单、可重复的基准,使团队从一开始就能够取得成功。
此外,生产级的企业级开发框架并不是一夜之间就能出现的。像 Spring 和 .NET + Steeltoe 这样的框架,经过数十年的经验积累,已经变得成熟稳健。最好的应用加速器使用最优秀的基础框架,而它们都是 Tanzu 产品组合的一部分。
通过本章的学习,你现在已经掌握了部署和使用应用加速器的技能,这些加速器可以帮助你确保第 0 天做对每一件事——而且,你已经借助行业标准的应用框架迈出了成功的第一步。
既然你已经解决了通过一个出色的应用程序顺利启动的问题,那么接下来让我们来了解如何将这个应用程序转化为能够在像 Kubernetes 这样的容器平台上运行的格式。就像项目初期的第 0 天充满了风险一样,创建精简、安全和可重复的容器镜像也会带来一系列问题。这些问题正是我们将在下一章讨论的内容,主题是 Tanzu Build Service。
第三章:使用 Build Service 构建安全的容器镜像
在上一章中,我们讨论了 VMware Tanzu 的应用加速器如何帮助组织以统一、高效的方式构建绿地应用。这为构建基于预定义模板的云原生应用打下了良好的基础。这些模板帮助开发人员专注于业务逻辑,从而为组织带来收入。
绿地和云原生应用
绿地(Greenfield)是建筑行业的术语,指的是未开发的土地。在 IT 领域,绿地指的是从零开始开发的软件项目,而不是基于现有程序构建的软件项目。它通常与棕地(Brownfield)相对,后者描述的是从现有程序构建的软件。参考:techterms.com/definition/greenfield。
云原生应用,如你所料,是为了充分利用云计算而编写的。它们的特点是使用容器、服务网格、微服务、不变基础设施和声明式 API 等技术。参考:github.com/cncf/toc/blob/main/DEFINITION.md。
然而,要从容器平台(如 Kubernetes)中真正受益于云原生应用,我们需要将这些应用作为容器来运行。为了以容器形式运行它们,我们需要为这些应用构建容器镜像。虽然有多种方式可以为我们的应用构建容器镜像,但业界最流行的方法之一是使用称为 Dockerfile 的配置文件来构建。Dockerfile 包含了应用程序所需构建的容器镜像的定义、要求和属性。尽管使用 Dockerfile 是构建容器镜像的流行方法之一,但它并不总是最优的选择。
本章将深入探讨这一概念,并涵盖以下主题:
- 
为什么选择 Tanzu Build Service? 
- 
解锁 Tanzu Build Service 
- 
开始使用 Tanzu Build Service 
- 
Tanzu Build Service 的常见日常活动 
那么,让我们开始吧。
技术要求
在开始安装Tanzu Build Service(TBS)之前,需要满足一些技术要求。这些要求将在本章开始使用 Tanzu Build Service部分的开头进行详细介绍。不过,你可能不需要它们来理解 TBS 带来的好处。让我们开始了解它吧。
为什么选择 Tanzu Build Service?
在为应用程序构建容器镜像时,存在各种业务、技术和安全挑战。在大规模企业中进行此操作时,挑战会变得更加复杂。让我们了解这些挑战是什么,以及 TBS 如何解决这些问题。
提高开发者生产力
如前所述,构建容器镜像的最流行方法之一是使用 Dockerfile。在大多数情况下,应用程序团队负责构建和维护这些 Dockerfile。这些 Dockerfile 包含了如基础容器操作系统及其版本、应用程序包(如 Java 应用程序的 JAR 文件)、环境变量以及有用的库及其版本等详细信息。
JAR 文件
Java ARchive(JAR)文件是包含应用程序的一个打包文件,包含已编译的源代码文件、配置文件和应用程序所需的外部库。JAR 文件可以是一个支持库,也可以是一个可以在Java 运行时环境(JRE)中运行的应用程序包。
开发人员对自己的应用程序了解最深。因此,允许他们定义应用程序的 Dockerfile 内容是有道理的。但与此同时,构建和管理 Dockerfile 是开发人员的额外负担。开发人员应该将所有时间都用在为应用程序构建更多有商业影响的功能上。你可能会争辩说,构建和更改这些 Dockerfile 并不是一个频繁的任务。此外,你还可以围绕构建容器创建一些自动化流程来减少工作量。然而,这种内部自动化会带来其他维护上的挑战。它并不能消除应用程序团队所需要的时间。这不仅仅是开发人员花时间创建或更新 Dockerfile 的问题。他们还需要花时间去研究和决定其中的内容。最后,这些 Dockerfile 必须保持最新,以反映其中引用的库的最新安全补丁。这确保了运行中的容器拥有最佳的安全态势。这种持续不断的维护消耗了大量开发人员的生产时间,进行的却是无生产性的活动。
容器镜像中的层
一个应用程序的最终容器镜像可能是多个较小镜像的组合,这些镜像像层一样堆叠在一起,提供可重用性、分离性和易用性。
为了应对这些挑战,Pivotal Software Inc.(于 2020 年被 VMware Inc.收购)与 Heroku 合作,启动了一个名为buildpacks.io的开源项目,该项目隶属于Cloud Native Computing Foundation(CNCF)。我们将在本章稍后详细讨论这个项目。TBS 是一个商业支持的打包方案,包含 buildpacks.io 以及其他一些开源工具。
TBS 通过提供一个完整的自动化引擎来应对这一挑战,当您提供应用程序代码或构建的工件时,它可以构建容器镜像。作为输出,TBS 会为应用程序生成一个符合 OCI 标准的容器镜像。这个镜像可以部署到 Kubernetes 或任何其他符合 OCI 标准的容器编排平台。通过 TBS,开发人员无需再负责构建和维护容器镜像,减少的责任帮助开发人员将注意力集中在对业务更为重要的部分。
什么是 OCI?
开放容器倡议(OCI)是由 Linux 基金会设立的标准,描述了容器镜像的特性,这些镜像可以由各种容器镜像构建工具实现,并被像 Kubernetes 这样的不同容器调度平台理解。所有主要的容器平台,包括 Kubernetes,都支持符合 OCI 规范的容器镜像。
TBS 支持包括 Java、.Net、Python、Go、NodeJS 等多种语言。
减少定制自动化
组织通常会创建持续集成(CI)流水线来构建应用程序的容器镜像。这些流水线通常使用 Jenkins 等工具开发,并且大多数使用 Python 或 Shell 脚本等语言编写。组织可能需要先投入资源开发此类定制自动化流程,然后还需要持续维护。而且,缺乏关于这些定制自动化流程的良好文档,使得维护变得非常困难。因此,这种依赖人员的自动化在相关人员离开组织后,维护起来就成了一个大问题。此外,如果这些人员能够投入到更具业务价值的任务中,组织可能会获得更好的业务成果,而不是仅仅参与这种低价值的工程工作。
TBS 也有助于解决这一挑战。它在容器镜像构建过程中实现了高度自动化。虽然这不会替代整个 CI 流水线,但它通过覆盖构建容器镜像所需的各个步骤并实现完全自动化,能够显著简化这一流程。
容器构建过程的标准化
在大型开发团队的企业中,往往可以看到许多部门之间的孤岛(silos)。这些孤岛有各自的工具和流程。这可能会导致组织在多个层面上浪费宝贵的资源,例如重复劳动。这种重复可能体现在人员为相似的结果所花费的时间、工具的许可证费用以及自动化使用的基础设施。这可能会引发一个全新的问题——缺乏标准化。非标准化的做法会导致透明度、治理和安全态势的下降。在构建容器镜像时,缺乏标准化可能会证明是一个非常昂贵的错误,导致安全风险暴露。这是由于使用未经批准的库,或者没有及时修补这些库。当不同的团队有不同的容器镜像构建方法时,他们可能会遵循不同的做法。他们可能使用不同的容器操作系统、开源工具、第三方库及其版本。这使得应用全公司范围的标准化变得非常困难。强制执行的标准不应影响不同团队的生产力和选择自由。
TBS 通过两种方式解决了这个问题。首先,它包括由 VMware 提供的集中式软件库,形式为构建包(buildpacks)和栈(Stacks)。在这里,构建包(buildpacks)包含了应用在容器中运行所需的所有库,包括应用程序运行时环境,如Java 运行环境(JRE)以及中间件,如 Tomcat 服务器。另一方面,栈(Stacks)包括不同版本的容器操作系统。其次,TBS 提供了一个标准化的容器镜像构建自动化引擎。因此,当组织使用 TBS 构建容器时,它会自动在容器构建过程中实现标准化。这种标准化体现在自动化要求和镜像中支持的应用程序内容上。
TBS 不仅帮助公司标准化容器构建过程,还提升了整体的安全态势,正如以下部分所述。
更强的安全态势
安全暴露是大多数成熟组织在云转型过程中面临的主要问题。大多数云原生应用程序都作为容器部署在公共或私有云平台上,以获得多个好处。容器其实就是运行应用程序的小型虚拟机。至关重要的是,这些容器必须使用安全的组件来构建,确保不含有安全漏洞。然而,今天的安全库版本可能明天就会被发现存在漏洞,因为常常会看到新安全漏洞的发布,这些漏洞可能影响到所有操作系统和库,而这些操作系统和库可能会被用于容器镜像中。相应的组织会发布新版本,以解决这些常见漏洞和暴露(CVE)。然而,用户组织需要自行获取这些软件的新版本,并用它们来重新构建受影响的容器镜像。这类容器镜像重建工作可能会带来两个大痛点。第一个问题是,当有多个开发团队管理着数百个容器化应用程序时,寻找受影响的应用程序变得非常困难。这样的识别和修复过程可能需要数周时间,使得这些应用程序在此期间容易受到攻击。与此同时,要让所有应用团队在同一时间使用新版本软件重建其应用程序的容器镜像也是非常困难的。由于应用团队需要处理他们的产品待办事项和优先级,修补工作通常会延迟。而历史一再证明,大多数重大软件相关的安全漏洞都是由于长时间没有修补的软件组件导致的。
TBS 可以通过其集中资源库和基于该资源库的容器镜像重建自动化,极大地加速受影响容器镜像的 CVE 修补。当库中的受影响组件发布新的 CVE 补丁时,VMware 会发布包含该漏洞修复的仓库组件的新版本(可以是构建包或栈)。TBS 使用内部容器镜像及其关联依赖项的映射来识别受影响的应用程序容器镜像。因此,当 VMware 在集中仓库中发布新组件版本来修复任何 CVE 时,TBS 会立即触发使用已修补版本的受影响应用镜像的修补。这样的自动化镜像重建可以在几小时内完成数百个应用的修补,而无需 TBS 的话可能需要数周时间。这可能是考虑使用 TBS 等工具的最重要原因之一。应用程序、其容器镜像和其中使用的相关软件组件的这种映射为安全团队提供了所需的透明度和可审计性。使用 TBS,我们可以快速为任何由 TBS 管理的应用生成物料清单(BOM)。BOM 是一份详细报告,列出在相应容器镜像中使用的所有组件及其版本。它极大地简化了容器化环境的安全审计。
优化的网络带宽和存储利用率
如前所述,符合 OCI 标准的容器镜像是由多个较小的镜像集合构成,这些小镜像包含了构成最终容器镜像所需的不同组件。这些层包括应用代码、配置、第三方库和操作系统。像 Docker Hub 和 Harbor 这样的容器镜像仓库会将这些层分开存储,并维护哪些镜像层依赖于其他镜像层的映射关系。因此,当你从容器镜像仓库拉取特定的容器镜像时,仓库会将所有依赖的容器镜像层一起推送过来。由于这个原因,当应用发生变化时,只有受影响的层会通过网络传输到容器仓库,所有其他未受影响的镜像层将不会通过网络传输。这使得镜像的推送和拉取操作更加高效,同时也有助于减少容器镜像仓库的存储需求,因为未改变的层会被重复使用。然而,为了充分利用这些层,你应该在镜像构建过程中遵循一定的规范。如果 Dockerfile 的作者不够谨慎,可能会导致镜像层的数量比最优情况要少。以下的图示展示了同一应用的容器镜像结构,它们的层数不同,且是通过两种不同的 Dockerfile 构建的。这些快照是使用名为 Dive 的开源工具拍摄的 (github.com/wagoodman/dive),该工具可以详细显示容器镜像的各个层及其内容:

图 3.1 – 使用四层构建的演示 Java 应用的容器镜像
如你所见,图 3.1 仅有四层,而 图 3.2 则有八层,尽管最终镜像的总大小几乎相同。构建容器镜像有多种方法,这些方法可能会导致相同应用代码产生不同的结果:

图 3.2 – 使用八层构建的相同演示 Java 应用的容器镜像
当开发人员没有足够的意识,或者没有企业级的指南来指导如何构建应用容器镜像时,每个团队可能会最终形成自己的标准和实践。由于缺乏知识和控制,大型组织可能会拥有多个不理想的应用容器镜像,这可能导致每次容器镜像推送和拉取操作时,浪费网络带宽和存储空间。
另一方面,TBS 使用一个广受好评的 Cloud Native Computing Foundation (CNCF) (cncf.io)认证项目,名为 Cloud Native Buildpacks (CNB) (buildpack.io),作为其底层工具,当使用此工具构建应用容器镜像时,它通过多个较小的层来构建容器镜像。它提供了一种组织级标准化方法来构建容器镜像,同时具有非常高的资源效率,并带有前述的其他好处。以下是一个高层次表示,展示 TBS 如何执行这一操作:

图 3.3 – TBS 如何通过层级构建容器镜像的高层次表示
上述图示展示了 TBS 如何获取一些应用代码,执行内部各种操作,并创建一个最终符合 OCI 标准的应用容器镜像,该镜像包含多个较小的层。
总的来说,TBS 有助于提升开发者生产力,减少学习曲线,降低运维负担,并增强安全性,同时提供其他若干构建安全容器镜像的好处。所有这些都将帮助你加速云原生应用的旅程。在了解了使用 TBS 这类工具的不同好处之后,接下来让我们深入解锁它,了解它的架构。我们将深入探讨 TBS 所包含的所有不同组件。
解锁 Tanzu Build Service
如前所述,TBS 建立在两个主要开源项目之上:CNB 和 kpack。下图展示了 TBS 的整体包装结构:

图 3.4 – Tanzu Build Service 的构建模块
如前图所示,kpack 包含引擎和 CLI,而 CNB 包含诸如 Builder、buildpacks 及其组、堆栈、构建和运行镜像以及生命周期过程等内容。此外,还有一些 VMware 提供的组件,提供额外的功能,这些组件已打包在 TBS 中。让我们详细了解这些组件。
云原生构建包
CNB 的概念来源于 Cloud Foundry 中构建包的概念,Cloud Foundry 是另一个用于云原生应用的容器编排平台。Cloud Foundry 中的构建包已经证明是经过多年考验的工具,已有十多年历史。Cloud Foundry 中的构建包用于扫描应用源代码,根据所使用的技术和语言确定应用需求,将所有所需的依赖项与应用程序包一起打包,并创建一个离线容器,称为droplet。这些 droplet 是包含所有运行所需内容的大型二进制对象,用于在 Cloud Foundry 平台上作为容器运行对应的应用程序。尽管 droplet 拥有稳定的记录,但它们也存在一些局限性,具体如下:
- 
Cloud Foundry 的构建包生成的 droplet 非常大,因为它们包含应用程序所需的所有内容。它们不像现代的 OCI 合规容器镜像那样有层的概念。因此,应用程序或其依赖项的每一个小变化都会重新创建一个新的重型 droplet。这些 droplet 需要更多存储空间,因为它们不仅仅包含差异,还包含完整的应用程序包。由于这个原因,使用 droplet 在 Cloud Foundry 中部署容器的过程比在如 Kubernetes 等 OCI 兼容平台上使用 OCI 镜像部署更新版本的应用程序要慢。这种容器调度的慢速会影响应用程序在扩展或重新部署时的部署时间。 
- 
Buildpack 项目仅设计用于 Cloud Foundry,因此无法在只支持 OCI 合规容器镜像的 Kubernetes 等平台上使用。 
- 
Cloud Foundry 的构建包在扩展性或定制化方面非常有限。它们不能像层或插件一样添加新的更改,而必须完全打开并修改。 
- 
Cloud Foundry 的构建包在构建新 droplet 时较慢,因为它们未能最优化使用缓存资源。 
鉴于所有这些局限性,并且利用构建包概念在更广泛和流行的平台(如 Kubernetes)中的潜力,两个软件公司 Heroku 和 Pivotal(2019 年被 VMware 收购)携手合作,宣布共同开发一个新的开源项目 CNB,该项目保留了原始 Buildpack 项目的优点,同时解决了它的弱点。基于这个背景,我们来详细讨论 CNB 的结构。
以下是 CNB 中一些重要的概念和术语,它们是 TBS 的关键构建模块。
构建镜像
这是一个基础容器操作系统层,用于创建构建者的容器镜像。构建容器的生命周期较短。它执行构建应用容器镜像的生命周期过程,完成后会被终止。
运行镜像
这是一个基础容器操作系统层,用于创建应用程序的容器镜像。这是 TBS 的主要成果。所有由 TBS 构建的特定应用程序容器镜像都使用此镜像作为基础容器操作系统层。
堆栈
这是一个配置实体,包含有关构建镜像的详细信息,并运行将在容器镜像构建过程中使用的镜像风味。作为包的一部分,TBS 提供了四种不同的堆栈风味,包含不同风味的构建和运行操作系统。这些操作系统层可以是薄层或厚层,具体取决于需要使用它们的应用程序的要求。
构建包
这是一个可执行文件集合,检查你的应用程序代码并确定是否应用构建包(buildpack)到该应用程序,并因此应该成为结果应用程序容器镜像的一部分。例如,Java 应用程序有一个构建包,它检测应用程序代码或工件中是否存在 Java 特定文件,然后决定应用程序是否需要支持以作为 Java 应用程序运行。在 TBS 架构中,这些构建包存储在容器注册表中,作为容器镜像。
构建包组
这是一个构建包集合,通常一起用于构建特定类型应用程序的容器镜像。构建包组中的构建包可以是强制性的,也可以是可选的,具体取决于其使用场景和应用程序的需求。例如,Java 运行时环境(JRE)、Maven、Gradle、Tomcat 服务器和 Jetty 服务器的构建包可能都属于同一组,因为它们都是与 Java 应用程序相关的依赖项。然而,JRE 的构建包对于 Java 应用程序来说是必须的,而前述的其他构建包则属于可选类别,因为应用程序可能需要也可能不需要它们。针对不同类型应用程序,还有其他多种构建包组,如 Python、.Net、NodeJS 等。
生命周期
这决定了构建包的应用,并协调它们的执行。生命周期过程包含多个组件,它们执行不同阶段。在所有阶段结束后,我们将得到一个符合 OCI 标准的最终容器镜像。让我们回顾一下这些生命周期组件:
- 
分析器:该工具检索并检查在镜像构建过程中需要的所有文件,并由构建包使用。它还会检查构建所需的所有镜像是否在 TBS 使用的容器注册表中可以访问。通过快速检查依赖关系,如果某些内容丢失,构建过程会迅速失败,而不是在构建过程后期才发现问题。 
- 
检测器:它检查在构建过程中,哪个构建包组适用于该应用程序。它还会按特定顺序获取所有可用构建包组的列表。然后,它依次检查每个组的适用性,直到第一个组满足所需的标准。检测器随后创建一个执行计划,以执行容器镜像构建过程,作为最终的产物。 
- 
恢复器:它根据从之前的容器构建过程缓存中选择的构建包组,恢复所有所需的依赖镜像层,这些缓存是由相同的镜像层放入的。此阶段减少了构建时间和网络流量,以便传输频繁使用的镜像。 
- 
应用程序构建器:它将应用程序源代码转化为可执行的工件,以便可以在容器内打包执行。例如,这一阶段将 Java 应用程序的源代码转换为包含已编译类文件的 JAR 文件,作为可执行的工件。该阶段的应用可能是可选的,具体取决于应用程序提供的工件,甚至可能根据技术需求来决定。例如,如果构建过程中已经提供了一个准备好的 Java 应用程序 JAR 文件,而不是源代码,那么就不需要为该应用程序准备构建,这一阶段可能会被跳过。 
- 
导出器:它创建最终的符合 OCI 标准的容器镜像文件。它还准备一份报告,包含容器镜像中所使用的组件及其版本的 BOM(物料清单)。最后,它将容器镜像推送到目标注册表。 
构建器
要构建一个应用程序的容器镜像,TBS 需要在 Kubernetes 上部署一个临时容器,执行之前描述的生命周期组件,以创建最终的容器镜像。构建器是一个容器镜像,它部署这个容器,其中包含生命周期进程的可执行文件,以及构建包组和构建镜像的列表。
kpack
kpack (github.com/pivotal/kpack) 是由 Pivotal 发起的开源项目,现在由 VMware 积极维护。kpack 提供了一种在 Kubernetes 平台上使用 CNB 的方式。kpack 使用一些 Kubernetes 自定义资源定义(CRDs)将自己部署为在 Kubernetes 上运行的工具。因此,kpack 是一个在 Kubernetes 上运行的工具,利用 CNB 构建符合 OCI 标准的容器镜像。
自定义资源定义(CRDs)
Kubernetes 有几个现成的 API,称为资源。此类资源的一些示例包括 Pod、Node、Deployment、Service、ReplicaSet 等。尽管 Kubernetes 提供了许多现成的资源,但它是一个非常可扩展的平台,允许添加更多自定义资源。此类自定义资源被称为 CRD。你可以在这里了解更多关于 CRD 的信息:kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/。
kpack 有两个主要组件,如 图 3.4 所示:
- 
kpack Kubernetes CRD 帮助使用 CNB 并定义容器镜像规范。 
- 
kpack 命令行接口(CLI)提供了所需的用户界面,以便使用 kpack 资源。kpack CLI 提供了通过 kpack 创建和管理容器镜像构建规范的方法。 
TBS 使用的 kpack CRD 对象
尽管 kpack 是 TBS 的内部组件,但以下是 TBS 使用的一些关键 kpack CRD 对象:
- 
Image对象引用应用程序源代码或包的位置、构建过程的运行时详细信息,以及存储构建镜像的容器注册表详细信息。
- 
ClusterStore:它包含以容器镜像位置形式引用的 buildpacks。 
- 
ClusterStack:它包含以构建镜像和运行镜像形式引用的操作系统层,以及它们的容器注册表位置。 
- 
ClusterStore和ClusterStack的组合。ClusterBuilder对象还定义了构建包的顺序,以便对任何应用程序进行验证。
VMware 提供的组件和功能
除了 TBS 的两个主要开源构建模块 — CNB 和 kpack — VMware 还提供了一些额外的组件和功能,企业可以作为 TBS 打包的一部分获取。我们快速浏览一下:
- 
TBS 提供了一种专有的安装方式,并通过一个名为 Carvel 的开源工具包( carvel.dev)提升用户体验。Carvel 是一个 Kubernetes 应用程序打包和部署工具包,主要由 VMware 维护。我们将在下一节中使用它来安装 TBS。
- 
TBS 具有一个依赖更新器组件,它保持所有由 TBS 构建的容器镜像与其相应的 buildpacks 或堆栈中的更改保持同步。此功能有助于确保所有容器镜像都通过操作系统和应用程序依赖项的最新更新进行修补和安全加固。 
- 
TBS 还附带了一套 VMware 提供的 buildpacks。它支持离线 buildpacks、Windows 容器,以及新版本 buildpack 的快速可靠发布工程,包括新功能和 CVE 修复。 
在本节中,我们了解了 TBS 的结构和组件。我们还学习了每个组件在构建整个解决方案中的作用。现在,让我们开始使用 TBS。在下一节中,您将学习如何在 Kubernetes 集群中安装和配置 TBS,并获得我们之前讨论的所有好处。
开始使用 Tanzu Build Service
在了解了 TBS 解决的挑战和 TBS 所包含的内容后,让我们学习如何快速在 Kubernetes 集群中启动并运行它。
重要说明
所有这些说明适用于Tanzu Build Service(TBS)v1.3 版本。
以下部分详细介绍了在 Kubernetes 集群中完全启用 TBS 所需的不同前提条件。
前提条件
在 Kubernetes 环境中配置 TBS 时,您需要以下内容:
- 
管理员级别的 kubectlCLI 访问权限,要求 Kubernetes 集群版本为 1.19 或更高。如果无法获得管理员级别的访问权限,则用户至少需要具有github.com/tandcruz/DevSecOps-in-Practice-with-VMware-Tanzu/blob/main/chapter-03/tbs-k8s-cluster-permissions.yml中列出的权限,才能安装和配置 TBS。
- 
Kubernetes 集群的工作节点应至少具有 50GB 的临时存储,因为 TBS 会存储构建镜像的历史版本以供记录。TBS 存储的历史版本数量是可以配置的。后续将在本章的第二天活动中讲解这一点。 
- 
访问任何支持 Docker HTTP API V2 并具有至少 5GB 存储配额的容器注册表,排除由 TBS 构建的应用程序镜像所需的空间。为了简化操作,我们将使用 Docker Hub( hub.docker.com/),它提供一个免费的账户,足以支持 TBS 集成。
- 
您的 Kubernetes 集群中应配置一个默认的StorageClass,以供 TBS 创建所需的存储卷。默认情况下,TBS 将需要一个PersistentVolumeClaim,用于缓存已经构建的工件。这样的缓存有助于加快后续构建的速度。 
- 
用于此安装的操作机应已安装 Carvel CLI 工具。以下是 TBS 使用的 Carvel 工具,以及它们的下载位置和用途: - 
kapp版本 0.41.0(network.tanzu.vmware.com/products/kapp/)用于部署 TBS 所需的 Kubernetes 资源包。
- 
ytt版本 0.37.0(network.tanzu.vmware.com/products/ytt/)用于替换 TBS Kubernetes 资源部署中使用的 YAML 模板文件中的自定义配置值。
- 
kbld版本 0.31.0 (network.tanzu.vmware.com/products/kbld/) 用于在基于您选择的容器注册表的 Kubernetes 配置文件中引用容器映像,这些映像已经根据您的选择进行了重定位。
- 
imgpkg版本 0.23.1 (network.tanzu.vmware.com/products/imgpkg/) 用于部署包含所需配置和 OCI 映像的 TBS 打包应用程序包。对于无外出 Internet 连接的空气隔离环境,它有助于将所有必需的 OCI 映像重定位到正在使用的私有容器注册表。
 
- 
- 
操作员机器应该安装有 kpCLI v0.4.*,可以从 Tanzu Network 网站上的network.tanzu.vmware.com/products/build-service/下载。
- 
操作员机器应该安装 dockerCLI:docs.docker.com/get-docker/。
- 
操作员机器应该从 Tanzu Network 网站的 TBS 依赖页面上下载 descriptor-<version>.yaml格式的依赖描述符文件,该书使用了descriptor-100.0.229.yaml文件。此文件包含 TBS 将需要执行图像构建的容器映像路径。根据您下载的时间,可能会找到不同的版本,这是可以接受的。
重要提示
运行 Containerd v1.4.1 的 Kubernetes 集群与 TBS 不兼容。以下 kubectl 命令将获取底层容器运行时的版本以检查此问题:
kubectl get nodes -o=jsonpath='{.items[0].status.nodeInfo.containerRuntimeVersion}'
让我们从首先安装 TBS 开始我们的旅程,并执行一些基本测试,以确认它是否按预期工作。
安装过程
在本章中,我们将使用 Docker Hub 作为与 TBS 配合使用的容器注册表。此外,安装步骤假定基本 Kubernetes 集群具有完全的外部 Internet 连通性。对于空气隔离环境和要使用的自定义容器注册表,安装和配置 TBS 的过程有所不同。您可以根据不同的用例查看官方产品文档 (docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-installing.html)。
此外,在所有命令中使用的 p********t 值应替换为您的相应用户名,并将 ********** 替换为您的相应密码。
有了这些期望,让我们通过执行以下步骤来安装和配置 TBS:
- 
确保您正在正确的 Kubernetes 集群和上下文中进行工作,以便安装 TBS: $ kubectl config use-context <CONTEXT-NAME>
- 
将所需的容器镜像从 Tanzu Network 注册表迁移到您的 Docker Hub 帐户。为此,登录到您的 Docker Hub 帐户,操作如下: $ docker login -u p********tPassword:Login Succeeded
- 
登录 Tanzu Network 容器注册表,使用您的 Tanzu Network 凭据拉取所需的安装镜像: $ docker login registry.tanzu.vmware.comUsername: p********t@*******.ioPassword:Login Succeeded
- 
使用以下 imgpkg命令将镜像从 Tanzu Network 迁移到您的 Docker Hub 注册表:$ imgpkg copy -b "registry.tanzu.vmware.com/build-service/bundle:1.3.0" --to-repo p********t/build-service-1-3copy | exporting 17 images...copy | will export registry.tanzu.vmware.com/build-service/bundle@sha256:0e64239d34119c1b8140d457a238050751360617d8e8b64703d8b7b4f944054a..copy | will export registry.tanzu.vmware.com/build-service/smart-warmer@sha256:4d865b7f4c10c1099ae9648a64e6e7da097d0a375551e8fd2ef80a6d1fc50176copy | exported 17 imagescopy | importing 17 images...443.39 MiB / 443.64 MiB [==============================================================================================] 99.94% 1.92 MiB/s 3m51scopy | done uploading imagescopy | Warning: Skipped layer due to it being non-distributable. If you would like to include non-distributable layers, use the --include-non-distributable-layers flagSucceeded
您可以忽略成功消息之前的警告,因为 TBS 默认不包括 Windows 组件,因为它们有许可证限制。
- 
使用 imgpkg命令将 TBS 包镜像拉取到本地:$ imgpkg pull -b "p********t/build-service-1-3:1.3.0" -o /tmp/bundlePulling bundle 'index.docker.io/p********t/build-service-1-3@sha256:0e64239d34119c1b8140d457a238050751360617d8e8b64703d8b7b4f944054a'Extracting layer 'sha256:872d56ff2b8ef97689ecaa0901199d84e7f7ae55bfef3ad9c7effa14b02e6dfd' (1/1)Locating image lock file images...The bundle repo (index.docker.io/p********t/build-service-1-3) is hosting every image specified in the bundle's Images Lock file (.imgpkg/images.yml)Succeeded
- 
使用相关的 Carvel 工具( ytt,kbld和kapp)安装 TBS,执行以下命令。这是一个非常长的命令,它将通过ytt使用-v标志将提供的自定义参数值注入部署配置文件中。然后,命令使用kbld根据您的注册位置替换容器镜像位置。最后,它使用kapp通过带有自定义参数值和从您的存储库拉取的所需容器镜像文件的配置文件部署 TBS:$ ytt -f /tmp/bundle/values.yaml -f /tmp/bundle/config/ -v kp_default_repository='p********t/build-service-1-3' -v kp_default_repository_username='p********t' -v kp_default_repository_password='**********' -v pull_from_kp_default_repo=true -v tanzunet_username='p********t@*******.io' -v tanzunet_password='**********' | kbld -f /tmp/bundle/.imgpkg/images.yml -f- | kapp deploy -a tanzu-build-service -f- -yresolve | final: build-init -> index.docker.io/p********t/build-service-1-3@sha256:838e8f1ad7be81e8dab637259882f9c4daea70c42771264f96be4b57303d85f2resolve | final: completion -> index.docker.io/p********t/build-service-1-3@sha256:765dafb0bb1503ef2f9d2deb33b476b14c85023e5952f1eeb46a983feca595c6....Succeeded
重要提示
在撰写本书时,所有 Carvel 下提供的二进制文件,包括ytt,kbld和kapp,都是未签名的二进制文件。因此,您的操作系统,尤其是 macOS,可能会对使用它们提出安全警告。但是,您可以在操作系统的安全设置中明确允许执行这些二进制文件。此外,由于此命令执行多个长时间的镜像拉取操作以在 Kubernetes 集群中部署 TBS,您可能会看到命令未成功完成并出现错误——use of closed network connection。在这种情况下,您可以再次运行相同的命令,可能就能成功。
您可能需要根据以下规范替换前述命令中的突出显示值:
- 
将 kp_default_repository和kp_default_repository_username参数中的p********t替换为您的 Docker Hub 用户名
- 
将 **********替换为kp_default_repository_password参数中的 Docker Hub 帐户密码
- 
将 tanzunet_username中的p********t@*******.io替换为您的 Tanzu Network 用户名
- 
将 tanzunet_password中的**********替换为您的 Tanzu Network 密码
在最后一个命令成功完成后,TBS 应已在您的 Kubernetes 集群中启动并运行。让我们验证安装并确保 TBS 正常工作。
验证安装
要验证 TBS 安装,执行以下kp命令以列出 TBS 环境中可用的集群构建器:
$ kp clusterbuilder list
上述命令的结果应如下所示,您应看到您的 Docker Hub 用户名,而不是p********t:
NAME       READY    STACK                          IMAGE
base       true     io.buildpacks.stacks.bionic p********t/build-service-1-3:clusterbuilder-base@sha256:7af47645c47b305caa1b14b3900dbca206025e30b684e9cd32b6d27f9942661f
default    true     io.buildpacks.stacks.bionic    p********t/build-service-1-3:clusterbuilder-default@sha256:7af47645c47b305caa1b14b3900dbca206025e30b684e9cd32b6d27f9942661f
full       true     io.buildpacks.stacks.bionic    p********t/build-service-1-3:clusterbuilder-full@sha256:714990fdf5e90039024bceafd5f499830235f1b5f51477a3434f3b297646b3d0
tiny       true     io.paketo.stacks.tiny          p********t/build-service-1-3:clusterbuilder-tiny@sha256:29d03b1d4f45ce6e7947ab2bf862023f47d5a6c84e634727900a1625e661ee3b
如果您看到上述输出,恭喜您,TBS 已在您的 Kubernetes 环境中运行,并准备构建您的应用程序的容器镜像!
既然我们已经开始使用 TBS,让我们探讨一些常见的第 2 天操作,这些操作可以根据不同的用例在 TBS 上执行。
Tanzu Build Service 的常见第 2 天操作
在本节中,我们将介绍一些可以在 TBS 上执行的有用操作。
构建应用程序容器镜像
在本节中,我们将学习如何首次将应用程序注册到 TBS,创建第一个容器镜像,在本地运行该容器镜像,通过修改应用配置重新触发镜像构建过程,最后验证新创建的容器镜像以反映应用程序的变化。这将是一次令人兴奋的旅程,展示如何使用 TBS 来实现其主要目的。
将应用程序注册到 TBS
使用 TBS 的主要原因是获得以完全自动化和安全的方式构建应用程序容器镜像的能力。让我们看看如何使用我们完成的 TBS 设置构建云原生应用程序的容器镜像。我们将使用一个基于 Spring 框架的示例应用程序——Spring Pet Clinic,地址为github.com/tandcruz/DevSecOps-in-Practice-with-VMware-Tanzu/tree/main/spring-petclinic。要跟随本教程,你需要在你的 Git 仓库中 fork 这个项目。
我们将使用kp CLI 将应用程序注册到 TBS。要注册一个应用程序,我们必须创建一个image资源,这是一个 kpack CRD 对象,用于在其列表中创建应用程序的记录。创建image资源后,TBS 会创建一个build,它也是一个 kpack CRD 对象,用于创建已注册应用程序的容器镜像。根据创建新容器镜像的实例数量,image和build对象之间可以是多对一的关系。在注册我们的应用程序之前,让我们验证当前的镜像对象:
$ kp image list
Error: no image resources found
正如你可能猜到的那样,我们在 Kubernetes 集群中通过新部署的 TBS 并没有管理任何现有的image对象。
此外,我们还需要向 TBS 提供 Docker Hub 帐户的凭证,以便它能够将构建的镜像推送到那里。你也可以使用其他的容器注册表或 Docker Hub 帐户来推送构建的应用镜像。但为了简化操作,我们将使用之前用来安装 TBS 的相同 Docker Hub 帐户。为了提供 Docker Hub 帐户的登录凭证,我们需要创建一个 Kubernetes Secret对象,如下所示:
$ DOCKER_PASSWORD="**********" kp secret create tbs-dockerhub-cred –dockerhub p********t
Secret "tbs-dockerhub-cred" created
现在,让我们开始创建一个image对象。
我们可以通过三种不同的方式配置应用程序,以使用 TBS 构建容器镜像。让我们一起了解一下它们,帮助你理解在何时使用哪种方式:
- 
使用 Git 仓库 URL:在此方法中,我们注册 Git 仓库 URL 和我们希望监视更改并根据该分支中提交的更改触发 TBS 镜像构建的仓库分支。这是创建容器镜像的最自动化方法,一旦应用程序更改合并到最终代码分支中,我们将采用此方法。我们将在本书中使用此方法。 
- 
使用本地路径:在此方法中,我们提供应用程序包的位置,例如 Java 应用程序的 JAR 文件,该文件在本地系统上预编译并打包,或提供应用程序源代码在本地系统上的位置。此方法不能完全通过 TBS 自动化,并假定您有一个外部 CI 流程,该流程会在需要为应用程序创建容器镜像时显式调用 TBS,而不是基于推送到 Git 仓库分支的新更改自动创建新镜像。 
- 
zip、tar.gz、tar或jar文件。此方法也用于像前面一样的显式构建触发器。
现在,让我们注册应用程序 Spring Pet Clinic 以与 TBS 一起使用,并注册其 Git 仓库。请参阅以下命令及其结果,了解如何执行此操作。该命令使用应用程序的 Git 仓库和我们希望 TBS 监视更改并基于这些更改构建容器镜像的分支:
$ kp image create tbs-spring-petclinic --tag p********t/tbs-spring-petclinic:1.0 --wait --git  https://github.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/tree/main/spring-petclinic --git-revision main
在此命令中,将 --git 和 --git-revision 的值替换为您已分叉的仓库详细信息。
重要说明
此命令可能需要几分钟才能运行,因为这是第一次构建和应用程序注册。此外,它假定 Git 仓库是公开可访问的。但如果该仓库需要用户凭据来拉取源代码,您可能需要为 Git 仓库凭据创建一个 TBS secret 对象,如下所述:docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-managing-secrets.html#create-a-git-ssh-secret。
如您所见,此命令执行了多个操作,包括访问应用程序的源代码、下载所有必需的依赖项、执行所有 CNB 生命周期阶段,最后将应用程序镜像推送到您的 Docker Hub 注册表,如命令中所指定。
让我们检查应用程序的 image 对象的存在:
$ kp image list
NAME                    READY    LATEST REASON    LATEST IMAGE                                                     NAMESPACE
tbs-spring-petclinic    True     CONFIG           index.docker.io/p********t/tbs-spring-petclinic@sha256:45688e54b22ee96e798f3f28e09a81020acc69fa0db806690aeb2ba07ae3ab00    default
在这里,我们可以看到已创建一个名为 tbs-spring-petclinic 的 image 对象。现在,让我们检查为我们的应用程序创建的 build 对象的数量:
$ kp build list
BUILD    STATUS     BUILT IMAGE                                                     REASON    IMAGE RESOURCE
1        SUCCESS    index.docker.io/p********t/tbs-spring-petclinic@sha256:45688e54b22ee96e798f3f28e09a81020acc69fa0db806690aeb2ba07ae3ab00    CONFIG    tbs-spring-petclinic
在这里,我们可以看到为我们的应用image对象创建了一个build对象。如果为应用的更改触发了更多的镜像构建,我们可能会看到更多的build对象。名为REASON的列表示由 TBS 触发此构建的原因。可能的原因如下:
- 
配置 表示在镜像配置文件中对提交、分支、Git 仓库或构建字段进行更改 
- 
提交 表示由应用代码仓库中推送的更改引发的构建,TBS 监视此过程 
- 
堆栈 表示运行镜像操作系统层发生变化 
- 
构建包 表示通过更新的构建器提供的构建包版本的变化 
- 
触发 表示手动触发的构建 
现在应用已在 TBS 中注册,当您在受监控的分支中提交一个小的更改时,您应该会看到几秒钟内创建一个新的构建,如下所示:
$ kp build list
BUILD    STATUS      BUILT IMAGE                                                              REASON    IMAGE RESOURCE
1        SUCCESS     index.docker.io/p********t/tbs-spring-petclinic@sha256:45688e54b22ee96e798f3f28e09a81020acc69fa0db806690aeb2ba07ae3ab00    CONFIG    tbs-spring-petclinic
2        BUILDING                                  COMMIT    tbs-spring-petclinic
您现在可以拉取旧的和新的镜像,在本地 Docker 环境中部署它们的容器,以验证应用所做的更改。现在我们已经学会了如何为已注册的应用创建新的容器镜像构建,让我们学习如何检查构建日志,以查看生命周期阶段的执行细节。
检查镜像构建日志
要检查新构建镜像的 TBS 日志,请使用以下命令:
$ kp build logs tbs-spring-petclinic
..
..
Saving p********t/tbs-spring-petclinic:1.0...
*** Images (sha256:322010cd44fa9dc3bcb0bfadc7ba6873fb65f1bfe4f0bbe6cf6dc9d4e3112e84):
      p********t/tbs-spring-petclinic:1.0
      index.docker.io/p********t/tbs-spring-petclinic:1.0-b2.20211213.072737
===> COMPLETION
Build successful
输出已被截断以简洁为主。
通过这一点,我们已经学会了如何创建第一个应用配置、触发新构建以及检查 TBS 上的构建日志。现在,让我们讨论另一个关于 TBS 的非常重要的活动,那就是保持我们的容器镜像始终保持安全,并及时更新应用容器镜像中使用的软件库和操作系统层的最新版本。
升级构建包和堆栈
正如我们在为什么选择 Tanzu Build Service 部分中看到的,使用该工具的主要好处之一是通过保持最新的修补程序应用依赖和构建容器镜像时使用的操作系统层,从而提高安全性。正如我们所知,构建包包含对不同软件库版本的引用,堆栈包含构建容器镜像的操作系统层。因此,当构建包中引用的软件库或堆栈中的操作系统有新的补丁版本发布时,VMware 会发布更新后的构建包和堆栈版本,以提供它们引用的软件的最新修补版本。
保持 TBS 组件版本最新的最推荐方式是启用 TBS 自带的自动更新功能。当我们使用 Tanzu 网络账户凭据部署 TBS 时,TBS 会在我们的 Kubernetes 集群中部署一个名为TanzuNetDependencyUpdater的 CRD 对象。这个 CRD 对象负责自动保持我们的 TBS 组件最新。我们在本章早些时候的安装中使用了相同的方法。你可以通过运行以下命令来验证这个设置:
$ kubectl get TanzuNetDependencyUpdater -A
NAMESPACE       NAME                 DESCRIPTORVERSION   READY
build-service   dependency-updater   100.0.240           True
在这里,DESCRIPTIONVERSION 的值可能不同,这取决于你在本章开始时作为前提条件下载的描述文件的最新可用版本。
如果在安装过程中未启用自动更新,则以下链接展示了如何在安装后启用它,或者如何手动更新各个组件,以便更好地控制更新的时间和变更的影响:docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-updating-deps.html。
管理图像和构建
我们可能需要执行各种日常操作,以便处理应用程序配置,这些配置以图像对象的形式存在,并且对应的构建过程作为构建对象生成,这些过程会因之前提到的不同原因而触发,包括 STACK、BUILDPACK、CONFIG、COMMIT 和 TRIGGER。你可以在docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-managing-images.html了解更多关于这些操作的信息。此外,TBS 会保留最后 10 次成功和失败的构建历史记录,包括它们完成的 Pod 及其相应的 Image 资源的日志。这些历史构建有助于你获取历史日志和详细信息,但也会占用大量集群存储空间。在大规模企业环境中,随着多个 Image 资源的创建,这可能会产生更大的影响。如果你想更改默认的 10 次历史构建的配置,可以参考以下文档,设置为其他数字:docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-faq.html#faq-18。
配置基于角色的访问控制
推荐在专门用于平台服务的 Kubernetes 集群中安装 TBS,而不是用于实际业务负载的集群。此类支持服务集群由平台运维特定用户组控制。集群级别的分离是选择性地允许用户访问 TBS 的一个好方法。如果ClusterBuilder定义发生意外更改,可能会触发构建与该ClusterBuilder相关联的应用程序的数百个容器镜像。而且,如果有自动化部署管道部署了所有应用程序的新版本并使用了新的容器镜像,那么这种错误可能会更加严重。因此,围绕 TBS 设置必要的保护措施非常重要。为此,TBS 提供了使用两个 Kubernetes ClusterRoles 的某种级别的访问控制,具体如下:
- 
build-service-user-role:允许处理镜像和构建资源
- 
build-service-admin-role:允许在 TBS 上执行所有其他管理活动
具有访问镜像和构建权限的 TBS 用户应在各自的 Kubernetes 命名空间中创建这些对象,以限制这些对象的访问权限仅限于同一命名空间的成员。通过这种方式,我们可以结合 Kubernetes 的访问控制功能,获得更强的控制力。你可以在这里找到如何配置这些权限的更多详细信息:docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-tbs-with-projects.html#rbac-support-in-tanzu-build-service。
升级 TBS 到新版本
升级 TBS 到新版本非常简单。你只需执行与安装过程中相同的步骤,除了在不需要的情况下重新导入依赖项。
卸载 TBS
要从 Kubernetes 集群中卸载 TBS,只需运行以下kapp命令;它将删除集群中所有 TBS 对象,除了 TBS 创建的容器镜像。此命令非常具有破坏性,使用时应极其小心:
$ kapp delete -a tanzu-build-service
自定义 buildpacks
TBS 采用非常模块化、可定制和可扩展的架构。它允许我们进行各种自定义更改,例如添加新的 buildpacks、改变 buildpack 顺序、添加新的操作系统层等。你可以通过以下参考资料了解更多关于此类自定义的信息:
- 
管理 ClusterStores:docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-managing-stores.html
- 
管理 ClusterStacks:docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service/GUID-managing-stacks.html
- 
创建和管理 buildpacks: buildpacks.io/docs/buildpack-author-guide/
总结
在本章中,我们学习了围绕为应用程序构建安全容器镜像的不同问题,以及 TBS 如何通过不同的功能来应对这些问题。接着,我们深入了解了 TBS 的完整结构,以理解它的所有构建模块。之后,我们进行了 TBS 的安装过程演示,帮助我们开始使用它。最后,我们了解了如何在 TBS 上执行各种关键操作。使用像 TBS 这样的基于 CNB 的解决方案是 CNCF 推荐的最佳实践之一,现在我们可以理解为什么这是一个有效的做法。
在任何 Kubernetes 环境中,我们都会部署两种不同类型的容器镜像——它们要么属于我们的应用程序,要么属于第三方软件。现在我们已经学习了如何使用开箱即用的自动化工具为我们的应用程序构建安全容器镜像,在下一章中,我们将学习如何使用流行开源软件的安全容器镜像,为我们的应用程序提供后端服务。
第四章:为应用程序提供后端服务
在上一章中,我们看到如何使用Tanzu 构建服务(TBS)以充分的安全性和较少的操作开销构建应用程序容器镜像。这些容器镜像是运行我们云原生应用程序的基本构建模块,可以在Kubernetes等容器编排平台上运行。我们可以将这些容器镜像部署到 Kubernetes 集群中,并运行我们的应用程序。然而,在实际情况中,事情并不像看起来那么简单。在大多数情况下,业务应用程序依赖于数据库、队列、缓存等后端服务。此外,还有一个日益增长的趋势是将这些现成的后端服务也作为容器部署到类似 Kubernetes 的平台上,出于各种原因。
在本章中,我们将深入探讨VMware 应用目录(VAC),它提供了一种安全、快速和可靠的方式,在容器化环境中使用这种开源后端服务。我们将覆盖以下主题:
- 
为什么选择 VMware 应用目录? 
- 
什么是 VMware 应用目录 
- 
开始使用 VMware 应用目录 
- 
使用 VMware 应用目录的常见第二天活动 
我们有很多内容需要覆盖。所以,让我们开始探索 VAC 解决了哪些业务和技术挑战。
技术要求
在开始使用 VAC 之前,有一些技术要求需要满足。这些要求将在本章后面开始使用 VMware 应用目录部分的开头介绍。然而,您可能不需要这些要求就能理解该应用程序和工具的细节。
为什么选择 VMware 应用目录?
以下是 VAC 通过其能力解决的关键领域,能够为开发者生产力、安全性和操作实践带来改善,特别是在提供一种消费流行的开源软件(OSS)并将其部署为运行中的容器方面。
使用合适的工具实现合适的目的,同时保留选择的灵活性
如我们之前讨论的,大多数业务应用程序依赖于一个或多个后端服务,且根据应用程序的性质,这些后端服务的需求可能会有所不同。我们已经看到,使用关系型数据库作为后端数据存储在过去几年里是最常见的后端服务。但一些现代云原生应用程序可能会通过其他数据存储(如 NoSQL)表现得更好。类似地,如果应用程序需要队列作为后端服务,我们可以选择 Kafka 或 RabbitMQ。但 Kafka 和 RabbitMQ 都有各自独特的使用场景,根据应用程序的需求,其中一个可能比另一个更适合。类似的选项也存在于缓存、日志记录、持续集成/持续部署(CI/CD)自动化等工具中,以及运行云原生应用程序的其他多个方面。对于这些用例,今天有许多强大且成熟的开源软件解决方案,这些解决方案非常流行且被广泛采用。图 4.1 显示了开源软件工具在最近的过去如何超过专有工具:

图 4.1 – 开源数据存储受欢迎度的上升趋势
尽管有大量的选择和经过验证的良好记录,但为应用团队提供采用这些开源工具的自由往往是具有挑战性的。这有两个可能的原因。首先,批准这些工具的使用并创建一个安全的容器镜像供应链需要大量的操作开销。其次,鉴于它们各自的容器镜像是公开存储在容器仓库中的,这意味着它们并不总是值得信赖。因此,开发团队要么因为缺乏选择而受到困扰,要么因为生产力损失而导致等待时间增加。
VAC 通过提供大量开源工具目录来解决这一挑战,企业可以从中选择。一旦准备好自定义的开源工具目录,VAC 服务会创建一个自动化供应链,将所选工具的容器镜像和 Helm charts 流式传输并交付到目标容器注册中心,该注册中心可以是内部部署的,也可以是外部部署的,如 Google Container Registry(GCR)。随后,我们将不断获得这些开源工具的新版本,它们以更新的容器镜像和 Helm charts 形式提供。这些可以通过最小的操作开销进行配置,并为应用团队提供丰富的选择。一旦开始获取我们目录项目的工件、容器镜像和 Helm charts,我们可以将该目录暴露给内部使用。然后,经过授权的内部成员可以使用该目录,在几分钟内在 Kubernetes 上部署这些开源工具。这种选择的灵活性,且没有操作开销,应该能够鼓励在不影响用户生产力的情况下为正确的用例使用合适的后台服务。
增强的安全性和透明度
在容器平台上使用开源软件(OSS)部署非常快捷、简单,并且正在变得越来越流行。所有主要的公共容器仓库,如 Docker Hub 和 GCR,都有所有主要开源软件的容器镜像。我们只需提供容器镜像的名称,几秒钟内就能下载。然而,尽管从这些公共容器仓库拉取容器镜像有许多好处,几乎所有具有一定安全实践的企业都不允许这么做。以下是其中几个原因:
- 
很难确定公共仓库中哪些容器镜像是由合法来源托管的。你可能会发现多个由不同组织或普通用户托管的相同软件的容器镜像。在这种情况下,创建一个认证来源的白名单来拉取这些托管镜像将非常困难。 
- 
即使有办法找到可以使用的认证来源及其容器镜像,围绕它创建一个治理模型来限制未知来源托管的容器镜像的使用也是非常困难的。 
- 
同时,也很难获得物料清单(BOM),以了解这些外部提供的容器镜像包含了什么。这些第三方镜像往往充当黑盒,企业难以获得所需的信心来允许在任何环境中使用它们。审核运行这些黑盒容器镜像的环境也将非常困难。 
- 
任何一个成熟的组织都有一套标准的操作系统(OSes),这些操作系统会被允许在其基础设施中使用。这些操作系统要求通常也适用于容器镜像。然而,对于第三方提供的容器镜像来说,往往没有足够的控制选项来选择操作系统。这可能是企业不赞成使用托管在公共容器注册表上的开源工具容器镜像的一个主要原因。 
- 
对于一个以安全为首要思想的组织,涉及信息安全标准时,通常会有几个审计和合规要求。为了获得在企业生产环境中运行 OSS 容器所需的信心,应该提供多个详细信息,包括常见漏洞和暴露(CVE)扫描报告、测试结果、病毒扫描和其他有关已部署工作负载的细节。 
为了满足这些要求,公司通常会控制自己的开源软件(OSS)容器镜像构建过程。当他们将更多的开源软件添加到内部镜像编排过程中时,往往会意识到这种做法并不具备很好的可扩展性、速度不足以满足需求、效率低下或存在安全隐患。出现这种情况的原因有几点:当需要将新的开源工具添加到内部管理的目录时,就需要构建新的自动化流水线、测试用例、基础设施容量等。
- 
这种定制的内部自动化工作通常只有少数工程师理解并维护。当团队中的关键人员轮换离开时,会造成知识的空白,这种空白有时很难填补,从而造成知识缺口。 
- 
随着目录的增大,维护工作量呈指数级增加。因为每个目录项的更新版本都需要为内部使用构建一个新的相应容器镜像。由于这种额外的工作量,平台运营团队可能会滞后于跟上最新的修补版本。这种生产最新修补容器镜像的延迟会增加安全风险,因为未修补的 CVE 可能会在企业范围内被使用,直到新的容器镜像准备好。 
- 
由于为内部使用提供新的目录项所需的工作量,可能会出现反对添加新项目的情况。这些反对意见可能会减少开发者的生产力,因为他们需要花时间等待,或者影响业务应用程序的质量,因为无法为特定的使用场景选择正确的工具。 
- 
即使平台团队同意将新项目添加到目录中,但消费者实际获得可生产认证的容器镜像的时间仍然较长。这类延迟再次浪费了重要劳动力的宝贵生产时间,或者劳动力通过使用外部可用但不安全的容器镜像来源找到解决方法。 
- 
从事此类内部自动化工作的人员时间和为此原因利用的基础设施容量,本可以更好地用于推动更具商业成果的事业。 
为了解决这些挑战,VAC 应运而生,提供以下好处,帮助提供一个安全的解决方案,以提高开发者生产力和运营效率:
- 
VAC 允许企业为其所有选择的 OSS 容器镜像使用自己的黄金操作系统镜像层。这是一个重要的优势,因为客户组织可以在其选择的操作系统版本上使用经过硬化的操作系统层,并按需配置安全设置。 
- 
VAC 为每个目录项的容器镜像和 Helm 图表(如适用)的创建和分发创建了自动化流水线。由于这种自动化,VAC 可以在较新的上游版本发布后迅速为订阅者提供更新的修补版本。快速提供修补版本能够有效预防黑客攻击,提升安全防范水平。 
- 
VAC 为所有交付的容器镜像提供以下工件,以增强消费者信任并提高容器镜像的透明度: - 
资产规范,详细说明容器镜像内容信息 
- 
自动化测试用例结果,供交付前执行的测试运行使用 
- 
CVE 扫描报告 
- 
CVE 扫描报告,格式为 CVRF 
- 
杀毒扫描报告 
- 
用户文档参考 
 
- 
- 
VAC 将所有工件推送到客户提供的私有容器注册表中,这为所有容器镜像和 Helm 图表创建了一个可信赖的来源,供内部使用。 
什么是 CVRF?
通用漏洞报告框架(CVRF)1.1 版于 2012 年 5 月发布。CVRF 是一种基于 XML 的语言,使不同组织之间的不同利益相关者能够以统一格式共享关键信息,从而加速信息交换和消化。参考文献:www.icasi.org/the-common-vulnerability-reporting-framework-cvrf-v1-1/。
在前面的几个要点中,我们讨论了 VAC 的主要优势。目前,VAC 仅适用于 OSS 工具。然而,许多大型组织在没有企业级支持的情况下不会使用 OSS 工具,特别是在生产环境中。需要理解的是,VAC 作为一种解决方案,仅支持使用客户端选择的操作系统层的 OSS 容器镜像和 Helm 图表的安全供应链。但 VAC 并不支持作为订阅的一部分的基础 OSS 工具。例如,如果一个组织通过 VAC 需要 PostgreSQL 数据库容器镜像,那么 VAC 将支持 PostgreSQL 数据库上游版本容器镜像的打包和及时分发。但 VAC 不会支持基础的 PostgreSQL 数据库本身。因此,为了支持 PostgreSQL,企业可能需要使用由供应商支持的服务,如 VMware 的 Tanzu 数据管理服务订阅,该订阅支持开源 PostgreSQL 和 MySQL 数据库。或者,他们可以使用供应商特定版本的开源解决方案,比如由 Crunchy Data 提供的 PostgreSQL 版本。在这种情况下,组织可以从相应的第三方供应商(如 Crunchy Data)获取容器镜像。对于这种情况,VAC 并没有什么用处。但如果企业希望使用供应商支持的纯粹上游版本 PostgreSQL(例如由 VMware 或 EnterpriseDB (EDB) 提供支持),则可以使用 VAC 来享受所有列出的好处。
上游与供应商特定版本的 OSS
直接使用上游的 OSS 发行版而不添加供应商特定的版本有助于避免潜在的供应商锁定,这是使用 OSS 技术的首要原因。VAC 使企业更容易采用这些 OSS 工具。尽管如此,许多组织仍然使用供应商特定版本的 OSS,因为这些版本包含了上游 OSS 发行版中没有的附加功能和特性。因此,这两种方法各有利弊。
在了解 VAC 的优势和适用范围之后,让我们更深入地了解一下 VAC 是什么以及它包含哪些内容。
VMware 应用程序目录是什么
在详细介绍了 VAC 可以解决的业务、安全和技术挑战,以及它不适用的场景之后,让我们现在更详细地了解这个工具,看看它包含了什么内容。在此之前,让我们先了解一下 VAC 的背景,以便更深入地了解它。
VMware 应用程序目录的历史
在 2019 年末,为了策划一个全面的现代应用开发和管理工具组合,VMware 决定收购一家名为 Bitnami 的流行 OSS 打包和分发公司。Bitnami 在这一领域有多年经验,最初以二进制文件、虚拟机镜像和容器镜像的形式提供精心策划且可消费的 OSS 工具。收购后,VMware 将 Bitnami 更名为 Tanzu 应用目录,以定义一个企业级 OSS 容器镜像分发产品,可以根据企业客户的需求定制镜像规范。2021 年,VMware 决定在原有的容器镜像和 Helm 图表之外,还包括 开放虚拟设备(OVA)镜像目录,以构建虚拟机,这也是 Tanzu 应用目录的最初构想。正如我们在本书中看到的,VMware 的 Tanzu 产品组合涵盖了所有与容器和 Kubernetes 相关的工具和技术。这也是该产品最初被命名为 Tanzu 的原因。但是,随着 VMware 最近宣布将扩展该产品以支持 OVA 镜像和容器镜像以及 Helm 图表,这一产品被重新命名为 VMware 应用目录(VAC),因为它不再仅仅关乎容器生态系统。
重要提示
本书的主要焦点是 Tanzu 及其周边生态系统。此外,在撰写本书时,关于虚拟机镜像的产品仍在发展中,尚未达到与 VAC 中容器镜像相同的水平。因此,本章只会涵盖容器镜像目录管理和消费的相关细节,而不会涉及虚拟机镜像。
在了解了 VAC 的历史并明白为什么它名字中有 VMware 而不是 Tanzu 后,让我们现在来了解一下这个产品的关键组成部分。
VMware 应用目录的组成部分
以下工具是 VAC 的组成部分。我们来一一审视它们。
VMware 应用目录门户
该产品的主要组成部分是 VAC 门户,在此我们可以策划和管理应用目录。它是一个软件即服务(SaaS)组件,由 VMware 托管和管理。VAC 客户端可以通过其 VMware Cloud (console.cloud.vmware.com/) 账户访问 VAC 服务。目录管理员可以创建新目录、在目录中添加新的 OSS 产品,并下载与目录项相关的支持元素,包括测试结果日志、CVE 报告、防病毒扫描报告以及其他此类项目。总之,VAC 门户提供了一个基于 Web 的用户界面,用于安全地策划一个可以供企业内部用户自由使用的 OSS 工具目录。我们将在本章后面详细介绍这个门户的更多细节。
Kubeapps
一旦目录管理员在 VAC 门户上定义了带有 Helm 图表的支持的 OSS 工具目录,开发人员或操作员可以使用 Kubeapps (kubeapps.com/) 来消费发布的目录项供内部使用。Kubeapps 是 云原生计算基金会(CNCF)旗下的 OSS 工具。这个项目最初由 Bitnami 启动,旨在提供一个 图形用户界面(GUI),通过 Helm 图表在 Kubernetes 集群上部署软件。自从被 Bitnami 收购后,VMware 积极维护该项目。它是一个非常轻量级的应用程序,可以部署在运行在组织环境中的 Kubernetes 集群上。Kubeapps 的用户可以从可访问的目录中选择要部署的软件,更改所需的部署配置(例如,用户凭据、存储大小、安全配置等),并最终将其作为运行中的容器部署到选定 Kubernetes 集群的目标命名空间中。一旦目录中有软件的新版本可用,用户可以快速升级,或者如果不再需要该部署,可以将其删除。总结来说,如果 VAC 门户提供了所需的控制,以安全地公开 OSS 工具目录,那么 Kubeapps 就为开发人员或其他目录用户提供了所需的灵活性和生产力,可以根据需要使用已发布的目录来管理各种 OSS 工具的生命周期。
让我们了解这些组件是如何协同工作,以提供所需的功能。图 4.2 描述了在 VAC 门户上定义 OSS 目录的整体过程,并通过 Kubeapps 或 持续部署(CD)自动化来消费这些目录工件。
VAC 管理和消费过程
在上一节中回顾了该服务的关键组件后,让我们现在来了解这些组件如何协同工作,通过使用 VAC 提供端到端的目录编排和消费功能。以下几点对应于图 4.2中给出的每个数字,并描述了在该步骤中发生的过程。图 4.2中的云表示 VAC 的 SaaS 基础设施,矩形框定义了客户组织的基础设施边界。这个客户基础设施可以是私有数据中心、公共云,或者两者的结合:
- 
客户组织中的目录管理员,拥有 VMware Cloud 账户的访问权限,定义了一个新的选定 OSS 工具目录。在此步骤中,目录管理员还选择了要使用的基础容器操作系统,决定是否包括或排除所选项目的 Helm 图表,并提供一个容器仓库引用,用于将目录工件推送到安全的消费位置。 
- 
一旦目录管理员提交了目录配置,VAC 自动化过程将继续推进,部署所需的自动化流水线,以创建符合目录管理员在步骤 1中提供的规格生成的容器镜像和 Helm 图表。 
- 
VAC 自动化过程根据每个选择的 OSS 工具,从授权的第三方源拉取所需的 OSS 二进制文件。在获取所需的二进制文件后,VAC 自动化执行某些操作,包括自动化测试 OSS 工具的版本、使用客户端指定的操作系统镜像层打包工具、准备容器规格报告,以及执行病毒扫描和 CVE 扫描。此步骤会针对 VAC 涵盖的每个 OSS 工具的每个新版本重复执行。 
- 
一旦目录项准备好供消费,它将被推送到目录管理员在步骤 1中指定的目标容器注册表。此步骤对于每个 OSS 工具的版本,也会在步骤 3中为其准备的每个版本重复执行。 
- 
一旦目录项被推送到目标容器注册表,目录管理员可以拉取在步骤 3中为已发布的工件准备的报告,如 CVE 扫描报告等。VAC 门户还会指定使用 CLI 命令来使用发布工件的容器镜像和 Helm 图表。 
- 
在此步骤中,目录管理员在 Kubeapps 上配置已发布的目录供内部使用。 
- 
在此步骤中,Kubeapps 拉取所需的目录详细信息,以便在 GUI 上发布供消费使用。 
- 
一旦目录在 Kubeapps 上配置好,目录消费者可以访问 Kubeapps GUI 来部署所需的 OSS 工具作为 Kubernetes 部署: 

图 4.2 – VAC 管理与消费过程
- 
当 Kubeapps 接收到来自目录消费者的请求,要求在 Kubeapps GUI 上使用其 Helm 图表部署工具时,Kubeapps 将从在步骤 4中推送到容器注册表的工件中拉取所需的 Helm 图表和容器镜像,以进行工具的部署。 
- 
由 Kubeapps 触发的 Helm 安装程序使用目录消费者在步骤 8中提供的配置,在目标 Kubernetes 集群中部署 OSS 工具。在此步骤结束时,目标 Kubernetes 集群中将运行该 OSS 工具实例。在大多数情况下,此步骤将在几分钟内完成。 
- 
此步骤描述了使用 CD 自动化过程消费 VAC 提供的工件的另一种方式。此步骤可以配置为每当容器注册表中有新版本的工件可用时触发,从而启动自动化部署过程。 
- 
在此步骤中,CD 过程将在目标 Kubernetes 集群中部署已下载的 OSS 工具。 
下图总结了所有这些步骤,突出了 VAC 的功能以及其使用方式:

图 4.3 – 高级视图中的 VAC (https://docs.vmware.com/)
到此,我们已经覆盖了理解 VAC 历史、VAC 如何获得当前名称、VAC 的关键组成部分,以及从目录创建到使用的端到端过程的所有细节。现在,让我们开始使用 VAC,更好地理解如何使用它。
开始使用 VMware 应用程序目录
本章这一部分将涵盖以下内容:
- 
如何配置应用程序目录 
- 
如何在 Kubernetes 集群上安装 Kubeapps 
- 
如何配置 Kubeapps 使用目录 
所以,让我们开始动手操作。但在此之前,我们需要满足以下先决条件。
先决条件
以下几点列出了实现 VAC 所需的先决条件:
- 
拥有 VAC 访问权限的 VMware Cloud Services 账户 ( console.cloud.vmware.com/)
- 
以下任一容器仓库,VAC 可以访问它们以推送目录项: - 
GCR 
- 
Azure 容器注册表 
- 
Harbor 
 
- 
- 
具有以下属性的 Kubernetes 集群: - 
版本 1.19 或更高版本 
- 
外网访问 
- 
VAC 使用的容器注册表访问 
- 
自动化 持久卷(PV)创建,基于 持久卷声明(PVC) 
 
- 
- 
配备 Linux 或 macOS 的工作站 
- 
在工作站机器上安装 Helm v3.x 
Helm 安装
如果你需要帮助进行 Helm 安装,请参考此文档:docs.bitnami.com/kubernetes/get-started-kubernetes/#step-4-install-and-configure-helm。
我们首先定义一个可以被各种应用程序访问的后端服务目录。我们将选择 MySQL 作为关系型数据库,作为 OSS 目录项的示例,以便在本章后续部分描述各种细节。在实际操作中,我们可能会将许多其他 OSS 工具添加到目录中,并以类似的方式使用它们。你可以在 VAC 门户上找到更多可用的 OSS 工具列表,以便创建目录。
在 VAC 门户上创建目录
在 VAC 门户上创建目录,请按照以下步骤操作:
- 登录到你的 VMware Cloud Services 账户,并从可用服务中选择 VMware 应用程序目录。如果你没有看到该服务,可能需要联系你的 VMware 账户团队成员以获取访问权限:

图 4.4 – 从服务列表中选择 VAC
- 你将看到一个空目录页面,如下图所示,因为之前没有添加任何目录项。点击下图所示的 ADD NEW APPLICATIONS 按钮:

图 4.5 – 空目录中的 ADD NEW APPLICATIONS 按钮
- 选择目录工件的基础操作系统层。如本章之前所述,我们将重点关注基于 Kubernetes 的应用程序目录,而不是虚拟机。作为一个简单的示例,Ubuntu 18.04 被选择为基础操作系统层,但您也可以选择自定义基础镜像选项。有关更多详细信息,请访问 VAC 产品文档:docs.vmware.com/en/VMware-Application-Catalog/services/main/GUID-get-started-get-started-vmware-application-catalog.html#step-3-create-custom-catalogs-5:

图 4.6 – 为目录项选择基础操作系统
- 从可用选项中选择所需的 OSS 项目以包含在目录中。如果需要,您也可以进行搜索:

图 4.7 – 选择目录项
- 点击添加注册表按钮,添加目标容器注册表,以将所需的目录工件交付:

图 4.8 – 添加容器注册表
- 提供所需的容器注册表详细信息,以允许 VAC 将目录工件推送到该注册表:

图 4.9 – 添加注册表详细信息
虽然图 4.9 显示了 GCR 的详细信息,但它也支持其他注册表,包括 Azure 容器注册表和 Harbor。您可以通过以下链接获取有关其他注册表的更多信息:docs.vmware.com/en/VMware-Application-Catalog/services/main/GUID-get-started-get-started-vmware-application-catalog.html#step-3-create-custom-catalogs-5。
- 为该目录指定名称和描述:

图 4.10 – 为目录添加名称和描述
- 验证输入摘要并提交目录请求:

图 4.11 – 提交目录请求
在此之后,我们将看到一条确认我们目录请求提交的消息。在我们开始将目录项交付到选定的容器注册表目标之前,可能需要大约几周的时间来审核和处理该请求。
就这样。我们已经定义了 OSS 工具的目录,以便能够将其发布给内部用户,方便快捷地访问。但他们如何访问这个目录呢?让我们在下一节中查看。
使用 Kubeapps 消费 VAC
在上一部分中,我们学习了如何在 VAC 门户上请求应用目录。一旦我们开始从容器注册中心获取 Helm charts 和容器镜像,就可以使用 Kubeapps 访问这些工具,它是一个用于管理基于 Kubernetes 的软件部署的图形界面。在本章的VAC 组件部分中,我们已经详细讨论了 Kubeapps。现在让我们来看如何安装和配置它。
Kubeapps 安装
Kubeapps 本身是一个基于 Kubernetes 的部署,用于管理其他可以通过 Helm charts 和 operators 部署的 Kubernetes 部署。由于我们计划使用 Kubeapps 来使用 VAC 提供的发行版,包括 Helm charts 和容器镜像,因此我们在本节中不讨论 operators 的使用。作为一种部署拓扑结构,我们可以在任何 Kubernetes 集群上安装 Kubeapps,以在同一个或任何其他与 Kubeapps 连接的 Kubernetes 集群及其命名空间中部署目录项。在本章中,我们将使用一个单一的 Kubernetes 集群,以最小化配置复杂度。
我们需要满足一些先决条件,以便继续操作,这些内容在本章的先决条件部分中有详细说明。以下步骤描述了在具有足够资源的 Kubernetes 集群上安装和配置 Kubeapps:
- 
将 Bitnami Helm chart 仓库添加到本地 Helm 库: $ helm repo add bitnami https://charts.bitnami.com/bitnami
- 
为 Kubeapps 创建一个 Kubernetes 命名空间: $ kubectl create namespace kubeappsnamespace/kubeapps created
- 
使用 Helm chart 在 kubeapps命名空间中安装 Kubeapps:$ helm install kubeapps --namespace kubeapps bitnami/kubeappsNAME: kubeappsLAST DEPLOYED: Wed Jan 19 19:45:20 2022NAMESPACE: kubeappsSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:CHART NAME: kubeappsCHART VERSION: 7.7.0......
前面的输出为了简洁而被截断了。到此为止,我们已经在集群中运行了 Kubeapps。现在让我们验证一下。
- 
验证 Kubeapps 的部署,以查看是否一切运行正常: $ kubectl get all -n kubeapps
上面的命令应列出pods、services、deployments、replicasets、statefulsets和jobs,由于篇幅原因这里未列出。
- 
创建一个临时服务账户来访问 Kubeapps GUI: $ kubectl create --namespace default serviceaccount kubeapps-operatorserviceaccount/kubeapps-operator created
- 
将服务账户与 Kubernetes 角色绑定,以允许所需的访问: $ kubectl create clusterrolebinding kubeapps-operator --clusterrole=cluster-admin --serviceaccount=default:kubeapps-operatorclusterrolebinding.rbac.authorization.k8s.io/kubeapps-operator created
- 
获取账户的访问令牌,以登录 Kubeapps GUI: $ kubectl get --namespace default secret $(kubectl get --namespace default serviceaccount kubeapps-operator -o jsonpath='{range .secrets[*]}{.name}{"\n"}{end}' | grep kubeapps-operator-token) -o jsonpath='{.data.token}' -o go-template='{{.data.token | base64decode}}' && echo
这个长命令会打印出一长串字符,这就是我们用来登录 Kubeapps GUI 的令牌。请保存此令牌以备将来参考。
重要说明
前面三个命令用于为 Kubeapps 创建访问权限,它们采用了一种非常原始的方法,以简化操作并作为学习参考。在生产级别的实现中,我们可能需要使用更复杂的方法来配置可以访问 Kubeapps 的真实企业用户。此类用户权限通常通过与 OIDC 或 LDAP 身份提供者的外部集成来进行管理。此外,使用cluster-admin角色并不是一种安全的方法,除非是用于学习目的,否则不应使用该角色。
- 
公开 Kubeapps GUI,以便在浏览器中本地访问。对于生产级部署,GUI 应该分配一个合适的域名,并通过负载均衡器在 Kubernetes 集群外部公开。在此步骤中,我们将使用 Kubernetes 端口转发进行快速简单的访问: $ kubectl port-forward -n kubeapps svc/kubeapps 8080:80Forwarding from 127.0.0.1:8080 -> 8080Forwarding from [::1]:8080 -> 8080
- 
在本地浏览器中访问 Kubeapps,使用 http://localhost:8080/。这将打开 Kubeapps 的以下界面:

图 4.12 – Kubeapps GUI – 身份验证页面
- 使用 第 7 步 中获取的令牌访问 Kubeapps。将令牌值粘贴到登录页面并提交。这应该会打开如 图 4.13 所示的 Kubeapps GUI:

图 4.13 – Kubeapps GUI – 初始登陆页面
重要说明
本章中描述的截图和步骤基于当前可用的 VAC 和 Kubeapps 版本。根据阅读本书的时间,内容和体验可能会根据将来对这些产品进行的更改有所不同。
如你所见,Kubeapps 配有配置来访问公开可用的通用 Bitnami 目录。一旦我们在 VAC 门户上定义的客户目录准备好,并且开始获取其工件,我们可以配置 Kubeapps 使用相同的目录。我们将在第二天活动中涵盖如何将自定义应用程序目录链接到 Kubeapps。
到此,我们已经完成了本章关于 VAC 和 Kubeapps 入门部分的内容。我们已经了解了如何在 VAC 门户上创建目录,并在 Kubernetes 集群中安装 Kubeapps。在下一节中,我们将看到以下内容,涵盖 VAC 周围的常见第二天活动:
- 
如何检查已交付的目录工件并获取所需的报告 
- 
如何将 VAC 与 Kubeapps 连接,以便发布供使用 
- 
如何通过自动化管道使用 Kubeapps 消费目录项 
- 
如何使用 Kubeapps 将 MySQL 部署为运行在 Kubernetes 集群中的后端服务 
- 
如何管理目录项 
现在让我们来学习如何使用 VAC。
与 VAC 相关的常见第二天活动
根据本章前一节中涵盖的细节,我们现在有一个在 VAC 门户上提交的 OSS 工具目录请求,以及一个运行在 Kubernetes 集群中的 Kubeapps 实例。现在让我们回顾一些目录管理员可以执行的关键第二天活动,以确保 OSS 工具使用的安全性和合规性,以及目录消费者可以执行的活动,以便在 VAC 目录中快速以不同方式部署和使用这些 OSS 工具,从而释放生产力和灵活性。
检查目录交付物
一旦我们通过 VAC 门户向 Vmware 提交了目录请求,如前一节所述,我们可以使用 VAC 门户检查我们的目录交付物状态,如下图所示,在 我的 请求 标签下:

图 4.14 – 检查 VAC 请求状态
当我们完成目录请求后,我们开始在我的应用程序页面上查看交付的工件,如下图所示:

图 4.15 – 在 VAC 门户上列出目录应用程序
根据我们在目录创建请求期间的选择,我们可能会看到 Helm 图表及其容器镜像,如图 4.15所示。现在,我们通过点击右侧该项的详细信息链接来检查 MySQL 容器镜像的详细信息。以下截图显示了 MySQL 容器镜像的详细信息:

图 4.16 – VAC 门户上的目录项详细信息
我们可以从目录项详细页面的不同部分获取以下详细信息,如图 4.16所示。以下列表中的数字对应于图 4.16中的数字:
- 
摘要:这是我们在目录创建过程中提供的目标容器注册表中放置的工件的名称和位置。 
- 
使用您的容器镜像:这是 Docker 命令,用于将此容器镜像拉取到 Docker 运行时环境中。 
- 
容器标签:这些是此容器镜像的不同标签别名,我们可以在 Kubernetes 部署清单文件中使用这些标签来拉取此容器镜像,以便在 Kubernetes 上运行该应用程序。 
- 
验证报告:此项允许我们下载自动化测试结果日志文件,该文件在创建此容器镜像之前用于测试此版本的 MySQL。 
- 
构建时间报告:此部分包含各种容器构建报告,包括病毒扫描和 CVE 扫描报告以及包含所用软件及其版本列表的资产规范(物料清单)报告。 
- 
发布关系:此部分显示使用此镜像的依赖 Helm 图表。 
与容器镜像的详细信息类似,Helm 图表的详细信息包括部署图表所需的helm CLI 命令、图表的测试结果、资产规范和容器镜像依赖项。
使用应用程序目录
在检查了 VAC 门户上为我们目录项提供的工件所需的详细信息后,现在是时候使用它们在我们的环境中部署这些工具了。我们可以通过多种方式使用 VAC 提供的容器镜像。根据工具的需求,我们可以简单地在工作站的容器运行时环境中运行一些工具,例如 Docker。然而,对于企业级部署,我们需要多个支持组件来运行工具。例如,我们看到创建了所有 Kubernetes 资源来部署和运行我们在本章中之前部署的 Kubeapps 实例。部署此类工具的一种可能方式是使用自定义脚本和 CI/CD 工具(如 Jenkins 和/或 ArgoCD)通过 GitOps 基于部署模型进行部署。另一种可能的选择是使用 Kubernetes 打包工具,如 Helm charts。Helm chart 将部署和运行工具所需的所有依赖项捆绑到一起,以便在 Kubernetes 集群上进行部署。使用 Helm charts 等工具使得配置和快速部署工具变得非常简单,所有必需组件都可以在几分钟内以最小的努力完成。正如我们之前看到的,VAC 允许我们在适用的地方为目录项选择容器和 Helm charts。作为应用程序打包的一部分,Helm charts 还允许暴露某些配置属性,这些属性可能需要根据不同的部署进行更改。我们可以使用 VAC 提供的这些 Helm charts 来部署这些工具,并根据我们的自定义配置需求进行调整。例如,在 MySQL 数据库部署中,我们可以更改其名称、登录凭据、存储卷大小等属性。
什么是 GitOps?
GitOps 坚持 Git 是唯一真实来源的原则。GitOps 要求将系统的期望状态存储在版本控制中,以便任何人都可以查看变更历史。所有对期望状态的更改都通过 Git 提交 来执行。来源:blogs.vmware.com/management/2020/08/ops-powered-by-git-gitops-in-vrealize-automation.html。
正如我们之前讨论的,Kubeapps 是一个用于部署和管理我们在 VAC 上配置的 Helm charts 目录的工具。那么,让我们来看一下如何将 VAC 提供的 Helm charts 与我们在本章中之前部署的 Kubeapps 实例进行链接。
将应用程序目录添加到 Kubeapps
以下步骤描述了如何在我们的 Kubeapps 实例上配置 VAC 提供的 Helm charts 的新目录:
- 获取 Helm charts 所在的 chart 仓库位置。你可以在 VAC 门户上,查找 Helm chart 项目的详细页面中找到此信息,如下图所示:

图 4.17 – 获取 Helm chart 仓库位置
高亮部分的 URL 是我们在 VAC 门户定义的所有 Helm chart 的存储位置。请记下这个 URL,我们将在接下来的步骤中使用它:
- 
在 VAC 门户上为 VAC 账户生成 API 令牌,我们将使用它来验证我们的 Kubeapps 实例,以拉取选定目录项的 Helm chart。以下子步骤描述了如何在 VAC 门户上生成 API 令牌: - 使用右上角下拉菜单进入 VAC 门户的我的账户页面,如以下截图所示:
 

图 4.18 – 转到 VAC 我的账户设置
- 点击API 令牌标签:

图 4.19 – 转到 API 令牌列表页面
- 如果此页面上已列出了具有访问 VAC 服务权限的令牌,则可以跳过以下步骤以生成新的 API 令牌,并直接跳转到步骤 3在 Kubeapps 中添加仓库。否则,点击如以下截图所示的生成新 API 令牌链接:

图 4.20 – 转到 API 令牌配置页面
- 输入令牌配置,如以下截图所示:

图 4.21 – 为 VAC 生成新的 API 令牌
- 
你可以根据需求更改令牌的名称和有效期。但是,作用域对允许从 Kubeapps 访问 VAC 至关重要。它不能是只读或支持角色。你也可以生成一个通用令牌,用于所有 VMware 云服务的所有服务。然而,这将非常宽泛,允许所有类型的访问,因此不推荐使用。 
- 
保存生成的令牌以供将来使用: 

图 4.22 – 保存生成的令牌
- 登录到我们部署的 Kubeapps 实例,并通过右上角的图标打开其配置菜单,然后选择应用仓库选项,如以下截图所示:

图 4.23 – 将 Helm chart 仓库添加到 Kubeapps
- 点击添加应用仓库按钮以配置新仓库的详细信息:

图 4.24 – 转到新的仓库配置页面
- 为其命名,添加在步骤 1中捕获的 Helm chart 仓库 URL,粘贴在步骤 2中生成的 API 令牌,选择跳过 TLS 验证选项,然后点击安装 仓库按钮:

图 4.25 – 在 Kubeapps 中安装 VAC Helm 仓库
我们必须选择 跳过 TLS 验证 选项,如 图 4.25 所示,因为我们的 Kubeapps 部署没有分配外部域名和 TLS 证书。在企业级环境中,这不是推荐的做法。
- 如果收到成功消息,那么目录应已与 Kubeapps 集成。为了确认这一点,请点击 Kubeapps 上的 Catalog 标签并选择 demo-catalog 选项,如下截图所示:

图 4.26 – 在 Kubeapps 上新配置的目录
这样,我们的 Kubeapps 部署就完全与我们在 VAC 上创建的自定义应用目录集成了。接下来,让我们学习如何使用 Kubeapps 从我们的自定义目录部署 MySQL 服务实例。
使用 Kubeapps 部署服务
在这一部分,我们将使用 Kubeapps 在 Kubernetes 集群上部署一个 MySQL 数据库实例。以下步骤描述了如何操作:
- 点击 图 4.26 中显示的 MySQL 瓷砖,开始在 Kubernetes 集群上进行安装。点击后我们将看到以下屏幕:

图 4.27 – Kubeapps 上 MySQL 部署说明页面
此页面显示了如何使用 MySQL Helm 图表的详细说明。我们可以使用这些说明,通过 Helm 图表命令行工具手动部署它。然而,我们将展示如何使用 Kubeapps 图形界面进行这样的配置和安装。您可以向下滚动页面,查看此 Helm 图表允许我们更改的所有配置参数的详细信息,以便定制我们的 MySQL 数据库实例。通过点击 图 4.27 中高亮显示的 DEPLOY 按钮,我们可以进入一个屏幕来更新这些属性,以满足我们的定制需求并触发安装。
- 根据 Helm 图表的类型,我们可能会看到一个类似图形界面的表单,用于修改一些最常见的部署属性。例如,图 4.28 中的 MySQL 数据库实例配置表单显示我们可以选择部署架构以及主副数据库存储卷的大小。但我们也将使用基于 YAML 的详细配置方法来展示这一点。所以,请点击以下屏幕截图中高亮显示的 YAML 标签以继续操作:

图 4.28 – Kubeapps 上 MySQL 数据库的 Helm 配置表单
- 选择目标 Kubernetes 命名空间,更新 YAML 配置,并部署服务:

图 4.29 – 使用 Kubeapps 部署 MySQL 数据库的详细 Helm 图表配置
- 
图 4.29 中的第一部分显示了我们可以选择此安装目标位置的位置。如前所述,我们可以使用 Kubeapps 在许多其他连接的 Kubernetes 集群及其命名空间中部署 Helm charts,具体取决于 Kubeapps 配置以及 Kubeapps 用户在这些集群和命名空间上的权限。在这种情况下,我们只有一个选项 —— 默认 —— 它对应的是 Kubeapps 所部署的 Kubernetes 集群。同样,如果需要,我们还可以选择或创建一个命名空间用于此部署。 
- 
图 4.29 中的第二部分显示了 Helm chart 的 YAML 配置,在这里我们可以自定义部署配置。本书中使用的部署仅更改了用户凭据,其他所有属性保持默认值,以保持配置简单。一旦完成所需的配置更改,我们可以通过 更改 选项卡验证它们,以确保部署配置中仅有预期的更改。 
- 
完成所需更改后,图 4.29 中的第三部分显示了触发部署到我们 Kubernetes 集群的按钮。 
- 触发 Helm chart 部署以更新安装状态后,我们将看到以下页面:

图 4.30 – MySQL 数据库在 Kubeapps 上的部署状态
图 4.30 包含以下详细信息:
- 
第一部分显示了用于执行部署生命周期操作的不同按钮,包括将其升级到 MySQL 的更新版本、回滚到先前版本或删除不需要的部署。点击按钮会触发它们对应的 Kubernetes 部署生命周期操作。 
- 
第二部分显示了我们的部署中健康运行的 pod 数量。 
- 
第三部分显示了在之前的安装配置步骤中提供的身份验证凭据,如 图 4.29 所示。 
- 
第四部分显示了使用已部署工具的一些有用提示和细节。例如,在我们的案例中,它显示了如何连接到此处部署的 MySQL 数据库实例。 
- 
第五部分显示了作为此安装的一部分部署的不同 Kubernetes 资源。我们可以通过点击相应的标签来查看资源的详细信息。 
- 
第六部分显示了用于部署该 MySQL 数据库实例的最终安装配置。我们可以将 YAML 配置保存到文件中,以便以后使用该配置重新部署相同类型的 MySQL 实例。 
通过这些内容,我们已经涵盖了如何使用 Kubeapps 来消费通过 VAC 创建的自定义应用程序目录,从而以自助服务的方式快速部署多个 OSS 工具的详细信息。将这样的设置提供给开发人员以部署所需的应用程序后端服务,可以提高他们的生产力,减少整体应用程序开发时间,从而提高企业的创新速度。而且,使用 Kubeapps 和 VAC 不仅是为了开发人员,也适用于 DevOps、平台和基础设施工程师,他们可以使用来自受信来源的容器镜像和 Helm 图表来部署和使用许多流行的 OSS 工具。
现在,让我们再来看看 VAC 的另一个第二天活动,目录管理员需要执行的活动——在 VAC 门户上更新目录。
更新应用程序目录
在本章前面,我们看到,作为第二天活动的一部分,如何从 VAC 门户获取供应的工件的不同报告和日志。然后我们讲解了如何使用自动化流水线或 Kubeapps 来消费 VAC 提供的 OSS 工具目录。现在,让我们来看看关于 VAC 的最后一个主要第二天活动——更新目录项目。
添加新目录项目
若要将新的 OSS 应用程序添加到企业目录中,目录管理员可以使用 VMware Cloud Services 凭证访问其企业 VAC 账户。进入 VAC 门户后,目录管理员可以在应用程序部分选择添加新应用程序按钮,如图 4.31所示:

图 4.31 – 在 VAC 门户上添加目录新项目
点击图 4.31中突出显示的按钮后添加新目录项目的步骤与我们在本章前面创建新目录时讲解的步骤相同:

图 4.32 – 在 VAC 门户上请求状态跟踪
新添加的项目将出现在我的请求下,如图 4.32所示。
做出额外的目录更改
除了在目录中添加新项目外,我们还可能需要从目录中移除不需要的工具,更新基础操作系统层,更新目标存储库详细信息,以及包括/排除 Helm 图表。如果在撰写本书时,所有这些操作只能通过联系 VAC 支持来执行,因为 VAC 门户目前未提供自助服务接口来执行这些操作。
这样,我们就涵盖了 VAC 的大部分第二天活动。让我们回顾一下,总结一下我们在本章中的学习内容。
总结
在本章中,我们看到近年来使用开源软件(OSS)工具的普及程度显著增加。如今,有几款成熟的开源软件工具,许多组织在其生产环境中自信地使用它们。此外,在 Kubernetes 上运行软件,如容器,与容器化的客户端应用程序一起运行,是为应用程序配备适当后端技术的快速方法。但是,使用公共容器注册中心(如 Docker Hub)上可用的容器镜像并不是部署这些开源软件工具的安全方式。因此,大多数组织不鼓励这种做法,并试图采用一些内部机制来生成专门用于开源软件消费的内部管理容器镜像。将这些工作放在内部进行,不仅浪费大量资源,还会使开发团队不愿意尝试各种工具,或者浪费生产力等待这些工具准备好供使用。这时,VAC 就派上了用场。我们看到 VAC 如何通过提供一种方式,帮助我们策划定制的所需开源软件工具目录,确保它们可以在内部安全地使用。
我们还学习了 VAC 的工作原理及其关键组件。接下来,我们学习了如何开始使用 VAC 来定义一个目录,并设置 Kubeapps 来消费在该定制目录下提供的 Helm 图表和容器镜像。最后,我们了解了一些关于目录消费和管理的关键日常操作。我们看到如何通过该目录提供的 Helm 图表,快速部署 MySQL 数据库实例。我们还回顾了目录管理员如何查看并获取 CVE 扫描报告、病毒扫描日志、测试日志和所有通过 VAC 服务交付的容器镜像和 Helm 图表的资产规范(物料清单)副本。
在看到如何利用丰富的开源软件工具选择,快速构建我们的应用程序并将其作为后端使用后,在下一章中,我们将学习如何使用 Tanzu 应用程序工具来构建和管理由我们应用程序暴露的 API 接口。
第五章:定义和管理业务 API
应用程序编程接口(API)与数字计算的发展一样悠久,但随着我们不断将现代生活的各个方面互联,它们比以往任何时候都更为重要。它们构成了大多数企业应用程序的骨干,并帮助推动现代世界的发展。正是这种 API 的迅猛增长,使得它们成为企业中浪费、冗余和不良实践的主要来源。
本章介绍了两款专注于解决这一问题领域的产品:Spring Cloud Gateway for Kubernetes 和 API 门户 for VMware Tanzu。和 Tanzu 组合中的每个产品一样,这些产品解决了一个具体的迫切业务需求:即开发、运维、发布、保护、监控、文档化、搜索和消费 API。
在本章中,我们将涵盖以下主题:
- 
Spring Cloud Gateway for Kubernetes 和 VMware Tanzu 的 API 门户 – 概述 
- 
为什么选择 Spring Cloud Gateway for Kubernetes? 
- 
为什么选择 VMware Tanzu 的 API 门户? 
- 
Spring Cloud Gateway for Kubernetes – 入门指南 
- 
VMware Tanzu 的 API 门户 – 入门指南 
- 
Spring Cloud Gateway for Kubernetes 和 VMware Tanzu 的 API 门户 – 真实世界的应用案例 
- 
Spring Cloud Gateway for Kubernetes 和 VMware Tanzu 的 API 门户 – 第二天操作 
Spring Cloud Gateway for Kubernetes 和 VMware Tanzu 的 API 门户 – 概述
在开始产品安装之前,让我们重新审视一下我们为何要做这个。 我喜欢用三种角色来看待 API 空间。分别是 API 开发者、API 消费者 和 API 运维人员。每个角色都有自己的一套问题。
如果我开发 API,每个项目中都有一些反复出现的问题,我必须解决:
- 
将我的 API 提供给客户 
- 
终止 TLS 
- 
处理 CORS 和浏览器限制 
- 
使我的 API 可发现 
- 
保护我的 API 端点,确保只有特定的群体才能执行某些功能 
- 
通过速率限制请求来防止滥用 
- 
重写请求路径 
- 
重写请求和响应头 
API 术语
传输层安全性(TLS)是您在银行网站 URL 旁边看到的那个安慰性锁的加密技术。它在 API 领域尤为重要,因为大多数敏感的财务数据、个人消息和健康信息都是通过 API 传输的。它尤其难以正确实现,最好通过 API 网关集中处理,而不是让每个 API 开发者自己实现。
跨域资源共享(CORS)是 API 领域工程师特别重要的一个话题。CORS 是一种机制,它允许浏览器在后台(通常称为 AJAX 调用)让一个网站向另一个网站发起请求。这样做有正当理由,但这一技术常常被不法分子利用,试图窃取凭证或敏感信息。配置网站及其支持的 API,使得只有受信任的 AJAX 调用被允许,是复杂的,并且容易出错。这也是为什么最好将这一逻辑集中在 API 网关中的原因之一。
现在,假设我需要使用 API,我将面临一组完全不同的问题:
- 
我需要的 API 是否存在? 
- 
我在哪里可以找到我需要的 API? 
- 
一旦我找到这些 API,如何访问它们? 
- 
这些 API 是否需要认证?如果需要,是什么权限范围? 
- 
在编写大量代码来消费 API 之前,如何测试这些 API? 
最后,如果我是一个托管 API 的平台运营者,我可能需要做以下事情:
- 
提供开发者自助访问 API 网关的能力,让他们可以自行配置 
- 
监控并对 API 的相关指标进行告警 
- 
提供一个具有极高吞吐量的 API 网关,以避免成为瓶颈 
- 
提供统一的实现,涵盖以下常见功能: - 
SSO(单点登录) 
- 
限流 
- 
头部操作 
- 
头部/内容丰富化 
 
- 
- 
在必要时,让开发者构建自定义过滤器并将其插入到 API 网关中 
- 
管理开发者的 API 网关生命周期和升级 
- 
在可能的情况下,根据部署到网关的内容自动生成 API 文档 
- 
提供一个单一可搜索的位置,开发者可以在这里发现并试用我所管理的所有 API 
Kubernetes 的 Spring Cloud Gateway 和 VMware Tanzu 的 API 门户 主要是为所有三类用户的需求提供简单、直接、面向企业的解决方案。
现在我们对所涵盖的话题有了一个高层次的概览,让我们将其细分为两个产品的“为什么”。我们从 Kubernetes 上的 Spring Cloud Gateway 开始。
为什么选择 Kubernetes 上的 Spring Cloud Gateway?
Kubernetes 的 Spring Cloud Gateway 基于开源的 Spring Cloud Gateway 项目:spring.io/projects/spring-cloud-gateway。Spring Cloud Gateway 是一个用于构建高性能 API 的库。你像正常的 Spring 应用一样部署它,并按照配置 Spring 应用的方式进行配置。不幸的是,开源项目并没有解决许多先前提到的问题——这些问题通常在企业中会遇到。
除了业务逻辑,开发人员还必须打包、配置并部署一个 Spring Cloud Gateway 应用,或者将其作为库捆绑到现有应用中。无论哪种方式,都会增加相当大的复杂性。除非他们使用 Spring 框架的一些高级功能,否则任何对 API 路由的更改都将涉及重建和重新部署应用。
此外,开源的 Spring Cloud Gateway 仍然没有解决操作员的一些问题。如果每个开发团队都在做自定义部署 Spring Cloud Gateway,操作员就无法推理每个网关的路由如何暴露,或者它如何发出度量指标。此外,多个团队共享一个网关也没有简单的方法,因为它们都需要在各自的时间表上配置和部署它。
这就是 Spring Cloud Gateway for Kubernetes 进入的地方。Spring Cloud Gateway for Kubernetes 是一个商业化的 Tanzu 产品,包含了开源版本的超集功能。它专门面向企业,旨在大规模管理软件。它使用 Kubernetes Operator 来管理三个主要对象:
- 
Spring Cloud Gateway 的实例 
- 
API 路由——告诉网关如何过滤传入请求并将其发送到哪里 
- 
API 路由到 Spring Cloud Gateway 的映射 
通过将这三个实体暴露为 Kubernetes 自定义资源,Spring Cloud Gateway for Kubernetes 可以抽象出以下内容:
- 
打包和部署 Spring Cloud Gateway 实例 
- 
管理 Spring 代码以配置这些实例 
- 
在不重新部署的情况下动态更新该配置 
- 
生命周期管理——跨所有 Kubernetes 集群管理所有网关实例 
- 
批量推理网关实例: - 
它们以相同的方式发出度量指标,因此我可以轻松地聚合它们的所有度量数据 
- 
它们以相同的方式暴露其 API 配置,因此我可以聚合该配置并对其进行报告,或者正如我们稍后将看到的,利用它来驱动其他有用的工具,比如 VMware Tanzu 的 API Portal 
 
- 
总结一下,Spring Cloud Gateway for Kubernetes 使用 Kubernetes Operator 和一些非常战略性的自定义资源定义,使得已经非常强大的开源 Spring Cloud Gateway 成为一个一流的 Kubernetes 产品,并真正关注企业级问题,成为一个企业级的产品。这可以通过以下图示来总结:

图 5.1 – Kubernetes 上的 Spring Cloud Gateway 一览
既然我们已经讨论了如何部署 API,现在让我们来看看如何最佳地使用它们。我们来看看VMware Tanzu 的 API Portal。
为什么选择 VMware Tanzu 的 API Portal?
就像 Spring Cloud Gateway for Kubernetes 是一个自助工具,允许开发者和运维人员统一部署、管理和保护他们的 API,API Portal for VMware Tanzu 也是一个自助工具,允许开发者和消费者发布、记录、搜索、发现并尝试这些 API。
就像 Spring Cloud Gateway for Kubernetes 使得部署多个网关以支持多个用例或环境变得简单一样,API Portal for VMware Tanzu 使得在这些相同的用例或环境中部署多个可搜索的目录变得容易。
这种面向 API 目录的分布式 Kubernetes 原生方法可以跨多个大型团队进行扩展,并支持自助服务,从而提高开发者的生产力和满意度。
此外,将 API 门户与企业 SSO 集成是一个简单直接的操作,这样合适的人就可以找到适合他们需求的 API。
既然我们知道了为什么要学习这些产品,现在就让我们开始安装并尝试它们吧。我们先来了解一些技术要求,然后就可以开始使用Spring Cloud Gateway for Kubernetes了。
技术要求
API Portal for VMware Tanzu 是本书中另一个产品的子组件,Tanzu 应用平台 (TAP)。要开始使用 VMware Tanzu 的 API Portal,首先需要安装一个 Kubernetes 集群,然后在该集群上安装 TAP。你可以自由选择任何你喜欢的 Kubernetes 发行版。如果你需要有关如何搭建集群的指导,可以参考本书末尾的附录,其中介绍了几种搭建 Kubernetes 集群的选项。
一旦你有了一个正在运行的 Kubernetes 集群,你需要稍微跳转到第八章,通过 Tanzu 应用平台提升开发者生产力,并安装Tanzu 应用平台。那一章讲解了一个更复杂的端到端用例,而这一章仅专注于API Portal 组件。
接下来,你需要一个容器注册表账户,该注册表提供一个被你的 Kubernetes 集群信任的 TLS 证书。最简单的方法是注册一个 Docker Hub 的免费开发者账户。只需访问 hub.docker.com 并注册即可。
如果你想部署真实世界的用例,你将需要一个 OIDC 提供者来支持 SSO。如果你还没有相关服务,我推荐你在 Okta 上注册一个免费的开发者账户:developer.okta.com/signup/。在本章稍后,你将看到一些关于如何设置账户以便与我们的真实世界示例应用程序一起使用的详细说明。
在撰写时,Spring Cloud Gateway for Kubernetes 安装需要 helm CLI,你可以在这里找到它:helm.sh/docs/intro/install/。
最后,我们需要 kustomize CLI,可以在这里找到:kustomize.io。如果你只想下载二进制文件,也可以访问这里:kubectl.docs.kubernetes.io/installation/kustomize/binaries。
现在,我们已经在 Kubernetes 上运行了 Tanzu 应用平台,可以安装 Spring Cloud Gateway for Kubernetes 和 API Portal for VMware Tanzu。
首先,让我们再次确认我们是否已经准备好了所有先决条件:
- 
我们需要一个最新版本的 kapp控制器——至少是 0.29.0:$ kubectl get deploy -n kapp-controller kapp-controller -ojsonpath='{.metadata.annotations.kapp-controller\.carvel\.dev/version}'v0.29.0
- 
我们还需要 secretgen控制器:$ kubectl get deploy -n secretgen-controllerNAME READY UP-TO-DATE AVAILABLE AGEsecretgen-controller 1/1 1 1 23h
- 
让我们确保安装了最新版本的 helm和kustomize:$ helm versionversion.BuildInfo{Version:"v3.5.3", GitCommit:"041ce5a2c17a58be0fcd5f5e16fb3e7e95fea622", GitTreeState:"dirty", GoVersion:"go1.15.8"}$ kustomize version{Version:kustomize/v4.0.5 GitCommit:9e8e7a7fe99ec9fbf801463e8607928322fc5245 BuildDate:2021-03-08T20:53:03Z GoOs:darwin GoArch:amd64}
- 
最后,我们应该测试是否有可写的 Docker 仓库和工作中的 Docker CLI。以下是一种简单的方法来测试一切是否已正确设置。我将使用 dockerhub作为注册表,但你也可以使用你选择的任何解决方案:$ export DOCKER_USER=<your dockerhub username>$ docker pull hello-world$ docker tag hello-world docker.io/$DOCKER_USER/hello-world$ docker push docker.io/$DOCKER_USER/hello-world
如果一切没有错误,恭喜!你应该已经具备了所有技术要求,可以继续进入下一部分,安装 Spring Cloud Gateway for Kubernetes 和 API Portal for VMware Tanzu!
Spring Cloud Gateway for Kubernetes – 入门指南
让我们从安装 Spring Cloud Gateway for Kubernetes 开始。这个产品有两个独立的部分:Kubernetes 操作员和部署的网关。
Kubernetes Operator 与 Kubernetes API 协同工作,处理三个 自定义 资源定义:
- 
SpringCloudGateway(缩写:scg):这是一个(可选)高可用实例的 Spring Cloud Gateway——为开发人员集中打包、部署并进行生命周期管理。 
- 
SpringCloudGatewayRouteConfig(缩写:scgrc):这是为 Spring Cloud Gateway 实例提供的一组指令,涉及接受哪些主机/路径上的请求、如何过滤请求以及最终将其代理到哪个后端 Kubernetes 服务。 
- 
SpringCloudGatewayMapping(缩写:scgm):这告诉 Kubernetes 操作员哪些 SpringCloudGatewayRouteConfig 与哪些 SpringCloudGateways 关联。操作员会自动重新配置 SpringCloudGateways,使其与 SpringCloudGatewayRouteConfig 的内容相匹配所需的 Spring 配置属性。 
部署的 Spring Cloud Gateway 实例是产品的另一部分。Kubernetes 操作员启动多个这些网关,能够通过 Kubernetes 服务或 Ingress 接受传入的流量。然后,它会查找与特定 Spring Cloud Gateway 实例映射的 SpringCloudGatewayRouteConfig,并动态配置这些路由。
部署的 Spring Cloud Gateway 实例负责处理开发者 API 的 API 流量。Kubernetes 操作符是开发者自助服务配置 Spring Cloud Gateway 实例的方式,而(人工的,非 Kubernetes 的)操作员则可以自动监控并管理这些实例,且具备规模化能力。
安装过程非常简单,只需运行几个脚本将所需的容器镜像迁移到你的容器仓库,然后使用Helm将必要的 Kubernetes 工件部署到你的集群中。官方安装说明可以在此找到:docs.vmware.com/en/VMware-Spring-Cloud-Gateway-for-Kubernetes/1.0/scg-k8s/GUID-installation.html。
换句话说,安装步骤如下:
- 
从这个链接下载二进制文件: network.tanzu.vmware.com/products/spring-cloud-gateway-for-kubernetes。
- 
解压缩它。 
- 
运行脚本,将本地 .tgz镜像层推送到你的容器仓库。
- 
运行脚本,通过helm将一切部署到你的 Kubernetes 集群。 
首先,让我们迁移我们的镜像。Kubernetes 操作符和已部署的 Spring Cloud Gateway 实例需要存在于一个外部镜像仓库中,该仓库必须能从 Kubernetes 集群访问。在此时,Spring Cloud Gateway for Kubernetes 是通过下载交付的,所有镜像文件都包含在下载的文件中。为了将这些文件放到 Kubernetes 可以访问的地方,我们需要将它们加载到本地 Docker 环境中并推送到远程仓库。如果你感兴趣的话,简单的 Docker 命令位于scripts/relocate-images.sh文件中。否则,只需导航到scripts目录并调用该脚本即可。我将分享我运行时的简短输出。docker.io/rhardt是我的仓库。如果你设置了 Docker Hub 账户,你的仓库会是docker.io/<your-username>:
bash-5.0$ ./relocate-images.sh docker.io/rhardt
Relocating image
================
image name: gateway
version: 1.0.8
source repository: registry.tanzu.vmware.com/spring-cloud-gateway-for-kubernetes/gateway:1.0.8
destination repository: docker.io/rhardt/gateway:1.0.8
Loaded image: registry.tanzu.vmware.com/spring-cloud-gateway-for-kubernetes/gateway:1.0.8
The push refers to repository [docker.io/rhardt/gateway]
1dc94a70dbaa: Layer already exists
… (more layers)
824bf068fd3d: Layer already exists
1.0.8: digest: sha256:8c1deade58dddad7ef1ca6928cbdd76e401bc0afaf7c44378d296bf3c7474838 size: 4500
Relocating image
================
image name: scg-operator
version: 1.0.8
source repository: registry.tanzu.vmware.com/spring-cloud-gateway-for-kubernetes/scg-operator:1.0.8
destination repository: docker.io/rhardt/scg-operator:1.0.8
Loaded image: registry.tanzu.vmware.com/spring-cloud-gateway-for-kubernetes/scg-operator:1.0.8
The push refers to repository [docker.io/rhardt/scg-operator]
1dc94a70dbaa: Layer already exists
… (more layers)
824bf068fd3d: Layer already exists
1.0.8: digest: sha256:da9f2677e437ccd8d793427e6cafd9f4bb6287ecffdc40773cf3b1f518f075fb size: 4498
所以,现在,我们已经将容器镜像放在了 Kubernetes 可以找到的地方。relocate-images.sh脚本的另一项功能是创建一个名为scg-image-values.yaml的文件,Helm 在部署到 Kubernetes 时会使用该文件。
我们将要运行的第二个脚本是install-spring-cloud-gateway.sh,同样位于scripts目录中。我建议你浏览一下这个脚本,它是一个全面的 helm 部署的优秀示例,包含了更新现有安装、超时设置、失败时的错误诊断以及检查部署是否成功的具体说明:
bash-5.0$ ./install-spring-cloud-gateway.sh
chart tarball: spring-cloud-gateway-1.0.8.tgz
chart name: spring-cloud-gateway
Waiting up to 2m for helm installation to complete
Release "spring-cloud-gateway" does not exist. Installing it now.
NAME: spring-cloud-gateway
LAST DEPLOYED: Mon Feb 21 18:25:13 2022
NAMESPACE: spring-cloud-gateway
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
This chart contains the Kubernetes operator for Spring Cloud Gateway.
Install the chart spring-cloud-gateway-crds before installing this chart
Checking Operator pod state
deployment "scg-operator" successfully rolled out
 Operator pods are running
Checking custom resource definitions
 springcloudgatewaymappings.tanzu.vmware.com successfully installed
 springcloudgatewayrouteconfigs.tanzu.vmware.com successfully installed
 springcloudgateways.tanzu.vmware.com successfully installed
Successfully installed Spring Cloud Gateway operator
bash-5.0$
现在我们已经安装了 Spring Cloud Gateway for Kubernetes,让我们继续进行 VMware Tanzu 的 API 门户操作。
VMware Tanzu 的 API 门户 – 入门
与 Spring Cloud Gateway for Kubernetes 不同,VMware Tanzu 的 API 门户是 Tanzu 应用平台 的一部分,你之前在 技术要求 部分已经安装了它。你可以通过访问 Tanzu 应用程序 GUI 来验证 API 门户是否已安装并运行,地址可以是本地端口转发地址,如 http://localhost:8081,也可以是你的 ingress 域名,如 http://tap-gui.example.com。这取决于你选择的 Kubernetes 集群和 TAP 安装方式。一旦访问到 Tanzu 应用平台 GUI,点击左侧的 APIs 菜单项,你应该看到如下界面:

图 5.2 – API 门户
VMware Tanzu 的 Spring Cloud Gateway 和 API 门户 – 真实世界的使用案例
现在,我们将实现一个使用 VMware Tanzu 的 API 门户 和 Spring Cloud Gateway for Kubernetes 的真实世界案例。这将展示这些产品如何自然协同工作,以及作为开发者、消费者或 API 操作员,如何通过结合使用它们获得显著价值。
以下是我们接下来的步骤概览:
- 
我们将下载一个以 API 为驱动的应用,名为 Animal Rescue,其模拟了一个真实的动物领养网站,且支持 SSO。 
- 
我们将设置 Okta 环境,使我们的应用能够使用 Okta 进行 SSO。然后,我们将 Okta 参数插入到 Animal Rescue 应用中。 
- 
我们将把 Animal Rescue 应用部署到我们的 Kubernetes 集群,这将创建必要的 Spring Cloud Gateway 工件。通过这样做,我们将能够浏览和互动使用 Animal Rescue Web 应用。 
- 
我们将修改 API 门户的安装,使其连接到 Spring Cloud Gateway Kubernetes Operator,该 Operator 现在已经知道所有 Animal Rescue 应用的 API 路由,并将其作为 OpenAPIv3 暴露。 
- 
我们将通过端口转发到我们的 API 门户,以便探索和尝试 Animal Rescue 的 API。 
现在你已经知道我们要实现的目标,接下来是步骤。
步骤 1 – 克隆本书的 Git 仓库并导航到 Animal Rescue 应用
使用 Git CLI 克隆本书的代码库,然后导航到 animal-rescue 应用,如下代码片段所示:
bash-3.2$ git clone https://github.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu
Cloning into 'DevSecOps-in-Practice-with-VMware-Tanzu'...
remote: Enumerating objects: 499, done.
remote: Counting objects: 100% (499/499), done.
remote: Compressing objects: 100% (351/351), done.
remote: Total 499 (delta 95), reused 473 (delta 75), pack-reused 0
Receiving objects: 100% (499/499), 9.80 MiB | 10.39 MiB/s, done.
Resolving deltas: 100% (95/95), done.
bash-3.2$ cd DevSecOps-in-Practice-with-VMware-Tanzu/chapter-05/animal-rescue/
bash-3.2$
步骤 2 – 配置你的 Okta 开发者账户,以为 Animal Rescue 提供 SSO
这些步骤稍显复杂,因此我建议直接参考 VMware 文档中的说明:docs.vmware.com/en/VMware-Spring-Cloud-Gateway-for-Kubernetes/1.0/scg-k8s/GUID-sso-setup-guide.html。
完成设置后,我们需要再执行一个额外的步骤,以使此示例生效。我们需要为“gateway”应用添加两个额外的登录重定向 URI。此截图展示了我的 Okta 设置:

图 5.3 – Okta 登录重定向 URI 的截图
我们将会将动物拯救应用程序端口转发至 http://localhost:8084,API 网关端口转发至 http://localhost:8085;我们希望两者都能通过 Okta 进行身份验证。
在此练习结束时,您需要从您的 Okta 环境中获取三个信息:issuer-id、client-id和client-secret。
VMware 文档将指导您如何使用该信息配置动物拯救应用程序。我也会在此处包含它。这些步骤是相对于我们在前一节从 GitHub 克隆的 animal-rescue 应用程序:
- 
创建 backend/secrets/sso-credentials.txt,内容如下:jwk-set-uri=<issuer uri>/v1/keys
- 
创建 gateway/sso-secret-for-gateway/secrets/test-sso-credentials.txt,内容如下:scope=openid,profile,email,groups,animals.adoptclient-id=<client id>client-secret=<client id>issuer-uri=<issuer uri>
文档中提到的一些额外步骤,如编辑 roles-attribute-name 或配置路由安全性,已经在您下载的应用程序版本中完成。
第三步 – 部署动物拯救应用程序
从 animal-rescue 目录开始 – 也就是您克隆的应用程序的主目录 (DevSecOps-in-Practice-with-VMware-Tanzu/chapter-05/animal-rescue) – 运行以下命令:
bash-5.0$ kustomize build . | kubectl apply -f -
namespace/animal-rescue created
secret/animal-rescue-sso created
secret/sso-credentials created
service/animal-rescue-backend created
service/animal-rescue-frontend created
deployment.apps/animal-rescue-backend created
deployment.apps/animal-rescue-frontend created
ingress.networking.k8s.io/gateway-demo created
springcloudgateway.tanzu.vmware.com/gateway-demo created
springcloudgatewaymapping.tanzu.vmware.com/animal-rescue-backend-routes created
springcloudgatewaymapping.tanzu.vmware.com/animal-rescue-frontend-routes created
springcloudgatewayrouteconfig.tanzu.vmware.com/animal-rescue-backend-route-config created
springcloudgatewayrouteconfig.tanzu.vmware.com/animal-rescue-frontend-route-config created
此时,您可以观察动物拯救命名空间中所有 Pod 何时启动完成:
bash-5.0$ kubectl get pods -n animal-rescue -w
NAME                                     READY   STATUS    RESTARTS   AGE
animal-rescue-backend-546fc6c569-kgj2s   1/1     Running   0          27m
animal-rescue-frontend-b74f54847-rq284   1/1     Running   0          27m
gateway-demo-0                    1/1     Running   0          23m
gateway-demo-1                    1/1     Running   0          24m
一旦 Pod 启动完成,我们可以将端口转发到 localhost:8084。
此时,我强烈建议在无痕浏览器窗口中操作,以防止应用程序对您的 Okta 开发人员帐户产生混淆。
打开您的浏览器访问 http://localhost:8084;您应该看到动物拯救 Web 应用程序,其中包含可爱的动物供您领养,并在右上角有一个 SSO 登录按钮。如果您正确配置了一切,点击该按钮将带您进入 Okta 登录页面,然后登录后返回运行中的应用程序。这就是我在浏览器中看到的样子。请注意右上角显示我的 Okta 用户名的文本:

图 5.4 – 动物拯救截图
到目前为止,一切顺利!现在,让我们将事情提升到下一个级别,并将此 API 集成到VMware Tanzu 的 API 门户中。
第四步 – (可选)查看动物拯救 API 的 OpenAPI 3.0 规范
在我看来,这是这对产品中最引人注目的特性之一。
在实践中,开发人员负责手动将其 API 规范保持在某种文档格式中,通常是 OpenAPI 3.x 或 Swagger。对于开发人员来说,这是件繁琐的事情,在激烈的战斗中,API 规范往往是第一个不再维护的东西。这意味着新的消费者将根据不正确、过时的 API 文档来构建他们的客户端。
一旦您部署了动物救援应用程序,Spring Cloud Gateway Kubernetes Operator 将管理所有路由 - 也就是说,Kubernetes Operator 管理 Spring Cloud Gateway 实例的配置,以便每个 API 调用都正确路由到正确的后端服务,以及任何过滤器、安全性和元数据。这足以自动生成 API 的 OpenAPI 3.0 规范。
很难低估这是一个突破。控制 API 运行时配置的实际 Kubernetes 对象用于自动生成始终准确、始终最新的 OpenAPI 3.0 文档。这减轻了 API 开发者的文档创建和维护负担,以及 API 消费者在处理过时文档时的负担。
让我们快速查看一下我们的动物救援 API 自动生成的文档。通过 Spring Cloud Gateway Operator 在所有网关上部署的每个 API 的 OpenAPI 3.0 文档可通过 Web 端点访问。该 Web 端点通过 ClusterIP 服务公开。
在生产环境中,您可能希望在该服务前面放置一个 TLS 安全的入口,但出于演示目的,让我们快速设置一个端口转发:
bash-5.0$ kubectl get svc -n spring-cloud-gateway
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
scg-operator   ClusterIP   10.98.103.232   <none>        80/TCP    40h
bash-5.0$ kubectl port-forward -n spring-cloud-gateway svc/scg-operator 8083:80
Forwarding from 127.0.0.1:8083 -> 8080
Forwarding from [::1]:8083 -> 8080
首先,我们确定spring-cloud-gateway服务在端口80上运行,因此我们将本地工作站的端口8083转发到该服务的端口80。现在,我们可以将 Web 浏览器指向http://localhost:8083,神奇的事情发生了!您将看到动物救援API 的 OpenAPI 3.0.1 表示,如下面的屏幕截图所示:

图 5.5 - 动物救援自动生成的 OpenAPI 3.0.1 规范
这是一个 100%有效和准确的 OpenAPI 3.0 文档,因此可以使用任何可以从该格式生成客户端或服务器存根的工具。此外,Kubernetes 的SpringCloudGatewayRouteConfig对象包含以下字段:
- 
人类可读的描述 
- 
所有可能的响应代码及其含义 
- 
需要任何形式的身份验证 
换句话说,驱动实际运行时行为的现实世界 Kubernetes 对象也驱动文档,因此它始终准确且最新。
第 5 步 - (可选)将 API Portal for VMware Tanzu 连接到 Spring Cloud Gateway for Kubernetes OpenAPI 端点
正如我们之前演示的,API Portal for VMware Tanzu完全由 OpenAPI 3 或 Swagger 文档驱动。因此,我们设置 API 门户以消费Spring Cloud Gateway for Kubernetes生成的 OpenAPI 3 文档是理所当然的。如果您在上一步骤中设置了端口转发,您可以退出它。由于 API 门户和 Spring Cloud Gateway 位于同一 Kubernetes 集群上,它们可以通过 ClusterIP 服务进行通信。
我们之前安装了tanzu package命令。现在,让我们编写一个简单的配置文件,用于覆盖 API 门户将搜索 OpenAPI 3 文档的位置,并更新软件包安装。
首先,创建一个名为api-portal-values.yaml的文件,其内容如下:
apiPortalServer:
   sourceUrls:  https://petstore.swagger.io/v2/swagger.json,https://petstore3.swagger.io/api/v3/openapi.json,http://scg-operator.spring-cloud-gateway.svc.cluster.local/openapi
正如您所见,我们正在将 Spring Cloud Gateway Operator 的 ClusterIP 服务附加到 API 门户将搜索 API 文档的位置列表中。
现在,我们可以使用tanzu package命令更新安装。在幕后,API 门户将使用新配置重新部署。这种部署软件的方法消除了配置漂移,因为对部署的任何手动配置更改都将被kapp控制器覆盖:
bash-5.0$ tanzu package installed update api-portal -n tap-install -f api-portal-values.yaml
| Updating installed package 'api-portal'
| Getting package install for 'api-portal'
| Getting package metadata for 'api-portal.tanzu.vmware.com'
| Creating secret 'api-portal-tap-install-values'
| Updating package install for 'api-portal'
/ Waiting for 'PackageInstall' reconciliation for 'api-portal'
/ 'PackageInstall' resource install status: Reconciling
Updated installed package 'api-portal' in namespace 'tap-install'
bash-5.0$
现在,让我们重新配置我们的端口转发到我们的 API 门户:
bash-5.0$ kubectl get svc -n api-portal
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
api-portal-server   ClusterIP   10.103.142.154   <none>        8080/TCP   40h
bash-5.0$ kubectl port-forward -n api-portal svc/api-portal-server 8085:8080
Forwarding from 127.0.0.1:8085 -> 8080
并且在打开 Web 浏览器到http://localhost:8085时,我们应该在列表中看到我们的Animal Rescue API,如下图所示:

图 5.6 – 带有 Animal Rescue API 的 API 门户
在Animal Rescue图块中,点击VIEW APIS。然后,在结果屏幕上,依次点击/api/animals,然后尝试执行,最后执行。如果一切配置正确,您应该在服务器响应部分看到一些 JSON 格式的动物数据,如下图所示:

图 5.7 – 从浏览器尝试 API
只要清楚,您可以直接从 API 门户界面尝试API。
在安装了这两个产品、将它们连接在一起并实现复杂的现实世界应用程序的令人兴奋体验之后,我们必须面对不可避免的事实。在部署一个工作的软件片段的乐趣已经消失之后,维护和支持的持续任务将继续存在。我们将在下一节讨论这一点。
使用 Tanzu Application Accelerator 的常见第二天操作
恭喜!如果您已经走到这一步,您已经建立了一个可以在企业软件开发操作中释放令人难以置信的价值的 API 发布和消费模型。
企业中通常的情况是,困难并不在于安装和配置某些东西,而是在于随着时间的推移对其进行操作。让我们看看一些这样的第二天操作。
更新 API 的路由定义
假设我们发现了一个 API 路由描述中的拼写错误。我们希望能够实时更新该路由,并且让它自动传播到 API 门户,而无需额外配置。我们来做一下。导航到你从 GitHub 克隆的 animal-rescue 应用,并在编辑器中打开 ./backend/k8s/animal-rescue-backend-route-config.yaml 文件。在第 17 行,你会看到一个以 Retrieve all the anmals 开头的描述。将其修改为 Retrieve all the animals。如果你想更确定一些,可以插入一些额外的文本。以下是我在编辑器中的样子。我特别想确认自己看到的是修改后的内容:

图 5.8 – 编辑 API 路由的描述
现在,我们只需要更新 Kubernetes 中的 Spring Cloud Gateway 路由配置,文档应该会自动更新。别忘了命名空间,原始安装时是通过 kustomize 添加的:
$ kubectl apply -f ./animal-rescue-backend-route-config.yaml -n animal-rescue
springcloudgatewayrouteconfig.tanzu.vmware.com/animal-rescue-backend-route-config configured
现在,如果你仍然保持着到 api-portal 的端口转发,你可以访问 http://localhost:8085,点击进入动物救援 /api/animals 路由,并实时查看你的更新!

图 5.9 – 查看 API 规范的实时更新
到目前为止,我们已经深入探讨了许多day-0和day-1任务,比如部署和使用 API。但任何在企业软件领域工作过的人都知道,我们的大多数时间和精力都花在day-2任务上:更新、监控、测量和改进软件。接下来我们简要介绍一些这些 day-2 任务。
更新 API Portal 包
tanzu package 命令与 kapp 控制器结合,给你带来了强大的能力,能够生命周期管理你部署的软件。在 API Portal 的情况下,你可以获取当前部署的版本,并查看哪些版本是可用的。然后,只需执行 tanzu package installed update -n tap-install api-portal -v <new version> 命令来更新它:
bash-5.0$ tanzu package installed list -n tap-install
| Retrieving installed packages...
  NAME        PACKAGE-NAME                 PACKAGE-VERSION  STATUS
  api-portal  api-portal.tanzu.vmware.com  1.0.8            Reconcile succeeded
我们当前安装的是 1.0.8 版本:
bash-5.0$ tanzu package available list -n tap-install api-portal.tanzu.vmware.com
/ Retrieving package versions for api-portal.tanzu.vmware.com...
  NAME                         VERSION  RELEASED-AT
  api-portal.tanzu.vmware.com  1.0.8    2021-12-15 19:00:00 -0500 EST
  api-portal.tanzu.vmware.com  1.0.9    2022-01-02 19:00:00 -0500 EST
看起来版本 1.0.9 最近已经发布:
bash-5.0$ tanzu package installed update api-portal -n tap-install -v 1.0.9
| Updating installed package 'api-portal'
| Getting package install for 'api-portal'
| Getting package metadata for 'api-portal.tanzu.vmware.com'
| Updating package install for 'api-portal'
/ Waiting for 'PackageInstall' reconciliation for 'api-portal'
Updated installed package 'api-portal' in namespace 'tap-install'
只需一个简单命令,我们的 api-portal 包就会自动更新到最新版本。
总结
API 无处不在。随着 OpenAPI 3 和 REST 成为开发者普遍接受的标准,企业开发者的工作中,创建、发布、发现和使用 API 已经占据了很大一部分。
在一个有大量开发者分布在不同团队的环境中,这不可避免地导致浪费:大量的时间、精力和金钱浪费。
开发者浪费精力逆向工程文档不足的 API。他们浪费时间找寻正确的 API。他们在弄清楚如何使 API 被广泛使用时消耗了不必要的资源。
一旦 API 部署完成,就会浪费大量时间和精力来确保 API 的安全性,并确保它能够在大型组织中共享,更不用说确保这些 API 得到维护并保持更新。
架构师可能会花费不必要的时间来构建一个用于发现 API 的中央集散地以及一个用于部署 API 的中央网关。
最终,操作员还需要负责监控和衡量跨多个平台的许多多语言 API。
使用你在本章中已经熟悉的工具,我希望你能大幅减少 API 的浪费,使你的团队、你的开发组织和你的公司变得极其成功、高效,并且以 API 为驱动。
在下一章中,我们将把重点从构建软件转移到运行软件。我们将通过深入探讨使用VMware Harbor Registry托管和维护 OCI 容器镜像及 Helm Charts 来开启我们的新重点领域。
第二部分 – 在 Tanzu 上运行云原生应用
本部分内容重点介绍了帮助在 Kubernetes 上运行现代云原生应用的工具和技术,涵盖了多云和多集群部署。
本书的这一部分包含以下章节:
- 
第六章,使用 Harbor 管理容器镜像 
- 
第七章,使用 Tanzu Kubernetes Grid 跨云编排容器 
- 
第八章,使用 Tanzu 应用平台提升开发者生产力 
第六章:使用 Harbor 管理容器镜像
在前几章中,我们介绍了 Tanzu 产品组合中的工具,帮助我们构建云原生应用程序。我们从回顾构建、运行和管理现代云原生应用程序及其平台的发展历程开始。接着,我们看到如何使用模板开始应用开发,如何构建安全的容器镜像,如何为应用程序快速配置后端服务,以及如何使用各种 Tanzu 产品管理 API。在了解了如何构建云原生应用程序后,本章将深入探讨运行它们的各个方面。
正如本章标题所示,我们将学习如何管理我们的容器镜像,并通过 Harbor 安全地使其可访问,以便在 Kubernetes 上部署我们的应用程序。Harbor 是一个开源容器注册表项目,隶属于云原生计算基金会(CNCF)。尽管 Harbor 完全是开源工具,我们仍将其纳入本书,主要有三个原因。首先,Harbor 是由 VMware 孵化的,并于 2018 年中期捐赠给 CNCF。自那时起,VMware 也是该项目的主要贡献者之一,并积极投资于 Harbor。其次,Harbor 也被 CNCF 认定为一个毕业项目,这是 CNCF 生态系统中被标记为非常流行、成熟且稳定的项目状态。最后,将 Harbor 纳入本书的主要原因是,作为该项目的重要利益相关者,VMware 也为 Harbor 提供商业企业支持,并将其作为 Tanzu 产品组合的一部分。
附注
从此章开始,为了简洁起见,我们将把容器镜像简称为镜像。
在本章中,我们将详细介绍 Harbor,涵盖以下主题:
- 
为什么选择 Harbor?:Harbor 的功能和特性概述 
- 
探索 Harbor:对 Harbor 架构的详细概述 
- 
开始使用 Harbor:学习如何安装和配置 Harbor 
- 
Harbor 常见的二次操作:学习如何执行与 Harbor 配置和使用相关的各种活动 
让我们从了解 Harbor 的背景开始。
为什么选择 Harbor?
在本节中,我们将回顾使用 Harbor 作为容器注册表的各种特性、功能以及使用 Harbor 的理由。这些理由将通过以下内容进行解释:Harbor 的安全性、控制能力和可扩展性特性。
使用 Harbor 保障安全
Harbor 具备一些强大的安全性特点,使其成为容器注册表的优秀选择,它将安全性从应用程序生产过程中的反应性措施转变为主动性措施。让我们来回顾一下这些安全性优势:
- 
Harbor 具备扫描每个镜像是否存在关键漏洞暴露(CVEs)的功能,这些漏洞可能源自镜像中使用的某些软件库和操作系统版本。此类扫描提供了详细的 CVE 报告,包括发现的 CVE 及其严重性等级、漏洞的详细信息以及该 CVE 已被修复的软版本。我们可以通过 web 门户或使用 Harbor 提供的 REST API 获取这些扫描结果。Harbor 还允许您使用外部镜像扫描工具,替代或附加默认工具。通过这种方式,您可以在应用部署过程中提前了解镜像中可能存在的安全漏洞,从而提供预防性的安全防护。 
- 
根据应用环境和偏好的容忍度,Harbor 还提供了一种方法,防止客户端拉取那些已扫描 CVE 且包含高于允许严重性等级的 CVE 的镜像。例如,我们可以在 Harbor 中配置一个策略,要求任何在名为 Production Repo的项目中发现的 CVE 严重性高于中等的镜像,无法被拉取来部署容器。此功能提供了所需的保护措施,防止在前门就发生损害,确保被标记的镜像永远无法被拉取来运行工作负载,避免不法分子稍后利用它们。
- 
Harbor 还支持与 Notary( github.com/notaryproject/notary)的集成,Notary 是一个开源项目,可以为镜像进行数字签名以保证其真实性。您可以使用这种镜像签名工具创建一个容器部署管道,从而仅允许签名且经过授权的镜像在生产环境中进行部署。这样的安排可以大大增强您的安全防护,因为在您的环境中无法部署任何未验证、未扫描或潜在危险的镜像。
- 
Harbor 拥有强大的基于角色的访问控制(RBAC)功能。它允许您在项目级别和系统级别配置用户,提供在多租户环境中所需的控制和灵活性。 
此外,Harbor 还允许您将用户帐户与系统帐户(在 Harbor 中称为机器人帐户)分开,后者可以用于持续集成(CI)和持续部署(CD)自动化流程。我们可以为这些机器人帐户指定所需的权限,使其仅能通过自动化流程执行允许的操作。
- 
我们可以创建一个中心-辐射架构,在这种架构中,Harbor 作为中心节点,负责将镜像从外部或其他内部 Harbor 容器注册表之间进行复制。这样的部署示例如 图 6.1 所示。通过这种安排,组织可以防止内部用户从未经授权的来源拉取任意和不安全的镜像。与此同时,它允许他们只从内部部署的 Harbor 拉取镜像,而这些镜像已经从外部镜像库复制了授权的镜像。这个功能提供了所需的控制机制,以确保安全,同时不影响开发人员的自由和生产力。 
- 
正如我们在本章稍后将看到的,Harbor 拥有多个组件,并支持许多外部集成,以实现各种功能。为了确保这些数据传输的安全性,所有这些组件间的通信通道都使用 传输层安全性(TLS)加密。 
在回顾了 Harbor 在安全方面的关键特性之后,我们来看看从运营控制的角度来看,它的优势是什么。
使用 Harbor 进行运营控制
市场上有多个流行的容器注册表,作为在线 软件即服务(SaaS)提供,包括 Docker Hub、Google 容器注册表(GCR)以及许多其他云服务提供商的产品。Harbor 与这些在线选项的不同之处在于,它可以部署在隔离的环境中。当需要保持应用镜像私密且本地存储时,我们需要像 Harbor 这样的解决方案。通过此类本地部署,如前一节关于安全性的讨论,Harbor 提供了一个控制机制,确保仅暴露从外部源复制到 Harbor 中的授权镜像供内部使用。这样,运营人员可以防止内部镜像用户从未经授权的源下载可能存在漏洞的镜像。
此外,Harbor 还是一个由社区驱动的开源项目,处于 CNCF 的 毕业级成熟度阶段,类似于 Kubernetes。CNCF 只有在开源项目有显著的社区贡献和采用时才会将其毕业。由于 VMware 是该项目的主要贡献者之一,它也为 Harbor 提供商业支持。
除了作为一个成熟的 CNCF 项目并且得到商业支持的开源项目外,Harbor 还具有一系列的多租户功能。我们将在本章稍后讨论其中的一些功能。但从高层来看,Harbor 管理员可以为不同团队配置存储配额,选择不同的镜像漏洞扫描器、镜像保留期限、为触发 CD 流水线配置团队级别的 Webhook、CVE 白名单等其他选项。为使用同一 Harbor 部署的不同团队设置这些独立的配置,为 Harbor 管理员提供所需的操作控制,并为用户组提供所需的灵活性。
最后,在操作控制领域,Harbor 提供了各种通用的管理配置,适用于部署和所有用户组。这些配置包括以下管理控制:
- 
使用垃圾回收程序清理所有未标记的工件,该程序可以按需触发或定期调度。 
- 
管理用户组及其权限。 
- 
配置外部或内部认证提供者,包括轻量级目录访问协议(LDAP)和开放 ID 连接(OIDC)系统。 
- 
配置自定义开放容器倡议(OCI)工件,将除镜像外的二进制对象存储在 Harbor 中。 
- 
配置镜像代理缓存,以允许外部托管的镜像以离线模式存储。 
- 
访问关键性能指标,检查 Harbor 的健康状况。 
- 
启用分布式追踪遥测数据,以增强 Harbor 的故障排除能力。 
提示
开放容器倡议(OCI)是一个开放的治理结构,旨在围绕容器格式和运行时创建开放的行业标准。来源:opencontainers.org/。
在了解了 Harbor 如何帮助获得对各种配置类型的控制之后,让我们来看一下使用 Harbor 的另一个原因——它的可扩展性。
使用 Harbor 以利用其可扩展性。
Harbor 是一个由几个不同的微服务组成的解决方案,这些微服务协同工作,旨在作为一个专用的容器注册表。它有多个组件,可以用其他提供类似功能的选项替换。此外,我们可以扩展一些功能,为最终用户提供更多选择。可扩展性领域包括与外部容器注册表、CVE 扫描器、认证提供者和可以托管在 Harbor 上的 OCI 合规对象的集成。以下部分将详细描述这些内容。
通过复制扩展镜像源和目标。
Harbor 允许你创建镜像复制规则,通过外部镜像仓库扩展镜像库。这样,Harbor 客户端可以从外部仓库(如 Docker Hub)拉取所需的镜像,而无需直接访问 Docker Hub。此类扩展对于空中隔离部署(即不希望从安全角度访问公开互联网和公开仓库下载镜像)非常有帮助。此外,Harbor 允许你为推送和拉取操作创建复制规则,实现双向的工件流动。图 6.1 展示了 中央 Harbor 仓库 如何从 Docker Hub 和 GCR 拉取(复制)镜像,然后将这些镜像推送到 远程 Harbor 仓库,以便更好地网络共址在附近的 Kubernetes 集群中。图中的箭头指示了镜像的流动方向:

图 6.1 – Harbor 部署拓扑图,以利用复制功能
针对不同来源和目标的镜像仓库位置扩展,对于从安全性和治理角度控制对复制镜像的访问非常有用。此外,它还可以帮助减少网络延迟和带宽需求。
除了使用 Harbor 进行复制外,我们还可以将 Harbor 配置为代理来缓存外部位置的镜像。此缓存安排有助于减少传输频繁使用镜像时的网络延迟,并节省所需的互联网流量带宽。此外,使用 Harbor 进行缓存时,可能只会缓存在给定时间段内被使用的镜像。如果镜像没有被主动拉取,它会被移除。然而,这种代理配置相比仅复制的镜像,更加自由地访问任何可用的镜像。复制和缓存各自有其使用场景、优点和缺点。
添加或更换漏洞扫描器
默认情况下,Harbor 配备了 Trivy(github.com/aquasecurity/trivy)用于对镜像进行 CVE 扫描。然而,如果你有自己的 Trivy 实例,也可以将其集成到 Harbor 中。你还可以在 Harbor 中集成其他 CVE 扫描器,替代或与 Trivy 一起使用。此扩展功能允许不同的团队使用 Harbor 支持的扫描器列表中他们偏好的扫描器。在当前场景下,Harbor 除了 Trivy 外,还支持 Clair、Anchore、Aqua、DoSec、Sysdig Secure 和 Tensor Security。
扩展身份验证提供程序
Harbor 提供数据库级别的身份验证,用户帐户可以直接在 Harbor 中配置,作为默认和原始方法。然而,管理员可以配置 Harbor 使用 LDAP/Active Directory 服务或 OIDC 提供者。在这种情况下,这些外部身份验证提供者将用于创建和管理用户帐户。Harbor 将把身份验证请求重定向到这些外部身份验证提供者,并根据身份验证提供者提供的身份信息,Harbor 授予用户所需的访问权限。
扩展用户定义的 OCI 制品托管
除了镜像外,Harbor 还可以存储 Helm 图表和其他用户定义的 OCI 制品。这些制品可以是Kubeflow 数据模型,用于 Kubernetes 上的机器学习。对于这种扩展,对象必须遵循 Harbor 特定的配置,并使用清单文件。这些用户定义扩展的使用场景较少,但也是可能的。
到目前为止,在本章中,我们已经看到了一些不同的安全、运营和可扩展性的原因,解释了使用 Harbor 作为容器注册表的原因。它是开源的,但由 VMware 支持,是一个轻量级、灵活、专为容器注册设计的注册表,还通过镜像扫描、复制和签名功能帮助增强整体容器安全性。在本章的下一节中,我们将讨论 Harbor 的功能部分,了解它的内部工作原理。
开箱 Harbor
在看到一些关于使用 Harbor 作为容器制品库的商业、安全、运营控制和可扩展性等方面的好理由后,让我们了解一下 Harbor 的组成部分。在本节中,我们将学习 Harbor 的内部组件和功能。作为一个服务于云原生社区的容器注册表,Harbor 本身是一个由多个较小的微服务组成的云原生应用,这些微服务执行不同的任务。让我们通过提供 Harbor 的架构概述来理解它们如何协同工作。
架构概述
Harbor 有多个内部和外部组件。如 图 6.2 所示,我们可以将这些组件分为以下几类:
- 
消费者:由所有客户端和客户端接口组成 
- 
基础服务:由 Harbor 项目中的所有核心功能和其他对整体包至关重要的第三方关键项目组成 
- 
数据访问层:由所有不同的数据存储组成 
- 
身份提供者:由所有外部身份验证提供者扩展组成 
- 
扫描提供者:由所有外部镜像 CVE 扫描扩展组成 
- 
复制的注册表提供者:由所有外部镜像复制扩展组成: 

图 6.2 – Harbor 2.0 架构 (github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor)
让我们回顾一下图 6.2中涵盖的一些关键组件。你将在稍后安装和配置 Harbor 时,看到这些组件在你的 Kubernetes 环境中被部署。
Harbor 图表博物馆
如前所述,除了镜像,Harbor 还支持存储 Helm 图表。为了支持这一功能,Harbor 内部使用 my-harbor-chartmuseum,并且当你在 Kubernetes 集群中运行一个 Harbor 实例时,会有一个名称相同的 Kubernetes 服务在后台运行。
Harbor 核心
如图 6.2所示,Harbor 核心是由多个模块组成的集合,这些模块包括 Harbor 作为容器注册中心的关键功能。这些功能包括诸如 API 管理、身份验证和授权、接口连接(包括可插拔的镜像复制提供者、镜像扫描器、镜像签名提供者)以及其他基础功能,如多租户能力、配置管理、工件管理器等。在我们的基于 Kubernetes 的 Harbor 部署中,所有在图 6.2中显示的模块都位于my-harbor-core下,并作为具有相同名称的 Kubernetes 服务资源对外暴露。
Harbor 作业服务
这是 Harbor 的异步任务执行引擎,暴露了所需的 REST API 供其他组件提交其作业请求。例如,一个作业是扫描一个镜像。你将看到这个微服务也会作为独立的 Kubernetes 部署和名为my-harbor-jobservice的服务进行部署。
Harbor 公证服务
Notary (github.com/notaryproject/notary) 是一个在 CNCF 旗下的第三方开源项目。它用于提供内容可信度建立能力,这通过镜像签名过程来实现。如前文所述,出于安全相关的原因使用 Harbor,这种镜像签名能力是确保只有经过验证的镜像在 Kubernetes 环境中部署的好方法。它允许镜像发布者使用私钥对镜像进行数字签名,从而验证签名者的身份。然后,镜像的消费者可以验证该镜像的发布者/签名者,并根据数字签名及相关元数据做出是否信任该镜像的决策。在安全且完全自动化的 Kubernetes 平台中,镜像签名及其验证操作是 CI/CD 流水线的步骤之一。Notary 通过其两个主要组件——服务器和签名者,提供此功能。Notary 服务器负责存储内容元数据,确保上传内容的有效性,附加时间戳,并在客户请求时提供这些内容。另一方面,Notary 签名者负责将私钥存储在与 Notary 服务器数据库分开的数据库中,并在 Notary 服务器请求时使用这些密钥执行签名操作。你将在本章稍后看到这两个组件作为名为 my-harbor-notary-server 和 my-harbor-notary-signer 的 Kubernetes 部署资源进行部署,以及其对应的服务资源。
Harbor 门户
正如其名称所示,它就是 my-harbor-portal,以及其对应的同名服务,稍后将在本章中讲解。
Harbor 注册表
这是基于一个名为 Distribution 的开源项目(github.com/distribution/distribution),该项目封装了打包、运输、存储和交付内容的功能。它实现了由 OCI Distribution Specification 定义的标准,是进行镜像注册表操作的核心库,被许多开源和商业注册表所使用,包括 Docker Hub、GitLab 容器注册表和 DigitalOcean 容器注册表,包括 Harbor。你将在本章稍后看到这个组件作为一个名为 my-harbor-registry 的 Kubernetes 部署资源进行部署,以及其暴露的同名服务。
PostgreSQL 数据库
这是 Harbor 的主数据库,用于存储所有所需的配置和元数据。它存储了所有 Harbor 结构,包括但不限于与项目、用户、策略、扫描器、图表和镜像相关的数据。它作为一个 StatefulSet 部署在 Kubernetes 集群上,名为 my-harbor-postgresql,同时暴露其同名的服务资源。
Redis 缓存
它也作为一个有状态集部署在 Kubernetes 上,称为 my-harbor-redis-master。它作为键值存储,用于缓存作业服务所需的元数据。
Trivy 扫描器
这是 Aqua Security 提供的一个开源项目(github.com/aquasecurity/trivy),也是 Harbor 2.x 中默认部署的图像 CVE 扫描器。它可以扫描操作系统层和图像中使用的特定语言包,查找这些工件中存在的已知漏洞。Harbor 使用此类扫描器提供全面的扫描能力。这些扫描器可以扫描图像并生成详细的报告,包括 CVE 元数据。此类元数据包括 CVE 编号、漏洞领域、严重性级别、修复版本(如果可用)以及其他详细信息。安装后,你会看到这个组件作为 Kubernetes 部署 my-harbor-trivy 被部署。
什么是 my-harbor?
你在不同组件名称中看到的前缀 my-harbor 是在部署时为 Harbor 的 Helm 图表实例指定的一个任意名称。它可以替换为任何其他名称。
除了我们在此介绍的内容,图 6**.2 中还描述了其他一些内部和外部组件。我们介绍的组件基于在 Kubernetes 集群中 Harbor 命名空间下部署的内容。要了解有关 Harbor 架构的更多详细信息,请访问此链接:github.com/goharbor/harbor/wiki/Architecture-Overview-of-Harbor。
现在我们已经了解了 Harbor 的不同模块,接下来我们将学习如何在 Kubernetes 集群上安装和配置它。
开始使用 Harbor
在本节中,我们将学习如何在现有的 Kubernetes 集群上安装和配置 Harbor 注册表实例。但在此之前,我们需要确保满足以下前提条件。
前提条件
以下是本节中给出的 Harbor 安装说明的前提条件:
- 
Kubernetes 集群版本 1.10+ 
- 
Kubernetes 集群需要具备对外的互联网连接 
- 
操作机应该具备以下工具: - 
dockerCLI:docs.docker.com/get-docker/
- 
helmCLI 版本 2.8.0+:helm.sh/docs/intro/install/
- 
kubectlCLI 版本 1.10+:kubernetes.io/docs/tasks/tools/
 
- 
- 
你的 Kubernetes 集群中应该配置有一个默认的 StorageClass,Harbor 可以使用它来创建所需的存储卷。默认情况下,Harbor 需要多个 PersistentVolumeClaim 资源,这些资源被 Redis 缓存、PostgreSQL 数据库、注册表存储等使用。 
- 
运行 Kubernetes 集群的基础设施应该能够在创建 LoadBalancer类型的 Kubernetes 服务时暴露一个外部可访问的 IP 地址,使其能够从 Kubernetes 集群外部访问。我们在 GKE 集群中使用了LoadBalancer类型的服务。
- 
操作机器应该具备浏览器来访问 Harbor 的图形用户界面(GUI)。 
额外学习
为了使 Kubernetes 上的 Harbor 部署更简单,我们也可以将它部署为 NodePort 服务,并通过 Kubernetes 节点的 IP 地址和与 Harbor 服务关联的端口进行外部访问。但是,我们无法通过 Docker 客户端访问此 Harbor 部署来推送和拉取镜像,因为 Docker 客户端只能通过端口 443(HTTPS)或端口 80(HTTP)连接到仓库。
在 Kubernetes 集群中运行多个 LoadBalancer 类型服务时,为每个 LoadBalancer 类型的服务部署一个负载均衡器机器或服务实例并不是一种高效的方式。因为这样,我们可能需要为 Kubernetes 集群中每个面向外部的服务部署多个外部负载均衡器实例。在 GKE 等公共云环境中,这种方式尤其低效,因为此类负载均衡器实例需要单独收费。更为高级的方式是,我们可以使用在 Kubernetes 集群中运行的 Ingress Controller 服务,将这些面向外部的服务暴露到 Kubernetes 集群之外。Contour (projectcontour.io/) 就是一个这样的开源项目,旨在作为 Ingress Controller,支持 VMware,并随 Tanzu Kubernetes Grid 提供,我们将在下一章中详细介绍。
为了简化学习,我们在本章中使用了 GKE 来将 Harbor 公开到外部。然而,AWS 弹性 Kubernetes 服务(EKS)和 Azure Kubernetes 服务(AKS)也可以像 GKE 一样提供负载均衡器。如果你的 Kubernetes 集群运行在一个无法自动使用外部端点暴露 LoadBalancer 服务的基础设施上,你也可以手动进行此操作。为此,你需要创建一个反向代理服务器,例如 Nginx,并将 Harbor 部署为 NodePort 服务,而不是使用 LoadBalancer 服务,方法是在部署 Harbor 时,使用 --set service.type=NodePort 选项来执行 helm install 命令,后续的安装步骤中将会详细讲解。
现在,让我们开始安装 Harbor。
安装 Harbor
虽然有多种方法可以安装和配置 Harbor 仓库,但我们将使用 Bitnami 提供的 Helm chart 方法,这是一种简单且易于跟随的方式,在 Kubernetes 集群中启动和运行 Harbor 实例。本节中的所有步骤必须在同一台工作站上执行。让我们开始吧:
- 
将 Bitnami 的 Helm 仓库添加到你的工作站: $ helm repo add bitnami https://charts.bitnami.com/bitnami"bitnami" has been added to your repositories
- 
在集群中创建一个命名空间,用于部署所有 Harbor 组件: $ kubectl create namespace harbor
- 
安装 Helm chart 以在 harbor命名空间中部署 Harbor 组件。它应该会部署所有 Harbor 组件,并暴露一个LoadBalancer类型的 Kubernetes 服务来暴露门户:$ helm install my-harbor bitnami/harbor -n harbor
如果命令成功执行,你将在几秒钟内看到以下输出。这里,my-harbor 是给此 Helm 部署指定的一个名称,可以使用该名称引用来升级或删除该安装:
NAME: my-harbor
LAST DEPLOYED: Mon Mar 28 22:36:23 2022
NAMESPACE: harbor
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: harbor
CHART VERSION: 12.2.4
APP VERSION: 2.4.2
** Please be patient while the chart is being deployed **
1\. Get the Harbor URL:
    echo "Harbor URL: https://127.0.0.1:8443/"
    kubectl port-forward --namespace harbor svc/my-harbor 8443:443
2\. Login with the following credentials to see your Harbor application
  echo Username: "admin"
  echo Password: $(kubectl get secret --namespace harbor my-harbor-core-envvars -o jsonpath="{.data.HARBOR_ADMIN_PASSWORD}" | base64 --decode)
上述代码片段显示了成功执行 helm install 命令后的输出。
- 
检查 harbor命名空间中所有 Pod 的状态,确保一切正常运行:$ kubectl get pods -n harbor
你应该能看到所有 Pod 正在运行,且所有容器处于就绪状态,如以下代码片段所示:
NAME                                       READY   STATUS    RESTARTS        AGE
my-harbor-chartmuseum-64bdb5df6f-jsflz     1/1     Running   0               5m38s
my-harbor-core-54fb5d55c9-jjw8p            1/1     Running   1 (3m23s ago)   5m38s
my-harbor-jobservice-66894459d4-rtv4n      1/1     Running   2 (3m28s ago)   5m38s
my-harbor-nginx-54f6b75d9b-9dtxt           1/1     Running   0               5m38s
my-harbor-notary-server-5fc48d989c-b5s96   1/1     Running   0           5m38s
my-harbor-notary-signer-5bffc645b-26r4c    1/1     Running   1 (3m38s ago)   5m38s
my-harbor-portal-697d84949-k7hrv           1/1     Running   0               5m38s
my-harbor-postgresql-0                 1/1     Running   0        5m38s
my-harbor-redis-master-0                1/1     Running   0            5m38s
my-harbor-regtry-6f55746685-rr4ts        2/2     Running   0        5m38s
my-harbor-trivy-0           1/1     Running   0           5m38s
- 
检索安装过程中生成的管理员用户密码。记下此密码,稍后我们将用它访问 Harbor GUI: $ echo "admin password: $(kubectl get secret --namespace harbor my-harbor-core-envvars -o jsonpath="{.data.HARBOR_ADMIN_PASSWORD}" | base64 --decode)"
- 
运行以下命令以检索 Harbor 服务暴露的外部 IP 地址: $ echo "Harbor Service IP: $(kubectl get service my-harbor -n harbor -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
- 
使用浏览器访问 Harbor 门户,地址为 https://<external-ip>/。由于我们未使用有效证书颁发机构签名的证书,因此可能需要忽略浏览器的安全提示。你应该能看到以下屏幕:

图 6.3 – Harbor 登录页面
- 输入用户名 admin和你在 第 5 步 中检索到的密码。你应该能够成功登录并看到 Harbor GUI 的首页:

图 6.4 – Harbor 登陆页面
如果你能使用上述凭据登录并看到之前的屏幕,那么你已经完成了在 Kubernetes 集群中运行 Harbor 实例所需的设置。接下来的步骤是通过将一个镜像推送到此注册表来进行一个小的烟雾测试,以验证我们的设置。
验证设置
执行以下步骤以验证安装:
- 
按照以下步骤检索 Harbor 使用的 CA 证书。我们需要将此证书添加到 Docker 客户端使用的信任存储中,以便连接到 Harbor 部署: - 通过点击高亮链接进入 library 项目:
 

图 6.5 – 点击库项目
- 使用以下屏幕截图中的 REGISTRY CERTIFICATE 链接下载证书到工作站:

图 6.6 – 下载注册表证书
- 根据操作系统的不同,按照此处的说明,将 Harbor 门户证书导入到 Docker 客户端使用的信任存储:docs.docker.com/registry/insecure/#use-self-signed-certificates。
对于 macOS,运行以下命令:
$ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <downloaded-harbor-certificate>
在这里,将 <downloaded-harbor-certificate> 替换为 第 1 步 中下载的证书路径。
- 
如果 Docker 守护进程正在运行,请重启它;否则,启动它,使证书对 Docker 客户端可见。 
- 
在 /etc/hosts文件中创建一个本地 DNS 条目,将默认域名core.harbor.domain与用于访问门户的外部负载均衡器 IP 地址关联。
- 
使用 dockerCLI 登录 Harbor 注册表以启用推送/拉取操作:$ docker login -u admin https://core.harbor.domainPassword: <as retrieved from the step #5 of installation>Login Succeeded
- 
使用 Docker 客户端将镜像推送到你新设置的 Harbor 注册表: - 使用 dockerCLI 下载busybox:latest镜像。以下命令将从 Docker Hub 仓库下载镜像到你的本地工作站:
 $ docker pull busybox:latest- 通过运行以下命令,验证 busybox:latest镜像是否存在于你的本地镜像仓库中:
 $ docker images | grep busybox- 
你应该能看到一个记录,显示前面命令的结果中带有 latest标签的busybox镜像。
- 
给 busybox:latest镜像打标签,以准备将其推送到我们的 Harbor 注册表实例:
 $ docker tag busybox:latest core.harbor.domain/library/busybox:latest- 将新标记的镜像推送到你的 Harbor 实例:
 $ docker push core.harbor.domain/library/busybox:latest
- 使用 
- 
在成功推送操作之后,你应该能看到该镜像在门户的 library 项目中列出,如下图所示: 

图 6.7 – 验证新镜像的存在
如果你在之前的界面中看到了busybox镜像,那么你的 Harbor 安装已完成。你也可以选择进行拉取测试,方法是通过删除本地仓库中的现有镜像,在同一工作站上执行,或者使用具有 Docker 客户端的另一台工作站。如果你希望使用不同的工作站,可能需要在那里配置 Harbor 证书,并通过 docker CLI 对 Harbor 仓库进行身份验证。
在下一节中,我们将介绍一些使用此安装的 Harbor 的关键第二天操作。
Harbor 的常见第二天操作
现在我们已经有了一个可以正常工作的 Harbor 设置,接下来让我们来看看在其上可能需要执行的一些重要第二天操作。本节中我们将涵盖以下活动:
- 
在 Harbor 中创建并配置一个项目,这是 Harbor 上启用多租户的构造,允许不同的团队拥有各自独立的配置 
- 
配置自动化镜像扫描并处理扫描结果 
- 
防止使用不安全的镜像来部署容器 
- 
配置镜像复制以允许选择性访问外部镜像 
- 
执行清理操作,删除未使用的镜像标签,以释放项目的存储配额 
正如你在这里看到的,我们有很多内容需要涵盖。那么,让我们开始吧。
在 Harbor 中配置项目
我们来创建一个名为 project-1 的新项目,并使用之前用来验证安装的管理员用户进行配置:
- 作为admin登录 Harbor 门户的主屏幕上,点击新项目按钮:

图 6.8 – 创建新项目
- 配置项目的名称和配额,如下截图所示,并点击确定。我们将保持此项目私有,这意味着您需要进行身份验证才能拉取图像。我们也不会将此项目配置为用于外部注册表(如 Docker Hub)的拉取缓存:

图 6.9 – 输入新项目详细信息
- 您应该能够在屏幕上看到列出的新项目,如下截图所示:

图 6.10 – 验证新项目的存在
现在我们创建了这个项目,该项目的用户可以通过在图像中应用core.harbor.domain/project-1/前缀来推送他们的图像。该项目在达到 2GB 存储配额后将不再接受新图像,这是我们在步骤 2创建时配置的。现在,让我们了解一些重要的项目级配置。
配置 Harbor 项目的图像扫描
为了保证 Harbor 的安全性,扫描图像中 CVE 的存在是一个重要的安全功能。现在,让我们配置project-1,以便在将图像推送到该项目时立即启用自动 CVE 扫描,使用默认的扫描工具Trivy:
- 点击高亮链接进入project-1详细页面:

图 6.11 – 选择新创建的项目
- 打开配置选项卡,并选择高亮选项,以便在每次推送时扫描每个图像。最后,点击保存:

图 6.12 – 启用项目图像自动扫描
现在,让我们验证这个配置是否有效,通过推送我们之前从 Docker Hub 拉取的busybox:latest镜像。这应该存在于您本地工作站的 Docker 仓库中。
- 
准备将 busybox:latest镜像推送到 Harbor 的project-1仓库,通过应用适当的标签:$ docker tag busybox:latest core.harbor.domain/project-1/busybox:latest
- 
推送新标记的 busybox:latest镜像到project-1仓库:$ docker push core.harbor.domain/project-1/busybox:latestThe push refers to repository [core.harbor.domain/project-1/busybox]797ac4999b67: Layer already existslatest: digest: sha256:14d4f50961544fdb669075c442509f194bdc4c0e344bde06e35dbd55af842a38 size: 527
如您在之前的命令结果中所见,Harbor 在我们之前执行验证过程中,使用了图像的同一层,我们将其推送到library项目下。
验证project-1中图像的存在,并点击以下截图中突出显示的project/busybox链接:

图 6.13 – 点击图像仓库
- 如下图所示,busybox:latest镜像的扫描已完成,且未发现任何漏洞。此扫描是在将新镜像推送到仓库时自动触发的:

图 6.14 – 验证扫描结果
现在,让我们基于这样的扫描结果创建一个策略,防止拉取具有中等以上严重性 CVE 的镜像,以避免运行包含此类漏洞的容器。
防止在 Harbor 中使用不安全的镜像
要防止不安全的镜像被拉取,导航到 project-1 的项目主页。在 配置 选项卡下,你可以看到一个名为 防止易受攻击的镜像运行 的选项,如下图所示。选中此选项,从下拉菜单中选择 高,并保存配置更改:

图 6.15 – 防止拉取包含高危 CVE 的镜像
现在,让我们测试这个配置更改。为此,我们需要将一个不安全的镜像推送到 project-1。你可以按照以下步骤执行此测试:
- 
从 Docker Hub 拉取 nginx:1.9.5镜像,这是一个非常旧且漏洞多的版本:$ docker pull nginx:1.9.5
- 
为 Harbor project-1 仓库打标签 nginx:1.9.5:$ docker tag nginx:1.9.5 core.harbor.domain/project-1/nginx:1.9.5
- 
将 nginx:1.9.5推送到 Harbor project-1 仓库:$ docker push core.harbor.domain/project-1/nginx:1.9.5
- 
验证 Harbor 中 project-1 下的镜像已扫描并显示 CVE,如下图所示: 

图 6.16 – 验证 CVE 扫描结果
- 
从本地 Docker 仓库中删除 nginx:1.9.5镜像,以便我们可以尝试从 Harbor project-1 仓库拉取它:$ docker image rm core.harbor.domain/project-1/nginx:1.9.5 nginx:1.9.5
- 
尝试从 Harbor project-1 仓库拉取 nginx:1.9.5镜像:$ docker pull core.harbor.domain/project-1/nginx:1.9.5Error response from daemon: unknown: current image with 721 vulnerabilities cannot be pulled due to configured policy in 'Prevent images with vulnerability severity of "High" or higher from running.' To continue with pull, please contact your project administrator to exempt matched vulnerabilities through configuring the CVE allowlist.
如你所见,Harbor 因镜像中存在超出配置容忍阈值的 CVE,拒绝发送该镜像。
重要提示
我们采用这种测试方法是为了简化操作。但你也可以尝试在 Kubernetes 集群中使用该镜像创建一个 Pod,以模拟实际场景。结果是一样的,你将无法使用 core.harbor.domain/project-1/nginx:1.9.5 镜像创建 Pod。然而,要测试使用此 Harbor 设置创建 Pod,你可能需要将 DNS 条目添加到所有 Kubernetes 集群节点的 /etc/hosts 文件中。或者,你可能需要创建一个更像生产环境的 Harbor 设置,使用正确的域名,通过 Kubernetes 集群中的外部 DNS 记录解析。
这就是我们配置及其测试的总结,旨在防止从 Harbor 仓库中拉取不安全的容器镜像。在下一节中,我们将学习如何配置远程仓库同步,以允许内部开发人员通过 Harbor 拉取所需的外部可用的允许镜像。
在 Harbor 中复制镜像
本节将学习如何在 Harbor 中配置镜像复制。Harbor 中有两种类型的复制,如下所述,并介绍了它们的实际应用:
- 
推送型:配置规则将特定镜像从 Harbor 推送到另一个仓库,这可以是另一个远程 Harbor 部署,甚至是公共仓库。这种类型的复制对于实现“中心-边缘”类型的部署非常有用,其中需要在边缘位置的 Kubernetes 集群中提供某些镜像。在边缘位置的 Kubernetes 集群上拥有所需的镜像有助于减少网络延迟和依赖(从而提高应用可用性),尤其是在需要拉取镜像以在边缘 Kubernetes 集群上部署容器时。此场景在 图 6.1 中有所描绘。 
- 
拉取型:配置规则从远程公共或私有仓库拉取特定镜像。这种复制策略允许开发者从外部仓库(如 Docker Hub 或 GCR)访问某些允许的容器镜像。Harbor 的这一功能不仅允许开发者自由使用经批准的外部托管镜像,而且还允许运维人员防止“无人管辖”的情况,避免任何人从外部仓库拉取任何镜像。图 6.1 显示了中心 Harbor 仓库如何使用此功能从 Docker Hub 和 GCR 拉取所需镜像。 
现在我们了解了这些类型及其用途,接下来我们来看如何在 Harbor 中配置这些复制规则。在这里,我们将配置一个拉取型策略,以允许开发者从 Docker Hub 访问 MySQL 镜像。我们将配置远程仓库位置和复制规则,然后快速验证这些配置是否按预期工作:
- 
添加 Docker Hub 作为外部仓库端点: - 点击 管理 菜单下的 Registries 选项,然后点击 NEW ENDPOINT 按钮,如下图所示:
 

图 6.17 – 添加新的外部仓库端点
- 从下拉菜单中选择 Docker Hub,输入名称和描述,然后点击 TEST CONNECTION 按钮。您可以在此测试中将身份验证详情留空。然而,对于生产环境部署,您应该提供这些凭据,以防止 Docker Hub 应用镜像拉取速率限制。Docker Hub 会对未验证的拉取请求应用较低的速率限制:

图 6.18 – 添加 Docker Hub 详情并测试连接
- 
点击 OK 按钮以保存并退出。 
- 
在 Registries 页面下验证新创建的条目,如下图所示: 

图 6.19 – 验证 Docker Hub 端点是否存在
- 
创建一个复制规则,允许我们通过刚才创建的注册表端点从 Docker Hub 拉取 MySQL 镜像: - 点击管理菜单下的复制选项,并点击新建复制规则按钮,如下图所示:
 

图 6.20 – 创建新的复制规则
- 输入复制规则的名称和描述,选择基于拉取的复制选项,从下拉菜单中选择我们在步骤 1中创建的 Docker Hub 注册表端点,提供镜像过滤标准,如下图所示,并点击保存按钮:

图 6.21 – 提交复制规则的详细信息
我们将保持其他选项不变。这些选项包括镜像目标详情,用于指定我们是否想要一个与源不同的镜像文件夹名称和目录结构。它还提供了选择何时触发拉取符合过滤标准的镜像的选项。默认值是根据需要手动拉取,但我们也可以创建基于计划的拉取。然后,我们可以限制带宽要求,以防止网络因执行大量拉取请求而被淹没。最后,还有一个选项,可以在源注册表端点上有一个不同 SHA 但相同名称和标签的镜像时,启用/禁用镜像被覆盖。
自定义过滤模式
在之前的配置中,我们使用了非常基础的过滤标准来选择所有标签以8.开头的 MySQL 镜像。然而,你可以在这里应用复杂的模式,根据需求允许/拒绝镜像。你可以在这里了解更多关于这些模式的信息:goharbor.io/docs/2.4.0/administration/configuring-replication/create-replication-rules/。
- 通过选择新创建的规则并点击复制按钮,手动触发复制操作:

图 6.22 – 触发镜像复制
- 确认复制操作,点击复制按钮:

图 6.23 – 确认镜像复制
- 从复制页面的执行部分验证复制是否成功,如下图所示。根据网络连接情况,可能需要几分钟才能成功复制所有镜像:

图 6.24 – 验证镜像复制执行
- 在复制成功完成后,转到 项目 屏幕并点击 库 项目:

图 6.25 – 打开库项目
- 你将在 仓库 标签页下看到一个名为 library/mysql 的新命名空间。点击该链接:

图 6.26 – 验证新复制的仓库
- 你可能会看到在 library/mysql 下列出了多个图像,这是由于复制操作的结果:

图 6.27 – 验证新复制的仓库内容
- 将其中一个图像拉取到本地工作站的 Docker 仓库,以验证其是否按预期工作:
$ docker pull core.harbor.domain/library/mysql:8.0.27
此命令应该能够从我们的 Harbor 仓库成功拉取图像。
这就是我们复制配置步骤的结束。现在,开发人员可以直接从 Harbor 仓库拉取所需的 MySQL 图像,而无需从 Docker Hub 获取。
作为这个列表中的下一个第 2 天活动,我们将学习如何配置基于规则的标签保留策略,以清理过期的图像并释放存储空间。
在 Harbor 中配置基于规则的标签保留策略
如你在之前的配置中所见,我们为 MySQL 复制了超过 25 个不同的图像。在生产环境中,我们经常会遇到一些过期的图像,这些图像未被使用,却占用了项目分配的空间配额。在我们之前的 MySQL 复制中,可能只会看到几个使用的图像标签,而我们可以移除其余的图像。为此,我们将学习如何配置基于标签的自动化保留策略,以清理旧的和无用的内容。让我们开始吧:
- 转到 项目 屏幕并点击 库 项目:

图 6.28 – 打开库项目
- 在 库 项目下,转到 策略 标签页,点击 添加 规则 按钮:

图 6.29 – 添加新的图像保留规则
- 输入 mysql作为匹配仓库,选择1作为保留数量,然后点击 添加 按钮:

图 6.30 – 输入图像保留规则的详细信息
该策略将移除所有 MySQL 图像,除了 mysql:8.0.27,因为我们在验证步骤中已经拉取了这个图像。
- 如你所见,新的标签保留策略已经生效。虽然我们也可以按照定期频率安排此活动,但现在我们将通过点击 立即运行 按钮手动执行它:

图 6.31 – 验证图像保留规则的创建
- 通过按下RUN按钮并接受批量删除操作的警告来继续:

图 6.32 – 执行镜像保留规则
- 通过检查活动日志记录,验证清理活动是否成功完成,日志应显示从 24 个标签中只保留了一个标签,这是预期的结果:

图 6.33 – 验证镜像保留规则的执行情况
- 点击Repositories标签,列出现有的仓库。在该页面上,你应该能看到只有一个mysql标签,而不是之前的 24 个标签:

图 6.34 – 验证保留规则执行后剩余镜像的数量
- 导航到 mysql仓库,验证除了8.0.27之外的标签是否已被删除:

图 6.35 – 验证剩余镜像的保留规则执行情况
这标志着我们的标签保留策略配置结束。与标签保留类似,我们还可以配置标签不可变性策略,以防止某些关键的镜像标签被新的镜像版本覆盖。如果没有这样的策略,你可能会推送带有相同标签值的新的镜像版本。这样,针对某一标签版本的应用测试,可能无法确保下次拉取该标签时内容不变。如果新版本的同一标签镜像发生了任何意外变化,这可能会导致应用程序无法正常工作。理想情况下,这种情况不应发生,因为这是一种不良的开发实践。但应该有一些控制措施来防止这种情况发生。因此,Harbor 在这种情况下提供了帮助,允许你创建策略,防止 Harbor 用户推送具有不同内容但相同标签的镜像,而这些内容是由 SHA-256 算法决定的。
重要信息
为了保护我们的容器化应用免于因相同标签值的镜像内容发生变化而失败,最好使用镜像的 SHA 值而不是标签来拉取镜像。使用 SHA 值拉取镜像(也称为摘要)可以确保你始终获取相同的镜像,并且没有被意外覆盖的风险。例如,使用 docker pull ubuntu:20.04 命令拉取的镜像内容在多次执行时理论上可能会有所不同,但当你使用其摘要通过 docker pull ubuntu@sha256:82becede498899ec668628e7cb0ad87b6e1c371cb8a1e597d83a47fac21d6af3 命令拉取时,镜像内容始终相同。
在 Harbor 上,我们可能需要执行更多的管理和用户 day-2 活动,包括用户账号管理、用于自动化的机器人账号、镜像签名、基于 Webhook 的自动化触发器等等。在本章中,我们涵盖了一些通常在容器注册表(如 Harbor)上执行的最常见活动。虽然我们可以为其他操作添加更多细节,但本书的目标并不仅限于成为 Harbor 指南。不过,如果你愿意,你可以在 Harbor 的官方文档 goharbor.io/docs/2.4.0/ 中找到更多详细信息。
总结
让我们回顾一下本章我们所涵盖的内容。首先,我们讨论了 Harbor 的多种好处和用例,同时解释了使用它的原因。我们查看了 Harbor 的不同安全相关好处,包括镜像扫描、强大的 RBAC 功能以及使用镜像复制限制公共库访问需求的能力。对于操作控制方面,我们讨论了诸如本地部署和空隙部署、作为 CNCF 下的热门开源项目、全面的多租户支持以及管理配置等好处。在可扩展性方面,我们看到了 Harbor 如何通过其镜像库内容的扩展功能与复制特性一起使用。本类别还讨论了 Harbor 的漏洞扫描器和认证提供程序的可插拔模型。
之后,我们详细讨论了 Harbor 的架构细节,并了解了构成 Harbor 的不同组件。接着,我们学习了如何使用 Bitnami Helm 图表快速开始使用 Harbor,并验证了安装。最后,我们深入探讨了围绕 Harbor 的一些重要 day-2 操作,包括创建项目、执行镜像扫描、阻止拉取风险镜像、从 Docker Hub 复制镜像以及清理过期镜像以释放项目的存储配额。
在下一章中,我们将学习如何使用 Tanzu Kubernetes Grid 在多云环境中运行这些镜像,这是 VMware 提供的多云 Kubernetes 解决方案。
第七章:使用 Tanzu Kubernetes Grid 在云之间编排容器
在上一章中,我们了解了作为 Tanzu 产品包一部分的容器注册中心 Harbor。通过了解如何使用 Harbor 托管容器镜像,接下来我们将在本章学习如何使用 Tanzu Kubernetes Grid(Tanzu 的多云且企业级的 Kubernetes 分发版)将它们部署到 Kubernetes 上。近年来,Kubernetes 已经广泛被接受,成为行业运行容器的默认规范。根据Cloud Native Computing Foundation(CNCF)的最新调查,96%的受访组织要么正在评估,要么已经在使用 Kubernetes(来源:www.cncf.io/wp-content/uploads/2022/02/CNCF-Annual-Survey-2021.pdf)!此外,许多受访者在不同的云平台上使用 Kubernetes,原因包括风险缓解、避免厂商锁定以及提高运营支出效率。但在一个或多个云上运营大型 Kubernetes 平台是一个复杂的任务,原因多种多样。每个云平台都有各自的 API 和管理 Kubernetes 服务的独特方式。当组织还需要在本地运行 Kubernetes 服务时,复杂性会进一步增加。对于这种本地 Kubernetes 部署,许多企业会使用自定义自动化构建自己的平台。虽然使用开源工具构建这样的自定义平台可以带来初期的成本节省,但当最初构建平台的人离开组织后,长期维护这些平台将变得非常困难。相比之下,组织可以更好地利用其人才,使用Tanzu Kubernetes Grid(TKG)这样的企业级产品,专注于构建更多具有收入创造潜力的定制应用程序,而不是为这些低价值的工作分心。
TKG 是 VMware 的 Kubernetes 发行版,提供了部署企业级容器平台所需的一切功能,适用于基于 vSphere 的本地数据中心、Amazon Web Services(AWS)和 Azure 公有云基础设施。在本章中,我们将详细了解此产品,并涵盖以下主题:
- 
为什么选择 Tanzu Kubernetes Grid?:深入了解 TKG 的功能和能力 
- 
开箱 Tanzu Kubernetes Grid:详细概述 TKG 的组件和概念 
- 
开始使用 Tanzu Kubernetes Grid:学习如何安装和配置 TKG 
- 
Tanzu Kubernetes Grid 的常见日常操作:学习如何使用 TKG 执行各种集群生命周期活动 
让我们从了解 Tanzu Kubernetes Grid 的背景开始。
为什么选择 Tanzu Kubernetes Grid?
简而言之,TKG 是企业支持的开源 Kubernetes 平台的一个版本。与其他许多发行版一样,TKG 使用上游 Kubernetes 发行版,而不修改开源代码库。然而,有几个充分的理由使得企业更倾向于使用 TKG 而非开源社区的 原生 Kubernetes 发行版。我们将在本节中探讨这些原因。
多云应用部署
根据 Gartner 的一项调查(www.gartner.com/smarterwithgartner/why-organizations-choose-a-multicloud-strategy),超过 81% 的受访者表示他们有多云部署或策略。企业采用多云策略的原因包括避免供应商锁定,并使用各个云服务提供商提供的最佳服务。此外,企业有些应用程序可能无法部署在公共云平台上,因此选择在本地部署。Kubernetes 提供了一个很好的选项,允许在多云和混合云平台上部署应用程序。一旦应用程序准备好在 Kubernetes 中运行并包装在容器中,它就可以部署到任何符合上游标准的 Kubernetes 平台,不论是在任何云环境还是数据中心中。Kubernetes 使得应用程序的多云部署几乎变得轻而易举。Kubernetes 可以很好地管理容器化应用程序,但从本质上讲,它并不懂得如何管理其所部署的基础设施。这使得平台和基础设施的管理成为一个外部问题。所有主要的云服务提供商除了提供 Kubernetes 作为服务之外,还提供仅使用其基础设施来部署自我管理 Kubernetes 平台的选项。然而,每个平台都有其独特的接口,因此用户体验也各不相同。此外,每个平台在操作系统、网络、存储和计算等方面都有各自的差异。管理大型 Kubernetes 平台本身就是一个难题,当我们需要管理一个多云环境时,这个问题会更加复杂。虽然学习一个云平台的细节并不复杂,但现在,基础设施和平台团队如果计划以多云方式部署 Kubernetes,就需要学习多个云平台的相同内容。由于这些原因和所涉及的复杂性,许多企业尽管使用单一平台所带来的风险较高,仍然避免走向多云。
TKG 通过提供统一的体验来解决这些挑战,使得在 vSphere(用于本地部署)、AWS 和 Azure 云平台上操作 Kubernetes 成为可能。TKG 的核心组件之一是集群 API(cluster-api.sigs.k8s.io/),这是一个由 CNCF 维护的开源项目,提供了一个基础设施之上的抽象层。集群 API 部署并管理 Kubernetes 节点,确保所选云平台所需的存储和网络配置。此外,TKG 通过 tanzu CLI 来暴露其接口,提供相同的用户界面来执行不同的 Kubernetes 集群生命周期操作,无论基础设施提供商是什么。TKG 还为三大支持的云提供商捆绑了 VMware 支持的操作系统层。凭借这些特性,TKG 提供了一个易于使用的多云 Kubernetes 平台。
开源对齐
使用 TKG 的另一个主要好处是,它使用了适用于不同用例的开源工具。作为其核心组件,TKG 使用由 CNCF 社区维护的上游开源 Kubernetes 发行版。TKG 并没有从任何开源组件中派生代码并加入自己的定制特性。这一特点为 TKG 用户提供了使用开源软件的所有好处,包括通过可移植性避免厂商锁定,并通过开源贡献为其需求丰富功能的途径。
考虑到这些好处,近年来所有企业都希望尽可能使用开源解决方案。然而,云原生生态系统中充满了许多开源产品,这些产品解决相似的问题,并且在生产环境中使用时成熟度不同。图 7.1 是一张来自 CNCF 官网的截图(landscape.cncf.io/),展示了一个非常拥挤的空间,里面有许多解决不同问题的工具,运行容器化应用程序。为特定问题选择合适的工具,并且该工具具有可接受的成熟度、活跃的社区和企业级支持,是一项具有挑战性的任务。而且,这个生态系统在不断变化,新解决方案频繁地被添加到列表中。更复杂的是,一个工具与另一个工具的兼容性并不总是能得到保证。因此,解决这个问题有三种可能的方案:
- 
企业通过仔细评估这个多样化且竞争激烈的生态系统中的各项选择,运行长期的概念验证项目来缩小选择范围,从而构建定制的容器平台。虽然这种方式能提供完全的控制权和可能的短期成本优势,但这种方法也有一些相当大的缺点。其中之一是,企业可能需要花费大量的工程师时间来构建定制的容器平台。从市场上找到合适的人才并在内部培养所需的技能是一个艰难且昂贵的挑战。此外,这些技能人才在市场上需求旺盛,可能无法长时间留在企业内支持他们所构建的系统。最终,这些定制构建的解决方案很快就会成为企业的一项昂贵的负担。 
- 
企业可以选择由云服务提供商提供的所有解决方案,在这种方式下,企业不再需要花时间选择工具,也不必担心这些工具的支持和兼容性。通过这种方式,企业可以使用 AWS、Azure 或 Google Cloud Platform 等单一云服务商提供的所有服务来构建一个强大且符合生产要求的容器平台。然而,这种方法可能会导致潜在的厂商锁定问题。长期来看,脱离将非常痛苦,而且这将成为与一个云服务商的昂贵的婚姻: 

图 7.1 – CNCF 生态图
- 企业可以选择像 Tanzu 这样的多云平台,它可以抽象化基础设施提供商,从而使部署在平台上的工作负载具备可移植性。与前两种方式类似,这种方式也有缺点。使用这种多云平台可能会导致多云平台提供商本身的厂商锁定问题。在使用任何第三方产品时,避免厂商锁定没有万无一失的解决方案。然而,如果第三方解决方案完全由开源组件支持,这种风险可能会在一定程度上得到缓解,而 TKG 恰好就是这种情况。
TKG 是许多流行的开源项目的集合,包括作为容器运行时的 Kubernetes、用于 Kubernetes 集群生命周期管理的 Cluster API、用于容器覆盖网络的 Antrea、作为节点操作系统的 Ubuntu 和 Photon、用于日志记录的 Fluent Bit、用于监控的 Prometheus 和 Grafana 等。我们将在下一部分详细介绍它们。VMware 为所有这些开源工具提供签名的二进制文件,这些工具会协同工作并适用于特定版本的 TKG。通过这种方式,TKG 帮助企业避免了痛苦的工具选择过程,使工具能够协同工作,获得支持,并在很大程度上避免了厂商锁定。
至此,我们已经回答了为什么选择 Tanzu Kubernetes Grid?的问题。现在,让我们了解 TKG 包中包含的内容及其核心概念。
解开 Tanzu Kubernetes Grid
在本节中,我们将回顾 TKG 的所有构建模块,包括其接口、核心组件和扩展组件。之后,我们将理解该平台的核心概念,从而理解其工作原理。我们还有很长的路要走,所以让我们开始吧。
Tanzu Kubernetes Grid 的构建模块
正如上一节所提到的,TKG 是由许多开源工具集合而成,这些工具分别解决不同的问题,共同构建出一个企业级的 Kubernetes 平台。我们可以将这些组件分为三类——接口、核心和扩展——如图 7.2所示:

图 7.2 – Tanzu Kubernetes Grid 包
让我们回顾这些组件,了解它们在 TKG 包中的角色。
Tanzu Kubernetes Grid 的接口组件
正如其名称所示,这些组件包括 TKG 与用户及基础设施提供者(包括 vSphere、AWS 和 Azure)之间的接口。接下来的章节将更详细地说明这些工具。
Tanzu 命令行界面(CLI)
与 Tanzu 产品组合中的其他一些产品类似,TKG 也使用 tanzu CLI 作为其主要用户界面。tanzu CLI 采用插件结构,允许不同的 Tanzu 产品使用相同的界面。TKG 使用 tanzu CLI 执行所有集群操作,例如查看、创建、扩展、删除和升级 TKG 集群。我们将在下一节中使用这个 CLI 设置我们的 TKG 基础平台。tanzu CLI 是名为 Tanzu Framework 的更广泛开源项目的一部分(github.com/vmware-tanzu/tanzu-framework)。你可以在这里了解更多关于该 CLI 的信息:github.com/vmware-tanzu/tanzu-framework/tree/main/docs/cli。
除了这个 CLI,Tanzu 产品组合还包括一个名为 Tanzu Mission Control 的图形用户界面(GUI)工具,用于所有 TKG 集群操作。我们将在第九章《使用 Tanzu Mission Control 管理和控制 Kubernetes 集群》中详细了解这个工具。
Tanzu Kubernetes Grid 安装程序
TKG 安装程序是一个图形用户界面组件,提供了一个向导,用于在选定的基础设施上安装 TKG,撰写时该基础设施可以是 vSphere、AWS 或 Azure。在 TKG 的初始设置过程中,一个非常小的引导 Kubernetes 集群会被部署在操作员的工作站上(也称为引导机器)。TKG 安装程序 Pod 会在该本地 Kubernetes 集群上部署,以部署并启动引导机器上的图形用户界面。然后,操作员使用本地运行的 TKG 安装程序图形用户界面,在目标云基础设施上部署实际的 TKG 基础平台。这看起来可能会让人困惑,因为在这里,TKG 使用一个(小型)Kubernetes 平台来部署一个(大型)Kubernetes 平台。在下一节的 TKG 安装步骤中,我们将使用这个图形用户界面。
值得注意的是,TKG 还提供了一种使用 tanzu CLI 安装基础设施的方法,同时也提供了图形用户界面(GUI)体验。然而,建议在第一次安装时使用 GUI,因为 GUI 中使用的向导会生成一个安装配置文件,该文件可以稍作修改后用于通过 tanzu CLI 快速安装其他类似的 TKG 基础设施。
kind
kind 代表 Kubernetes inside Docker。kind 是一个在 Kubernetes 特殊兴趣小组 (SIGs) 旗下的开源项目 (kind.sigs.k8s.io/),它允许你在 Docker 环境中运行一个非常小型的 Kubernetes 集群。kind 是一个符合 CNCF 标准的 Kubernetes 安装工具,通常部署在本地桌面环境中,用于部署一个小型的 Kubernetes 集群。TKG 安装器 Pods 仅在 kind 集群中用于引导目的。一旦实际的 TKG 基础设施安装完成,kind 集群以及运行的安装器组件会被销毁,因为它们的用途已经结束。
Cluster API
Kubernetes 包含一个名为 Kubeadm 的工具 (kubernetes.io/docs/reference/setup-tools/kubeadm/),该工具帮助配置服务器,将其转换为 Kubernetes 集群节点。它通过安装所需的 Kubernetes 特定组件来实现这一目标。Kubeadm 有助于节点以最佳实践 快速路径 的方式加入集群,用于创建 Kubernetes 集群。然而,Kubeadm 并不知道如何为特定云提供商配置所需的基础设施。Kubeadm 需要在将服务器转换为 Kubernetes 节点之前,先确保服务器已经创建并配置了所需的计算、存储和网络环境。Kubeadm 在基础设施管理方面的这一空白由 Cluster API 填补。
TKG 用户通常不会直接使用 Cluster API,但它是 TKG 中最重要的构建模块之一,它与底层云基础设施进行交互并进行抽象。API 这个术语代表 应用程序编程接口,这是计算机编程领域中一个广为人知的术语。Cluster API 也是一个 SIG 项目 (cluster-api.sigs.k8s.io/)。该项目的目的是为像 TKG 这样的平台提供一个接口层,以执行各种 Kubernetes 生命周期操作,包括集群配置、升级和运行。正如我们所知,不同的云提供商在操作其基础设施方面有不同的方式。在 vSphere 中,虚拟机称为 EC2 机器,而在 AWS 中,它则是 EC2 机器。在 AWS 中,虚拟网络边界称为 虚拟私有云 (VPC),但在 Azure 中则称为 虚拟网络 (VNet)。Cluster API 接口的实现通过抽象这些云特定的术语和操作差异来进行统一。
为了提供完全自动化的 Kubernetes 集群生命周期管理,TKG 使用了 Cluster API;Cluster API 内部使用 Kubeadm。通过这种方式,TKG 完全利用不同的开源项目,提供统一的多云 Kubernetes 集群管理体验。
Carvel
Carvel (carvel.dev/) 是 TKG 用于安装自身及其他可选包的一个额外开源包管理工具包。Carvel 是一个非常强大且灵活的 Kubernetes 部署打包工具。Carvel 包含多个用于不同包管理和部署任务的工具,如下所列:
- 
kapp-controller:以 GitOps 方式提供 Kubernetes 集群中应用和包的持续交付 
- 
ytt:用于创建和使用模板化的 YAML 配置文件进行包部署,允许在 Kubernetes 集群安装时自定义包配置 
- 
kapp:将多个 Kubernetes 资源捆绑为一个可以作为整体安装、升级或删除的应用包 
- 
kbld:以不可变的方式构建或引用 Kubernetes 资源配置中使用的容器镜像 
- 
imgpkg:用于打包、分发和重新定位 Kubernetes 配置及相关的容器镜像作为一个整体 
- 
vendir:声明目录的内容 
- 
secretgen-controller:用于管理包所使用的各种类型的秘密 
在了解了与 TKG 相关的接口组件后,我们现在来回顾一下 TKG 的核心组件。
Tanzu Kubernetes Grid 的核心组件
除了之前看到的接口组件,TKG 还包含了一组核心组件,它们是 Kubernetes 平台最基本的构建模块。让我们在这里了解它们。
操作系统
使用 TKG 的众多优势之一是,您可以获得来自 VMware 的 Kubernetes 节点支持和加固的操作系统。TKG 支持基于 Photon 和 Ubuntu Linux 的操作系统。此外,TKG 还允许您在支持的几种 Linux 和 Windows 操作系统中构建,并提供一定的自定义功能。
Kubernetes
Kubernetes 是 TKG 的主要组成部分。每个版本的 TKG 包括一个或多个上游开源 Kubernetes 发行版,且没有任何修改。这个组件是主要的 Kubernetes 平台,包含了构建该平台的主要工具集。它包括以下工具:
- 
kube-apiserver:Kubernetes 控制平面的 API 接口 
- 
etcd:一个键值存储,用于持久化 Kubernetes 集群的状态及其工作负载配置 
- 
kube-scheduler:根据各种选择标准将新创建的 pod 安排到节点上 
- 
kube-controller-manager:运行不同的控制过程来管理节点、任务、服务端点和服务账户 
- 
cloud-controller-manager:运行不同的云/基础设施特定进程,以管理节点健康检查、路由和云特定的服务负载均衡器 
- 
kubelet:一种驻留在节点上的代理,确保 Pod 的运行状态并将其报告给控制平面 
- 
kube-proxy:一种驻留在节点上的网络代理,确保服务路由到运行在节点上的终端 Pod 
- 
容器运行时:一种驻留在节点上的软件(在 TKG 中是containerd),用于运行和管理容器 
除了 Kubernetes 的核心组件外,还有一些 TKG 包含的其他核心组件,平台需要这些组件才能正常运行。让我们来看看。
指标服务器
指标服务器聚合 Kubernetes 集群中容器、节点 CPU 和内存使用等资源使用数据,并通过 Kubernetes 中定义的指标 API 提供这些数据。在使用kubectl top node或kubectl top pod命令后,需要此组件来获取详细信息。
容器存储接口(CSI)
容器存储接口(CSI)是一个 Kubernetes 规范,要求存储基础设施提供商进行实现。它将在 Kubernetes 平台中用于为需要持久存储的工作负载提供持久卷。它为 Kubernetes 用户提供了更多不同存储解决方案的选择。一个 Kubernetes 集群可以拥有不同类型的存储,包括固态硬盘(SSDs)、机械硬盘(HDDs)以及其他提供不同数据输入和输出速率的变种。TKG 使用专门针对 vSphere、AWS 或 Azure 的存储驱动程序。
CoreDNS
CoreDNS(coredns.io/)是一个开源 DNS 服务器,用于提供 Kubernetes 服务名称解析。开源的 Kubernetes 为此目的安装了 kube-dns,但允许您用 CoreDNS 替换 kube-dns,CoreDNS 是一个更为增强的 DNS 服务器。TKG 集群默认部署 CoreDNS。
容器网络接口(CNI)
根据 Kubernetes 网络规范,集群中的每个 Pod 应具有唯一的 IP 地址,并且应能够与集群中任何其他节点上的其他 Pod 进行通信,而无需进行网络地址转换(NAT)。此外,运行在节点上的所有代理,例如 kubelet,应该能够与其各自节点上运行的每个 Pod 进行通信。这些要求确保同一集群上部署的应用程序之间的顺畅通信。然而,我们需要一个特定的网络配置来实现这一规范。这就是 CNI 实现,也称为 Kubernetes 集群的覆盖网络。有许多 CNI 实现可供选择用于 Kubernetes 集群,其中 TKG 支持Antrea(antrea.io/)和Calico(www.tigera.io/project-calico/),我们可以在平台设置期间选择其中之一。
控制平面负载均衡器
TKG 可以创建多主节点的 Kubernetes 集群,以实现 Kubernetes 集群控制平面对象的高可用性。这类集群通常有三个 Kubernetes 控制平面(主节点)节点,负责处理 Kubernetes API 流量并执行重要的工作负载管理活动。对于 AWS 和 Azure 上的 TKG 部署,TKG 会创建各自的虚拟负载均衡器对象,将其置于这些控制平面节点前面,用于分配 API 服务器流量。对于 vSphere,TKG 包含了NSX 高级负载均衡器(www.vmware.com/products/nsx-advanced-load-balancer.html)来为同一目的创建虚拟负载均衡器。然而,如果 TKG 在 vSphere 上没有配置 NSX 高级负载均衡器,它会使用一个名为 kube-vip 的开源轻量级虚拟负载均衡器(kube-vip.io/)。kube-vip 也是一个 CNCF 监管的项目。
Tanzu Kubernetes Grid 的扩展包
开源的 Kubernetes 发行版包括部署 Kubernetes 平台所需的最小组件。然而,要部署一个生产级的 Kubernetes 环境,我们还需要一些其他的功能,例如日志记录、监控、访问控制、备份和恢复等。由于 TKG 是一个企业级的 Kubernetes 发行版,它还附带了许多这样的开源扩展包,并提供 VMware 签名的二进制文件。让我们来了解这些组件。
日志记录
Fluent Bit (fluentbit.io/)是一个高性能的开源日志转发工具,支持不同版本的 Linux 和 Windows 操作系统。Fluent Bit 也是一个 CNCF 子项目。该工具的目的是处理从 Kubernetes 节点和工作负载 Pod 发出的日志,并可以配置将其转发到多种日志聚合目的地,包括 Splunk、Elasticsearch、Amazon CloudWatch、Kafka 等。
Ingress 控制器
TKG 提供了 Contour (projectcontour.io/)二进制文件,作为扩展包提供用于部署在 Kubernetes 集群上的面向外部服务的入口路由。Contour 是一个开源项目,属于 CNCF 旗下,内部使用 Envoy 代理(www.envoyproxy.io/),这是另一个 CNCF 开源项目。结合 Envoy(作为数据平面)和 Contour(作为控制平面),提供了入口控制器所需的实现,通过 Kubernetes 的入口资源定义提供 HTTP 层(网络层 7)服务路由。
身份验证与认证
TKG 还包括了Pinniped(pinniped.dev/),另一个由 VMware 支持的 CNCF 开源项目,用于提供 Kubernetes 集群用户身份和认证管理的便捷按钮。上游 Kubernetes 发行版不包含任何身份验证机制,仅提供授权配置。因此,TKG 提供了 Pinniped 作为一个扩展包,允许集群用户使用基于轻量级目录访问协议(LDAP)服务器或Open ID Connect(OIDC)的现有身份提供者进行认证。
可观测性
对于集群的可观测性,TKG 还提供了Prometheus(prometheus.io/)和Grafana(github.com/grafana/grafana)的签名二进制文件,这两个在 Kubernetes 生态系统中非常流行的开源监控工具。在这里,Prometheus 是一个指标聚合引擎,而 Grafana 是用于可视化的指标渲染工具。除了这些内置的监控工具外,TKG 还支持与 VMware Aria Operations for Applications 进行一流集成,这是 VMware 组合中的软件即服务(SaaS)平台,提供更多关于扩展、功能和全栈可观测性的能力。我们将在第十章**,使用 VMware Aria Operations 实现全栈可见性 详细介绍此产品。
容器注册表
TKG 还包含了Harbor,一个专为容器注册表的定制扩展包,如果需要,可以在集群中安装。我们在第六章**,使用 Harbor 管理容器镜像 详细介绍了 Harbor。
备份和恢复
灾难恢复是支持生产应用的平台中非常重要的一个方面。Kubernetes 集群运行关键生产工作负载时也不例外。然而,Kubernetes 本身并未包含任何用于备份和恢复其集群中工作负载状态的工具。为填补这一空白,TKG 在捆绑包中包含了Velero(velero.io/),作为一个扩展包。Velero 也是一个 CNCF 项目下的开源项目。Velero 提供了在集群级别、Kubernetes 命名空间级别或基于附加元数据的特定工作负载级别进行备份和稍后恢复的方法。Velero 还可以对包含有状态应用数据的持久卷进行备份和在需要时进行恢复。这是在 Tanzu Mission Control 中用于备份和恢复功能的工具。我们将在第九章详细介绍,使用 Tanzu 管理和控制 Kubernetes 集群。
ExternalDNS
TKG 还提供了ExternalDNS (github.com/kubernetes-sigs/external-dns),这是一个开源的 Kubernetes SIG 项目,作为扩展包使用。ExternalDNS 允许你动态控制集群中部署的外部服务的 DNS 记录,使用 Kubernetes 资源定义文件的方式,独立于 DNS 提供商。运行在 Kubernetes 集群上的外部服务可以通过 ExternalDNS 在连接的 DNS 服务器(如 AWS Route53 或 Google Cloud DNS)上处理所需的 DNS 记录绑定。可以说,它提供了一种使用 Kubernetes 资源定义来控制外部 DNS 配置的方式。
cert-manager
cert-manager (cert-manager.io/) 是另一个 CNCF 开源项目,TKG 将其作为扩展包来管理 Kubernetes 集群中使用的 X.509(身份)证书。cert-manager 从多种配置的证书颁发机构获取证书,确保证书的有效性,并在证书到期前尝试自动续期。
现在我们已经了解了 TKG 包含的组件,接下来我们来学习这个平台的一些重要概念。
Tanzu Kubernetes Grid 的重要概念
TKG 是一个分布式系统,包含多个组成部分。为了理解 TKG 的工作原理,我们需要了解这个系统的一些概念。让我们来看看。
启动集群
如本章前面所述,TKG 使用一个 kind 集群在选定的基础设施上部署 TKG 基础平台。这个 kind 集群非常小,运行在操作员的工作站中的 Docker 容器里,通常是个人电脑。这个 kind 集群包含所需的设备,包括 Tanzu 安装门户和其他帮助启动 TKG 基础平台的组件。正因为如此,这个 kind 集群也被称为启动集群(bootstrap cluster)。
Tanzu Kubernetes 版本(TKrs)
TKG 部署可能支持多个不同版本的 Kubernetes。TKr 是 TKG 下的一个自定义资源定义,包含一个 Kubernetes 版本的引用,TKG 可以部署和管理该版本。TKr 包括组件,如 Antrea 及其与给定 Kubernetes 版本相关的版本定义。TKG 的管理集群运行一个 TKr 控制器,持续检查公共注册表中是否有新的 Kubernetes 版本可用。一旦新版本可用,TKr 控制器会在 TKG 管理集群中下载所需的工件,以供使用。通过这种方式,一个 TKG 管理集群可以部署和管理多个 Kubernetes 版本,这些版本都在该 TKG 版本下受到支持。这样的安排为不同的团队提供了灵活性,允许他们在不同版本的 Kubernetes 上运行自己的应用,同时仍由同一个 TKG 控制平面进行管理。
管理集群
每个 TKG 基础设施都有一个管理集群。管理集群仅仅是一个运行特定工作负载的 Kubernetes 集群,用于管理其他 Kubernetes 集群的生命周期。一个 TKG 基础设施及其管理集群是与基础设施相关的。因此,如果我们想在所有平台上部署 TKG 集群,我们需要为 vSphere、AWS 和 Azure 各自配置一个管理集群。这是因为管理集群包含底层特定云平台的集群 API 配置。通过这种方式,管理集群可以在其部署的同一云平台上创建多个 Kubernetes 工作负载集群。除了创建、扩展、升级和删除 Kubernetes 集群之外,管理集群还会跟踪 Kubernetes 集群节点的实际状态与期望状态之间的差异(如果配置了此功能)。管理集群会重启或重新创建它所管理的集群中的不健康或丢失的节点。管理集群只是一个正常的 Kubernetes 集群,也可以运行任何自定义应用,但它应该仅用于其主要目的,即操作大量的 Kubernetes 集群。考虑到它对其他 Kubernetes 集群的管理权限,管理集群的访问权限应该严格限制在 TKG 平台操作团队中。TKG 平台操作人员可以通过在管理集群下使用 Kubernetes 命名空间来授予管理集群有限的访问权限。这样,不同的团队可以使用相同的管理集群来管理与特定命名空间关联的 Kubernetes 集群的生命周期。除了上游 Kubernetes 组件外,TKG 管理集群还部署了以下 TKG 特定组件:
- 
集群 API 组件 
- 
cert-manager 
- 
secretgen-controller 
- 
kapp-controller 
- 
tkr-controller 
工作负载集群
工作负载集群是由管理集群创建的正常 Kubernetes 集群。工作负载集群是我们部署应用程序的地方。根据组织的实践和规模,不同的团队及其应用环境可能会使用独立的工作负载集群。工作负载集群的节点数量仅受基础设施可用性的限制。然而,建议将集群规模保持尽可能小,以减少出现问题时的影响范围,并加快维护时间。TKG 使得管理多个 Kubernetes 集群变得非常简单。正如我们之前讨论的那样,管理集群下的工作负载集群可能会根据使用它们的团队的需求,支持不同版本的 Kubernetes。
节点池
一个 TKG 集群可能有不同类型的工作节点,这些节点具有不同的配置和附加的资源。这样的异构节点类型使得不同类型的工作负载可以根据特定的资源需求或仅为了隔离目的来利用它们。例如,一个工作负载集群可能有一些带有可用 图形处理单元(GPU)的节点,这些节点可以被极度依赖计算的机器学习工作负载使用。我们可以通过 TKG 中的 节点池 将这些不同类型的节点添加到工作负载集群中。之后,我们可以配置这些节点的污点和容忍度,以便只允许需要使用某些类型节点的工作负载进行调度。
部署拓扑
TKG 支持两种不同的部署拓扑,用于创建管理集群和工作负载集群:
- 
开发计划:在此拓扑中,TKG 创建一个控制平面节点和所需数量的工作节点。此计划用于非关键性部署,可以容忍 Kubernetes API 服务器、etcd 和其他控制平面功能的不可用。该拓扑需要较少的资源,通常用于实验环境。 
- 
生产计划:在此拓扑中,TKG 创建三个控制平面节点,并通过负载均衡器将其前置,提供高可用的 Kubernetes 控制平面。如其名所示,它用于承载关键工作负载的集群,并且不能容忍任何控制平面停机。 
图 7.3 显示了 TKG 在高层次上的工作原理。如图所示,操作员使用 tanzu CLI 或 TKG 引导 UI 提供基础设施所需的配置。一旦管理集群创建完成,操作员可以直接使用它来创建所需数量的工作负载集群:

图 7.3 – TKG 布局
在下一节中,我们将学习如何在 AWS 上创建 TKG 管理集群,并详细了解操作流程。
开始使用 Tanzu Kubernetes Grid
作为一个多云解决方案,TKG 可以安装在基于 vSphere 的本地环境中,或者在 Microsoft Azure 和 亚马逊 Web 服务(AWS)等公有云平台上。为了保持本章的长度适中,我们将仅介绍如何在 AWS 上安装和配置 TKG 基础设施。您可以在此链接中找到更多 TKG 安装和配置的详细信息:docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.5/vmware-tanzu-kubernetes-grid-15/GUID-mgmt-clusters-prepare-deployment.html。
在本节中,我们将执行以下任务:
- 
配置引导机器 —— 安装将从中触发的操作员工作站 
- 
部署 TKG 管理集群 
- 
使用管理集群创建 TKG 工作负载集群 
- 
获取访问工作负载集群的权限 
但在我们开始之前,我们需要确保满足以下前提条件,以完成这些任务。
前提条件
以下是遵循本节中 TKG 安装说明的前提条件:
- 
一个 AWS 账户,包含以下内容: - 
一个访问密钥和访问密钥的秘密 
- 
注册了用于 TKG 安装区域的 SSH 密钥对 
- 
有权限创建一个 CloudFormation 堆栈,该堆栈定义了身份与访问管理(IAM)资源及其权限 
- 
足够的资源配额,允许在选定区域中创建两个虚拟私有云(VPC)、九个子网(每个可用区两个互联网-facing 和一个内部)、四个 EC2 安全组、两个互联网网关、三个 NAT 网关和三个弹性 IP 地址用于 TKG 部署 
 
- 
- 
一台运行以下配置的 Linux 或 Mac 工作站: - 
互联网访问 
- 
命令行访问 
- 
Web 浏览器访问 
- 
所有 EC2 实例对端口 6443的访问权限,以访问 Kubernetes APIs
- 
已安装并运行 Docker Desktop,分配了 6 GB 内存 
- 
2 核 CPU 
- 
kubectl CLI v1.22 或更高版本 
 
- 
- 
访问网络时间协议(NTP)服务器 
- 
访问 my.vmware.com/并设置账户以下载所需的二进制文件
让我们从第一个任务开始,那就是准备将用于此安装的引导机器。在开始安装之前,我们需要一些工具和环境配置。
配置引导机器
以下子任务为 AWS 上的 TKG 安装准备一个配置了所需工具和设置的引导机器。
安装 Tanzu 和 Kubectl CLI
按照以下步骤操作:
- 
在本地计算机上创建一个目录,用于存储所需的文件: $ mkdir $HOME/tkg-154
- 
访问 my.vmware.com/并使用您的 My VMware 凭证登录。
- 
访问 customerconnect.vmware.com/downloads/details?downloadGroup=TKG-154&productId=1162下载所需的文件。
- 
确保下拉菜单中选择的版本是1.5.4: 

图 7.4 – 选择下载版本
- 在产品下载标签下,滚动至VMware Tanzu CLI 1.5.4部分并下载适用于您操作系统的二进制文件。请注意,本章所采用的操作步骤是在 macOS 机器上进行的。虽然本章中列出的大多数命令在其他平台上也应有效,但可能会有一些小的差异:

图 7.5 – 下载适当的 Tanzu CLI
- 接受最终用户许可协议:

图 7.6 – 接受最终用户许可协议
- 
将二进制文件下载到我们在 第 1 步 中创建的 $HOME/tkg-154目录。
- 
现在,在你下载二进制文件的同一页面,进入 Kubectl 1.22.9 for VMware Tanzu Kubernetes Grid 1.5.4 部分: 

图 7.7 – 下载适当的 Kubectl CLI
- 
将二进制文件下载到相同的 $``HOME/tkg-154目录。
- 
进入 $HOME/tkg-154目录,并解压你之前下载的 CLI 二进制文件。运行以下命令进行此操作:$ cd $HOME/tkg-154$ tar -xvf tanzu-cli-bundle-darwin-amd64.tar.gz$ gunzip -dvf kubectl-mac-v1.22.9+vmware.1.gz
- 
在本地系统上安装 Tanzu CLI: $ sudo install cli/core/v0.11.6/tanzu-core-darwin_amd64 /usr/local/bin/tanzu
- 
通过运行以下命令验证安装: $ tanzu version
你应该在输出中看到版本 0.11.6。
- 
初始化 Tanzu CLI: $ tanzu init
- 
清理任何现有的 Tanzu 插件,以便从头开始: $ tanzu plugin clean
- 
确保你在 $HOME/tkg-154目录下,该目录包含解压的cli目录:$ cd $HOME/tkg-154/
- 
运行以下命令安装此 TKG 版本所需的所有插件: $ tanzu plugin sync
你应该能够看到以下命令执行的输出:
Checking for required plugins...
Installing plugin 'cluster:v0.11.6'
Installing plugin 'kubernetes-release:v0.11.6'
Installing plugin 'login:v0.11.6'
Installing plugin 'management-cluster:v0.11.6'
Installing plugin 'package:v0.11.6'
Installing plugin 'pinniped-auth:v0.11.6'
Installing plugin 'secret:v0.11.6'
Successfully installed all required plugins
  Done
- 
通过运行以下命令验证插件的安装状态: $ tanzu plugin list
你应该能够看到所有插件列出,包括它们的版本和状态,如下图所示:

图 7.8 – 已安装的 TKG 插件列表
现在,让我们安装 Kubectl CLI。
- 
从 $HOME/tkg-154目录运行以下命令,这里是我们下载并解压 Kubectl CLI 的地方:$ chmod ugo+x kubectl-mac-v1.22.9+vmware.1$ sudo install kubectl-mac-v1.22.9+vmware.1 /usr/local/bin/kubectl
- 
通过运行 kubectl version命令验证安装。你应该看到客户端版本为 v1.22.9+vmware.1。
安装 Carvel 工具
正如我们在上一节中讨论的,TKG 使用 Carvel 工具包进行打包和安装。因此,我们需要在引导机上安装一些 Carvel 工具的 CLI 二进制文件。我们之前下载并解压的 Tanzu CLI 包含了所有这些工具。以下步骤描述了安装这些工具的过程:
- 
进入 $HOME/tkg-154下的cli目录:$ cd $HOME/tkg-154/cli
- 
使用以下命令安装 ytt: $ gunzip ytt-darwin-amd64-v0.37.0+vmware.1.gz$ chmod ugo+x ytt-darwin-amd64-v0.37.0+vmware.1$ mv ./ytt-darwin-amd64-v0.37.0+vmware.1 /usr/local/bin/ytt
- 
验证 ytt --``version命令。
- 
使用以下命令安装 kapp: $ gunzip kapp-darwin-amd64-v0.42.0+vmware.2.gz$ chmod ugo+x kapp-darwin-amd64-v0.42.0+vmware.2$ mv ./kapp-darwin-amd64-v0.42.0+vmware.2 /usr/local/bin/kapp
- 
验证 kapp --``version命令。
- 
使用以下命令安装 kbld: $ gunzip kbld-darwin-amd64-v0.31.0+vmware.1.gz$ chmod ugo+x kbld-darwin-amd64-v0.31.0+vmware.1$ mv ./kbld-darwin-amd64-v0.31.0+vmware.1 /usr/local/bin/kbld
- 
验证 kbld --``version命令。
- 
使用以下命令安装 imgpkg: $ gunzip imgpkg-darwin-amd64-v0.22.0+vmware.1.gz$ chmod ugo+x imgpkg-darwin-amd64-v0.22.0+vmware.1$ mv ./imgpkg-darwin-amd64-v0.22.0+vmware.1 /usr/local/bin/imgpkg
- 
验证 imgpkg --``version命令。
安装 AWS 特定工具
在 AWS 平台上部署 TKG 基础设施需要在引导机上安装 aws CLI。让我们进行配置:
- 
使用以下说明安装 aws CLI: docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html。
- 
通过运行以下命令验证 aws CLI 的安装: $ aws –version
你应该能够看到 CLI 版本,如下所示的输出。版本可能会有所不同,取决于安装时的时间,但应该是 v2.x 版本:
aws-cli/2.5.3 Python/3.9.11 Darwin/21.4.0 exe/x86_64 prompt/off
- 
运行以下命令,配置你的 AWS 账户访问配置文件,以便用于此次安装,且具有先前定义的权限和配额: $ aws configure –profile tkg
- 
提供访问密钥、秘密访问密钥、区域和命令输出格式的值,如下所示的代码: AWS Access Key ID [None]: ********************AWS Secret Access Key [None]: ****************************************Default region name [None]: us-east-1Default output format [None]: text
在这里,你可以将 us-east-1 替换为任何其他符合先前列出要求的 AWS 区域。
- 
运行以下命令,确保你能看到该区域中列出的现有 SSH 密钥对,如先前要求中所列: $ aws ec2 describe-key-pairs --profile tkg
此命令的输出应至少显示列出的一个密钥对。
现在我们已经在引导机器上配置了所有所需的工具,可以开始安装 TKG 管理集群了。让我们开始吧。
安装管理集群
在本节中,我们将使用 Tanzu 安装程序 UI 在配置好的 AWS 账户上部署管理集群。
重要提示
默认情况下,上游 Kubernetes 发行版不包含用户身份验证功能,并且允许用户拥有管理员级别的访问权限。为了填补这一空白,TKG 配备了 Pinniped,用于集成外部 LDAP 或 OIDC 身份提供者。为了简化安装前提条件和复杂度,我们将不使用此类集成,因为它需要预先配置好的 LDAP 或 OIDC 设置访问。现实中的 TKG 集群绝不应在没有外部身份提供者集成的情况下配置。你可以在此了解更多相关内容:docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.5/vmware-tanzu-kubernetes-grid-15/GUID-iam-configure-id-mgmt.html。
此外,尽管旨在最小化复杂性和基础设施占用,但遵循此在 AWS 上配置 TKG 会产生云服务使用费用,因为它将使用不符合免费额度资格的 EC2 实例类型,并且还会使用一些其他收费服务,如 Elastic IP、NAT 网关、EBS 卷、Elastic Load Balancer 等。如果你计划按照本指南在 AWS 上安装 TKG,建议你在本章稍后的过程中清理资源,并手动检查以验证所有配置的资源已被移除。
以下步骤概述了安装过程:
- 
确保本地的 Docker 守护进程正在运行,以便在引导机器上部署和运行容器。 
- 
运行以下命令以在引导工作站的默认浏览器窗口中启动安装程序 UI。此 UI 支持 Chrome、Safari、Firefox、Internet Explorer 和 Edge,以及它们的较新版本: $ tanzu mc create --ui
此命令应自动打开浏览器窗口并运行 UI。否则,可以通过 http://127.0.0.1:8080/ 访问。
- 点击Amazon Web Services下的DEPLOY按钮,如下图所示:

图 7.9 – 选择用于部署的 Amazon Web Services
- 
按照以下子步骤选择必要的 AWS 账户详细信息;这些已在下图中突出显示: - 
将AWS CREDENTIAL TYPE设置为Credential Profile。 
- 
从 AWS CREDENTIAL PROFILE 下拉菜单中选择 tkg,并选择我们在本章 aws CLI 配置期间配置的相关 REGION。 
- 
点击CONNECT按钮,以确保 UI 能通过先前创建的配置连接到选定的 AWS 账户。 
- 
点击NEXT按钮进入下一个配置部分: 
 
- 

图 7.10 – 选择用于安装的 AWS 账户
- 点击NEXT按钮选择默认的 VPC 配置,如下图所示:

图 7.11 – 选择默认 VPC 配置
- 将管理集群部署计划设置为开发,并将实例类型设置为t3.large。此实例类型具有 2 个 vCPU 和 8 GiB 内存,足够用于实验室级别的设置:

图 7.12 – 选择管理集群的部署计划和实例类型
- 
输入管理集群的其他详细信息,如下述子步骤所示,并在下图中显示: - 
在 tkg-aws-mgmt-cluster下输入一个简短的名称。
- 
输入在 aws CLI 配置的步骤 5中获得的 SSH 密钥对名称,在EC2 KEY PAIR下提供。 
- 
保持复选框选项的默认选择不变。 
- 
从所选区域的 AVAILABILITY ZONE 1 下拉菜单中选择一个可用区以部署管理集群。对于生产部署计划,我们需要为管理集群的三个控制平面节点选择三个可用区。 
- 
从 AZ1 WORKER NODE INSTANCE TYPE 下拉菜单中选择t3.large作为工作节点实例类型。 
- 
点击NEXT按钮继续: 
 
- 

图 7.13 – 输入管理集群的详细信息
- 可选地,输入管理集群的元数据并点击NEXT按钮:

图 7.14 – 输入管理集群的元数据
- 保持默认的 Kubernetes 容器网络配置不变,并点击NEXT按钮:

图 7.15 – 保持默认的 Kubernetes 网络配置不变
- 禁用身份管理设置后,点击下一步按钮:

图 7.16 – 禁用身份管理设置
- 选择管理集群的操作系统镜像,如截图所示,然后点击下一步按钮:

图 7.17 – 选择管理集群的操作系统
- 可选地,选择参与 VMware 的客户体验改进计划(CEIP),然后点击下一步按钮:

图 7.18 – 选择参与客户体验改进计划
- 点击审查配置按钮,验证输入后再触发 AWS 上的管理集群创建:

图 7.19 – 打开配置摘要进行审查
- 以下截图显示了验证摘要页面的底部。所显示的命令可以在未来用于通过 Tanzu CLI 重新触发相同的部署。右下角的导出配置链接允许我们将此配置导出为文件,以便作为参考,在 AWS 上部署其他管理集群并进行必要的修改。最后,点击部署管理集群按钮以触发部署:

图 7.20 – 启动管理集群的部署
- 您将看到各种部署日志及其安装状态,如下图所示。如日志中所示,Cluster API 正在创建所需的基础设施组件,以便在 AWS 上部署管理集群:

图 7.21 – 部署状态及日志
- 安装应该在大约 10 到 15 分钟内完成,您应该会看到一个成功消息,如下图所示。如图中所示,日志还显示了如何从引导机访问管理集群并执行不同的 TKG 操作。您还应该能够在运行 tanzu mc create --ui命令的命令行中看到这些日志,这个命令会弹出安装浏览器窗口:

图 7.22 – 成功安装管理集群
现在我们已经完成了管理集群的安装,让我们来学习如何使用它创建第一个 TKG 工作负载集群。
创建工作负载集群
以下步骤概述了如何使用从安装管理集群时启动的引导机器访问新创建的 TKG 管理集群。作为安装步骤的一部分,TKG 将kubeconfig详细信息添加到引导机器,以便允许管理员级别访问管理集群,从而使 Tanzu CLI 指向管理集群。让我们使用管理集群和 Tanzu CLI 创建我们的第一个工作负载集群。以下步骤将在引导机器上执行:
- 
运行以下命令设置指向新创建的 TKG 管理集群的 kubectl 上下文: $ kubectl config use-context tkg-aws-mgmt-cluster-admin@tkg-aws-mgmt-cluster
- 
运行 tanzu mc get命令查看管理集群的详细信息。该命令将显示管理集群已创建一个控制平面和一个工作节点:

图 7.23 – 管理集群详细信息
要创建工作负载集群,我们需要将工作负载集群配置文件提供给管理集群。该文件包含以下详细信息:
- 
集群名称 
- 
集群部署计划(开发或生产) 
- 
工作节点数量 
- 
工作节点 EC2 类型 
- 
AWS 特定配置,如区域、可用区、网络和 SSH 密钥 
- 
节点操作系统 
- 
节点健康检查配置 
- 
节点级别自动扩展配置 
我们不需要在配置文件中包含所有属性,只需要指定必需的属性。有关配置文件的更多属性列表,请访问docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.5/vmware-tanzu-kubernetes-grid-15/GUID-tanzu-k8s-clusters-aws.html#tanzu-kubernetes-cluster-template-0。
我们将从本书的 GitHub 仓库下载一个预配置文件,并使用它来创建工作负载集群。
- 
使用以下命令将工作负载集群配置文件复制到引导机器: $ curl https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-07/tkg-workload-cluster-config.yaml -o $HOME/tkg-154/tkg-workload-cluster-config.yaml
- 
配置文件应位于 $HOME/tkg-154/目录中,并命名为tkg-workload-cluster-config.yaml。使用您选择的编辑器打开该文件,并更新以下参数值:- 
如果您使用的 AWS 区域不是us-east-1,请根据所选区域更新AWS_NODE_AZ、AWS_NODE_AZ_1和AWS_NODE_AZ_2。 
- 
如果适用,请根据您的AWS_PROFILE配置更新AWS_REGION。 
- 
更新AWS_SSH_KEY_NAME以使用选定区域中您 AWS 帐户的 SSH 密钥。这是必须更改的。 
 
- 
- 
运行以下命令使用我们在上一步中准备的配置文件创建工作负载集群。这里,我们使用 --tkr选项创建一个 Kubernetes v1.21.11 的集群,以便我们稍后学习如何将集群升级到 v1.22.9:$ tanzu cluster create --file $HOME/tkg-154/tkg-workload-cluster-config.yaml --tkr v1.21.11---vmware.1-tkg.3
如果所有配置更改都正确完成,工作负载集群应在大约 10 到 15 分钟内创建完成。
- 
使用以下命令验证集群的创建状态: $ tanzu cluster list
您应该看到集群正在运行,如下面的截图所示:

图 7.24 – 验证工作负载集群的创建
到此,TKG 工作负载集群已创建。现在,让我们访问工作负载集群。
- 
运行以下命令获取工作负载集群的 kubeconfig:$ tanzu cluster kubeconfig get tkg-aws-workload-cluster --admin
- 
运行以下命令切换 kubectl上下文,使其指向工作负载集群:$ kubectl config use-context tkg-aws-workload-cluster-admin@tkg-aws-workload-cluster
- 
运行以下命令列出工作负载集群的节点以确保连通性: $ kubectl get nodes
您应该能够看到 Kubernetes 节点列表,如下面的截图所示:

图 7.25 – 验证工作负载集群的连通性
到此,我们已经完成了开始使用 TKG 所需的所有任务。我们从引导机器的配置开始,安装了所有必需的工具和 CLI。然后,我们使用 Tanzu 安装器 UI 在 AWS 上创建了一个 TKG 管理集群。最后,我们使用我们创建的管理集群创建了一个 TKG 工作负载集群。值得注意的是,一个引导机器可能会引用多个 TKG 管理集群。操作员可以通过切换 kubectl 上下文到适当的管理集群配置,然后使用 tanzu login 命令进行管理集群的身份验证,来管理其下的工作负载集群。现在,在本章的下一部分也是最后一部分中,我们将学习关于 TKG 周围一些最常见的 Day-2 活动。
与 Tanzu Kubernetes Grid 的常见 Day-2 操作
现在我们在 AWS 上有一个完全配置和运行的 TKG 基础设施,让我们学习如何在其上执行一些 Day-2 操作。TKG 通过在幕后执行所有繁重的工作使这些操作变得非常简单:
- 
缩放集群以添加或移除节点 
- 
升级集群以提升 Kubernetes 版本 
- 
删除一个集群 
- 
删除整个 TKG 基础设施 
让我们开始扩展工作负载集群,使其具有三个工作节点,而不仅仅是一个。
缩放 Tanzu Kubernetes Grid 集群
运行以下命令以扩展我们创建的工作负载集群:
- 
切换 kubectl上下文,使其指向我们之前创建的管理集群,该集群用于创建工作负载集群:$ kubectl config use-context tkg-aws-mgmt-cluster-admin@tkg-aws-mgmt-cluster
- 
通过运行以下命令确保工作负载集群仅有一个工作节点: $ tanzu cluster list
您应该看到以下输出,显示 1/1 个工作节点:

图 7.26 – 确保工作节点计数
- 
运行以下命令添加两个工作节点,将总数增加到三: $ tanzu cluster scale tkg-aws-workload-cluster -w 3
你应该看到以下消息,显示扩展正在进行中:

图 7.27 – 工作节点扩展进行中
- 
运行以下集群列出命令来验证扩展是否已完成: $ tanzu cluster list
现在你应该在输出中看到 3/3 个工作节点:

图 7.28 – 确认集群扩展已完成
这些步骤展示了如何扩展 TKG 集群。相同的过程也适用于缩减集群。scale 命令的 -w 选项声明了所需的工作节点数量。根据所需数量的变化,TKG 会添加或删除工作节点。扩展命令还提供了扩展控制平面节点或特定节点池节点的选项。你可以通过运行 tanzu cluster scale --help 命令了解更多关于扩展的信息。
升级 Tanzu Kubernetes Grid 集群
现在我们已经完成扩展,让我们学习如何将 TKG 工作负载集群升级到部署一个更新版本的 Kubernetes。TKG 允许在管理集群下按需升级选定集群。在这里,集群的所有者可以选择他们需要的 Kubernetes 版本,以便有足够的时间准备升级他们的工作负载集群。以下步骤概述了升级过程:
- 
切换 kubectl上下文,使其指向我们之前创建的管理集群,该集群用于创建工作负载集群:$ kubectl config use-context tkg-aws-mgmt-cluster-admin@tkg-aws-mgmt-cluster
- 
使用以下命令确保工作负载集群部署的是 Kubernetes v1.21.11: $ tanzu cluster list
你应该看到以下输出,显示集群已部署 Kubernetes 版本 1.21.11:

图 7.29 – 检查集群当前的 Kubernetes 版本
- 
运行以下命令检查可用的 Kubernetes 版本以进行升级: $ tanzu kubernetes-release get
你应该看到以下输出,显示 v1.22.9 作为升级 v1.21.11 的选项,如下图所示:

图 7.30 – 检查可用的版本升级选项
- 
运行以下命令将工作负载集群升级到 Kubernetes 版本 1.22.9: $ tanzu cluster upgrade tkg-aws-workload-cluster --tkr v1.22.9---vmware.1-tkg.1
--tkr 选项指定了我们从之前步骤中可用版本列表中选择的升级目标版本。此命令将以滚动方式升级工作负载集群,一次升级一个节点,以最大程度减少工作负载停机时间。运行多个 Pod 的应用程序在这种滚动升级过程中不会面临任何停机。执行上述命令后,你应该在大约 15 到 20 分钟后看到以下确认消息:

图 7.31 – 集群升级日志
以下截图显示了在 AWS EC2 控制台上回收工作负载集群节点以创建新版本的过程。这里可以看到,旧节点已被终止,新的版本节点已创建并替换它们:

图 7.32 – 在 AWS EC2 控制台上回收集群节点
- 
运行以下命令确保工作负载集群正在使用较新的 Kubernetes 版本: $ tanzu cluster list
以下截图显示工作负载集群正在运行 Kubernetes 版本 1.22.9:

图 7.33 – 确认工作负载集群的升级
除了允许 Kubernetes 版本进行升级,tanzu cluster upgrade命令还允许你升级特定操作系统及其版本的集群。运行tanzu cluster upgrade –help命令了解更多信息。除了为了这些原因升级 TKG 集群外,还有一个升级维度——升级 TKG 版本本身。升级 TKG 版本(从 TKG v1.5.x 到 v1.5.y 或从 v1.4.x 到 v1.5.y)超出了本书的范围。然而,你可以在这里了解更多:docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.5/vmware-tanzu-kubernetes-grid-15/GUID-upgrade-tkg-index.html。
删除 Tanzu Kubernetes Grid 工作负载集群
毁灭总是比建设容易。这对于 TKG 工作负载集群也是如此。以下简单步骤概述了删除本章中我们使用过的 TKG 工作负载集群的过程:
- 
切换 kubectl上下文,使其指向我们之前创建的管理集群,该集群用于创建工作负载集群:$ kubectl config use-context tkg-aws-mgmt-cluster-admin@tkg-aws-mgmt-cluster
- 
运行以下命令删除工作负载集群及其在 AWS 账户上的资源: $ tanzu cluster delete tkg-aws-workload-cluster
你应该在控制台看到以下确认信息,表示集群删除正在进行中:

图 7.34 – 集群删除进行中
以下来自 AWS EC2 控制台的截图显示,所有工作负载集群的节点已被终止:

图 7.35 – 在 AWS EC2 控制台上终止的集群节点
除了 EC2 实例外,TKG(借助 Cluster API)还会删除在你的 AWS 账户中为已删除集群创建的其他网络资源。正如你可能已经猜到的,删除 Kubernetes 集群是一个非常敏感的操作,可能会导致正在运行的应用程序长时间停机。因此,应采取广泛的措施,防止在实验环境之外的其他环境访问此类操作。现在,让我们看一个更具破坏性的操作:删除整个 TKG 基础设施,包括管理集群。
删除 Tanzu Kubernetes Grid 基础设施
除非在这样的实验环境中,否则你很少需要从根本上删除 TKG 基础设施。不过,我们将会在本章中讲解这一 TKG 生命周期活动。要删除一个 TKG 基础设施,我们只需要删除为其创建的管理集群。和删除工作负载集群一样,删除管理集群也是一个简单但高度破坏性的过程。以下步骤概述了这一过程:
- 
通过运行以下命令,确保你指向的是正确的 Kubernetes 集群的 kubectl上下文:$ kubectl config use-context tkg-aws-mgmt-cluster-admin@tkg-aws-mgmt-cluster
- 
运行以下命令删除管理集群及其在 AWS 账户中的资源: $ AWS_REGION=us-east-1 tanzu mc delete --verbose 5
根据管理集群的部署区域,你可能需要在命令中替换区域名称。执行命令后,你应该在控制台上看到如下日志,这表明由于 --verbose 选项,集群删除正在进行,并随后显示日志的详细级别。此命令的日志详细级别从 0 到 9,9 表示最详细的日志:

图 7.36 – 管理集群删除日志
你可能从日志中了解到,TKG 在引导机器上创建了一个 kind 集群,以执行所有必要的清理操作,将 TKG 基础设施从 AWS 账户中删除。这与我们在本章早些时候看到的 TKG 创建管理集群时使用的方法相同。
至此,我们已经完成了关于 TKG 集群的一些重要的第 2 天活动。现在,让我们通过快速总结一下我们所学到的内容来结束这一章节。
总结
在本章的开始,我们讨论了 TKG 作为基于 Kubernetes 的容器平台可能是一个不错选择的一些原因。正如我们在动手实践中所看到的,TKG 通过提供统一的接口——Tanzu CLI,使 Kubernetes 平台的部署和管理变得非常简便且在操作上高效。在本章中我们执行的所有基于 Tanzu CLI 的操作都是基础设施无关的,提供了所需的多云操作简便性。
由于本书中 TKG 的范围有限,我们无法安装和使用 TKG 提供的所有可选扩展,但我们简要介绍了它们,以便了解它们的应用。我们看到 TKG 如何广泛使用来自 CNCF 生态系统的各种精心挑选的开源工具。通过这种方式,TKG 成为一个完全由开源社区支持的解决方案。
最后,我们了解了在 TKG 平台上的常见第 1 天和第 2 天活动,从在 AWS 上安装平台并创建工作负载集群以托管实际应用容器开始。接下来,我们学习了如何通过按需扩展为该工作负载集群增加更多容量。我们还了解了如何轻松地升级集群以应对不同的需求,最后还学会了如何在需要时删除集群及其基础设施。
如你所料,为了使本章的内容简洁,我们并未涵盖关于该主题的许多内容。然而,我们将在第九章《使用 Tanzu Mission Control 管理和控制 Kubernetes 集群》中学习关于 TKG 集群的备份与恢复、合规性扫描和治理策略配置,Tanzu Mission Control 是一个控制数百个 Kubernetes 集群的单一视图平台。
TKG 是 VMware 提供的商业许可软件。在下一章中,我们将深入探讨与Tanzu 应用平台相关的 Tanzu 开发者体验。
第八章:使用 Tanzu 应用平台提升开发者生产力
在企业软件的世界中,我们有大 A应用和小 A应用的概念。大 A可能是一个拥有数百个组件的巨大企业账单系统,而小 A应用可能是一个简单的任务,拉取记录并将它们写入 MongoDB。
类似地,在企业交付软件时,存在大 P和小 P问题需要解决。我今天遇到的一个小 P问题是将一些容器镜像从 VMware 公司容器注册表移动到客户的私有注册表,以便他们可以在不允许外部网络访问的情况下在内部使用它们。另一方面,在企业领域,你可能面临的一些大 P问题如下:
- 
使公司开发人员的生产力显著提高 
- 
快速、安全、一致地将应用程序投入生产 – 最小化繁琐操作和障碍 
- 
使开发人员、运维人员和安全专家朝着相同的方向努力,专注于相同的问题 
- 
当开发人员的经验有限时,将应用程序交付到现代容器平台(如 Kubernetes) 
恰巧,这正是我们在讨论Tanzu 应用平台时提到的四个问题。
在本章中,我们将涵盖以下主题:
- 
为什么我要使用 Tanzu 应用平台? 
- 
Tanzu 应用平台的构建模块 
- 
第一天 – 安装和配置 Tanzu 应用平台 
- 
第二天 – 将应用程序部署到 Tanzu 应用平台 
- 
第三天 – Tanzu 应用平台上的常见操作活动 
- 
下一步 
现在我们知道本章要完成的目标,让我们开始讨论你和你的团队可能需要使用 Tanzu 应用平台的原因。
为什么我要使用 Tanzu 应用平台?
正如我在章节介绍中提到的,编写软件时可能会遇到一些小问题,例如高效地对列表进行就地排序,或将流数据从传统数据库迁移到最新的 NoSQL 数据库,而也有一些大问题,如以下几项:
- 
开发者生产力:企业软件的存在仅仅因为大公司雇佣软件开发人员编写他们用来带来收入并使公司在竞争中脱颖而出的软件。有良好平台的公司可以将开发人员的时间和精力集中在直接影响公司盈利的有意义任务上。这使得开发人员感到被重视。没有好平台的公司将开发人员视为昂贵的成本中心,进而引发一种痛苦的恶性循环,导致士气低落和生产力低下。 
- 
将软件推向生产环境:如果你从未为大型公司编写过软件,可能会对将软件推向生产环境的困难感到惊讶。通常,有许多手动且繁琐的任务需要完成,以确保安全、合规性和下游风险的各项要求。这些领域中的先行者已经找到了自动化去除这些繁琐任务的方法,将这些步骤构建成一个自动化流程,并且将其抽象化,以便开发人员无需亲自处理。 
- 
使开发人员、运维人员和安全人员朝着同一个目标努力:通过将合规性、治理、最佳实践和安全性内建到一个流线化的自动化流程中,你消除了开发人员、运维人员和安全专家之间常见的摩擦。尽管运维人员反对任何形式的变更,安全专家却希望对发布版本进行严格审查。这可能会消耗开发团队数周的时间和精力,并且严重打击士气。通过在软件供应链中构建检查和控制,运维人员和安全专家可以放心地知道他们的指导意见得到了遵循,而开发人员则能专注于以高效的速度持续交付软件。 
- 
通向 Kubernetes 的快速通道:企业采用 Kubernetes 的趋势正在上升,且几乎没有放缓的迹象。Kubernetes 是一个非常强大的平台,能够实现一些重要的成果。然而,它也伴随着相当复杂性和陡峭的学习曲线。Tanzu 应用平台抽象掉了部分复杂性,使得软件团队能够利用 Kubernetes,同时受益于一些简化生产路径的抽象。 
总结一下,Tanzu 应用平台是一个端到端的软件供应链,旨在以安全、可靠的方式大规模地将软件交付到生产环境。现在我们已经大致了解它的概念,接下来我们将逐步拆解并查看各个组成部分。
Tanzu 应用平台的构建模块
Tanzu 应用平台是一组具有明确目标的技术,协同工作以为平台运维人员、开发人员和安全专家带来显著的成果。深入讲解每个组件将需要超出本章篇幅的空间,因此我建议你访问官方文档,获取关于这些组件的更多细节。
以下图展示了 Tanzu 应用平台的高层次视图:

图 8.1 – Tanzu 应用平台组件
此图试图将各个组件进行分组和分类。以下是根据该图的层次结构对产品的拆解:
- 
tanzuCLI 命令或workload.yaml文件。开发人员可以直接从他们的 IDE 将工作负载部署到 Kubernetes 集群中。
- 
实时更新:开发者可以在本地工作站上进行更改,并在几秒钟内看到这些更改在 Kubernetes 集群上实时运行。这背后使用了Tilt来同步本地代码库与远程 Kubernetes 上运行的工作负载。 
- 
远程调试:有时日志消息并不足够,你需要逐步调试代码,检查本地变量和更大范围的变量。如前所述,在本地工作站上调试是直接的,但在现代环境中,这通常不足以调试 Kubernetes 中出现的问题。在 Kubernetes 上直接调试工作负载通常涉及一堆混乱的启动参数和端口转发。这个插件自动化了整个过程,为开发者提供了一键远程调试的解决方案。 
- 
运行中的工作负载:通过这个仅限 VS Code 的功能,开发者可以在其 IDE 内获得一个面板,来可视化当前 Kubernetes 上下文中运行的所有工作负载。 
- 
Tanzu 应用平台 GUI:基于Backstage开源项目的 Tanzu 应用 GUI 是 Tanzu 应用平台的中央仪表盘。它提供了来自 Backstage 的一些开箱即用的功能,并且有许多非常有用的自定义插件,这些插件仅供 Tanzu 应用平台用户使用。这里是你可以在 Tanzu 应用平台 GUI 中看到的内容的快速预览,首先是 UI 的视觉概览及其布局: ![图 8.2 – Tanzu 应用平台 GUI]() 
图 8.2 – Tanzu 应用平台 GUI
这是你首次访问 Tanzu 应用 GUI 时看到的屏幕。以下是 GUI 组件的详细介绍:
- 组织目录:Tanzu 应用平台 GUI 为整个组织提供了一个中央仓库,用于发布和管理其软件。如果我们深入查看前面截图中的tanzu-java-web-app,我们将看到以下屏幕:

图 8.3 – Tanzu 应用平台 GUI 目录条目
目录条目允许团队为其应用程序的源代码、技术文档、API 定义以及任何相关链接提供一个“全方位服务”:
- 
TechDocs:这是一个 Backstage 插件,允许开发团队以 Markdown 格式创建文档,并将这些文档作为应用程序条目的一部分呈现在组织目录中。 
- 
运行时资源可见性:其他 Tanzu 产品的用户,例如Tanzu 应用服务( tanzu.vmware.com/application-service),通过能够在一个地方查看所有运行时资源,受益匪浅。Tanzu 团队也将这一功能带到了 Tanzu 应用平台 GUI 中。与注册目录实体相关的任何内容将在这里可见。
- 
应用实时视图:该功能与其他组件(如约定服务)协同工作,提供对正在运行的应用程序的运行时状态的深入洞察。 
- 
应用加速器:这个功能,我们在第二章**,开发云原生应用中进行了深入讨论,是 Tanzu 应用平台 GUI 的一部分。 
- 
API 文档:这个功能,我们在第五章**,定义和管理业务 API中进行了深入讨论,也是 Tanzu 应用平台 GUI 的一部分。 
- 
供应链编排器可视化:供应链编排器位于 Tanzu 应用平台的核心,它正如名字所示,是一组输入和输出的链条,指导应用程序从源代码到在生产环境中运行的应用程序。这个插件提供了一个引人注目的供应链可视化。 
- 
供应链编排器:如果你把 Tanzu 应用平台 GUI 看作平台的“眼睛和耳朵”,那么供应链编排器就是它的跳动的心脏。供应链编排器基于开源的Cartographer项目( github.com/vmware-tanzu/cartographer),它允许平台操作员和软件架构师预配置并预批准多个生产路径。可能有一个适用于 PCI 控制下的 Spring Boot API 的生产路径,也可能有另一个适用于事件驱动数据处理应用程序的生产路径。正如 Tanzu 应用平台 GUI 所做的那样,供应链编排器是平台的一项功能,它将其他功能捆绑在一起。以下是一些属于供应链编排器范畴的功能:- 
实时视图约定服务:在我们讨论 Tanzu 应用平台 GUI 时提到了应用实时视图GUI 插件。为了使该插件工作,应用程序需要通过一个有见解的、众所周知的 API 来公开其内部工作。一个简单的方法可能是要求所有应用程序团队自己实现这一点,通过引入一个特定版本的 Spring Boot Actuator,并让它在一个特定端口上运行,并遵循特定的端点命名约定。这将给开发团队带来额外负担,并可能导致配置错误。更好的方法是,在工作负载通过供应链时修改它,以一致且有见解的方式公开其内部工作。正是这个服务实现了这一目标。它位于供应链中,并向所有符合条件的应用程序添加一致的 Java 或 .NET Core 配置参数。 
- 
Cartographer 约定:应用程序实时视图并不是唯一一个适合应用供应链约定的功能。任何平台操作员或 DevOps 负责人希望在整个产品组合中应用的功能都非常适合在这里实现。一个例子是为所有应用程序工件标记项目的拥有者。另一个例子可能是为与 云原生运行时 一起自动扩展的应用程序配置合理的上下限。可能性是无穷无尽的,而 Cartographer 约定是一个方便的方式,能够在平台上运行的各种应用程序中应用约定。 
- 
云原生运行时:这是在 Kubernetes 上运行您可部署应用程序工件的组件。它基于开源 Knative 项目( github.com/knative),尽管它通常被认为是一个无服务器运行时,但也是运行常规 Web 面向工作负载的绝佳方式。它采用独特的负载均衡方法,允许基于可配置的度量进行自动扩展,同时最小化丢失或掉线的请求。
- 
服务工具包:这是另一个由备受喜爱的 Tanzu Application Service 演变而来的功能。该产品允许用户请求配置一个服务,可能是一个数据库或消息队列,并将该服务的凭证在运行时绑定到应用程序上。服务工具包 将相同的功能带入 Kubernetes。您可以将其视为面向开发者的数据服务,首先,他们不希望思考如何管理数据服务,其次,他们不希望手动将应用程序与这些数据服务连接起来。 
- 
Tanzu 构建服务:在前面的条目中,我们讨论了运行可部署工件的内容。Tanzu 构建服务是一个组件,它将应用程序的源代码作为输入,并输出一个以 OCI 容器镜像形式存在的可部署工件。我们在 第三章中深入探讨了这个功能,内容是构建安全的容器镜像与 Build Service。 
- 
工作负载类型:您可以将其视为一组预配置、预整理的供应链,您可以用它来快速启动不同种类的工作负载: - 
Web:这是一个标准的面向 Web 的应用程序,您希望能够根据需求进行扩展和缩减。 
- 
TCP:这非常适合运行一个处理其自身 Web 交互的传统应用程序,并且您希望直接将网络流量传递给它。 
- 
队列:这些是后台运行的应用程序,处理按队列到达的事件。 
- 
函数:这些是 Web 和队列应用程序的混合体,允许开发人员实现一个仅在有请求时才会实例化和调用的功能。 
 
- 
 
- 
- 
应用和平台安全:以下是使安全性在 Tanzu 应用平台中成为一等公民的一些组件: - 
Tanzu 应用平台身份验证和 RBAC 授权:Tanzu 应用平台的 GUI 使用与 Backstage 一起提供的单点登录功能。这使得平台运维人员能够配置 Okta、Google、Azure 和 GitHub 等提供商。此外,GUI 可以配置为监控多个 Kubernetes 集群中的运行资源,而不仅仅是其运行所在的集群。 
- 
应用单点登录:这是应用开发者常见的需求。他们不想管理自己的登录、用户身份验证(authN)或授权(authZ)。相反,他们希望将这些功能委托给平台,由平台为他们处理。这正是此功能所做的。它允许平台运维人员搭建预配置的、具有明确偏好的 Spring Authorization Server 部署,并通过集成到平台的软件供应链中使该服务器可供应用使用。此服务的目的是将单点登录从一开始就集成到应用中,而不是作为最后时刻的附加解决方案。 
- 
供应链安全工具:软件供应链攻击是许多企业软件领域的关注重点,原因也很充分。供应链安全工具是一套直接插入软件供应链的工具,当供应链的任何部分发生变化时,这些工具会使用持续更新的数据库扫描源代码、捆绑的依赖项和生成的容器镜像,查找所有已知的漏洞。这些工具负责扫描工件、存储扫描结果、报告存储的结果,并对生成的工件进行加密签名,以确保它们在扫描后无法更改。这样,平台运维人员只需将这些工具集成到供应链中,就能为其所有运行的工作负载启用最先进的安全性。 
 
- 
- 
启用功能:像 Tanzu 应用平台这样规模和范围的产品需要一种方式,使产品的用户和运维人员能够快速上手。Tanzu 应用平台为用户提供了自己的学习平台。它使平台运维人员能够快速轻松地设置实践工作坊,引导不同角色了解产品。它还包括一个简短的内置工作坊,教授如何构建自己的工作坊。下面是 Tanzu 应用平台学习中心,展示了我最喜欢的功能——浏览器嵌入式 VS Code 编辑器: 

图 8.4 – 带有嵌入式 VS Code 编辑器的学习中心
这使得架构师和运维人员能够构建实际的、可操作的工作坊,这些工作坊可以在浏览器中自动配置并独立运行。以下是一些可用功能的简要列表:
- 
kubectl指向一个实时的 Kubernetes 集群和嵌入式 Docker,因此任何需要 Docker CLI、构建、运行、推送等的操作也是可能的。
- 
嵌入式理解问题:工作坊构建者可以将问题嵌入到工作坊中,以确保用户正确理解概念。 
- 
嵌入式 VS Code 编辑器:工作坊构建者不仅可以将 VS Code 嵌入到工作坊中,还可以提供链接,打开文件、选择编辑器窗口中的代码块,甚至在正确的位置粘贴附加代码片段。 
- 
嵌入式网页:这允许用户将某些内容部署到其专用的工作坊 Kubernetes 实例,并立即在同一窗口中看到其运行情况。它还允许像 Kubernetes Web 控制台这样的工具被暴露出来。 
- 
验证工作坊状态:用户可以点击一个链接,这会触发在控制台中看不到的 Kubernetes 命令。这允许工作坊开发者在继续之前确保工作坊状态如预期。 
- 
Docker 构建:嵌入式控制台使用 Docker in Docker(DIND)来支持所有 Docker 命令的使用。 
- 
下载文件:工作坊开发者可以使用户能够下载任何或所有工作坊文件的本地副本,供以后参考。 
现在我们已经介绍了 Tanzu 应用平台的目标用户和组成内容,是时候开始动手安装它了,正如我们将在下一部分中所做的那样。
第一天 – 安装和配置 Tanzu 应用平台
要安装 Tanzu 应用平台,首先我们需要一些准备工作。
前提条件和技术要求
为了安装和运行 Tanzu 应用平台,必须满足一些技术前提条件。以下是所需的条件列表:
- 一个(大型) Kubernetes 集群
Tanzu 应用平台文档列出了几个受支持的 Kubernetes 集群,包括 Tanzu Kubernetes Grid 和 Minikube。然而,为了使这些说明更易于管理,我将推荐三种公共云 Kubernetes 集群。这些集群如下:
- 
Amazon 弹性 Kubernetes 服务(EKS) 
- 
Azure Kubernetes 服务(AKS) 
- 
Google Kubernetes 引擎(GKE) 
这有很多原因。以下是其中一些:
- 
开箱即用的负载均衡服务。虽然我们可以通过节点端口使 Tanzu 应用平台工作,但负载均衡服务使得这一过程变得更加简单。 
- 
开箱即用的持久化存储声明。与负载均衡器的简单性相同,动态存储的需求对于 Tanzu 应用平台也是必须的。 
- 
轻松(尽管昂贵)访问足够的资源。虽然你可以在 Minikube 上的笔记本电脑上安装 Tanzu 应用平台,但会面临内存和 CPU 限制。公共云选项使得构建一个能够扩展到足够规模、无问题运行 Tanzu 应用平台的集群变得更加简单。 
Tanzu Application Platform 的文档有一些关于 RAM 和 CPU 的推荐配置,但以下是我个人使用过并且有效的配置:
- 
一个或多个控制平面节点。如果你的 Kubernetes 集群可以访问控制平面节点,那么该节点应该至少有两个 vCPU 和 8 GB 的内存。 
- 
五个或更多的工作节点。每个节点应该至少有两个 vCPU 和 8 GB 的内存。 
- 
一个 Tanzu Network 账户 
软件安装是通过容器镜像来完成的,这些镜像托管在与 Tanzu Network 相关联的容器注册表中。你可以在这里注册: network.tanzu.vmware.com/.
- 一个生产级 容器注册表
再次强调,这里有多个选项可以选择,但我推荐两个可以让过程更加顺利的选项。它们需要付费账户,但大大简化了安装。我需要指出的是,Amazon Elastic Container Registry 目前还不受支持。以下是当前支持的容器注册表选项:
- 一个付费 Docker Hub 账户
Docker Hub 确实提供了免费层,但 Tanzu Application Platform 的安装需要大量空间(至少 1 GB)和频繁的镜像推送和拉取操作。Docker 对免费层有限制,这将影响平稳运行。
- Google 容器 注册表 (gcr.io)
这是我推荐的解决方案,因为你可以快速为你的 GCP 项目设置一个注册表,并将镜像推送到多个仓库。
- Azure 容器 注册表 (azurecr.io)
这是另一个不错的选择,尤其是如果你已经有了 Azure 账户。
- Harbor (自建)
除非你能够建立受信任的 TLS 并使用公认的证书颁发机构(CA)或 Let’s Encrypt,否则我建议在使用自建 Harbor 时要小心。如果你的 Harbor 使用的是自签名证书,那么 Tanzu Application Platform 的安装将变得更加复杂。Harbor 作为一个容器注册表非常好用,但如果你还没有配置好,它将需要你花时间进行正确的设置。
- 一个带 DNS 服务器的 自定义域名
所有公有云提供商都会为你注册一个域名并提供该域名的 DNS 查找服务。你也可以通过像 GoDaddy 这样的专门域名注册商来做这件事。唯一的要求是你能够创建可以公开解析的通配符 A 记录和 CNAME 记录。
- (可选但推荐)一个生产级 Git 服务器
你可以在没有自己 Git 服务器或公共服务账户的情况下完成演示,但任何实际使用 Tanzu Application Platform 的工作都需要一个。GitLab(gitlab.com)和 GitHub(github.com)上都有免费的选项,适合我们的需求。你只需要创建一个账户,并获取一组 SSH 或用户名/密码凭证,平台可以使用这些凭证推送和拉取远程 Git 仓库。
- kubectlCLI 以及Carvel工具。你可以分别在- kubernetes.io/docs/tasks/tools/和- carvel.dev/#install找到它们。- Kubectl的版本应为 1.22 或 1.23,且应具有在你要安装的 Kubernetes 集群上的集群管理员权限。所有 Carvel 工具都很有用,但本次安装中只需要- imgpkg。你还需要安装 Docker CLI,并确保不需要 root 权限即可运行它。
让我们进行一些快速检查,确保所有前提条件都已满足:
- 
让我们再次检查一下我们的Docker,看是否会出现令人头疼的权限拒绝错误。如果你的 Docker 守护进程不允许非 root 用户访问,通常会看到如下信息: rob@rob-virtual-machine2:~$ docker info # no good, notice 'permission denied'Client:Context: defaultDebug Mode: falseServer:ERROR: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/info: dial unix /var/run/docker.sock: connect: permission deniederrors pretty printing infoversion.BuildInfo{Version:"v3.5.3", GitCommit:"041ce5a2c17a58be0fcd5f5e16fb3e7e95fea622", GitTreeState:"dirty", GoVersion:"go1.15.8"}
这是成功安装后的样子:
rob@rob-virtual-machine2:~$ docker info # all good!
Client:
 Context:    default
 Debug Mode: false
Server:
 Containers: 0
  Running: 0
- 
最后,让我们验证一下 kubectl和我们的 Carvelimgpkg工具:ubuntu@ip-172-31-33-59 ~> kubectl versionClient Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.13", GitCommit:"a43c0904d0de10f92aa3956c74489c45e6453d6e", GitTreeState:"clean", BuildDate:"2022-08-17T18:28:56Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}Server Version: version.Info{Major:"1", Minor:"22+", GitVersion:"v1.22.11-eks-18ef993", GitCommit:"b9628d6d3867ffd84c704af0befd31c7451cdc37", GitTreeState:"clean", BuildDate:"2022-07-06T18:06:23Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}ubuntu@ip-172-31-33-59 ~> imgpkg versionimgpkg version 0.27.0
一旦你的命令行工具配置妥当,你就可以继续进行下一部分的安装了。
接受最终用户许可协议
在我们开始将软件包迁移到自定义注册中心并安装之前,我们需要接受最终用户许可协议(EULAs)。登录到 Tanzu 网络后,导航到这里列出的两个产品,并选择每个产品的最新版本。如果需要接受 EULA,你会在版本下拉菜单下看到一个黄色框,点击黄色框中的链接即可跳转到接受 EULA 的页面:
重新部署 Tanzu 应用平台软件包
虽然这一步并非绝对必要,但强烈建议将所有容器镜像从 Tanzu 仓库迁移到你自己的仓库。如果你考虑 Kubernetes 的工作原理,当任何构成 Tanzu 应用平台的几十个(或数百个!)Pod 需要启动或重启时,工作节点上的kubelet过程将需要拉取该 Pod 的容器镜像。如果你不将这些容器镜像迁移到你自己的注册表,它们将必须直接从 Tanzu 网络容器注册表中获取,这意味着你的运行时关键路径中将包含registry.tanzu.vmware.com。这意味着每次你需要重启一个 Kubernetes 工作节点上没有该 Pod 镜像的 Pod 时,Tanzu 注册表必须保持正常运行并响应。现在,Tanzu 团队拥有非常优秀的 SRE 团队,他们在保持 Tanzu 注册表正常运行方面做得非常出色,但他们的服务水平目标(SLOs)可能与你应用的 SLOs 不完全一致,因此,管理自己的命运并维护自己的容器注册表是一个好主意。此外,Tanzu 注册表是与其他 Tanzu 客户共享的,因此你不能排除需求激增导致容器镜像暂时无法访问的情况。
我们将使用imgpkg工具将所有 Tanzu 应用平台镜像从 Tanzu 注册表复制到我们的自定义注册表。这里的示例将使用gcr.io,但对于 Azure 容器注册表、Harbor 或 Docker Hub,步骤非常相似。
首先,让我们使用 Docker CLI 登录到 Tanzu 注册表:
ubuntu@ip-172-31-33-59 ~> docker login registry.tanzu.vmware.com
Authenticating with existing credentials...
Login Succeeded
ubuntu@ip-172-31-33-59 ~>
然后,再次登录到你的个人注册表。以下是gcr.io的登录方式:
ubuntu@ip-172-31-33-59 ~/t/packt> cat ./gcr-json-key.json | docker login -u _json_key --password-stdin gcr.io
Login Succeeded
对于 Docker Hub、Harbor 或 Azure,你可以发出docker login <registry-host>命令,并在提示符下输入用户名和密码。此时,我们已经通过身份验证,能够访问 Tanzu 注册表和我们的自定义注册表(gcr.io)。imgpkg工具要求本地 Docker 守护进程完成身份验证后,才能复制镜像。
现在,我们可以使用imgpkg从 Tanzu 注册表拉取镜像,并将它们推送到我们的自定义注册表。为了提高可读性,我们将设置一些环境变量:
ubuntu@ip-172-31-33-59:~/tap/packt$ export INSTALL_REGISTRY_USERNAME=_json_key
ubuntu@ip-172-31-33-59:~/tap/packt$ export INSTALL_REGISTRY_PASSWORD=$(cat gcr-json-key.json)
ubuntu@ip-172-31-33-59:~/tap/packt$ export INSTALL_REGISTRY_HOSTNAME=gcr.io
ubuntu@ip-172-31-33-59:~/tap/packt$ export INSTALL_REGISTRY_PROJECT_NAME=my-gcr-project
ubuntu@ip-172-31-33-59:~/tap/packt$ export TAP_VERSION=1.3.2
ubuntu@ip-172-31-33-59:~/tap/packt$ imgpkg copy -b registry.tanzu.vmware.com/tanzu-application-platform/tap-packages:${TAP_VERSION} --to-repo ${INSTALL_REGISTRY_HOSTNAME}/${INSTALL_REGISTRY_PROJECT_NAME}/tap-packages
copy | exporting 177 images...
copy | will export registry.tanzu.vmware.com/tanzu-application-platform/tap-packages@sha256:001224ba2c37663a9a412994f1086ddbbe40aaf959b30c465ad06c2a563f2b9f
…many, many more lines
copy | exported 177 images
copy | importing 177 images...
 6.77 GiB / 6.77 GiB [============================================================================================================] 100.00% 194.00 MiB/s 35s
copy | done uploading images
Succeeded
此时,安装和运行 Tanzu 应用平台所需的所有容器镜像都可以在gcr.io/my-gcr-project/tap-packages中找到。有关登录并将镜像迁移到 Docker Hub、Harbor 和 Azure 的具体说明,请参见 Tanzu 应用平台安装文档:docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.3/tap/GUID-install.html#relocate-images-to-a-registry-0。
安装 Tanzu CLI 和 Tanzu 应用平台插件
如果你尚未在其他章节中安装 Tanzu CLI,可以现在进行安装。此外,即使你已经安装了 Tanzu CLI,我们还将安装一些插件,帮助我们更高效地与 Tanzu 应用平台进行工作。
首先,我们将访问 Tanzu 网络上的 Tanzu 应用平台页面并下载 CLI。链接如下:network.tanzu.vmware.com/products/tanzu-application-platform/#/releases/1222090/file_groups/10484。
下载适合你平台的 tanzu-framework-bundle tarfile 后,将其复制到你的主目录。然后,在 Mac 和 Linux 上,你可以按照以下步骤操作。对于 Windows,你可能需要稍作调整,或者我推荐使用 VirtualBox 来创建一个 Linux 虚拟机并按照 Linux 的操作步骤进行。
下面是整个过程。我会在过程中加入一些注释,描述每一步的操作:
ubuntu@ip-172-31-33-59:~/downloads$ mkdir -p $HOME/tanzu
ubuntu@ip-172-31-33-59:~/downloads$ tar -xvf tanzu-framework-linux-amd64.tar -C $HOME/tanzu # extract the tar file into the working directory.
cli/
cli/core/
cli/core/v0.11.6/
cli/core/v0.11.6/tanzu-core-linux_amd64
cli/core/plugin.yaml
cli/distribution/
cli/distribution/linux/
cli/distribution/linux/amd64/
cli/distribution/linux/amd64/cli/
cli/distribution/linux/amd64/cli/accelerator/
cli/distribution/linux/amd64/cli/accelerator/v1.2.0/
cli/distribution/linux/amd64/cli/accelerator/v1.2.0/tanzu-accelerator-linux_amd64
cli/distribution/linux/amd64/cli/package/
cli/distribution/linux/amd64/cli/package/v0.11.6/
cli/distribution/linux/amd64/cli/package/v0.11.6/tanzu-package-linux_amd64
cli/distribution/linux/amd64/cli/apps/
cli/distribution/linux/amd64/cli/apps/v0.7.0/
cli/distribution/linux/amd64/cli/apps/v0.7.0/tanzu-apps-linux_amd64
cli/distribution/linux/amd64/cli/secret/
cli/distribution/linux/amd64/cli/secret/v0.11.6/
cli/distribution/linux/amd64/cli/secret/v0.11.6/tanzu-secret-linux_amd64
cli/distribution/linux/amd64/cli/insight/
cli/distribution/linux/amd64/cli/insight/v1.2.2/
cli/distribution/linux/amd64/cli/insight/v1.2.2/tanzu-insight-linux_amd64
cli/distribution/linux/amd64/cli/services/
cli/distribution/linux/amd64/cli/services/v0.3.0/
cli/distribution/linux/amd64/cli/services/v0.3.0/tanzu-services-linux_amd64
cli/discovery/
cli/discovery/standalone/
cli/discovery/standalone/apps.yaml
cli/discovery/standalone/services.yaml
cli/discovery/standalone/secret.yaml
cli/discovery/standalone/insight.yaml
cli/discovery/standalone/package.yaml
cli/discovery/standalone/accelerator.yaml
ubuntu@ip-172-31-33-59:~/downloads$ cd $HOME/tanzu
ubuntu@ip-172-31-33-59:~/tanzu$ export VERSION=v0.11.6
ubuntu@ip-172-31-33-59:~/tanzu$ sudo install cli/core/$VERSION/tanzu-core-linux_amd64 /usr/local/bin/tanzu  # move the executable into a well-known directory and make it executable.
ubuntu@ip-172-31-33-59:~/tanzu$ tanzu version
version: v0.11.6
ubuntu@ip-172-31-33-59:~/tanzu$ export TANZU_CLI_NO_INIT=true # instruct the CLI not to look in external repositories for plugins
ubuntu@ip-172-31-33-59:~/tanzu$ tanzu plugin install --local cli all  # install the plugins from the distributable tar file we just unpacked
Installing plugin 'accelerator:v1.2.0'
Installing plugin 'apps:v0.7.0'
Installing plugin 'insight:v1.2.2'
Installing plugin 'package:v0.11.6'
Installing plugin 'secret:v0.11.6'
Installing plugin 'services:v0.3.0'
  successfully installed 'all' plugin
ubuntu@ip-172-31-33-59:~/tanzu$ tanzu plugin list
  NAME                DESCRIPTION                                       SCOPE       DISCOVERY  VERSION  STATUS
  login               Login to the platform                                                Standalone  default    v0.11.6  update available
  management-cluster  Kubernetes management-cluster operations                                                 Standalone  default    v0.11.6  update available
  package             Tanzu package management                                                     Standalone  default    v0.11.6  installed
  pinniped-auth       Pinniped authentication operations (usually not directly invoked)                                  Standalone  default    v0.11.6  update available
  secret              Tanzu secret management                                               Standalone  default    v0.11.6  installed
  services            Explore Service Instance Classes, discover claimable Service Instances and manage Resource Claims  Standalone             v0.3.0   installed
  apps                Applications on Kubernetes                                           Standalone             v0.7.0   installed
  insight             post & query image, package, source, and vulnerability data                                        Standalone             v1.2.2   installed
  accelerator         Manage accelerators in a Kubernetes cluster                                           Standalone             v1.2.0   installed
恭喜你!如果你已经走到这一步,你就拥有了一个可以正常工作的 Tanzu CLI,配备了安装和运行 Tanzu 应用平台所需的所有插件。
安装 Cluster Essentials
Cluster Essentials 工具集是我们将 Tanzu 包部署到 Kubernetes 集群中的方式。也许你熟悉像 Helm 这样的工具。Cluster Essentials 工具也做类似的事情,但除了 Helm 的功能外,它们还具备以下功能:
- 
将所需的应用状态存储为 CR 在 etcd 中,以便该应用能够持续进行协调 
- 
管理复杂的依赖层次结构 
- 
以避免配置漂移的方式存储和维护模板化的应用配置 
- 
允许跨命名空间选择性地共享密钥 
我不会粉饰 Tanzu 应用平台是一个复杂的软件系统,安装它到 Kubernetes 并保持其顺畅运行,需要一个功能完备、适合企业级使用的工具集。Cluster Essentials 就是这个工具集。
要安装 Cluster Essentials,我们需要遵循与安装 CLI 时类似的脚本。在这种情况下,我们需要确保 kubectl 指向我们计划部署的 Kubernetes 集群,因为安装脚本将启动部署过程。我将再次通过注释描述这个过程:
ubuntu@ip-172-31-33-59:~/downloads$ mkdir -p $HOME/tanzu-cluster-essentials  # create working directory
ubuntu@ip-172-31-33-59:~/downloads$ ls # check our downloaded file
tanzu-cluster-essentials-linux-amd64-1.2.0.tgz
ubuntu@ip-172-31-33-59:~/downloads$ tar xvf ./tanzu-cluster-essentials-linux-amd64-1.2.0.tgz -C $HOME/tanzu-cluster-essentials    # unzip the downloaded file into the working directory
install.sh
uninstall.sh
imgpkg
kbld
kapp
ytt
ubuntu@ip-172-31-33-59:~/downloads$ cd $HOME/tanzu-cluster-essentials
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$ kubectl config get-contexts  # check our Kubernetes cluster
*         user@tap-install.us-west-2.eksctl.io             tap-install.us-west-2.eksctl.io                          user@tap-install.us-west-2.eksctl.io
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$ export INSTALL_BUNDLE=registry.tanzu.vmware.com/tanzu-cluster-essentials/cluster-essentials-bundle@sha256:e00f33b92d418f49b1af79f42cb13d6765f1c8c731f4528dfff8343af042dc3e   # Set some env vars for the install script to use
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$ export INSTALL_REGISTRY_HOSTNAME=registry.tanzu.vmware.com
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$ export INSTALL_REGISTRY_USERNAME=myuser@myemail.com
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$ export INSTALL_REGISTRY_PASSWORD=<my_super_secret_password>
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$ ./install.sh  # this will install the kapp and secretgen controllers onto our Kubernetes cluster
## Creating namespace tanzu-cluster-essentials
namespace/tanzu-cluster-essentials created
… much more output
Succeeded
ubuntu@ip-172-31-33-59:~/tanzu-cluster-essentials$
当 kapp CLI 等待安装成功完成时,你会看到大量的控制台输出,描述安装的进展。如果你在最后看到 Succeeded 消息,就说明安装确实成功了。现在,你已经安装了 Cluster Essentials 并且安装包已迁移,我们就快准备好安装 Tanzu 应用平台了。
设置开发者命名空间
Tanzu 应用平台的官方文档将此步骤放在安装之后,但我发现如果先执行这个步骤,安装过程会更加顺利。此步骤涉及在开发人员将工作负载部署到命名空间时创建一个密钥,并生成一些 Kubernetes RBAC 工件,以便该命名空间的默认服务帐户能够与构成 Tanzu 应用平台的 CR 进行交互。
首先,让我们创建命名空间,并向其中添加一个密钥,以便我们能够读取和写入容器注册表。此示例适用于 gcr.io,因为我们需要将密码作为文件传递。要为 Azure、Docker Hub 或 Harbor 创建密钥,你需要使用 --username 和 --password 标志。我的命名空间命名偏好为 workload1、workload2,以此类推。这可以清楚地让任何查看集群的人了解工作负载的运行位置:
ubuntu@ip-172-31-33-59 ~/t/packt> kubectl create ns workload1
namespace/workload1 created
ubuntu@ip-172-31-33-59 ~/t/packt> tanzu secret registry add registry-credentials --server gcr.io --username _json_key --password-file ./gcr-json-key.json -n workload1
| Adding registry secret 'registry-credentials'...
 Added registry secret 'registry-credentials' into namespace 'workload1'
ubuntu@ip-172-31-33-59 ~/t/packt>
接下来,我们需要为命名空间中的默认服务账户分配一些角色和密钥,以使 Tanzu 应用平台工作负载能够使用默认服务账户在该命名空间中运行:
ubuntu@ip-172-31-33-59:~/tap/packt$ cat <<EOF | kubectl -n workload1 apply -f –
apiVersion: v1
kind: Secret
metadata:
  name: tap-registry
  annotations:
    secretgen.carvel.dev/image-pull-secret: ""
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: e30K
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: default
secrets:
  - name: registry-credentials
imagePullSecrets:
  - name: registry-credentials
  - name: tap-registry
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: default-permit-deliverable
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: deliverable
subjects:
  - kind: ServiceAccount
    name: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: default-permit-workload
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: workload
subjects:
  - kind: ServiceAccount
    name: default
EOF
secret/tap-registry created
serviceaccount/default configured
rolebinding.rbac.authorization.k8s.io/default-permit-deliverable created
rolebinding.rbac.authorization.k8s.io/default-permit-workload created
ubuntu@ip-172-31-33-59:~/tap/packt$
接下来,我们将安装一些工具,这些工具将在我们的 Kubernetes 集群上运行,帮助我们管理安装过程。
安装软件包仓库
现在我们已经准备好所有客户端和服务器端的工具,可以开始安装了。首先,我们需要设置一个软件包仓库。这类似于 Docker 或 Apt 仓库。它仅仅是一个网络上的服务,用于存储和提供软件包。在本例中,我们将安装一个Kapp软件包仓库到我们的 Kubernetes 集群中,Kapp 控制器可以从该仓库安装软件包。之前,我们已经将软件包从 Tanzu 注册表迁移到我们自己的容器注册表。其中一个软件包叫做 tap。这个 tap 软件包充当我们的仓库,知道容器注册表中所有其他软件包的信息。稍后会更清楚明了。这个仓库及其所有软件包将位于 Kubernetes 集群中的专用命名空间内。我们假设你在迁移镜像时已设置了环境变量。如果没有设置,你需要重新设置它们:
ubuntu@ip-172-31-33-59:~/tap/packt$ kubectl create ns tap-install
namespace/tap-install created
ubuntu@ip-172-31-33-59:~/tap/packt$ tanzu package repository add tanzu-tap-repository --url ${INSTALL_REGISTRY_HOSTNAME}/${INSTALL_REGISTRY_PROJECT_NAME}/tap-packages:${TAP_VERSION} -n tap-install
 Adding package repository 'tanzu-tap-repository'
 Validating provided settings for the package repository
 Creating package repository resource
 Waiting for 'PackageRepository' reconciliation for 'tanzu-tap-repository'
 'PackageRepository' resource install status: Reconciling
 'PackageRepository' resource install status: ReconcileSucceeded
Added package repository 'tanzu-tap-repository' in namespace 'tap-install'
ubuntu@ip-172-31-33-59:~/tap/packt$ tanzu package repository get tanzu-tap-repository --namespace tap-install
NAME:          tanzu-tap-repository
VERSION:       789358
REPOSITORY:    gcr.io/fe-rhardt/tap-packages
TAG:           1.2.1
STATUS:        Reconcile succeeded
REASON:
ubuntu@ip-172-31-33-59:~/tap/packt$ tanzu package available list --namespace tap-install
  NAME                                                 DISPLAY-NAME                                              SHORT-DESCRIPTION                                                                LATEST-VERSION
  accelerator.apps.tanzu.vmware.com                    Application Accelerator for VMware Tanzu                                  Used to create new projects and configurations.                                               1.2.2
  api-portal.tanzu.vmware.com                          API portal                                                     A unified user interface to enable search, discovery and try-out of API endpoints at ease.
# … many more …
现在,我们将安装这些软件包以启动 Tanzu 应用平台的运行实例。
拉取并格式化 tap-values.yaml
接下来,我们需要一个配置文件来安装 Tanzu 应用平台。你可以拉取这个文件作为起点:github.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/blob/main/chapter-09/tap-values.yaml。
一旦你将该文件下载到本地,按照内联指令插入注册表凭证和域信息。填写完该文件后,我们可以从我们的软件包仓库安装tap包,参考该文件:
ubuntu@ip-172-31-33-59:~/tap/packt$ tanzu package install tap -p tap.tanzu.vmware.com -v $TAP_VERSION --values-file tap-values.yaml -n tap-install
 Installing package 'tap.tanzu.vmware.com'
 Getting package metadata for 'tap.tanzu.vmware.com'
 Creating service account 'tap-tap-install-sa'
 Creating cluster admin role 'tap-tap-install-cluster-role'
 Creating cluster role binding 'tap-tap-install-cluster-rolebinding'
 Creating secret 'tap-tap-install-values'
 Creating package resource
 Waiting for 'PackageInstall' reconciliation for 'tap'
\ 'PackageInstall' resource install status: Reconciling
此安装可能需要几分钟时间。此外,有时它会告诉你安装失败,实际上是因为某个组件稍微拖延了一些时间。为了获得更多关于安装的反馈,你可以通过监控 Kubernetes 中的PackageInstall(pkgi)对象来查看安装情况:
ubuntu@ip-172-31-33-59 ~> kubectl get pkgi -n tap-install -w
NAME                       PACKAGE NAME                                         PACKAGE VERSION   DESCRIPTION           AGE
api-portal                 api-portal.tanzu.vmware.com                          1.0.24            Reconcile succeeded   72s
appliveview-connector      connector.appliveview.tanzu.vmware.com               1.2.1             Reconcile succeeded   72s
appsso                     sso.apps.tanzu.vmware.com                            1.0.0             Reconcile succeeded   38s
buildservice               buildservice.tanzu.vmware.com                        1.6.1             Reconciling           72s
cartographer               cartographer.tanzu.vmware.com                        0.4.3             Reconcile succeeded   38s
恭喜!你已经拥有了一个运行中的 Tanzu 应用平台实例。接下来,让我们配置与之交互所需的其余组件。
创建 DNS 记录
一旦你安装了 Tanzu 应用平台,你会希望能够通过网页浏览器访问工具和已部署的应用程序。这时,你需要去域名的 DNS 服务,并将其指向你的 Tanzu 应用平台安装。首先,让我们找出负载均衡器服务的端点,并将通配符 DNS 记录指向它:
ubuntu@ip-172-31-33-59 ~> kubectl get svc -n tanzu-system-ingress envoy
NAME    TYPE           CLUSTER-IP       EXTERNAL-IP                         PORT(S)                      AGE
envoy   LoadBalancer   10.100.247.164   accd60a8feb5740b1ac24853ea17e546-817853481.us-west-2.elb.amazonaws.com   80:30409/TCP,443:30100/TCP   10m
ubuntu@ip-172-31-33-59 ~>
在这种情况下,tanzu-system-ingress 中的 envoy 服务将主机名作为其 EXTERNAL-IP。如果我控制 mydomain.com,我将进入我的域名的 DNS 配置设置,创建一个 CNAME 记录 *.mydomain.com,并将其指向通过 kubectl 命令获得的 LoadBalancer 主机。如果你使用的是 Azure 或 GCP,你可能会获得一个 IPv4 地址而不是主机名。在这种情况下,你需要创建一个 A 记录,而不是 CNAME。
这是一个实际的例子。我使用 *.packtinstall.k10s.io 域名安装了 Tanzu 应用平台。配置好 DNS 记录后,我可以使用 dig 命令验证 packtinstall.k10s.io 的任何子域名是否会返回指向与 tanzu-system-ingress/envoy Kubernetes 负载均衡器服务相关联的 AWS 负载均衡器的 CNAME:
ubuntu@ip-172-31-33-59 ~> dig testing123.packtinstall.k10s.io
; <<>> DiG 9.16.1-Ubuntu <<>> testing123.packtinstall.k10s.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17729
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;testing123.packtinstall.k10s.io. IN A
;; ANSWER SECTION:
testing123.packtinstall.k10s.io. 300 IN    CNAME    accd60a8feb5740b1ac24853ea17e546-817853481.us-west-2.elb.amazonaws.com.
accd60a8feb5740b1ac24853ea17e546-817853481.us-west-2.elb.amazonaws.com.  59 IN A    52.10.176.193
accd60a8feb5740b1ac24853ea17e546-817853481.us-west-2.elb.amazonaws.com.  59 IN A    35.155.17.135
accd60a8feb5740b1ac24853ea17e546-817853481.us-west-2.elb.amazonaws.com.  59 IN A    54.213.143.29
现在,如果一切顺利,你应该能够通过浏览器访问指向 tap-gui.<your-domain>.com 的 Tanzu 应用平台 GUI。成功!

图 8.5 – Tanzu 应用平台 GUI
我鼓励你探索 TAP GUI。本书的 第二章 和 第五章 详细介绍了应用加速器和 API 门户组件。接下来,让我们安装一些本地开发工具,以增强我们与 Tanzu 应用平台交互的体验。
安装 VS Code 开发者工具
为了真正看到 Tanzu 应用平台的运行效果,设置一个真实的开发工具链是非常有帮助的。此时,你已经有一个运行 Tanzu 应用平台的 Kubernetes 集群,并且已经配置了 kubectl 和带有必要插件的 Tanzu CLI。只需再添加几个工具,我们就能建立这个工具链。
首先,如果你还没有,请从这里下载并安装 VS Code:code.visualstudio.com/download。然后,从这里下载并安装 Tilt:docs.tilt.dev/install.html。最后,从 Tanzu 网络下载 VS Code 的开发者工具:network.tanzu.vmware.com/products/tanzu-application-platform。你可以通过 VS Code 的命令面板来安装这些开发工具。你可以通过 Extensions: Install from VSIX 打开命令面板。当自动完成显示时,选择该选项,并导航到你刚刚下载的 VSIX 文件进行安装。
恭喜你!你已经完成了一个非常复杂软件的安装和配置。我们的第 1 天任务已完成。现在,让我们进入第 2 天,开始使用我们强大的新工具包!
第 2 天 – 部署应用到 Tanzu 应用平台
在第二章《开发云原生应用》中,我们深入探讨了应用加速器。为了将应用部署到 Tanzu 应用平台,我们将再次使用该产品。前往你刚安装完成的TAP GUI,它应该位于tap-gui.<your-domain>。然后,在左侧菜单中点击gcr.io,它可能是类似gcr.io/<your-project-id>/tanzu-java-web-app的内容。你提供的值将用于 Tiltfile 中,告诉 Tilt 工具在哪里推送应用的源代码,以便被 Tanzu 应用平台的供应链接收。稍后你会明白这个步骤的意义。以下是加速器界面的样子,提醒一下:

图 8.6 – 填写加速器表单
一旦点击NEXT,你将很快看到一个按钮用于下载 ZIP 文件。下载 ZIP 文件,解压并打开 VS Code,进入你刚刚解压的应用目录。接下来,我们需要在 VS Code 中更新几个设置。进入 VS Code 设置窗口,导航到扩展 | Tanzu。
设置workload1或你在之前步骤中为开发者使用设置的任何命名空间。最后,再次确认gcr.io,它可能是gcr.io/<your-project-id>/tanzu-java-web-app-remote-src,具体取决于你在之前步骤中提供给应用加速器 UI 的内容。以下是我的设置样子:

图 8.7 – VS Code 开发者设置
现在,你可以关闭Tiltfile。当你右击Tiltfile时,应该会看到Tanzu: Live Update Start选项。以下截图能让你更清楚地了解应该寻找什么:

图 8.8 – VS Code 中的 Tanzu Java Web 应用
让我们尝试通过点击Tanzu: Live Update Start上下文菜单项来启动实时更新。很可能你会看到类似这样的消息:
*  Executing task: tilt: up - /Users/roberthardt/Downloads/tanzu-java-web-app 2/Tiltfile
Tilt started on http://localhost:10350/
v0.26.3, built 2022-03-24
Initial Build
Loading Tiltfile at: /Users/roberthardt/Downloads/tanzu-java-web-app 2/Tiltfile
ERROR: Stop! user@tap-install.us-west-2.eksctl.io might be production.
If you're sure you want to deploy there, add:
        allow_k8s_contexts('user@tap-install.us-west-2.eksctl.io')
to your Tiltfile. Otherwise, switch k8s contexts and restart Tilt.
不用担心。Tilt 工具非常小心,避免你在生产环境中意外启动实时更新会话。按照指示,向 Tiltfile 的底部添加allow_k8s_contexts('<your-k8s-context>')命令,然后再试一次。
第一次部署可能需要一段时间,但最终,你可以打开终端,查看workload1命名空间中的所有 Pod(kubectl get pods -n workload1),并看到类似这样的内容:

图 8.9 – 正在运行的应用的 Pod 列表
包含 build 字样的 pod 是那些将源代码转换为容器镜像的 pod。包含 config-writer 字样的 pod 是那些将可部署的 Kubernetes 工件的源代码写入 Git 或容器注册表,以便可以被提取并部署的 pod。最后,包含 deployment 字样的 pod 是你的应用程序正在运行的 pod。
接下来,让我们在浏览器中查看我们的应用。执行此命令以获取属于你应用的正在运行的 Knative 服务的 URL:
~/D/tanzu-java-web-app> kubectl get kservice -n workload1
NAME                 URL                         LATESTCREATED              LATESTREADY                READY   REASON
tanzu-java-web-app   http://tanzu-java-web-app.workload1.packtinstall.k10s.io   tanzu-java-web-app-00002   tanzu-java-web-app-00002   True
现在,将 URL 插入浏览器中。这是你应该看到的内容:

图 8.10 – 运行 Tanzu 应用
恭喜!你已经成功在 Tanzu 应用平台上启动了一个 Spring Boot 应用。而且,完全不需要安装本地 Java 运行时或除了 Tanzu 工具链以外的任何工具。插件将你的原始源代码传送到平台上,并在平台上完成构建和部署。接下来,让我们测试一下实时更新功能。
在 VS Code 中,导航到 /src/main/java/com/example/springboot/HelloController.java,然后修改问候语。也许在结尾添加 and Packt!!!。
请注意,当你保存更改时,VS Code 插件会自动检测到更改并部署它。以下是你在 VS Code 中对文件进行更改时发生的时间线:
- 
Tilt 插件检测到文件发生变化。 
- 
插件将你的源代码打包并存储在容器注册表中。 
- 
插件更新 Kubernetes 集群中的工作负载对象,使 .spec.source.image字段指向容器注册表中更新后的源代码镜像。
- 
Kubernetes 上的制图控制器检测到工作负载的变化,并触发供应链的新迭代。 
- 
供应链拉取源代码、构建它、推送已构建工件的容器镜像并运行该工件,在此过程中应用多个约定。 
一两分钟后,你可以刷新浏览器,看到本地更改实时反映在 Kubernetes 中运行的应用中。
直接部署工作负载
我们现在已经看到了开发者的工作流程,即本地源代码被打包并存储在容器仓库中,工作负载是从这些源代码创建的。然而,在现实世界的场景中,本地源代码并不会直接从 IDE 推送到平台。相反,代码会进入源代码控制系统,这之后驱动某种持续集成流程到平台上。让我们简要地探讨一下这个使用案例。
在我们下载并解压的应用程序的 /config 目录中,应该会看到一个名为 workload.yaml 的文件。该文件指示平台从以下 URL 拉取源代码:github.com/sample-accelerators/tanzu-java-web-app。Tanzu 应用平台将监视该 Git 仓库,并在检测到更改时,拉取最新的源代码并更新运行中的工作负载。现在,让我们试试看。
首先,为了避免命名空间冲突,让我们删除现有的工作负载。通过右键点击 Tiltfile 并选择 Tanzu Live Update Stop 来停止 Tilt。然后,使用以下命令删除我们的工作负载:
~/D/tanzu-java-web-app> kubectl delete workload -n workload1  --all
接下来,Tanzu 应用平台的某些版本中存在一个小 bug,我们需要进行绕过。尽管我们引用的 Git 仓库是公共的,但平台仍然希望存在一个用于认证的 secret。让我们创建一个空的 secret 作为解决方法:
~/D/tanzu-java-web-app> kubectl create secret generic -n workload1 git-ssh
现在,让我们直接部署工作负载,特别注意指定正确的命名空间:
~/D/tanzu-java-web-app> kubectl apply -f ./config/workload.yaml -n workload1
然后,我们可以观看工作负载部署时 Pods 的进度:
~/D/tanzu-java-web-app> kubectl get pods -n workload1
NAME                                                   READY   STATUS      RESTARTS   AGE
tanzu-java-web-app-00001-deployment-557f89455b-pg2td   2/2     Running     0          61s
tanzu-java-web-app-build-1-build-pod                   0/1     Completed   0          2m21s
tanzu-java-web-app-config-writer-7kl4k-pod             0/1     Completed   0          74s
最后,您可以通过浏览器访问 tanzu-java-web-app.workload1.yourdomain.com 来验证您的工作负载是否可见。
现在,我们几乎已经成为使用该平台的专家,让我们看看作为平台操作员接下来可能需要做什么。
第 3 天 – 在 Tanzu 应用平台上的常见操作任务
到目前为止,我们已经安装了一个功能完全的应用平台,但在某些方面,它仍然可能感觉像一个玩具。例如,没有企业会允许在没有 TLS 的情况下部署工作负载。此外,该平台有点像一个黑盒,它将我们的源代码转化为运行中的应用程序。我们如何知道平台上运行的是否正是我们提交的代码呢?深入探讨这些话题有点超出本书的范围,但我会描述一些额外的操作任务及其解决的问题,并引导您查看一些有用的深入资源,了解更多信息。
使用 TAP GUI 通过 TLS 保护运行中的工作负载
对于企业级应用平台,使用 TLS 来保护所有 Web 端点是不可谈判的。有几种方法我将在这里列出。某些方法涉及在 Kubernetes 外部获取证书并直接提供,其他方法则涉及使用名为 cert-manager 的开源项目(www.jetstack.io/open-source/cert-manager/),该项目会随着 Tanzu 应用平台一起自动安装。以下是您可能采购并将 TLS 证书部署到 Tanzu 应用平台的几种方式:
- 
直接使用第三方证书(DigiCert、Verisign 等)提供 
- 
直接使用自管 CA(OpenSSL)提供 
- 
直接使用企业 CA 签发的证书(例如,Nokia NetGuard) 
- 
直接使用 Let’s Encrypt 提供 
- 
通过 cert-manager 使用自管 CA 
- 
通过 cert-manager 与 Let’s Encrypt(这是我的偏好) 
如你所见,有许多选项,这些选项可能会轻松地将本章的篇幅加倍。如果你没有特别的偏好,我建议使用 Let’s Encrypt + cert-manager。如果你通过 AWS Route 53 等主要云提供商管理你的域名 DNS,过程会简单且无痛苦。
一旦你决定了如何获取证书,你还需要决定 mydomain.com;然后,你将配置以下的 SAN:
- 
*.``mydomain.com
- 
*.``workload1.mydomain.com
- 
*.``workload2.mydomain.com
- 
*.``workload3.mydomain.com
这将为你提供适用于 workload1、workload2 和 workload3 命名空间的 TLS。虽然有方法绕过限制,使你可以部署到任何任意的命名空间,但我会建议你参考文档了解如何操作。
现在我们已经决定了如何获取证书并确定了我们的 SAN,我将引导你阅读这篇出色的博客文章,文章详细介绍了如何安装支持 TLS 的 Tanzu 应用平台:tanzu.vmware.com/content/blog/tanzu-application-platform-install-with-tls-and-azure-ad。
启用测试和扫描
运行企业软件的另一个不可妥协的要求是,必须保证它通过了所有单元测试,并且已扫描已知的漏洞。Tanzu 应用平台可以通过一些额外的配置提供这两项保证。
首先,关于测试,任何平台都无法涵盖每种编程语言中的所有测试框架,因此,Tanzu 应用平台的架构师决定通过 Tekton Pipelines 将自动化测试交给应用开发人员,而不是进行不成熟的尝试。
Tekton (cloud.google.com/tekton/) 提供 Kubernetes 原生的持续集成和交付。因此,Tanzu 应用平台将寻找一个 Tekton 流水线,该流水线能够运行应用程序的测试并执行它。文档中还提供了一些用于 Java 和 Maven 等语言的示例流水线。
漏洞扫描稍微简单一些。Tanzu 应用平台将使用两个知名的扫描工具:Grype 或 Snyk,扫描应用程序的源代码和生成的容器镜像。
你可以在这里学习如何为你的应用供应链启用测试和扫描:docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.2/tap/GUID-getting-started-add-test-and-security.html。
一旦你掌握了这些主题,你应该对 Tanzu 应用平台有透彻的了解,并且对企业中优秀的表现有良好的直觉。那么接下来是什么呢?让我们在下一节中集思广益,探索一些下一步的计划。
下一步
既然你已经是一个真正的 Tanzu 应用平台专家,接下来可以做些什么呢?以下是一些想法:
- 
在多个 Kubernetes 集群中部署 Tanzu 应用平台,为查看、构建和运行工作负载提供专用集群 
- 
启用可以自动将凭证绑定到工作负载的托管服务(如数据库、消息队列等) 
- 
启用需要批准的拉取请求才能部署到生产环境的自定义 GitOps 工作流 
- 
使用 Cartographer 工具( cartographer.sh/)构建你自己的定制供应链
总结
Tanzu 应用平台可能是本书中最复杂的软件之一,值得单独出一本书来详细讨论。掌握这项技术将使你在任何希望大规模运行云上软件的企业中变得不可或缺。随着 Tanzu 应用平台的学习完成,我们将总结本书的第二部分,回顾在 Tanzu 上运行应用程序的内容,并过渡到下一部分,讨论如何使用工具(如 Tanzu Mission Control、VMware Aria Operations for Applications 和 Tanzu Service Mesh)来管理它们。这也意味着我们对 Tanzu 上运行应用程序的讨论结束了。建议你继续阅读下一部分,了解如何管理这些应用程序。我们将从Tanzu Mission Control开始,它是一个集中的控制点,用于跨多个云管理你所有的企业 Kubernetes 资产。
第三部分 – 在 Tanzu 平台上管理现代应用程序
本部分将涵盖一些重要的 Tanzu 工具,这些工具有助于管理、保护并主动监控容器应用程序和底层 Kubernetes 平台,支持多云部署的日常运营(day-2 活动)。
本书的这一部分包括以下章节:
- 
第九章,使用 Tanzu Mission Control 管理和控制 Kubernetes 集群 
- 
第十章,使用 VMware Aria Operations for Applications 实现全栈可视化 
- 
第十一章,使用 Tanzu Service Mesh 实现安全的服务间通信 
- 
第十二章,汇总与整合 
- 
第十三章,附录 
第九章:使用 Tanzu Mission Control 管理和控制 Kubernetes 集群
在本书的上一节中,我们介绍了 Tanzu 产品组合中的工具,这些工具帮助我们运行云原生应用。我们介绍了 Harbor 如何为您的容器镜像提供安全的存储环境,并展示了如何使用 Tanzu Kubernetes Grid 运行这些镜像,Tanzu Kubernetes Grid 在公共和私有云基础设施中提供一致的用户体验。最后,我们深入探讨了开发人员生产力领域,旨在自动化并保障软件供应链,从构思到生产环境中的应用程序运行。
本节内容涉及管理云原生应用及其相应的 Kubernetes 基础设施。在本章中,我们将学习如何使用 Tanzu Mission Control(TMC)管理、保护和治理各种 Kubernetes 集群,无论它们部署在什么样的基础设施上。接下来,我们将介绍 VMware Aria Operations for Applications,这是一款用于监控应用程序各个部分的工具,包括微服务之间的分布式追踪、应用性能、Kubernetes 对象、虚拟基础设施以及应用使用的其他服务。最后,我们将学习如何通过 Tanzu Service Mesh 使用开箱即用的双向 TLS 配置,安全地连接运行在 Kubernetes 上的应用并将其部署到不同的集群和环境中。
附注
从本章开始,为了简洁起见,我们将 Kubernetes 集群简称为 集群。
通过上一节的背景知识和对本节接下来章节的展望,我们将深入了解 TMC。我们将在本章中涵盖以下主题:
- 
为什么选择 TMC? – 了解管理大规模 Kubernetes 环境面临的挑战以及 Tanzu Mission Control 提供的解决方案 
- 
开始使用 TMC – 学习如何使用 TMC 来管理集群生命周期 
- 
使用 TMC 保护集群数据 – 学习如何备份集群和命名空间,并在需要时恢复它们,以保护正在运行的工作负载免受灾难的影响 
- 
应用和确保使用 TMC 进行集群治理策略 – 学习如何将不同的集群用户治理策略应用到集群和 Kubernetes 命名空间组,并进行检查以发现集群中的异常,从而采取预防性安全措施 
TMC 是 Tanzu 产品组合中的一款非常强大的 SaaS 服务,它为您的所有 Kubernetes 环境提供了统一的控制面板。让我们更深入地了解它。
为什么选择 TMC?
随着其受欢迎程度的不断上升,Kubernetes 已成为新的基础设施层。就像 10 年前,几乎所有的软件都运行在虚拟基础设施上一样,在未来几年,几乎所有新的应用程序可能会默认部署在 Kubernetes 上。事实上,大多数厂商提供的解决方案现在都可以在 Kubernetes 上运行。根据 Cloud Native Computing Foundation(CNCF)2021 年 12 月进行的调查,超过 560 万开发者表示他们使用 Kubernetes 部署应用程序,这仅在 1 年内就增长了 67%!由于 Kubernetes 提供的各种商业和技术优势,它将长期存在。根据这项 CNCF 调查,超过 96% 的组织已经采用 Kubernetes,并在不同的成熟度水平上运行其云原生应用程序!其中 73% 的组织已经在生产环境中运行 Kubernetes 负载!根据 CNCF 2022 年 2 月的博客文章,社区正见证着该技术的历史最高采用率。了解更多 CNCF 发布的详细信息,请点击这里:www.cncf.io/announcements/2022/02/10/cncf-sees-record-kubernetes-and-container-adoption-in-2021-cloud-native-survey/。
Kubernetes 面临的挑战
尽管 Kubernetes 是一个极受欢迎的工具,用于运行容器化应用程序,但在生产环境中操作 Kubernetes 仍然非常困难。正如你可能知道的,Kubernetes 仅通过 kubectl 命令行接口或使用其 REST API 进行操作。Kubernetes 中的每个配置都是 YAML 格式,通常很长且难以理解,除非你对 Kubernetes 的各种构件有深刻的理解。
面对超大集群的挑战
在这个上下文中,超大集群是指包含超过 50 个节点的集群。除了使用 Kubernetes 的基本复杂性外,运行生产级平台还面临其他一些安全和操作挑战。为了减少复杂性和运营开销,我看到一些企业部署了超大集群,仅维护、操作和保护少数几个关键集群。超大 Kubernetes 部署托管来自多个不同 业务线(LOBs)的应用程序,通过 Kubernetes 命名空间提供的逻辑隔离来实现。最初,这种做法可能听起来很合乎逻辑,但这种做法有几个缺点,如下所示:
- 
一个为多个不同业务线和应用程序服务的大型集群很难维护,因为所有应用程序及其业务线在维护窗口和对停机的容忍度方面都有不同的偏好。如果一个应用程序在一个集群中部署了两个或更多 Pods,那么它通常不会面临停机。然而,确保达到这种合规性水平是一个不同的挑战。此外,大型集群需要较长的维护窗口来完成诸如升级等活动。 
- 
当在一个大型集群中运行数百个应用程序时,如果集群遇到任何问题或停机,它们都会一起受到影响。大型集群具有较大的冲击范围和灾难影响。 
- 
由于一个大型集群被多个不同的应用程序使用,应用程序团队无法自由选择特定的集群设置和资源需求来部署和运行他们的应用程序,例如使用特定的操作系统或为计算需求使用 GPU。尽管 Kubernetes 通过诸如污点(taints)和容忍度(tolerations)等构件提供了一种将某些应用程序 Pods 部署到特定节点的方法,但实施、维护和使用这种设置在实际操作中非常困难。 
- 
尽管 Kubernetes 通过命名空间(namespaces)将不同团队的应用程序隔离开来,但这仅仅是逻辑层面的隔离。实际上,属于不同命名空间的 Pods 可能会在同一节点上运行。这可能会引发潜在的安全威胁问题,如果恶意行为者在同一个集群中运行,或者如果应用程序没有在其部署清单中请求并预留所需资源,就可能会因“吵闹的邻居”(noisy neighbor)问题而导致资源饥饿。 
考虑到大型集群面临的这些挑战,推荐使用多个较小的集群,特别是对于异构工作负载。如果在一个大型集群上运行的所有应用程序具有相同的需求,那么应该是没问题的;否则,推荐的做法是为不同的团队、业务单元(LOB)或应用程序创建较小的集群。
多个集群的挑战及 TMC 的解决方案
人们通常倾向于使用大型集群,以避免随着维护集群数量的增加而增加的操作开销。因此,一方面,我们可能需要多个属于不同团队、环境和目的的小集群,另一方面,也涉及到多个操作和安全挑战,这些挑战与保持这些集群正常运行有关。这正是 TMC 的作用所在,它通过从一个统一的控制面板管理多个集群来解决这些挑战。让我们简要了解一下这些挑战是什么,以及 TMC 如何帮助解决它们。
集群生命周期管理的开销增加
多个集群的基本生命周期管理操作,如创建、扩展、升级和删除,在没有完全自动化的情况下可能会成为一场噩梦。在这个过程中的任何手动干预都可能导致由基本人为错误引起的配置漂移。这很快可能导致一组集群具有不同的配置,所有集群的升级需求将频繁发生,因为上游 Kubernetes 每 3 到 4 个月发布一个新版本,而补丁版本则更加频繁。建议定期通过升级和补丁来维护集群,以保持安全性和支持。这种对大量集群的频繁维护需要一个复杂的自动化设置。另一方面,为了这些生命周期过程建立和维护完整的端到端自动化需要大量的内部努力。在这种情况下,组织建立这种自动化需要问自己是否应该投入这么多努力来支持容器平台的低价值线活动,还是宁愿将这些资源投入到为其应用程序添加新业务功能,从而带来更多收入。
TMC 通过 Tanzu Kubernetes Grid (TKG) 的帮助来解决这一挑战。在前一章中,我们了解了 TKG 及其管理控制平面的概念,用于管理该管理集群下多个工作负载集群的生命周期。TMC 提供了一个即插即用的集成体验,将 TKG 管理控制平面集群连接起来,并允许 TMC 用户通过 TMC 门户执行所有 TKG 集群生命周期操作。这种简单、快捷和用户友好的管理集群生命周期方法解决了保持 Kubernetes 版本更新以确保安全性的挑战。此外,TKG 提供的完整即插即用集群生命周期自动化及其与 TMC 的集成减少了为同样的原因创建和维护内部自动化所需的额外努力。
不同集群的特定配置要求
当不同集群具有不同的配置要求时,情况变得更加复杂。非生产集群组的安全要求与生产集群不同。此外,处理支付卡行业(PCI)数据环境的合规要求更为严格。根据环境不同,集群可能对用户访问、容器网络、工作负载隔离和部署策略有不同需求。例如,安全策略可能包括防止部署特权容器,这些容器可能允许对其部署主机进行根级访问,或者确保高可用性的策略只允许为应用程序部署两个以上的 Pod 等。找到适合所有集群的一种解决方案很困难。添加更多类型的集群会增加更多的复杂性。
为了解决这个挑战,TMC 允许我们创建集群组,并为不同的集群组创建不同的策略和处理方法。这样,开发集群组的访问策略可能与生产集群组的访问策略不同且更为宽松。此外,TMC 还允许您创建一组 Kubernetes 命名空间,称为工作空间,可以跨集群和集群组的边界。然后,我们可以为这些工作空间创建适用于命名空间级别的策略。在 Kubernetes 中,网络策略定义了哪些应用程序/服务可以跨不同命名空间连接到哪些应用程序/服务。
工具的安装和配置
每个组织都有一套他们想要在集群上部署的工具,用于跨切面的关注点,如日志记录、监控、证书管理、身份和访问管理(IAM)等。当不同团队负责管理自己的小集群时,为集群所有者提供自助服务方法变得具有挑战性,他们可以根据需要快速和一致地选择和部署所需的工具。
为了解决这一点,TMC 拥有一些流行的开源包目录,不同的集群所有者可以根据其要求一键安装。这种能力不仅减少了不同团队的开销,还允许您为其他集群所有者设立防护栏,只有某些授权的包可以安装在其集群上。作为额外的优势,所有这些包都可以使用通用方法安装,并且仅限于目录中发布的版本。
集群配置和工作负载数据保护
快速而简便的集群状态备份和恢复程序,也是大多数组织内集群的重要关注点。对于不使用持久化存储卷的静态工作负载,通过备份 Kubernetes 配置的 YAML 文件可以恢复这些对象,方法是重新应用这些配置,但如果运行状态与文档状态存在差异怎么办?在这种情况下,恢复的数据将不完全相同。对于有状态的工作负载,备份和恢复会增加更多复杂性,因为我们不仅需要备份这些工作负载使用的存储卷,还要备份它们的配置 YAML 文件。此外,对于许多集群执行这些活动,确保按要求的频率进行以最小化数据丢失,需要巨大的自动化努力。另一方面,如果备份和恢复的责任交给负责各个集群的团队,那么要么会出现疏漏,要么会面临如何在不同团队之间标准化执行这一过程的挑战。
为了应对这一需求,TMC 使用Velero(https://velero.io),这是一个由 VMware 支持的开源项目,用于备份和恢复 Kubernetes 集群。TMC 用户可以选择安排集群备份或按需进行备份。这些备份存储在简单存储服务(S3)兼容的对象存储位置,并通过 Web URL 进行访问。使用 TMC 控制台进行备份、调度和恢复非常简单,提供了一种一致的方法和存储位置,确保对集群上运行的所有内容(包括无状态和有状态的工作负载)提供所需的数据保护。通过 Velero,TMC 还允许你根据需要仅备份选定的重要命名空间。
什么是 S3?
S3 是 AWS 提供的一种对象存储或文件存储服务。S3 已经成为对象存储的标准,符合所需的 S3 接口。目前,除了 AWS 提供的 S3 服务外,市场上还有多个云托管和本地部署的 S3 兼容存储选项,包括 MinIO 和戴尔弹性云 存储(ECS)。
执行集群检查
当一个组织拥有数百个由多个团队管理的集群时,检查每个集群的安全性和操作政策合规性是一项庞大的工作。在医疗保健和金融等高度安全领域运营的企业有正式的义务定期审计其应用平台,以查找合规性并处理违规行为。手动审计和检查多个不同的集群,以查看它们是否遵循必要的安全合规性做法几乎是不可能的。这需要大量的自动化来构建一个扫描引擎,该引擎能够检查给定集群的检查清单上的所有不同规则,然后报告不同严重性的违规行为。官方 Kubernetes 规范中有一份安全生产级集群应遵循的推荐清单。类似地,互联网安全中心(CIS)也有一份基准测试推荐清单,应该在集群中遵循以确保安全。对数百个集群进行不同类型的检查是一项非常困难的任务。
然而,使用 TMC 进行集群检查只需几次点击。为了提供此功能,TMC 使用了Sonobuoy(https://sonobuoy.io),这是 VMware 支持的另一个开源项目,提供 Kubernetes 集群配置验证。TMC 允许你执行两种不同类型的检查——CIS 基准测试和 Kubernetes 规范合规性检查。检查完成后,TMC 用户将获得有关不同推荐合规性和违规的详细报告。这些结果可以帮助你采取快速的预防措施,在漏洞被利用之前关闭安全漏洞。
除了解决管理大量集群的挑战外,TMC 还会发出与其管辖下的集群相关的关键事件,以确保集群所有者充分了解它们的健康状况和关键生命周期阶段。此外,TMC 提供了一套全面的 REST API,允许你以编程方式执行所有这些操作。最后,作为主要的优势,TMC 可以为任何符合规范的 Kubernetes 版本执行所有这些操作,包括 AWS 弹性 Kubernetes 服务(EKS)、Azure Kubernetes 服务(AKS)、Google Kubernetes 引擎(GKE)、OpenShift、Rancher、开源上游发行版以及许多其他类型。这不包括我们在集群生命周期管理开销增加一节中提到的完整集群生命周期管理。本文写作时,Kubernetes 集群的升级仅支持 TKG 集群。此功能使 TMC 成为实施企业多云 Kubernetes 策略的优秀工具。下图显示了 TMC 控制台,其中部署了多个 Kubernetes 集群,分别位于不同的云环境中:

图 9.1 – 管理多个 Kubernetes 集群的 TMC 控制台
通过这一点,你应该已经获得了一个令人信服的答案,为什么选择 TMC?我们将在本章稍后详细介绍这些功能的细节,但现在让我们看看如何开始使用 TMC。
开始使用 TMC
TMC 是一个 软件即服务 (SaaS) 产品,隶属于 VMware Cloud Services。由于这一点,开始使用 TMC 无需任何安装和设置,这也是 SaaS 产品所带来的巨大便利。在 TMC 中,我们可以有两种类型的集群,如下所述:
- 
由 Kubernetes 平台管理控制平面管理的集群,这些集群已在 TMC 上注册 – 目前,TMC 仅支持此类别下的 TKG 集群。一旦在 vSphere、AWS 或 Azure 上运行的 TKG 管理集群(TKG 平台控制平面)在 TMC 中注册,我们就可以使用 TMC 界面执行所有生命周期操作,管理该管理集群下创建的所有集群。 
- 
已连接到 TMC 的集群 – 这些可以是任何外部创建的符合规范的 Kubernetes 集群。我们可以将这些集群连接到 TMC,以进行本章之前讨论的几项管理活动,但不包括完全生命周期操作,如创建、删除和升级。TMC 提供了一个公共的管理控制平面,适用于所有 Kubernetes 集群,无论其种类和供应商如何。 
在本节中,我们将执行以下操作以开始使用 TMC:
- 
通过 VMware Cloud Services 控制台访问 TMC 门户 
- 
注册在 AWS 上运行的现有 TKG 管理集群 
- 
在已注册的管理集群下创建 TKG 工作负载集群 
- 
连接一个 GKE 集群进行管理 
- 
创建一个集群组 
- 
在新创建的集群组中添加两个关联的集群 
- 
创建一个工作区,一个跨集群的 Kubernetes 命名空间组 
- 
从两个不同集群中添加两个 Kubernetes 命名空间到已创建的工作区 
然而,在你可以跟随操作之前,必须满足以下前提条件:
- 
通过 VMware Cloud Services 账户访问 TMC 的管理员级别权限。 
- 
一个现有的 TKG 管理集群(版本 1.4.1 或更高版本),并具有至少三个控制平面节点的生产计划 
- 
由之前提到的 TKG 管理集群未管理的现有 Kubernetes 集群 – 这可以是 GKE、AKS、EKS、OpenShift、Rancher,甚至是开源 Kubernetes 集群 
- 
集群节点应包含 4 个 vCPU 和 8 GB 内存,以确保顺利执行步骤 
- 
配备互联网浏览器(优选 Google Chrome)和 kubectlCLI 的用户工作站
- 
Kubernetes 集群应具有完全的互联网连接,且没有任何代理服务器,因为在不同操作中配置 TMC 的步骤会因为代理的存在而不同,本章中不考虑这一点 
- 
从与 TMC 关联的集群访问 AWS S3 或任何其他 S3 兼容的对象存储服务。 
此外,如果您的 TKG 管理集群运行在 AWS 上,并且您已经手动配置了在 TKG 使用的 CloudFormation 堆栈中定义的 IAM 权限,则必须将以下列出的权限添加到 nodes.tkg.cloud.vmware.com IAM 策略或角色中:
{
  "Action": [
    "servicequotas:ListServiceQuotas",
    "ec2:DescribeKeyPairs",
    "ec2:DescribeInstanceTypeOfferings",
    "ec2:DescribeInstanceTypes",
    "ec2:DescribeAvailabiilityZones",
    "ec2:DescribeRegions",
    "ec2:DescribeSubnets",
    "ec2:DescribeRouteTables",
    "ec2:DescribeVpcs",
    "ec2:DescribeNatGateways",
    "ec2:DescribeAddresses",
    "elasticloadbalancing:DescribeLoadBalancers"
  ],
  "Resource": [
    "*"
  ],
  "Effect": "Allow"
}
然而,当您通过运行 tanzu mc permissions aws set 命令创建或更新 CloudFormation 堆栈时,这些权限会自动包含在内。一旦这些前提条件得到解决,剩下的步骤应该就没有问题了。让我们开始执行计划,着手启动 TMC。
访问 TMC 门户
首先通过 VMware Cloud Services 门户按照以下步骤打开 TMC 门户:
- 
访问 VMware Cloud Services 门户,网址为:https://console.cloud.vmware.com/。 
- 
单击启动服务链接,位于VMware Tanzu Mission Control磁贴上,如下图所示: 

图 9.2 – VMware Cloud Services 控制台
- 这将打开如下图所示的 TMC 门户:

图 9.3 – Tanzu Mission Control 控制台
提示
如果您在 VMware Cloud Services 账户中没有 TMC 权限,您将无法在 VMware Cloud Services 控制台中看到 TMC 磁贴。您可能需要联系您的 VMware 联系人申请 TMC 试用访问,或者您可以通过以下 URL 请求访问 TMC Starter:https://tanzu.vmware.com/tmc-starter。
现在,我们已经进入 TMC 门户,接下来让我们在 TMC 中注册我们的第一个 TKG 管理集群。
在 TMC 中注册 TKG 管理集群
在 TMC 门户上执行以下步骤,以注册您现有的 TKG 管理集群, 无论其运行在 vSphere、AWS 还是 Azure 云环境上。本章中使用的管理集群部署在 AWS 上,这不会改变以下步骤中的任何过程,只需要为我们将创建的工作负载集群输入一些配置信息:
在 TMC 中注册 TKG 管理集群
在 TMC 门户上执行以下步骤,以注册您现有的 TKG 管理集群, 无论其运行在 vSphere、AWS 还是 Azure 云环境上。本章中使用的管理集群部署在 AWS 上,这不会改变以下步骤中的任何过程,只需要为我们将创建的工作负载集群输入一些配置信息:
- 单击左侧导航栏中的管理菜单选项,打开管理集群选项卡,如下图所示:

图 9.4 – 打开管理集群屏幕
- 在管理集群选项卡中,单击注册管理集群下拉菜单,选择Tanzu Kubernetes Grid选项,如下图所示:

图 9.5 – 选择 Tanzu Kubernetes Grid 注册为管理集群
- 在注册管理集群的详细信息屏幕中,输入唯一的名称,从下拉列表中选择默认(default),可选择性地添加简短描述,最后点击下一步(NEXT)按钮。我们将在本章稍后详细讨论集群组:

图 9.6 – 输入管理集群详细信息
- 点击下一步(NEXT)按钮,进入代理配置(Proxy Configuration)部分,因为我们不需要使用它:

图 9.7 – 跳过代理配置
- 您将获得一个包含 Kubernetes 资源的 YAML 文件的 URL,这些资源是您需要为管理集群创建的,以便将其与 TMC 帐户连接。请按照以下屏幕截图所示复制该 URL。您可以展开查看 YAML部分,查看将在管理集群上创建的 Kubernetes 资源及其配置详细信息:

图 9.8 – 复制注册 URL 以链接到管理集群
- 点击查看管理集群(VIEW MANAGEMENT CLUSTER)按钮,检查在 TMC 上新注册的管理集群:

图 9.9 – 验证管理集群创建情况
- 您应该看到如下屏幕截图中显示的页面。集群的状态为未知(Unknown),因为我们还没有将注册的 YAML 配置应用到我们的管理集群:

图 9.10 – 管理集群状态未知
- 
打开控制台窗口,在您的工作站上使用 kubectlCLI,并确保kubectl上下文指向管理集群。
- 
使用在步骤 4中复制的 URL 运行以下 kubectl apply命令:$ kubectl apply -f <tmc-url>
这应该列出为您的管理集群创建的多个不同 Kubernetes 资源。完成后,我们已经在 TKG 管理集群和 TMC 帐户之间建立了双向链接。我们应该能够在 TMC 上看到成功验证的管理集群。
- 经过 5 到 10 分钟后,点击验证连接(VERIFY CONNECTION)按钮,如步骤 6所示,或导航到管理 | 管理集群,以验证管理集群是否已成功注册。如以下屏幕截图所示,集群现在处于健康(Healthy)状态,并且已就绪(Ready)。点击屏幕截图中高亮显示的集群名称链接:

图 9.11 – 管理集群注册验证
- 一旦点击上一步中显示的管理集群名称,您将看到类似以下截图,显示管理集群的详细信息,包括集群中不同组件的健康指标:

图 9.12 – 管理集群详细信息
这就是通过 TMC 门户注册 TKG 管理集群的步骤。在接下来的部分,我们将展示如何使用 TMC 门户在新添加的管理集群下创建一个新的 TKG 工作负载集群。
在管理集群下创建新的工作负载集群
在 TMC 上设置好第一个 TKG 管理集群后,我们将使用此设置来创建一个新的 TKG 工作负载集群。正如前一章详细讨论的,TKG 工作负载集群用于运行容器化应用程序,而管理集群是多个工作负载集群的控制平面。
所有 TKG 工作负载集群都在provisioner下创建。Provisioner 是管理集群中的一个命名空间,负责管理管理集群中的所需工作负载集群。通过这种方式,TKG 中的 provisioner 提供了一个多租户结构,允许不同的团队创建和管理自己的工作负载集群,而不会干扰其他团队。在我们的案例中,我们将使用管理集群的default命名空间,该命名空间应该是默认存在的。
按照以下步骤为您的 TKG 管理集群创建一个新的 TKG 工作负载集群:
- 前往左侧导航栏的Administration菜单,打开Management clusters标签页,点击tkg-aws-mgmt-cluster链接以打开其详细页面:

图 9.13 – 打开管理集群页面
- 前往左侧导航栏的Clusters菜单,点击以下截图中突出显示的CREATE CLUSTER按钮:

图 9.14 – 创建工作负载集群
- 从早前在 TMC 上注册的列表中选择tkg-aws-mgmt-cluster,然后点击CONTINUE TO CREATE CLUSTER按钮:

图 9.15 – 继续创建工作负载集群
- 从Provisioner下拉菜单中选择default,然后点击NEXT按钮:

图 9.16 – 选择工作负载集群的 provisioner
- 输入集群名称,选择性地添加描述,然后点击NEXT按钮:

图 9.17 – 输入工作负载集群的详细信息
- 在此步骤中输入所需的基础设施特定详细信息,并点击下一步按钮。由于本章中使用的 TKG 管理集群运行在 AWS 上,以下截图显示了 AWS 特定的详细信息。对于 vSphere 和 Azure,某些字段会有所不同。你可以在这里获取更多详细信息:https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/services/tanzumc-using/GUID-42150344-CD4C-43AE-8C39-C059A97EF47C.html:

图 9.18 – 输入工作负载集群配置
- 选择要创建的工作负载集群的控制平面计划。你还可以选择性地更改其他字段的值,但这不是必需的,我们建议按照本章中的程序进行操作。最后,点击下一步按钮以选择工作节点详细信息:

图 9.19 – 选择工作负载集群类型
- 输入工作负载集群的工作节点数量,然后点击创建集群按钮:

图 9.20 – 输入工作节点数量
你将看到一条消息,表示正在创建工作负载集群,并显示其规格,如下图所示:

图 9.21 – 正在创建工作负载集群
- 一旦工作负载集群成功创建,你将看到如下截图所示的集群详细信息页面。根据集群的规模和基础设施,这可能需要 5 到 10 分钟:

图 9.22 – 工作负载集群详细页面
这就是我们的第三步,通过 TMC 门户使用 TKG 管理集群创建 TKG 工作负载集群。现在,我们将把一个外部管理的 Kubernetes 集群附加到 TMC,以便使用 TMC 对该集群执行各种第二天操作。
使用 TMC 附加现有 Kubernetes 集群
本节中,我们将把现有的 GKE 集群附加到 TMC 账户。你也可以选择其他类型的 Kubernetes 集群,包括 Rancher、AKS、EKS、OpenShift、上游开源等。TMC 允许你附加符合规范的 Kubernetes 集群,只要该集群具有管理员级别的kubectl访问权限。因此,让我们附加一个外部集群:
- 从左侧菜单栏进入集群菜单,并点击下图所示的附加集群按钮:

图 9.23 – 进入附加集群页面
- 输入集群名称,选择集群组为默认,可选择性地输入描述,最后,点击下图中高亮显示的下一步按钮:

图 9.24 – 输入附加集群的详细信息
- 跳过代理配置并点击下一步按钮:

图 9.25 – 跳过代理配置详细信息
- 就像我们在本章前面使用 Kubernetes YAML 配置文件注册管理集群一样,现在是时候使用类似的方法注册外部集群了。你可以查看将在目标集群上创建的 Kubernetes 资源的详细信息,以建立集群与 TMC 之间的双向通信:

图 9.26 – 复制代理配置命令以将集群附加到 TMC
- 
打开命令窗口,在该窗口中你可以通过 kubectl访问正在附加的集群,并将kubectl上下文更改为指向正在附加的集群。
- 
在命令窗口中运行 第 4 步 中复制的 kubectl命令,以在集群中创建所需的代理部署资源,进而附加到 TMC。
- 
在成功执行 kubectl create命令后,点击验证连接按钮。你应该能在列表中看到最近附加的集群,如下图所示。然后,点击附加集群的名称以验证其详细信息:

图 9.27 – 在列表中验证附加的集群
- 检查附加集群的详细信息。如以下屏幕所示,集群的类型为附加:

图 9.28 – 附加集群详细信息
这标志着我们将外部管理的 Kubernetes 集群附加到 TMC 的任务完成。接下来的步骤是创建集群组,并将我们的 TKG 工作负载和 GKE 附加集群添加到该组中。
在 TMC 上创建集群组
正如本章前面讨论的那样,TMC 允许你将具有相似性质的不同集群进行分组,并使用通用配置进行管理和操作。配置多个集群的组可以使大型 Kubernetes 基础设施的操作变得非常简便和高效。那么,接下来我们将学习如何在 TMC 中创建集群组:
- 点击左侧导航栏中的集群组菜单项,然后点击创建集群组按钮,如下图所示:

图 9.29 – 创建集群组
- 输入集群组名称,添加可选描述,然后点击创建按钮,如下图所示:

图 9.30 – 输入集群组详细信息
- 你应该能在列表中看到新创建的集群组,如下图所示:

图 9.31 – 验证集群组的存在
现在,让我们使用以下步骤将这两个集群添加到这个新创建的集群组中。
- 点击如下截图所示的默认集群组:

图 9.32 – 选择默认集群组
- 选择我们在 TMC 上的两个集群,分别用于 TKG 工作负载和 GKE,然后点击如以下截图所示的移动按钮:

图 9.33 – 选择用于分组的集群
- 选择我们在步骤 2 中创建的集群组并点击移动按钮:

图 9.34 – 选择集群组
- 进入集群组页面,点击我们创建的新集群组,检查我们在上一步中添加的两个集群的存在:

图 9.35 – 进入新的集群组
- 如下截图所示, 在本节中我们创建的两个集群都在集群组中:

图 9.36 – 集群组中的列出集群
将具有相似需求的集群进行分组是一种非常强大的方法,能够管理数百个具有异构需求的集群。除了集群组,TMC 还允许你将 Kubernetes 命名空间进行分组,以执行适用于多个集群中不同命名空间的某些命名空间级配置。让我们深入了解一下。
理解 TMC 中的工作区
如本章前面所讨论的,TMC 允许你将具有相似性质的集群进行分组。分组有助于我们为它们创建共同的配置和策略,从而提高运营效率。然而,Kubernetes 中的某些策略只能在命名空间级别应用,例如定义一个命名空间中的 Pod 可以与另一个命名空间中的 Pod 通信的网络策略。此外,我们还可以在命名空间级别配置集群用户访问策略,TMC 也允许我们在命名空间级别创建镜像仓库访问策略。虽然将集群级别的策略应用于集群组是一个简单的任务,但为单个命名空间应用命名空间级别的策略可能非常不实用。此外,如果我们试图管理数百个 Kubernetes 集群,尝试将命名空间级别的策略应用于集群中一组命名空间也不会有太大帮助。基于这些原因,TMC 提供了一种名为工作区的构造,它允许我们在不同的集群中创建一组命名空间——然后,我们可以创建一个适用于整个工作区的命名空间级别的策略,从而适用于同一工作区中的所有命名空间。在不同集群中部署的多云应用程序可能需要类似的用户访问或网络策略配置。对于包含此应用程序所有命名空间并运行不同集群的工作区,将它们作为一个单位进行管理会非常方便。
让我们在本章前一节中添加的两个集群中创建两个命名空间,然后创建一个工作区,将这两个命名空间添加到其中:
- 从左侧导航栏中打开工作区菜单,并点击创建工作区按钮,如下截图所示:

图 9.37 – 创建工作区
- 输入名称,任选地添加描述,并点击页面上的创建按钮,如下截图所示:

图 9.38 – 输入工作区详情
- 如下截图所示,一个新的工作区已经创建。点击工作区名称,确保其中没有列出任何命名空间:

图 9.39 – 验证工作区是否已创建
- 打开我们之前在 TMC 门户上创建的tmc-demo-clusters集群组,如下截图所示:

图 9.40 – 打开集群组
- 点击 TKG 工作负载集群,如下截图所示:

图 9.41 – 打开集群详情页面
- 点击集群详情页面的命名空间选项卡,选择default命名空间,然后点击ATTACH 1 NAMESPACE按钮,如下图所示:

图 9.42 – 选择要附加到工作区的命名空间
- 选择或输入工作区名称,然后点击ATTACH按钮,如下图所示:

图 9.43 – 选择要附加的工作区
- 如下图所示,你可以看到default命名空间现在位于tmc-demo-workspace下,我们在之前的步骤中创建了这个工作区:

图 9.44 – 验证命名空间与工作区的关联
- 
按照本章节的说明,重复步骤 5 到 8,将default命名空间添加到此新工作区中,适用于另一个集群gke-cluster-1,我们之前已将其附加到 TMC 并加入了tmc-demo-clusters组。 
- 
从左侧导航栏打开工作区菜单,点击我们之前创建的新的工作区tmc-demo-workspace: 

图 9.45 – 打开工作区详情
- 你应该能够看到来自两个不同集群的两个默认命名空间,它们作为我们在本部分创建的新工作区的一部分列出,如下图所示:

图 9.46 – 验证工作区中的命名空间
到此为止,我们已经涵盖了如何创建工作区以及如何将现有命名空间附加到工作区中的不同集群。在我们之前讨论的示例中,我们使用了与 TMC 中同一集群组内集群名称相同的默认命名空间。然而,你可以将任何命名空间添加到工作区,无论命名空间名称和其父集群的组状态如何。
到此为止,我们已经完成了本章节这一部分的所有步骤——开始使用 TMC。我们学习了如何在 TMC 中注册 TKG 管理集群,并使用 TMC 界面创建了一个 TKG 工作负载集群。然后,我们还将一个外部管理的 GKE 集群附加到 TMC。最后,我们学习了如何将集群和 Kubernetes 命名空间分组,以便将它们作为一个单位执行常见操作。在章节的下一部分,我们将学习如何使用 TMC 进行集群数据的备份和恢复。
使用 TMC 保护集群数据
Kubernetes 广泛用于在生产环境中运行业务关键应用程序。在这些情况下,应该有可靠的灾难恢复机制来定期进行集群数据和配置备份,并在任何原因导致数据丢失时恢复它们。尽管 Kubernetes 主要用于运行无状态工作负载,其中持久化数据存储在集群外部的数据库中,但运行有状态的软件,如缓存、队列和数据库,正逐渐被采纳。在第六章,《使用 Harbor 管理容器镜像》中,Harbor 注册表部署使用的是部署在 Kubernetes 上的数据存储。这使得备份数据变得更加重要。
为了涵盖这个重要主题,我们将学习如何通过 TMC 进行集群备份和恢复,步骤如下:
- 
配置一个兼容 S3 的远程备份存储位置。 
- 
配置集群使用远程存储位置来备份数据。 
- 
将自定义应用部署到集群。 
- 
对集群进行备份。 
- 
删除集群命名空间及其中的自定义部署,以模拟灾难。 
- 
恢复集群备份。 
- 
在恢复后,验证已删除的命名空间和其中的自定义部署是否存在。 
让我们开始逐步执行这些步骤。
配置备份目标位置
TMC 允许你为不同的集群组创建独立的备份目标位置。为集群组配置备份位置是一次性的管理活动。一旦目标位置与集群组关联,我们就可以使用该备份位置配置为集群组中的任何集群进行按需或定期备份。此外,一个配置好的备份位置可以被多个集群组使用。在本章中,我们将使用 AWS S3 选项作为存储位置。
以下步骤描述了如何在 TMC 中为集群组配置备份目标位置:
- 
创建你的 AWS 账户凭证,供 TMC 用于将备份数据存储在 S3 桶中: - 从左侧导航栏打开管理菜单,并点击创建账户凭证按钮,如下图所示:
 

图 9.47 – 创建 AWS 账户凭证
- 从TMC 配置的 存储选项中选择AWS S3选项:

图 9.48 – 选择已配置的存储
- 输入账户凭证名称并点击生成 模板按钮:

图 9.49 – 输入凭证名称并生成模板
- 应该下载一个凭证模板文件。这是一个 AWS CloudFormation 模板,用于创建所需的 S3 存储桶,并授予 TMC 所需的权限,以便访问该存储桶进行备份和恢复操作。将该模板文件保存在本地工作站上,并点击 下一步 按钮:

图 9.50 – 下载生成的 AWS CloudFormation 模板
- 按照 快速入门指南 链接,将下载的模板应用到你的 AWS 帐户中。应用 CloudFormation 模板后,你将在模板执行的输出中获得 Amazon 资源名称 (ARN),该 ARN 将在下一步中使用。你可以在快速入门指南中找到这些指令,如下图所示:

图 9.51 – 按照快速入门指南创建所需的 AWS S3 对象
- 在应用 CloudFormation 模板后,从 AWS 中复制 ARN 并点击 创建 按钮,最终创建我们可以用于任何集群的备份和恢复操作的帐户凭证:

图 9.52 – 应用复制的 ARN 并创建凭证
- 在帐户凭证成功创建后,你应该能在 管理 菜单下的 帐户 标签中看到它,如下图所示:

图 9.53 – 验证帐户凭证的创建
- 转到 管理 菜单下的 目标位置 标签,并点击 创建目标位置,选择 AWS S3 选项,如下图所示:

图 9.54 – 创建目标位置
- 选择我们在本节 第 1 步 中创建的帐户凭证,并点击 下一步 按钮:

图 9.55 – 选择帐户凭证
- 选择我们在本章早些时候创建的集群组,并点击 下一步 按钮:

图 9.56 – 将集群组添加到目标位置
- 输入目标位置的名称并点击 创建 按钮:

图 9.57 – 输入目标位置名称
- 你应该能在 管理 菜单下的 目标位置 标签中看到新创建的目标位置,以及帐户凭证和相关的 S3 存储桶名称,如下图所示:

图 9.58 – 验证目标位置的创建
现在,既然我们已经设置了备份目标位置并将其分配给集群组,我们可以继续对该组中的集群执行备份和恢复操作。
启用集群的数据保护
完成为集群组执行备份和恢复所需的步骤后,我们来为组中的一个集群启用它。在本示例中,我们将使用之前附加到 TMC 的外部管理 GKE 集群。执行以下步骤完成此任务:
- 点击附加的集群gke-cluster-1,位于tmc-demo-clusters组中。如果你使用了本章中未提到的名称,你需要相应地选择集群:

图 9.59 – 打开附加集群的详情页面
- 点击如下面截图中突出显示的启用数据保护链接:

图 9.60 – 点击启用数据保护链接
- 点击启用按钮以确认操作:

图 9.61 – 启用集群的数据保护
该操作部署了 Velero,这是一个开源的 Kubernetes 集群备份和恢复工具。通过这个操作,我们已经为集群准备好了备份功能,并且部署了所需的工具集。现在,让我们在集群中部署一个测试工作负载。
在集群中部署自定义应用
执行以下步骤,在我们之前任务中启用备份和恢复的集群上运行 nginx 部署:
- 
在目标集群的 kubectl上下文中,运行以下命令,这会创建一个名为nginx的命名空间,并在其中创建一个名为nginx-deployment的 Kubernetes 部署,部署三个 Pod。你可以查看以下命令中使用的部署清单文件,以获取更多详细信息:$ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/nginx-deployment.yaml
- 
使用 TMC 门户在集群详情页的工作负载标签下验证部署。如以下屏幕所示,nginx 部署和副本集都在健康状态下运行。为了减少屏幕上的杂乱,你还可以使用突出显示的切换按钮过滤 Tanzu 和 Kubernetes 特定的工作负载: 

图 9.62 – 验证集群的工作负载部署
现在,我们在目标集群的自己的命名空间中部署了一个可以备份的工作负载。让我们使用以下步骤对集群进行备份。
备份集群
执行以下步骤备份我们在上一个任务中部署 nginx 工作负载的集群:
- 在集群的概览标签页中,点击如下面截图中突出显示的创建备份链接:

图 9.63 – 启动集群备份过程
- 选择备份整个集群的选项,并点击NEXT按钮。我们也可以仅备份选定的命名空间或通过标签值标识的对象,这是一个非常灵活的选择:

图 9.64 – 选择备份范围
- 选择我们在本章中之前创建的指向 AWS S3 桶的备份目标位置,并点击NEXT按钮:

图 9.65 – 选择备份目标位置
- 选择备份计划。虽然我们可以创建定期的备份计划,但在这里,我们将选择NOW进行按需备份,以了解这一概念。然后点击NEXT按钮继续:

图 9.66 – 选择备份计划
- 输入备份保留天数的值并点击NEXT按钮:

图 9.67 – 输入备份保留天数
- 最后,输入备份的名称,并点击CREATE按钮,如下图所示:

图 9.68 – 输入备份名称
- 这将触发备份过程,在 2 到 5 分钟内,你应该能在集群的数据保护标签页下看到备份完成的状态。如果集群中有其他工作负载在运行,备份过程可能需要更长时间:

图 9.69 – 验证备份完成
在成功备份集群后,接下来我们将进行恢复操作——但在恢复之前,让我们不小心删除包含之前创建的 nginx 部署的nginx命名空间。
删除集群中运行的自定义部署
按照以下步骤执行此任务:
- 
运行以下命令删除目标集群中的nginx命名空间: $ kubectl delete namespace nginx
- 
在集群的工作负载标签页中验证 nginx 部署的缺失。如图所示,我们之前验证过的nginx-deployment及其相应的 ReplicaSet 现在已经缺失: 

图 9.70 – 验证工作负载删除
现在,由于我们不小心删除了整个命名空间及其中运行的工作负载,以模拟灾难情景,让我们使用之前为集群创建的备份来恢复已删除的命名空间并使其对象重新运行。
恢复集群备份
按照以下步骤恢复目标集群的备份,并将已删除的 Kubernetes 对象恢复到该集群中:
- 转到集群的数据保护选项卡,从备份列表中选择之前所做的备份,并点击恢复链接,如下图所示:

图 9.71 – 恢复备份
- 由于我们只删除了一个命名空间,我们只需选择高亮显示的选项以恢复特定的命名空间。选择需要恢复的nginx命名空间。在这里,TMC 还允许我们将备份中的源命名空间恢复到不同的目标命名空间(如果需要)。可以使用目标命名空间标题旁边的小铅笔图标进行此操作。选择命名空间后,点击下一步按钮:

图 9.72 – 选择恢复备份规范
- 输入恢复实例的名称并点击恢复按钮:

图 9.73 – 输入恢复实例名称
- 成功恢复后,您将在集群的数据保护选项卡下的恢复部分看到恢复的条目,如下图所示:

图 9.74 – 验证恢复是否已完成
- 在集群详细页面的工作负载选项卡下,验证nginx命名空间及其对象的存在。如您所见,nginx命名空间现已成功恢复:

图 9.75 – 验证恢复对象的存在
通过此步骤,我们可以总结关于备份和恢复 Kubernetes 集群的漫长而重要的一节。值得注意的是,本节中进行的几项配置是一次性活动。这包括创建 AWS S3 账户凭证、创建备份的目标位置、将目标位置与集群组关联等。完成这些设置后,备份和恢复集群或集群的一部分仅需几次点击。
现在让我们来看看 TMC 的另一个非常重要的功能——策略管理。
使用 TMC 应用治理策略到集群
在本章的前一部分中,我们学习了如何通过注册 TKG 管理集群、创建 TKG 工作负载集群、附加 GKE 集群以及最后进行集群分组来开始使用 TMC——但我们为什么要将所有集群引入 TMC?在本节中,我们将通过使用 TMC 界面执行这些集群的各种活动来探讨这个问题。我们将涵盖以下活动:
- 
为集群组配置安全策略 
- 
为工作区配置镜像注册表治理策略 
- 
为集群组配置部署治理策略 
- 
检查集群的策略违规状态 
- 
检查集群是否符合 CIS 基准 
本节内容涵盖了一长串活动,让我们一个个完成它们。
为集群组配置安全策略
在运行容器时,从安全角度来看,有几件事情可能会配置错误,这会给黑客留下利用这些漏洞的机会。根据集群中运行的工作负载的性质,Kubernetes 管理员可能需要保护多个方面。在微服务的世界中,Kubernetes 平台团队通常需要允许不同的团队部署其应用程序,并按应用程序要求配置相关设置。然而,确保所有团队遵循平台团队所概述的必要安全实践可能是一个非常困难的任务。这就是为什么 Kubernetes 管理员需要为集群设置保护措施,以防止工作负载以不安全的方式部署。为了解决这个需求,Kubernetes 提供了一种名为 PodSecurityPolicy 的构造,它定义了在 PodSecurityPolicy 生效时,Pod 在 Kubernetes 集群中可以做什么以及不能做什么。TMC 允许你为一组集群配置这些安全策略,从而避免集群之间出现配置漂移。
让我们为之前创建的集群组创建一个这样的安全策略。此策略将防止任何 Pod 获得对 Kubernetes 节点操作系统和资源的特权访问。以下步骤将帮助创建并测试此策略:
- 
确保在应用策略之前,可以部署具有特权访问的 Pod,按照以下子步骤进行操作: - 使用以下命令,在 tmc-demo-clusters组下的 TKG 工作负载集群中部署特权 Pod。你可以查看以下命令中使用的 Pod 定义文件——注意其中定义了安全上下文,以便允许 Pod 获取特权访问:
 $ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/privileged-pod.yaml- 验证 Pod 是否已创建并成功运行。这里假设没有任何安全策略阻止特权 Pod 的创建:
 $ kubectl get podNAME READY STATUS RESTARTS AGEprivileged-pod 1/1 Running 0 48s
- 使用以下命令,在 
- 
在验证我们可以在集群中运行特权 Pod 后,现在让我们使用以下子步骤在 TMC 中为集群组创建安全策略: - 从左侧导航栏的 策略 > 分配 菜单以及 安全性 选项卡中打开。然后,点击集群组 tmc-demo-clusters,并点击如下截图中突出显示的 创建安全策略 按钮:
 

图 9.76 – 为集群组创建安全策略
- TMC 允许您通过从头开始定义自定义安全策略来完全自定义您的安全要求。它还提供了两种现成的选择:基础和严格。让我们从安全模板下拉菜单中选择基础。您会注意到,它限制了特权容器的创建,如以下截图所示。最后,点击创建策略按钮,将限制应用于相关集群组:

图 9.77 – 进入安全策略配置
- 您将看到集群组的策略列表,如以下截图所示:

图 9.78 – 验证安全策略创建
- 
现在,让我们验证该策略是否已应用于组中的集群。请按照以下子步骤进行操作: - 首先,通过运行以下命令删除我们在第一步中在 TKG 工作负载集群中创建的 Pod:
 $ kubectl delete pod privileged-pod- 通过运行以下命令,再次创建相同的 Pod:
 $ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/privileged-pod.yaml- 您将看到如下错误信息,说明由于安全策略的原因,Pod 未能成功创建:
 Error from server ([tmc.cgp.tmc-security-policy-demo] Privileged container is not allowed: centos, securityContext: {"privileged": true}): error when creating "https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/privileged-pod.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [tmc.cgp.tmc-security-policy-demo] Privileged container is not allowed: centos, securityContext: {"privileged": true}
这就结束了我们关于如何配置适用于使用 TMC 部署和运行工作负载的 Kubernetes 集群安全策略的学习。我们测试了在应用该策略的集群组中的一个集群,但您也可以对组中另一个集群进行相同的操作,并应看到类似的测试结果。就像这里解释的运行特权容器的例子一样,我们可以使用 TMC 为集群组创建多种不同类型的安全策略。接下来,我们将学习如何应用一个工作区级别的策略,定义在特定集群命名空间中运行的工作负载如何从容器注册表拉取容器镜像。
为工作区配置镜像注册表策略
在拉取容器镜像时,建议采用一些经过验证的最佳实践。对于受监管环境的镜像拉取限制,可能会更为严格。以下是 TMC 根据不同的合规要求,允许您为容器注册表策略配置的参数。TMC 中的注册表策略可能根据需要具有所有或某些适用的参数:
- 
仅使用摘要(SHA)拉取镜像,而不使用标签 – 这是在生产环境中设置的重要规则,因为标签在技术上可能会为不同的拉取实例提供不同的内容,而同一摘要的镜像内容始终是相同的。使用摘要拉取镜像可以确保它们始终具有相同的内容。 
- 
仅从特定镜像仓库拉取镜像 – 如果要求容器只能从内部托管的容器注册表拉取镜像,这条规则将有所帮助。 
- 
myapp/*。
- 
允许具有特定标签值的镜像 – 这与之前的规则类似,但适用于标签名称。 
在本节中,我们将学习如何配置一个策略,仅通过摘要而不是标签来要求拉取镜像。以下是实现此操作的步骤:
- 从左侧导航栏进入策略 | 分配菜单,选择镜像注册表选项卡。然后,选择我们之前创建的工作区,点击创建镜像注册表策略按钮,如下图所示:

图 9.79 – 创建镜像注册表策略
- 从镜像注册表模板下拉菜单中选择要求摘要选项,提供策略名称,并点击创建 策略按钮:

图 9.80 – 输入镜像注册表策略详情
- 你可以看到为选定的工作区创建的新镜像注册表策略,如下图所示:

图 9.81 – 验证镜像注册表策略的创建
- 
在 GKE 附加的集群中创建一个新的命名空间的 Pod,该命名空间不受策略影响。此 Pod 使用标签拉取镜像。Pod 定义的 YAML 文件可以在以下链接查看:https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/image-tag-using-pod.yaml: - 使用以下命令在集群中创建一个新的命名空间:
 $ kubectl create namespace test-registry-policy- 创建一个使用标签拉取镜像的 Pod:
 $ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/image-tag-using-pod.yaml -n test-registry-policy
- 
你将看到 Pod 成功创建,没有任何问题: NAME READY STATUS RESTARTS AGEimage-tag-using-pod 1/1 Running 0 7s
- 
使用以下命令,在我们应用了镜像注册表策略且不允许通过标签值拉取镜像的default命名空间中创建相同的 Pod: $ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/image-tag-using-pod.yaml
- 
你将看到 Pod 无法创建,并显示以下错误信息,解释了所施加的限制: Error from server ([tmc.wsp.default.tmc-image-registry-policy-demo] container <busybox> has an invalid image reference <busybox:stable-uclibc>. allowed image patterns are: {hostname: [], image name: [] and require digest}): error when creating "image-tag-useing-pod.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [tmc.wsp.default.tmc-image-registry-policy-demo] container <busybox> has an invalid image reference <busybox:stable-uclibc>. allowed image patterns are: {hostname: [], image name: [] and require digest}
- 
使用以下命令创建相同的 Pod,替换镜像标签为摘要: $ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/image-digest-using-pod.yaml
- 
你将看到此时 Pod 在default命名空间中成功创建,且镜像策略的限制已生效: NAME READY STATUS RESTARTS AGEimage-digest-using-pod 1/1 Running 0 3s
这部分内容结束了如何为工作区创建适用策略的学习。之前配置和测试的限制同样适用于其他集群的default命名空间,作为同一工作区的一部分。
在下一个主题中,我们将学习如何使用 TMC 为集群组应用部署治理策略。
配置集群组的部署治理策略
在大多数 Kubernetes 平台部署中,平台团队负责确保他们的内部客户——应用团队,能够有序使用平台。这种有序使用包括公平使用可用的计算资源以及高可用性部署的应用程序。当多个不同的 Kubernetes 平台团队管理较少的集群时,实施适用于全企业的标准将具有挑战性,因为各个平台团队可能有各自的偏好。另一方面,如果由中央管理团队管理所有集群,那么确保符合治理政策将变得非常困难。为了解决这些挑战,TMC 允许您创建部署治理策略。TMC 使用一个名为Open Policy Agent(OPA)Gatekeeper(https://github.com/open-policy-agent/gatekeeper)的开源项目来实现这些策略。由于 Gatekeeper 策略配置的声明式特性,TMC 还允许您为任何用例创建自定义部署策略——天空是极限!
以下是 TMC 提供的部分开箱即用的策略,可以根据需要应用到不同的集群组:
- 
阻止某些 Kubernetes 资源的创建 
- 
强制为某些 Kubernetes 资源分配标签 
- 
阻止特定主题在集群中用于角色绑定 
- 
限制特定负载均衡器 IP 地址供 Kubernetes 服务使用 
- 
强制在集群中为入口资源配置 HTTPS 
- 
阻止在集群中创建 NodePort类型的服务
让我们学习如何为之前创建的集群组创建这样的治理策略,并测试它对集群操作的影响。在以下示例中,我们将创建一个策略,以防止创建没有名为app的标签的 Pod。换句话说,在应用了此策略的集群中,如果 Pod 没有指定它所属的应用程序名称,则创建该 Pod 将失败。
按照以下步骤创建并测试此策略:
- 从左侧导航栏的策略 | 分配菜单进入,并打开自定义标签。然后,从列表中选择我们之前创建的集群组,并点击高亮显示的创建自定义策略按钮:

图 9.82 – 创建自定义部署策略
- 在标签下选择app作为必需的键。最后,向下滚动并创建策略:

图 9.83 – 输入自定义部署策略详情
- 创建策略后,您应该能够看到这些设置已配置在集群组下,如下截图所示:

图 9.84 – 验证政策的创建
- 
在我们已将政策应用到的集群组中添加的两个集群之一(TKG 工作负载或 GKE)中创建一个 Pod,使用以下命令。您可以看到命令中使用的 Pod 定义文件,并验证该 Pod 在规格 YAML 中没有任何标签: $ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/pod-without-label.yaml
- 
您应该会看到类似以下的错误信息: Error from server ([tmc.cgp.tmc-deployment-policy-demo] You must provide labels with keys: {"app"}): error when creating "https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/pod-without-label.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [tmc.cgp.tmc-deployment-policy-demo] You must provide labels with keys: {"app"}
- 
现在,让我们使用以下命令创建一个带有所需标签的 Pod。这一次,我们将使用一个不同的 Pod 规格文件,其中指定了 app标签。打开命令中使用的文件查看新增的标签——app:$ kubectl apply -f https://raw.githubusercontent.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/main/chapter-10/pod-with-label.yaml
- 
您将看到,这一次,Pod 成功创建,因为我们提供了政策要求的标签: $ kubectl get podNAME READY STATUS RESTARTS AGEpod-with-label 1/1 Running 0 117s
这就结束了如何创建适用于组内所有集群的自定义政策并测试其影响。TMC 管理员可以根据任何逻辑需求创建这些政策并制定其模板。之后,可以使用这些模板和自定义参数(如前面示例中的标签键名称)来对一组集群应用政策——但是,我们如何跟踪政策合规失败,以便在 TMC 管理的数百个集群中及时了解这些问题呢?接下来我们将在下一部分找到答案。
检查所有集群的政策违规状态
如本章前面所讨论的,我们可以使用 TMC 在集群组和工作区级别创建几种不同类型的政策。除了为后续的 Kubernetes 平台创建安全边界外,TMC 还提供了一种方法,可以监控所有 TMC 负责的集群中关于政策违规的见解。为此,只需打开 政策 > 左侧导航栏中的 见解 菜单,您将看到如下一张详细报告截图。正如您所见,它显示了我们进行的几项政策测试,违反了我们的政策:

图 9.85 – 获取政策见解
了解了政策并检查其合规状态后,我们现在来学习如何对集群进行 CIS 基准审计。
检查集群是否符合 CIS 基准
如本章前面所讨论的,对集群进行安全合规审计以查找常见漏洞是防止网络攻击的积极措施。扫描 Kubernetes 集群以检查一套最佳安全实践并列出详细清单是一项具有挑战性的任务,除非有复杂的自动化工具来执行此操作。TMC 为其所有管理的集群提供了这一功能,通过使用开源工具 Sonobuoy,如前所述。当前版本的 TMC 可以执行以下两种类型的集群检查:
- 
符合性 – 检查集群配置是否符合官方 Kubernetes 规范 
- 
CIS 基准 – 检查 Kubernetes 集群部署是否遵循 CIS 基准中概述的安全最佳实践 
让我们学习如何检查由 TMC 管理的集群的 CIS 基准。按照以下步骤执行检查,并使用 TMC 控制台查看检查结果:
- 在左侧导航栏中点击检查菜单,然后点击截图中高亮显示的运行检查按钮:

图 9.86 – 运行集群检查
- 选择一个现有的集群,将检查类型设置为CIS 基准,然后点击运行按钮:

图 9.87 – 选择要运行的检查
- 您将在几分钟内看到检查结果,如下图所示。正如您所看到的,扫描已发现一些失败的测试用例,需要解决这些问题以增强安全性:

图 9.88 – 检查检查结果
- 点击前一个屏幕上的测试结果链接,您将看到有关失败的测试用例、警告和成功案例的详细报告,如下图所示。该报告提供了每个测试用例的详细信息和建议。您还可以下载报告以便离线查看:

图 9.89 – 查看详细的检查报告
这就结束了运行集群检查的主题。除了主要的检查菜单,我们还可以在 TMC 上的集群详情部分触发集群检查。
到此为止,我们已经涵盖了所有计划中的操作,主要是关于如何通过 TMC 为 Kubernetes 集群应用治理策略。首先,我们展示了如何创建安全策略来限制运行特权容器的能力。接着,我们学习了如何创建镜像注册表策略,示例中是防止没有摘要的镜像拉取。之后,我们创建了部署策略,防止没有特定标签的 Pod 被创建,并查看了使用 TMC 创建的各种自定义策略类型。接下来,我们了解了如何查找策略违规。最后,我们学习了如何运行集群合规检查并获取其详细报告。除了 TMC 的这些功能外,还有一些其他操作我们没有在本章中介绍:
- 
管理集群组、集群、工作区和命名空间的用户访问策略 
- 
在由 TMC 管理的集群上从已发布的目录中安装各种工具 
- 
检查由 TMC 管理的集群发出的各种事件 
- 
执行多个与 TMC 相关的管理活动,包括配置 TMC 访问权限、外部集成和代理配置等。 
要了解更多细节,请参考此文档链接:https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/index.html。
总结
在本章中,我们讨论了 TMC 如何帮助最小化管理在不同云环境中运行的任何上游 Kubernetes 发行版的工作量。该工具的高层次价值主张是为多云、多集群和多团队使用提供管理控制。首先,我们理解了采用少量大集群或大量小集群的部署方式所面临的不同挑战。接着,我们看到了 TMC 的使用案例以及它为管理 Kubernetes 部署时解决复杂问题提供的解决方案。我们讨论了在不同云环境中部署的不同集群的操作挑战,以及如何保持操作员和开发人员体验的一致性。我们看到 TMC 如何通过集群组和工作空间简化这一过程,工作空间是跨不同集群的 Kubernetes 命名空间的集合。
接着,我们学习了如何开始使用 TMC,包括如何将 TKG 管理集群与 TMC 集成。然后,我们讨论了如何使用 TMC 执行基于 TKG 基础的集群生命周期操作。之后,我们看到如何在 TKG 控制平面下创建新的工作负载集群,这些集群成为 TMC 管理的集群的一部分。接下来,我们还学习了如何将外部创建或管理的集群(如 GKE 集群)带入 TMC,并将其纳入 TMC 中定义的集群组。我们还学习了如何为部署在两个不同云环境中的集群创建 Kubernetes 命名空间组,即工作空间。开始使用 TMC 后,我们首先学习了如何通过 TMC 的备份和恢复功能保护集群数据。然后,我们介绍了如何通过在集群组或工作空间级别应用各种策略来管理集群队列。最后,我们讲解了如何检查不同的集群,以主动应对安全问题。
由于 TMC 是控制大规模 Kubernetes 部署的单一视图,VMware Aria 应用操作是一个用于观察Kubernetes 部署规模的单一视图,具备全栈可观测能力,从应用层到基础设施层。我们将在下一章详细介绍这个主题。
第十章:实现 VMware Aria Operations for Applications 的全栈可视化
在上一章中,我们学习了如何使用 Tanzu Mission Control 来管理数百个 Kubernetes 集群,进行生命周期管理、策略控制和数据保护。Tanzu Mission Control 是 Kubernetes 所有这些问题的单一控制点。在本章中,我们将讨论一个集中可视化的视角,用于监控在容器中运行的云原生应用,以及它们周围的所有支持层和系统。了解系统的关键健康状态是信息技术领域中的一个非常古老且基本的概念,被称为监控。它也被称为遥测。在监控传统的单体应用时,我们使用的工具多年来并不能为在不同集群、平台和云环境中运行的微服务提供所需的结果。随着微服务的出现,世界变得非常分布式。通常,微服务运行在容器中,而容器是短暂的——它们很快就会出现又消失。在这种情况下,微服务的上下文的连续性变得非常重要,因为它们可能会在几分钟后运行在不同的容器中,而传统应用则不会离开它们的虚拟和物理主机多年。更复杂的是,微服务还需要处理大量的基数问题,包括它们所属的更大应用、它们部署的环境,以及它们部署的节点、集群、可用区和区域等。在监控微服务时,我们需要一种不同的方法,因为它们的运行方式不同。某种程度上,将应用部署到容器中就像将航天器送往火星任务一样。我们无法知道容器最终会物理地停留在哪里——我们只能依赖它以固定频率发出的健康数据,并在需要时进行调整。在这些条件下,传统的监控工具是无法提供帮助的。当我们面临数百万次交易、成千上万的容器、数百个节点和数十个数据中心时,我们需要强大的可观察性。VMware Aria Operations for Applications(前身为 Wavefront 的 Tanzu Observability)是 Tanzu 产品组合中专门解决现代应用管理这一需求的工具。
2017 年 5 月,VMware 收购了位于加利福尼亚州帕洛阿尔托的私人公司 Wavefront。Wavefront 的强大之处在于其能够实时处理来自数百个位置的数百万个指标和其他数据点,并渲染出具有时间点的图表和警报,以便进行关联性可见性。后来,Wavefront 成为了 Tanzu 产品组合的一部分,为这一组合增添了一个至关重要的拼图——可观察性。因此,本章或标准产品文档中对 Wavefront 的任何引用都指的是 VMware Aria Operations for Applications。为了简洁起见,本章中我们将其简称为 Aria,并将通过以下主题详细介绍:
- 
为什么选择 Aria? – 涵盖该工具的各种功能和能力 
- 
解锁 Aria – 涵盖该工具的关键概念、组件及常见的部署架构 
- 
开始使用 Aria – 涵盖将 Kubernetes 集群和应用程序与该工具集成的内容 
- 
使用图表和仪表板 – 涵盖构建图表和使用该工具创建新仪表板的高级理解 
- 
使用警报 – 涵盖如何使用该工具创建、管理和观察警报的详细内容 
由于篇幅限制,我们必须跳过 Aria 的其他一些方面,以保持章节的合理长度。Aria 是一个非常强大的工具,能够执行与可观察性和应用性能管理(APM)相关的各种操作,但考虑到本书的广泛内容,我们只会覆盖与微服务、容器和 Kubernetes 监控相关的细节。在此基础上,让我们开始可观察性的旅程。
为什么选择 Aria?
Aria 是一个可观察性工具,而不是一个监控工具。监控工具可以告诉你一个应用程序运行缓慢,但可观察性工具可以帮助你找到应用程序变慢的根本原因。这是因为它允许你将来自所有可能影响应用程序性能的周边组件的健康指标进行关联。问题可能出在操作系统(OS)层,或者是数据库中的慢查询。可观察性工具的主要优势在于它能够从所有可能的系统和层次中摄取数据点,并收集所有不同的健康指标,这些指标可能会引发重大事件。然后,它通过应用关联公式到收集到的数据,减少无关数据的噪音,帮助你在信息海洋中找到针。可观察性工具可以帮助你识别异常的流量模式、延迟、错误率以及更多其他属性,这些都基于历史数据模式。例如,一个应用程序在午夜时段的平均请求率通常与白天的请求率不同。因此,如果在特定时间段内,应用程序的请求率异常,可观察性工具可以发出警报。这些工具的能力有助于在问题变得无法挽回和代价昂贵之前,早早发现异常。
随着微服务和容器化平台的兴起,可观察性近年来已经成为一个流行词。市场上有各种开源和商业解决方案,提供类似的功能。在这一章中,与其他章节一样,我们的目标不是将 Aria 与任何其他可观察性工具进行比较,而是突出 Aria 作为一个有吸引力的选择,其独特的功能使其脱颖而出。让我们从几个方面来看,回答为什么选择 Aria?
集成(几乎)所有东西
如前所述,观察性功能的强大取决于从各个层级摄取的数据以及支持关键业务系统的工具。为此,我们可能需要从许多不同的系统中摄取指标、事件、直方图和日志。这些系统可能是各种基础设施平台,如亚马逊网络服务(AWS)或 Azure 公共云;本地 vSphere 堆栈;操作系统,如 Windows、Ubuntu、Photon 或 RedHat;中间件层,如 Tomcat 服务器;像 Spring Boot 和 NodeJS 这样的应用框架;各种缓存;关系型数据库(RDBMS);NoSQL 和队列作为数据源;以及用于警报、容器化、可视化、终端用户分析等的其他多个组件。为了满足这一需求,Aria 支持超过 250 种即插即用的集成。这些集成有详细文档,帮助自助配置。许多流行的集成,如 Kubernetes、流行的公共云服务和应用框架,附带有现成的仪表板和警报,便于快速实现这些集成的价值。通过这些即插即用的仪表板和警报,用户可以在数据开始流入的几分钟内看到有意义的数据。以下是 Aria 即插即用集成的类别:
- 
VMware 产品 
- 
Web 应用平台,如.NET、Tomcat 和 nginx 
- 
云服务,如 AWS、Azure 和谷歌云平台(GCP) 
- 
数据存储,如 PostgreSQL、Redis、Cassandra 和 Oracle 
- 
DevOps 工具,如 Jenkins、GitHub、Chef、Ansible 和 Terraform 
- 
消息平台,如 RabbitMQ 和 Kafka 
- 
监控工具,如 AppDynamics、Dynatrace 和 Prometheus 
- 
操作系统,如不同版本的 Linux、Windows 和 macOS 
- 
应用框架,如 Spring Boot、Python、Go 和 Java 
- 
警报系统,如 PagerDuty、ServiceNow 和 Slack 
- 
认证提供商,如 Okta、Google 和 Microsoft Active Directory 
这个列表并不全面。每个类别中还有许多工具超出了这里列出的范围。除此之外,Aria 还具有可扩展框架,允许你通过其基于插件的模型和软件开发工具包(SDK)从任何系统中拉取指标和其他健康指标。正如我们将在本章后面看到的,Aria 可以通过一个名为Telegraf的开源指标收集代理(github.com/influxdata/telegraf)从大多数系统中获取指标。Telegraf 有一长串插件,使其非常可扩展。对于 Aria 即插即用集成中没有的数据源,我们可以通过最小的努力创建自定义集成。此外,如果没有现成的插件来摄取数据,可以使用 Aria SDK 进行自定义开发。有关详细信息,请访问docs.wavefront.com/wavefront_sdks.html。
获取全栈可见性
你是否曾经意识到,当你在容器中运行应用程序时,下面和周围有多少不同的层次?一个应用程序被封装在容器中。在 Kubernetes 中,一个或多个容器被封装在一个 Pod 中。这些 Pod 是 Kubernetes 节点的一部分。一个节点通常是运行在虚拟机上的虚拟机,这些虚拟机通常基于一个如 vSphere 的虚拟化平台。虚拟化平台位于物理主机之上。这些物理主机是位于世界某地数据中心机架的一部分。此外,应用程序可能还会使用外部服务,如其他依赖应用程序、运行时环境(如 Tomcat 服务器或 Java 运行时环境)、数据库、可能还有缓存、消息队列(如 RabbitMQ 或 Kafka),以及许多其他支持服务。当我们需要监控大量容器环境时,监控这些容器下方和其支持服务的所有层级变得至关重要,以便快速找出故障的根本原因并及时解决。当你能够从所有这些源收集健康数据并以有意义的方式进行可视化,或使用一个工具建立警报系统时,这变得可能。站点可靠性工程(SRE)团队通常面临的问题是,不同的系统使用不同的监控工具,例如应用程序监控使用一个工具,Kubernetes 监控使用另一个工具,虚拟基础设施监控使用另一个工具,等等。当我们在故障排除期间需要使用多个监控工具时,理解可用的健康数据变得非常困难,导致失去上下文。这是因为不同的工具采用不同的方法呈现收集到的健康数据,而且使用这些工具的团队使用的术语和语言也不同。在这种情况下,使用一个通用的方式过滤所有源在特定时间范围内收集的指标,并根据其他条件快速帮助定位问题,可以迅速解决问题。这样,我们可以很快指出,容器中运行缓慢的应用程序实际上是由于主机 CPU 温度过高而导致的性能下降。
由于 Aria 能够从几乎任何来源收集健康数据,我们可以为定制的应用程序创建定制的仪表板,并显示所有与应用程序相关的周边组件的健康数据。这样,你可以看到应用程序容器的内存使用情况,以及容器部署所在的 Kubernetes 节点的内存使用情况。
实时处理高容量数据
Aria 是一个功能强大的基于云的 SaaS 流式分析平台,具有很高的可扩展性,并且能够高效地收集大量数据。由于其设计,它可能支持每秒收集超过一百万个数据点。一旦数据被收集,我们可以实时在其相应的监控仪表板中查看,并且可以使用 Aria 强大的查询引擎在实时拉取摄取数据时计算任何预配置的告警条件。
长时间保留全保真数据
如前所述,Aria 可以处理非常大量的数据——此外,它还可以在撰写本文时保留所有度量数据长达 18 个月。这与其他可观察性工具不同,后者要么将数据存储在较短的时间段内,要么对数据应用某种程度的聚合,以在特定时间段后减少数据量。借助 Aria 的全保真度量数据保留能力,我们可以比较最多 18 个月的过去时段内系统的性能和状态。然而,健康数据类型(如直方图和跨度日志)有较短的保留期限。我们将在本章稍后讨论直方图和跨度日志。
编写强大的数据提取查询
从多个来源摄取大量数据,并在时间序列数据库中保留较长时间段的数据,如果无法使用特定的筛选器、聚合和与其他类似数据点的关联来提取数据,那么这些数据几乎没有什么用处。Aria 拥有一个详细的查询语言,使得可以具备所有这些能力的数据提取。这些查询可以包含正则表达式(Regex)的子集、通配符字符、简化引用的别名、变量、关系运算符、算术运算符以及几种类型的数据操作函数。以下是这些函数的分类:
- 
聚合函数,如求和、平均值、最小值、最大值等 
- 
筛选和比较函数,如区间、前几名、后几名、随机等 
- 
时间操作函数,如速率、速率差异、年、月、日等 
- 
移动窗口函数,用于对移动时间窗口的数据执行聚合操作——例如,获取过去一小时内主机的平均 CPU 使用率 
- 
缺失数据函数,用于用特定值替换缺失的数据 
- 
条件函数,如 if块
- 
指数和三角函数,如求平方根、指数、正弦、余弦等 
- 
元数据函数,用于临时重命名度量和来源或在时间序列数据值上创建自定义标签 
- 
字符串函数,用于操作字符串值 
- 
预测分析函数,用于预测某些值或发现异常值 
- 
直方图处理函数,用于处理摄取的事件数据 
- 
事件处理函数,用于操作摄取的事件数据 
- 
分布式追踪和跨度函数,用于查找和筛选应用程序发送的追踪数据 
- 
应用性能指数(Apdex)分数函数 
什么是 Apdex 分数?
Apdex 是一个开放标准,旨在简化应用性能报告。Apdex 分析应用程序最终用户的感知满意度。它不是一个 APM 工具。Apdex 通过计算用户期望与性能的对比程度,在 0(没有用户满意)到 1(所有用户满意)的分数范围内,数字化地评分最终用户的满意度。来源:TechTarget.com
Aria 在这些类别下累计支持约 200 种不同的函数,作为其查询语言的一部分,提供了极大的灵活性,帮助我们获取所需信息。
获取 SaaS 的好处
由于 Aria 是一个 SaaS 产品,我们可以在没有大量准备工作的情况下快速启动。通过几步集成,我们就能开始从中获得价值——像大多数其他 SaaS 解决方案一样,它也支持按需计费模型,费用以每秒点数(PPS)计算。为了理解 PPS 是什么,我们来看一个例子。假设有 6 个容器化应用,每个应用每 60 秒发送 10 个不同的指标,共计 60 个度量数据点来自这两个容器的每 60 秒。部署这些容器的 Kubernetes 集群每 10 秒发送 50 个不同的指标。这意味着我们在 60 秒内获取了 300 个度量数据点,总共摄取了这 60 秒的集群数据。因此,累计来看,来自集群和容器的数据点总数是 360 个数据点,也就是说数据摄取速率是 6 PPS(360/60)。这样,Aria 会计算整个账户的总 PPS,这将用于计费。
通过这一部分,我们已经总结了为什么 Aria 在管理现代应用程序(尤其是在容器中运行的应用程序)时是一个宝贵工具的潜在原因。我们了解了 Aria 如何通过汇集可能影响应用程序的各种数据源,帮助你实现全栈可见性。我们还学习了它摄取大量数据的能力,长期保存数据,并通过全面的查询语言提取这些数据。在下一部分中,我们将进一步了解 Aria,包括一些概念、术语以及其高层次的部署架构。
解锁 Aria
在了解 Aria 为何以及在何种使用场景下可以作为一个全面监控云原生应用的宝贵工具后,我们现在来更深入地了解该工具,了解它可以捕捉的不同数据格式、其部署架构以及组成该分布式系统的构建模块。
Aria 支持的数据格式
以下是 Aria 可以摄取并用于生成有用的图表、仪表板和警报的不同数据格式列表。
指标
指标是一个基于文本的小记录,携带在特定时间戳下被监控源的状态数据。它还可以有其他标签作为附加元数据,用于构建有用的连接和筛选查询。最常见的指标形式是基于时间序列的。我们用它来报告服务器内存在任何给定时间点上的占用量:

图 10.1 – 一个时间序列指标图表示例
图 10.1 向我们展示了一个简单的图表,展示了 Aria 中时间序列指标数据的显示方式。在此案例中,图表展示了一个名为kerrupt的集群节点在给定时间段内的 CPU 使用情况。
指标可以包含仪表值,即每个时间点上指标的当前值,例如正在监视的服务器的当前可用 CPU。仪表指标的值与之前的值无关。指标还可以是计数器类型的,即在任何时间点上的增量值,例如自计数器重置以来的订单数量。最后,指标还可以是增量计数器类型,报告一组相似源的子集值。例如,如果你有多个容器化应用程序副本来处理订单,每个应用程序容器副本可以报告它处理的订单的增量值。在这种情况下,一个容器无法报告所有副本处理的订单的总值。在这种情况下,Aria 可以将这些增量计数器值进行分组,生成该应用程序处理的所有订单的累计值。了解更多关于 Aria 中的指标,请参阅:docs.wavefront.com/metrics_managing.html。
直方图
虽然 Aria 可以接收系统整体每秒钟大量的数据点,但它每秒钟只能存储一个数据点,该数据点由源和其指标名称的组合决定。例如,你在一个非常繁忙的系统前面有一个负载均衡器,每秒接收数百个请求。在这种情况下,如果我们为每个请求发送一个指标值存储到 Aria 中,那么 Aria 只能为该指标和源存储一个值。如果源或指标名称不同,它才可以在一秒内存储多个值。假如我们要报告每个请求的响应时间,这是不可能的,因为我们每秒只能存储一个请求的响应时间。对于这些情况,我们可以使用直方图,显示在给定时间段内数据的分布。在我们的例子中,我们可以报告一个包含基于响应时间分布的请求的直方图,时间范围可以是分钟、小时或一天。图 10.2 显示了这种直方图的样子:

图 10.2 – 直方图示例
在图 10.2 中,y 轴表示落在一个范围内的请求数量,x 轴表示这些请求的响应时间(单位为毫秒)。通过查看这个直方图,我们可以得出结论,大多数请求的响应时间落在 40 到 800 毫秒之间。通过这种方式,我们可以知道这些请求的响应时间值的正常可接受范围。下次如果看到更多请求的响应时间落在较高的响应时间范围内,我们就会知道那里出现了问题。
事件
一般而言,事件是指在被观察的系统中发生的某些有趣的事情。在信息技术的领域中,事件可能是一个新应用版本的发布,或者是一个警报条件被触发。Aria 会在任何警报被触发时自动生成事件。此外,如果需要,Aria 还允许您手动创建事件记录。我们可以在与事件源相关的适用图表中看到这些事件的展示。例如,如果我们创建一个事件,表示应用程序的新版本被推送,我们可以清楚地比较新版本和旧版本在响应时间上的差异,因为其相应的图表会显示包含这些应用程序发布详情的事件标记。图 10.3 显示了 Aria 如何在适用图表中展示这些事件。如您所见,事件也可以是一个时间段,可能具有不同的开始时间和结束时间:

图 10.3 – 显示事件的图表
如您所见,图 10.3 显示了由警报条件的警告级别触发的事件。警报点后的阴影部分显示了警报条件处于激活状态时的持续时间,而事件在快照拍摄时仍在进行中。这类持续的事件可以手动关闭,也可以在警报条件被解决时关闭,或者 Aria 会在 60 天后自动关闭它们。
跨度日志
从高层次来看,span日志报告了分布式系统中任意两个服务之间通信通道的健康状况。在微服务的世界里,我们通常会看到一个用户请求穿越多个顺序和并行的服务调用,涉及许多微服务和第三方系统。例如,在一个电子商务应用中,最终用户提交的订单请求可能涉及调用支付服务、支付方式验证服务、订单配置服务、库存调整服务和数据库,最终用户才能收到响应。在这种情况下,任何两个微服务之间的请求/响应通道称为span。Span 日志可以报告任何两个微服务之间的请求/响应所花费的时间。例如,在这个案例中,span 日志可以报告订单服务和支付服务之间的请求/响应时长,支付服务和支付验证服务之间的时长,等等。当所有这些 span 形成一个完整的请求流时,称之为trace。这些都是分布式追踪的概念,分布式追踪是一种非常强大的监控微服务健康状况的方法,特别是当它们部署在容器中时。了解更多关于分布式追踪的概念,点击这里:docs.wavefront.com/tracing_basics.html。
为了为应用提供分布式追踪,Aria 支持OpenTracing(opentracing.io/)和OpenTelemetry(opentelemetry.io/)这两个开源标准。然而,OpenTracing 现在已经成为一个归档项目,建议使用其更好的替代品——OpenTelemetry,它是一个由Cloud Native Computing Foundation(CNCF)治理的项目。OpenTelemetry 提供了所需的工具、API 和 SDK,允许不同编程语言编写的应用程序发布 span 日志。一旦应用程序将其 span 日志发送到 Aria,我们就可以得到像图 10.4所示的应用地图:

图 10.4 – 一个应用地图示例
图 10.4 显示了一个电子商务应用的分布式追踪图,其中所有的圆圈表示不同的服务。箭头表示请求从一个服务流向另一个服务,箭头的颜色则表示系统的健康状况,具体反映了响应时间和错误率。Aria 中来自所有相关服务的正确 span 日志,对于在几分钟内发现潜在的性能问题非常有帮助。了解更多关于 Aria 中使用 span 日志生成的其他可视化信息,点击这里:docs.wavefront.com/tracing_basics.html。
通过 Aria 可以摄取的这四种数据类型,包括指标、直方图、事件和跨度日志,我们能够获得所需的可观察性,涵盖我们的应用、它们的支持系统以及运行这些应用的基础设施。接下来,我们将理解一种常见的部署架构模式,它能够将这些数据点摄取到 Aria 数据库中,并部署在其 SaaS 云平台上。
Aria 的数据集成架构
如前所述,Aria 是一个 SaaS 平台,支持两个可选组件——收集代理和代理服务。图 10.5显示了不同数据摄取方式的高层次示意图:

图 10.5 – Aria 的数据集成架构
让我们理解一下图 10.5所示的部署架构。该图包含以下几个组件。
数据源
图中左侧的大圆圈表示收集健康数据的来源。可能的来源类型如图 10.6所示:
- 
公共云 – 这些是主要的公共云服务提供商,包括 AWS、Azure 和 GCP。我们可以通过在 Aria 门户上进行账户级别配置,配置从这些云服务的流数据,而无需在这些云上配置任何收集代理。 
- 
主机 – 这可以是硬件设备、操作系统、网络组件,或者任何发出健康数据点的东西,之前我们已经介绍过。通常,你无法为这些组件配置自定义的端点来收集指标数据。它们只是发布指标。我们还需要为这些组件配置指标收集代理,这些代理可以将数据发送到 Aria 数据库。 
- 
主机上运行的软件包 – 这些可以是部署在主机(服务器)上的任何软件解决方案。例如,它可能是 MySQL 数据库或 Jenkins 服务器。我们可以通过一个收集代理来收集这些软件工具发出的指标数据。稍后我们会在本章中重新讨论这些代理。 
- 
自定义应用代码 – 这些可以是任何发送自定义业务指标的业务应用,例如订单数量或失败的支付。这些数据还可以包括由配备应用发出的特定操作的跨度日志。通过应用代码,结合特定的第三方库(取决于应用的技术栈),这些数据可以被导入到 Aria 中。Micrometer( micrometer.io/)就是这样一个开源库,广泛用于 Java 应用中自定义指标的发射。类似地,OpenTelemetry(opentelemetry.io/)为各种应用技术提供了多个库,以便从自定义应用中发射指标和跨度日志。
- 
日志文件 – 有些系统不会发布遥测数据,而是将数据写入本地日志文件。我们也可以通过在 Wavefront Proxy 中进行特定配置,从日志文件中收集这些数据。我们将很快介绍 Wavefront Proxy。 
这些都是我们可以收集遥测数据的不同类型的源。虽然某些源可以直接将数据发送到 Aria 系统,但对于许多源,例如运行在服务器上的软件(如数据库)、现成解决方案,或者像主机操作系统这样的源,收集器代理需要先收集这些数据并将其发送到下游。让我们来了解一下它们。
收集器代理
如前所述,许多源仅发布遥测数据,而不了解哪个系统将收集它们进行处理。这些源通常会在一个源端点提供数据,供收集使用。为了从源端收集这些数据,过滤掉不需要的子集,在必要时进行聚合,并将其转换为下游遥测可视化系统(如 Aria)能够理解的形式,我们需要一个能够帮助实现这些需求的工具。下图中的代理(图 10.6)紧挨着主机和软件包组件,正是出于这个原因。
Aria 是一个用于普遍可观测性的时间序列数据库,它接受来自不同源的数据,并以特定的格式进行理解。因此,Aria 需要收集器代理来处理那些在特定端点提供遥测数据并需要消费者按需拉取数据的源。虽然我们可以编写自定义程序来执行此任务,但也有一个非常优雅的现成解决方案可以直接作为收集器代理使用——Telegraf(github.com/influxdata/telegraf)。
Telegraf 是一个成熟且灵活的开源指标收集器代理工具,具有非常可扩展的基于插件的架构,支持收集、处理和分发遥测数据。Telegraf 有以下几种类型的插件,使其成为一个非常流行和广泛采用的工具:
- 
输入 – 这些插件允许你从不同的源类型收集数据。每个源都有一个特定的插件与之关联,能够用来收集其遥测数据。 
- 
处理器 – 这些插件允许你修改和过滤收集到的数据。 
- 
聚合器 – 这些插件在数据发送到源之前允许进行聚合,以减少数据量。 
- 
输出 – 这些插件用于将数据发送到特定的输出目的地。在我们的案例中,目标是 Wavefront Proxy,接下来我们会详细介绍。 
Aria 可以通过 HTTP API 端点接收遥测数据。因此,数据源始终可以通过此方式将数据导入 Aria。然而,对于仅提供健康数据供收集的数据源,我们需要像 Telegraf 这样的工具来填补这个空白——但建议不要直接将这些数据发送到 Aria 数据库,而是通过 Wavefront Proxy 进行传输。接下来,我们将了解 Wavefront Proxy。
Wavefront Proxy
Wavefront Proxy 是一个开源工具(github.com/wavefrontHQ/wavefront-proxy),用 Java 编写,位于收集器(有时直接位于源与 Aria 数据库之间)与云中的 Aria 数据库之间。虽然使用 Wavefront Proxy 不是强制性的,但它是 Aria 架构中非常有用的组件。出于这个原因,VMware 积极维护此项目。在架构上,Wavefront 靠近数据源。正如 图 10.6 所示,多个源可以共享一个 Wavefront Proxy,Wavefront Proxy 可以部署在与源相同的主机、数据中心或私有网络边界上。以下是考虑使用 Wavefront Proxy 而不是通过其 API 端点直接将遥测数据发送到 Aria 数据库的原因:
- 
Wavefront Proxy 提供了一层数据保护,能够在源与 Aria 数据端点之间的连接中断时,将数据缓存到内存中,这一功能通过互联网实现。 
- 
Wavefront Proxy 批量处理数据,以实现网络带宽的最佳利用和优化的传输速度。 
- 
Wavefront Proxy 提供了一种通过向其处理的每个数据记录添加更多标签(键值对)来丰富数据的方法。这些标签可用于获取监控所需的详细信息。例如,这些标签之一可能是 env=prod,定义该数据记录属于生产环境。之后,我们可以使用此标签来构建仅显示生产环境数据的图表。
- 
Wavefront Proxy 允许我们修改数据内容(如有必要)。一个使用案例可能是隐藏敏感系统的特定 IP 地址,以保持网络布局的隐私。通常,在遥测记录中包含源的 IP 地址是一个有用的细节,可以用来以相同的方式过滤数据。然而,组织可能需要根据其政策隐藏 IP 地址,以便将数据发送到位于公共云空间中的 Aria 数据库。为此,Wavefront Proxy 允许我们在数据记录中执行基于模式的替换。这样,我们可以将 10.1.0.2这样的 IP 地址替换为10.*.*.2或*.*.*.*或******。
- 
Wavefront Proxy 提供了最后一个中央网关,打开通向 Aria 服务端点的大门。如果所有源都通过同一个 Wavefront Proxy 实例发送遥测数据,我们可以将其作为最终的检查点,应用适用于所有源的通用数据过滤和丰富策略。 
- 
由于 Wavefront Proxy 是内部遥测数据到达 Aria 服务端点之前的最后一道关卡,因此我们只需在 Wavefront Proxy 与 Aria 服务之间通过互联网打开防火墙。所有内部数据源可以通过私有网络将数据发送到 Wavefront Proxy。这有助于减少网络攻击面。 
除了前述的好处之外,还有一点值得在这里提及。大型组织通常有多个数据中心,可能分布在私有或公有云环境中。在这种规模下,将所有来源数据部署在公共和私有网络空间之间仅依靠一个 Wavefront Proxy 实例是不太合适的。如前所述,我们应尽量将 Wavefront Proxy 的设置保持尽可能接近其数据源,这样可以利用其数据可靠性和数据丰富功能。因此,通常情况下,我们会部署多个 Wavefront Proxy 实例,它们将数据发送到 Aria SaaS 端点。由于需要在这些 Wavefront Proxy 实例之间保持配置一致性,这种设置可能会在后期维护中变得困难。为了解决这个问题,我们可以创建 Wavefront Proxy 链,将所有分布式的 Wavefront Proxy 实例的数据发送到一个集中式的 Wavefront Proxy 实例,而不是直接将数据发送到 Aria 服务端点。通过这种方式,我们可以将所有源特定的配置保存在远程的 Wavefront Proxy 实例中,而将所有通用配置保存在集中式的 Wavefront Proxy 实例中。
关于 Wavefront Proxy 的各种部署模式及其他细节,请访问此页面:docs.wavefront.com/proxies.html。
Wavefront 服务
在图 10.5中,右侧的元素标注为Tanzu Observability Service,实际上就是部署在 AWS 云上的 Aria SaaS 平台(截至本文撰写时)。这也是我们一直提到的 Aria 服务端点。Aria 服务由大量组件组成,包括门户、API 端点、时间序列数据库、各种数据处理器、警报引擎及其他多个组件。我们将在本章接下来的部分中介绍如何在 Aria 门户上进行各种操作。
至此,我们已经完成了关于解锁 Aria 的部分。在这一节中,我们看到 Aria 能够摄取指标、事件、直方图和跨度日志,提供全栈可观察性。此外,我们了解了 Aria 的常见部署架构。在此,我们了解到 Aria 可以从多个来源摄取数据,包括公共云平台、不同的主机及其操作系统,以及运行在这些主机上的各种软件,包括 Kubernetes 等平台、定制应用程序和日志文件。然后,我们了解了收集器代理的角色,Telegraf 是最流行的收集器代理之一。接着,我们了解了 Wavefront Proxy 在数据路径中的角色和好处。接下来,让我们看看如何开始使用 Aria,并将第一个 Kubernetes 集群与 Aria 服务账户集成进行监控。
开始使用 Aria
在本节中,我们将学习以下内容:
- 
为 Aria 设置试用账户(如果你没有现有账户的话) 
- 
将 Kubernetes 集群与账户集成进行监控 
- 
访问集成的 Kubernetes 集群的默认仪表板 
- 
访问各种 Kubernetes 集群条件的默认警报 
以下是本节及后续章节中所需遵循的前提条件:
- 
一个具有管理员级别 kubectl访问权限的 Kubernetes 集群
- 
一台安装了 kubectl和helm命令行工具、能够访问目标 Kubernetes 集群并具备浏览器的工作站
- 
一个有效的电子邮件地址 
如你所见,前提条件非常简单。让我们从将 Kubernetes 集群与 Aria 服务账户集成开始。
设置试用账户
如果你已经有现有的 Aria 服务账户并希望使用它,那么本节是可选的。否则,请按照以下步骤使用 Aria 的试用账户开始,无任何义务:
- 
点击开始免费试用按钮,如下图所示: 

图 10.6 – Aria 网站
- 提交试用账户设置详情,如下图所示:

图 10.7 – 提交试用账户设置详情
- 为账户配置密码:

图 10.8 – 配置试用账户密码
- 加载如下图所示的登录页面:

图 10.9 – 第一次登录时的 Aria 登录页面
完成了。我们成功地在几分钟内创建了一个具有所有功能可用的 Aria 试用账户。现在让我们使用这个账户来集成一个 Kubernetes 集群进行监控。
将 Kubernetes 集群集成到监控中
我们将使用在前一小节中创建的 Aria 试用账户,将现有的 Kubernetes 集群与其连接以进行监控。请按照以下步骤执行集成过程:
- 点击以下截图中展示的 Kubernetes 图标,该图标位于 Aria 的登录页面(开始使用):

图 10.10 – 启动 Kubernetes 集群集成
对于现有的非试用账户
您可以使用现有的账户来完成此操作。如果您之前访问过该账户,根据您的账户配置,您可能会看到与前面截图不同的登录页面。在这种情况下,请前往顶部导航栏中的集成菜单,然后点击Kubernetes集成组中的Kubernetes。在 Kubernetes 集成页面中,前往设置选项卡,并点击添加集成按钮继续操作。
- 选择中间的图块,点击在 Kubernetes 集群中安装选项以加载设置说明页面。Tanzu Kubernetes 集群的设置过程与此非常相似,除了少数附加配置。然而,集成 OpenShift 集群的过程非常不同,但本书不涉及此部分内容:

图 10.11 – 选择用于集成的 Kubernetes 类型
- 按照页面上提供的说明安装由 Aria 提供的 Wavefront Proxy 和 Kubernetes 的指标收集器。这是一种快速且简单的入门方式。然而,您始终可以执行由收集器以及 Wavefront Proxy 提供的各种精细配置,以实现生产级集成。请参考此文档链接以了解更多:docs.wavefront.com/kubernetes.html#kubernetes-manual-install:

图 10.12 – Kubernetes 集成说明
- 
在执行第 3 步中的命令后,我们可以看到以下输出。请注意最后一行提供了用于查看集群集成的 Aria 门户 URL: $ kubectl create namespace wavefront && helm install wavefront wavefront/wavefront\--set wavefront.url=https://longboard.wavefront.com \--set wavefront.token=**-306a-432b-bb28-62dc**2e97 \--set clusterName="eks-workload-cluster-1" --namespace wavefrontnamespace/wavefront createdNAME: wavefrontNAMESPACE: wavefrontSTATUS: deployedREVISION: 1NOTES:Wavefront is setup and configured to collect metrics from your Kubernetes cluster. Youshould see metrics flowing within a few minutes.You can visit this dashboard in Wavefront to see your Kubernetes metrics:https://longboard.wavefront.com/dashboard/integration-kubernetes-summary
- 
检查目标集群中 wavefront命名空间下的 Wavefront Proxy 和 Wavefront collector Pods 部署。如图所示,集群中有两个收集器,每个 Kubernetes 节点对应一个,以及一个 Wavefront Proxy Pod:$ kubectl get pods -n wavefrontNAME READY STATUS RESTARTS AGEwavefront-collector-2vbbt 1/1 Running 0 5m51swavefront-collector-xv9sk 1/1 Running 0 5m51swavefront-proxy-699f57f698-lbr9b 1/1 Running 0 5m51s
- 
使用在第 4 步中命令输出中给出的 URL 检查 Kubernetes 集成状态。您将看到如下截图所示的页面: 

图 10.13 – Kubernetes 集群摘要仪表盘
如您所见,Aria 账户已成功集成到现有的 Kubernetes 集群中。我们可以按需添加任意数量的集群,并通过一个窗口集中监控它们。然后,如果需要,您可以通过使用名为集群的下拉菜单按名称筛选特定集群,正如前一截图左上角所示。前面截图中显示的仪表盘是 Aria 提供的 Kubernetes 集成的许多现成仪表盘之一。我们可以通过钻取方式从此仪表盘访问其中的一些。让我们看看其他现成的 Kubernetes 仪表盘。
访问默认的 Kubernetes 仪表盘
在本节中,我们将访问一些默认随 Aria 提供的附加 Kubernetes 仪表盘。这些仪表盘在成功集成 Kubernetes 集群后会立即开始显示数据。让我们从第一个仪表盘——Kubernetes 概览——开始,该仪表盘在前一节中已打开。从那里,我们将访问其他各种仪表盘:
- 要从Kubernetes 概览仪表盘钻取到Kubernetes 集群仪表盘,请单击以下截图中左下角突出显示的集群名称:

图 10.14 – 钻取到 Kubernetes 集群仪表盘
- 您应该看到以下仪表盘,展示了 Kubernetes 集群的更详细视图。然后,单击截图中突出显示的节点链接,打开Kubernetes 节点仪表盘,查看该集群节点的详细视图。此外,您可以在这些仪表盘的页面上滚动时找到非常有价值的见解:

图 10.15 – Kubernetes 集群仪表盘
- 下图显示了Kubernetes 节点仪表盘,它包含了我们正在钻取的集群节点的详细视图。您可以使用节点下拉菜单选择集群的特定节点,如下图所示。此外,您还可以通过单击Pods链接来打开Kubernetes Pods仪表盘,如下图所示:

图 10.16 – Kubernetes 节点仪表盘
- 单击Kubernetes 节点仪表盘上的Pods链接后,我们进入Kubernetes Pods仪表盘,如下图所示。如图所示,您可以根据多个标准对这些 Pods 进行分组。当我们在集群中运行数百个 Pods 时,这些分组非常有用。此外,我们还可以从此页面钻取到Kubernetes 容器仪表盘,正如我们在前面的部分中所见:

图 10.17 – Kubernetes Pods 仪表盘
除了所有这些仪表板外,我们还可以通过以下步骤访问多个开箱即用的 Kubernetes 仪表板:
- 点击如下截图所示的顶部导航栏中的集成菜单:

图 10.18 – 打开集成页面
- 点击如下截图所示的Kubernetes图块:

图 10.19 – 打开 Kubernetes 集成图块
- 点击如下截图中高亮显示的仪表板标签:

图 10.20 – 打开 Kubernetes 仪表板页面
- 以下截图展示了 Aria 为 Kubernetes 监控提供的所有默认仪表板:

图 10.21 – 默认 Kubernetes 仪表板
所有这些开箱即用的仪表板都使用从所有集成的 Kubernetes 集群中收集的度量数据,结合 Aria 账户提供了有用的洞察,尽管 Aria 还允许你克隆这些仪表板并自定义它们,以满足任何特定的监控需求。我们可以添加新的图表和下钻功能,修改现有的可视化,重新排列不同的图块,并对这些默认仪表板进行其他多种自定义。
然而,仪表板只有在有人明确而仔细地观察时才能发挥作用,帮助发现异常。人们通常在报告问题后才会打开仪表板查找异常。这是一种对已发生问题的反应性分析,但我们使用这些复杂的工具,以主动的方式提前捕捉问题,防止客户感受到痛苦。因此,我们必须在这些工具中配置警报,一旦监控系统发现任何健康状态的异常,立刻通知我们。正是由于这个原因,Aria 拥有强大的警报功能——就像 Aria 为 Kubernetes 提供了一组开箱即用的默认仪表板一样,它还配备了一组预定义的警报配置,用于主动的 Kubernetes 监控。让我们来了解一下它们。
访问默认 Kubernetes 警报
在上一节中,我们探讨了 Aria 为 Kubernetes 集成提供的默认仪表板。对于 Kubernetes,Aria 还提供了一套有用的警报。这些警报是根据既定标准配置的,Aria 允许你出于不同的原因进行自定义。以下步骤展示了如何访问和配置 Kubernetes 集群监控的开箱即用警报:
- 点击如下截图所示的警报标签:

图 10.22 – 打开 Kubernetes 警报页面
- 以下页面展示了 Aria 为 Kubernetes 提供的所有默认警报:

图 10.23 – 默认 Kubernetes 警报
和仪表盘一样,所有这些警报都可以完全自定义,修改其触发条件和传递方式,例如文本、电子邮件、PagerDuty、ServiceNow、Slack 等。我们将在本章稍后的部分深入讲解如何使用警报。现在,让我们来看一下如何获取现有警报的更多详细信息和其状态,以查看是否存在任何活动的条件。为此,请执行以下步骤:
- 点击顶部导航栏中的所有警报选项,位于警报菜单下,如下截图所示:

图 10.24 – 打开警报页面
- 您将看到一个页面,如下截图所示,列出已触发当前警报条件的配置阈值或正在主动监控的警报:

图 10.25 – 警报页面
本节内容介绍了如何开始使用 Aria。我们学习了如何设置试用账户,以便全面访问 Aria 平台。然后,我们通过简单的三步流程将现有的 Kubernetes 集群与 Aria 账户集成。接着,我们了解了如何访问一些现成的仪表盘,这些仪表盘提供了集群的详细信息,并能深入查看以获取更多细节。最后,我们了解了如何访问 Aria 为 Kubernetes 集成提供的默认警报集。
正如我们所知,Aria 是一个可观察性工具。这类工具的主要使用案例是主动防止破坏性故障的发生,并且如果发生故障,能够快速找到根本原因并解决它。监控仪表盘和警报是这两个关键功能,对于实现这一目标至关重要。让我们通过深入了解仪表盘和图表,来学习更多相关内容。
使用图表和仪表盘
在本节中,我们将介绍以下有关在 Aria 中使用图表和仪表盘的详细信息:
- 
创建新的自定义图表以可视化发送到 Aria 的任何数据 
- 
使用现成或自定义图表创建新的自定义仪表盘 
- 
自定义现成的仪表盘 
让我们开始介绍此列表中的主题。
创建新的自定义图表
当我们按照为 Kubernetes 集群配置 Aria 集成时,可以看到多个度量数据被推送到 Aria,这些数据是由我们部署在主机上的代理收集的。与 Kubernetes 集群类似,我们可以获取任何集成的遥测数据。度量的数量以及它们被 Aria 接收的频率,取决于数据源和收集器及 Wavefront 代理的配置。然而,一旦度量数据进入 Aria 数据库,它将在那里保存最长达 18 个月,除非明确删除。我们可以随时使用这些数据,构建按需图表,以深入了解源的健康状态。
以下步骤展示了如何使用现有的度量端点构建图表:
- 点击顶部导航栏中的仪表盘菜单,并选择创建 图表选项:

图 10.26 – 选择创建图表选项
- 在此页面上,如果你了解Wavefront 查询语言(WQL)或Prometheus 查询语言(PROMQL),可以直接在相应的查询语言结构中编写查询。如果你不熟悉这些语言,Aria 允许你通过选择数据、过滤器和函数下拉框中的正确值,在后台自动生成查询。此外,Aria 还允许你从可用的列表中选择度量,或使用已配置的集成。由于我们已经集成了 Kubernetes 集群,因此可以看到 Kubernetes 作为选项,在以下屏幕截图中为 Kubernetes 集成构建图表。点击数据下拉框,并选择下图中高亮显示的Kubernetes图标:

图 10.27 – 选择 Kubernetes 集成
- 选择图表数据点,如下图所示:

图 10.28 – 选择用于图表的数据元素
- 以下图表显示了所有集成了 Aria 账户的 Kubernetes 集群中所有命名空间下所有 Pod 的实时 CPU 使用情况。因此,如果有多个 Kubernetes 集群,且每个集群中有多个 Pod 运行时,这个图表会显得非常混乱。我们可能需要实现某些过滤器,以使此图表更具可用性。在本书的背景下,应该只有一个 Kubernetes 集群,即我们在本书中早些时候集成的集群:

图 10.29 – 显示所有 Kubernetes 集群中所有 Pod 的 CPU 使用情况的图表
- 应用筛选器,仅显示如以下截图所示的在 wavefront 命名空间中运行的 Pods。这将显示我们在 Kubernetes 集群集成步骤中之前部署的 Wavefront Collector 和 Wavefront Proxy Pods 的 CPU 使用情况:

图 10.30 – 为图表应用筛选器
- 以下截图仅显示 wavefront 命名空间下 Pods 的图表。我们可以通过点击 Filters 下拉菜单旁边的 + 按钮,添加更多筛选器,并根据需求应用数据函数来进一步调整图表。点击 SAVE 按钮以保存此图表以供将来使用:

图 10.31 – 显示所有 Pods 在 wavefront 命名空间中 CPU 使用情况的图表
现在,我们有了一个图表,展示了属于某个命名空间的一组 Pods 在 CPU 使用率方面的一些有意义的数据。我们可以使用此图表执行以下操作:
- 
与他人分享图表,以便在讨论任何性能问题时,我们可以用相同的语言进行交流 
- 
将此图表添加到新的或现有的自定义仪表板中以供将来使用 
- 
回溯查看所选时间段内的历史性能数据 
- 
标记有趣的事件以供将来参考 
- 
将图表导出为 PDF 或 CSV 格式 
- 
更改图表的可视化方式,以获取其他图形格式,例如柱状图、饼图、表格图等 
- 
通过添加更多查询来增加更多数据层 
以下小节重点介绍可以在 Aria 中应用于图表的各种用户控件。
了解图表操作控件
以下截图突出了各种控件,并以相应的数字作为参考:

图 10.32 – 图表控件
前面截图中的控件在下面的列表中有对应的数字描述:
- 
这些控件允许你以实时数据查看图表,该数据会在几秒钟后自动刷新,或者选择过去的特定时间段仅拉取该时段的数据。 
- 
这些控件提供了向图表添加更多细节的方式: - 
异常检测 使用一些人工智能算法,基于过去的数据,找到被认为异常的特定图表模式。 
- 
比较 让你直观地比较相同来源集的历史数据,以发现任何模式变化。 
- 
时区 让你为所选的时区更改图表的时间线。默认情况下,Aria 使用互联网浏览器的时区。 
- 
抽样 让你选择是否启用数据抽样来生成图表,而不是考虑所有的数据点。 
 
- 
- 
筛选器 允许你根据提供的标签值减少数据点,而无需修改图表的查询语句。 
- 
这些控件用于以下原因,从左到右列出: - 
生成可以与他人共享的图表链接 
- 
准备将图表嵌入网页中 
- 
如果使用,显示/隐藏图表变量 
- 
在图表上标记事件点,记录详细信息,生成事件日志记录以供日后参考 
- 
将图表导出为 PDF 或 CSV 文件 
- 
将图表保存在新的或现有的仪表板中 
 
- 
- 
这些控件允许您对选定的时间窗口进行图表缩放。 
- 
该控件允许您更改图表的可视化方式,将其显示为不同的格式,如饼图、条形图、表格、单值图等。 
- 
以下列表描述了这些标签: - 
数据 标签允许您与查询一起工作,以提取图表数据 
- 
格式 标签允许您修改图表的视觉细节 
- 
轴 标签允许您修改图表的轴单位 
- 
图例 标签允许您在图表上配置数据图例 
- 
下钻链接 标签允许您配置指向显示相关数据的其他仪表板的链接 
- 
描述 标签允许您设置图表描述,在鼠标悬停时可以在图表的工具提示中看到 
- 
异常检测 标签允许您配置与其灵敏度、显示和数据采样相关的设置 
- 
高级 标签允许您提取过时的指标,并根据其父仪表板配置图表的时间线。 
 
- 
- 
该控件允许您为查询命名图表数据层。 
- 
这些控件允许您在 WQL 和 PROMQL 之间切换,以及在查询图形编辑器和文本编辑器之间切换。 
- 
这组控件允许您从左到右执行以下配置: - 
查看查询执行统计信息,以确定是否需要优化查询 
- 
克隆现有查询以创建图表的新数据层 
- 
从图表中删除查询及其相关的可视化数据 
- 
在不删除查询的情况下,显示或隐藏图表中的查询数据 
- 
各种其他选项,包括基于查询创建警报和图表格式化 
 
- 
- 
添加查询 链接允许您将新数据及其可视化层添加到图表中。 
所有这些图表控件在构建有意义的仪表板中起着关键作用。现在让我们来学习如何在 Aria 中使用仪表板。
创建新的自定义仪表板
正如我们在本章前面所看到的,对于 Kubernetes 集成,Aria 提供了一组现成的仪表板,能够用于来自相应集成源的遥测数据。然而,Aria 可以从各种集成源获取数据,包括应用程序、Kubernetes、虚拟基础设施层的虚拟机管理程序、操作系统、数据库等。在这种情况下,特定集成的默认仪表板可能无法提供完整的视图。例如,Aria 中没有任何默认的 Kubernetes 仪表板能够展示来自操作系统或硬件主机(即节点部署所在的主机)的数据。默认仪表板和特定集成的仪表板不能假设与其他集成相关的数据总是会存在。例如,在本章中,我们只有一个针对 Kubernetes 集群的集成。因此,如果默认仪表板期望从节点操作系统获取度量数据,那么它就会失败。在这种情况下,我们需要能够显示来自多个数据源的相关数据的自定义仪表板。展示来自不同数据源的数据的仪表板,可以显著帮助我们更广泛地了解系统状况,并快速找到问题的根源。数据库中的慢查询可能是导致应用程序响应迟缓的原因,因此,在同一个仪表板上显示应用程序和数据库这两个层次的详细信息,可能有助于迅速找到问题。
在 Aria 中,我们可以通过两种方式创建自定义仪表板。首先,我们可以使用自定义图表来构建新仪表板或添加到现有的仪表板中。其次,我们可以使用 Aria 提供的不同模板来构建自定义仪表板,或者在其中添加自定义图表。让我们使用前一节中构建的图表来创建一个新仪表板。以下步骤描述了这一过程:
- 点击保存按钮,然后点击保存到新仪表板按钮,如下图所示:

图 10.33 – 从自定义图表创建新仪表板
- 输入仪表板的名称并点击创建按钮:

图 10.34 – 命名和创建仪表板
- 以下截图显示了 Aria 仪表板编辑器,当前已添加了自定义图表。我们可以从 Aria 为其集成提供的现成图表模板中添加多个自定义或预定义的图表:

图 10.35 – 仪表板编辑器
以下几点解释了前面截图中仪表板编辑器中突出显示的部分:
- 
变量允许你操作仪表板中适用图表的数据。这些变量值可以添加到图表查询中。 
- 
一个部分是仪表板中类似图表的组合。我们可以使用部分来显示/隐藏图表或在非常大的仪表板中跳转到另一个部分。 
- 
这些部分控件允许您添加、移除或移动部分。 
- 
这些箭头允许您调整图表的大小,以在单行中添加多个图表,以便在一行中更好地整合数据。 
- 
所有这些瓷砖允许您在选定的部分向此仪表板添加更多图表。在这里,我们还可以导入由 Aria 提供的一些现有的集成罐头图表。 
在学习如何从头开始创建新仪表板后,现在让我们看看如何自定义 Aria 提供的现成仪表板。
自定义默认仪表板
尽管 Aria 提供的不同集成的默认仪表板设计得很周到,但在外观和感觉上可能会有一些我们想要更改的地方。在 Aria 中,我们不能直接更新开箱即用的默认仪表板,但我们可以克隆它并创建自定义副本。然后,我们可以根据需要更新默认仪表板的自定义副本。让我们看看如何使用以下步骤完成这一操作:
- 点击顶部导航栏中主要仪表板菜单下的所有仪表板菜单,如下面的截图所示:

图 10.36 – 打开仪表板页面
- 从左侧导航栏点击Kubernetes链接,然后点击下面突出显示的Kubernetes 集群仪表板:

图 10.37 – 打开 Kubernetes 集群仪表板
- 下图显示了Kubernetes 集群仪表板,这是 Aria 自带的默认仪表板之一。所有默认仪表板都标有突出显示的锁定符号。要克隆以进行自定义的仪表板,请点击右侧的突出显示点菜单,然后选择克隆选项:

图 10.38 – 克隆默认仪表板
- 给克隆的仪表板副本命名,并点击克隆按钮:

图 10.39 – 命名克隆仪表板
- 您将看到与之前检查过的相同的仪表板编辑器,允许您对仪表板进行任何更改,包括但不限于更改图表数据查询、图表可视化、瓷砖重新排列和添加新的数据可视化:

图 10.40 – 仪表板编辑器
一旦您进行必要的更改并保存此仪表板,您可以将其标记为收藏夹仪表板,并将其放入快速访问菜单下。您还可以定义谁可以访问该仪表板进行查看和编辑。
通过这些内容,我们已完成对图表和仪表盘的操作,并对其功能进行了非常高层次的概述。有关图表和仪表盘的更多细节,请参阅官方产品文档 – docs.wavefront.com/ui_charts.html 和 docs.wavefront.com/ui_dashboards.html。在本章的下一部分,也是最后一部分,我们将学习如何处理警报。
处理警报
任何监控工具如果没有良好的警报功能,都是不完整的。Aria 也不例外。它拥有一个功能强大且高度可配置的警报引擎,允许你配置具有多个阈值的警报、基于这些阈值级别的传递以及多种可能的传递方法,包括但不限于电子邮件、短信、Slack 消息、Microsoft Teams 消息、ServiceNow 工单或 PagerDuty 事件。此外,我们还可以配置通过 webhook 触发自动化流程,调用 Aria 边界之外的远程 API。通过 Aria 的警报功能,我们可以配置许多有用的功能。让我们在本节中了解更多有关警报的内容,包括以下内容:
- 
创建警报目标,定义谁应接收哪些警报,并使用何种传递机制 
- 
定义维护窗口以避免显而易见的警报 
- 
创建新的警报 
- 
检查触发的警报 
让我们从这些主题开始。
创建警报目标
Aria 中的警报目标包含多个细节,并提供了非常灵活的方式来高层次地定义以下内容:
- 
何时应该发送通知以及何时应暂停发送 
- 
使用何种媒介传递警报 
- 
谁应该接收警报以及在什么条件下接收 
- 
警报应包含哪些详细信息及其格式 
以下步骤展示了如何在 Aria 中创建最常见的基于电子邮件的警报目标:
- 从顶部导航栏打开警报菜单,并选择警报目标:

图 10.41 – 打开警报目标列表页面
- 点击创建警报目标按钮:

图 10.42 – 创建新的警报目标
- 在表单中输入如下截图所示的详细信息:

图 10.43 – 创建警报目标页面
以下是前述截图中的元素,按其编号排列:
- 
这是警报目标的名称。请在此指定一个唯一名称。 
- 
这是警报目标的描述。请指定任何可理解的描述。 
- 
一组触发器定义了何时应该将警报通知发送到目标,何时不应该。例如,它允许你配置在警报条件解决时是否希望发送警报通知。 
- 
类型 下拉菜单允许你选择三种主要的警报通知类型之一——电子邮件、PagerDuty 和 Webhook。 
- 
默认收件人 框允许你指定一组应该接收此警报目标电子邮件通知的电子邮件地址。这里指定的邮件列表将接收任何数据集的通知。 
- 
路由 配置允许你根据已定义的键和值将相同的警报通知发送到额外的目的地。通过此配置,我们可以根据警报数据中的应用标识符配置不同的应用团队进行通知。 
- 
这些控件允许你配置通知中的详细信息。当这涉及到电子邮件通知时,详细信息就是邮件的主题和正文。我们可以使用包含警报特定自定义数据的变量来配置这些值。 
- 
我们可以看到已创建的警报目标,如下图所示: 

图 10.44 – 创建的警报目标记录
现在,既然我们已经有了一个用于发送任何生成的警报通知的警报目标,我们可以利用这个目标来发送警报。我们可以使用一个警报目标配合多个警报配置——但在学习如何通过点击按钮创建警报之前,让我们先学习如何配置一个维护窗口,以便在计划的维护期间避免出现误报。
定义维护窗口
在维护窗口期间,对于正在观察的系统收到大量警报并不是好事,因为我们已经知道,在这些活动期间,系统可能会出现故障或表现异常。然而,在维护窗口期间,如果错过了需要关注的真实警报,那将更糟。为了防止关键警报被那些非关键警报淹没,Aria 允许你定义一个维护窗口,在该窗口内我们可以标记某些系统健康参数为忽略。这样,我们就可以在计划的活动期间认真对待实际的警报。以下步骤展示了如何在 Aria 中配置维护窗口:
- 从顶部导航栏点击 警报设置 菜单,并选择 维护窗口 选项,如下图所示:

图 10.45 – 打开维护窗口列表页面
- 点击 创建维护窗口 按钮:

图 10.46 – 创建维护窗口
- 输入维护窗口的必要详细信息,以选择时间和系统特征,如下图所示:

图 10.47 – 输入维护窗口详细信息
以下编号点描述了上一截图中的对应编号:
- 
输入维护窗口记录的唯一名称 
- 
输入维护窗口目的的描述 
- 
选择立即以按需启动维护窗口,或选择计划的开始和结束时间以及日期来定义窗口 
- 
输入源定义参数,以覆盖此维护窗口中的警报 
- 
选择是静音/忽略具有先前提到的标准的警报并在定义的时间窗口内,还是选择一个警报目标,在该时间窗口内将警报转发到该目标 
一旦点击保存按钮,维护窗口就会创建,如下图所示:

图 10.48 – 已创建的维护窗口记录
现在,维护记录已创建,让我们创建一个自定义警报记录。
创建新警报
在本节中,我们将学习如何创建一个新的警报。我们可以通过三种方式在 Aria 中创建警报。其中一种是通过主警报菜单使用警报创建向导来创建警报。第二种方式是复制一个警报并修改所需的详细信息。最后一种方式是通过使用现有图表来创建警报,通常这些图表已经存在于仪表盘上。虽然前两种方法较为直观,让我们学习如何通过第三种方法从现有图表创建警报,具体步骤如下:
- 在顶部导航栏的仪表盘菜单下,打开所有仪表盘页面:

图 10.49 – 打开所有仪表盘页面
- 从列表中点击Kubernetes 集群仪表盘,如下图所示:

图 10.50 – 打开 Kubernetes 集群仪表盘
- 点击Node Storage Utilization Avg图表上的铅笔图标,如下图所示。通过图表创建警报的相同方法可以应用于任何仪表盘上的所有图表:

图 10.51 – 编辑图表
- 在查询的点菜单下拉菜单中点击创建警报链接,如下图所示:

图 10.52 – 从图表编辑器创建警报
如你所见,在创建警报页面,拉取警报数据的查询已经使用图表的查询进行了填充。这对正确配置警报非常有帮助。接下来,我们设置其他警报详细信息。
- 在查询详情页面点击下一步按钮,如下图所示。如有需要,更新警报查询:

图 10.53 – 更新警报查询
- 配置带有不同阈值级别的警报条件,如以下截图所示:

图 10.54 – 配置警报条件
以下几点对应于前述截图中提到的数字,用于描述控件:
- 
这些是不同的警报阈值。达到某个条件时,警报会触发,并根据条件的严重性进行响应。 
- 
触发和解决窗口定义了将条件视为警报开始或结束的时间线。 
- 
额外的设置提供了定义警报检查频率的控件。 
- 
TEST CONDITION按钮允许您测试基于过去 2 小时的数据,验证配置是否会触发警报。 
- 
选择一个之前在账户中创建的警报目标。请注意,以下截图只显示了为SMOKE级别配置的一个目标,这个目标也适用于高于该级别的所有阈值级别,即WARN和SEVERE。但是,也可以为所有不同的阈值级别发送警报到不同的目标。点击NEXT按钮继续: 

图 10.55 – 配置警报目标
- 配置可能对警报分类有帮助的详细信息,如以下截图所示。之后点击NEXT按钮继续:

图 10.56 – 配置警报排查详细信息
以下几点描述了与前述截图中标记的数字对应的控件:
- 
在Runbook中,我们可以提供一个外部 URL,包含有关如何排查和解决警报条件的详细信息。 
- 
在Triage Dashboard(s)下,我们可以添加一个或多个仪表板,这些仪表板将被添加到警报详细信息中,提前提供所需的细节。 
- 
在Additional Information下,我们可以提供任何有助于排查此警报的任意详细信息。 
- 
给警报命名,并可以选择相关的标签值,以标识受影响的源,点击ACTIVATE按钮创建警报: 

图 10.57 – 激活警报
- 一旦激活,警报将在Alerts页面下显示,如以下截图所示:

图 10.58 – 新创建的警报
这就是在 Aria 中创建新警报的详细步骤。如果需要更多信息,请参考官方产品文档,了解如何创建警报:docs.wavefront.com/alerts_manage.html。接下来,让我们看看如何找到具有活跃警报条件的触发警报。
检查触发的警报
在本节中,我们将看到如何列出当前触发的警报,这些警报具有已配置的任何阈值级别。以下步骤描述了此过程:
- 点击左侧导航栏中的FIRING状态,这将列出该状态下的所有警报,并点击如下截图所示的触发警报名称:

图 10.59 – 查看触发警报的详细信息
- 以下截图显示了包含触发警报详细信息的页面视图,包括其他可能相关的警报条件、显示触发持续时间的图表、用于计算的查询以及许多其他内容:

图 10.60 – 触发警报的详细信息
至此,我们结束了本章的警报操作部分。在本节中,我们从创建警报目标开始,学习了如何根据警报的严重性及系统的其他属性灵活定义不同的警报通知类型和目标。接着,我们学习了如何创建维护窗口,以便在计划的活动期间以不同的方式处理警报,否则这些活动可能会触发大量警报。之后,我们学习了如何使用现有仪表板中的现有图表创建警报。同样的知识也适用于从头创建新的警报。最后,我们了解了 Aria 如何显示当前触发的警报的不同详细信息。
概要
在本章中,我们学习了 Tanzu 产品组合中的一个非常重要的组件——VMware Aria Operations for Applications by Wavefront。在本章的第一部分,我们提供了多个理由,解释了该工具在现代容器化应用程序可观察性中的重要性。在本节中,我们了解了 Aria 支持的不同开箱即用的集成。我们还讨论了 Telegraf 收集器和 Wavefront SDK 如何使集成几乎任何数据源成为可能,以实现可观察性。此外,我们讨论了 Aria 的其他优点,包括高速数据收集和处理能力,以及收集不同类型遥测数据的能力,包括指标、事件、直方图和跨度日志。然后,我们列出了可以与 WQL 一起使用的不同类别的数据处理功能,包括数据聚合、过滤、时间操作、移动窗口聚合、指数运算和三角运算。
在那之后,我们了解了该解决方案的各个组件。我们探索了度量标准、直方图、跨度日志和事件。接着,我们讨论了该解决方案的常见部署架构以及各个组件的详细信息和它们的角色。在那部分内容中,我们讨论了如何在 Aria 中摄取数据的不同方式、不同类型的来源、采集器、Wavefront 代理以及 Wavefront 服务,一个 SaaS 平台。随后,我们学习了如何为 Aria 开通试用账户,并将现有的 Kubernetes 集群与该账户进行集成。然后,我们看到如何访问 Aria 开箱即用的 Kubernetes 集成的默认仪表盘。最后,我们学习了如何为现有集成创建自定义图表、仪表盘和警报。
尽管看起来我们已经深入探讨了解决方案,但我们只触及了表面。由于本章的内容仅围绕 Kubernetes 监控展开,因此仍有许多功能未能涵盖。除了这里讨论的内容,Aria 还提供了基于摄取的跨度日志和应用健康度指标的 APM 强大功能。我们甚至没有涉及到派生指标、增量计数器、用户权限配置以及外部日志解决方案集成等主题,因为本章的范围有限。
在下一章中,我们将看到如何使用 Tanzu 服务网格安全地连接部署在不同 Kubernetes 集群中的各种应用,甚至跨越不同的云基础设施。
第十一章:使用 Tanzu Service Mesh 实现安全的服务间通信
企业软件在过去几年发生了显著变化。你们中的一些人可能还记得,大多数软件曾是由一小队开发者编写成一个单体应用。应用必须作为一个整体进行部署、更新、启动、停止和扩展。
随着软件在 2000 年代初期到中期的发展,软件和软件开发人员的需求开始在四个方面增长:
- 
价值实现时间:团队被期望在不断缩短的时间内交付 bug 修复、改进以及新功能。 
- 
弹性:团队需要独立扩展“热”服务,并能够部署单个功能,而不需要一次性构建、测试和部署整个单体应用。 
- 
容错性:当某个服务失败或开始下降时,不应该影响其他服务,系统应能够绕过出现问题的服务继续运作。 
- 
编程语言和框架:技术领域的发展速度太快,单体应用已无法跟上。开发人员感到受限,无法发挥较旧、不够灵活的技术。 
这些需求促使了如微服务等设计模式的几乎普遍采用(en.wikipedia.org/wiki/Microservices)。此外,随着微服务在软件开发中占据主导地位,团队变得更加独立和自主,新的架构范式开始出现,特别是混合云和多云:
- 
混合云:指的是在本地数据中心和公有云之间部署由传统虚拟机、Kubernetes 服务、无服务器函数以及可能的其他技术(如平台即服务(PaaS))组成的应用。 
- 
多云:指的是跨多个云提供商的多个虚拟私有云(VPC)部署应用。 
Google 在这里提供了有关这些架构的一些有趣材料:cloud.google.com/architecture/hybrid-and-multi-cloud-patterns-and-practices。
出于我们稍后将讨论的原因,Tanzu Service Mesh 是为那些在复杂现代环境中需要安全、一致地交付修复和新特性的团队量身定制的理想工具。
本章将涵盖以下主题:
- 
为什么选择 Tanzu Service Mesh? 
- 
Tanzu Service Mesh 的功能和特性 
- 
如何开始使用 Tanzu Service Mesh 
- 
如何在 Tanzu Service Mesh 上执行关键的日常运营 
- 
使用 NSX-T 高级负载均衡器和 Tanzu Service Mesh 实现 GSLB 
既然如此,我们开始深入探讨为什么团队可能需要 Tanzu Service Mesh。
为什么选择 Tanzu Service Mesh?
Tanzu Service Mesh 是一个专为支持我们刚刚描述的有意义的业务成果(快速价值交付、弹性、容错等)而构建的工具,同时它也能在混合云或多云环境中运行。以下是一些示例:
- 
当核心服务从一个云迁移到另一个云时,我们必须更新 100 个依赖服务,那么如何更快地交付价值? 
- 
如果每个云都有不同的部署和扩展流程及工具集,那么我们是否真正实现了弹性系统的全部价值? 
- 
检测和修复故障同样如此。如果我们不得不为跨云的监控、警报和修复维护不同的工具,那么我们能充分受益于一个具有弹性的系统吗? 
- 
假设你投入时间和精力,将工具和监控集中化以便跨多个云平台工作。当语言、框架和技术持续向前发展时,你如何保持技术的更新?这种持续的投资是否值得? 
Tanzu Service Mesh 完全位于这个问题空间的核心,它将大型分布式微服务架构的好处带入到多云和混合云架构中。你可以通过想象这个问题空间来帮助理解:跨云和本地,跨多个技术和框架交付业务成果:

图 11.1 – 跨云和技术的业务成果
既然我们已经初步了解了为什么你会想使用这个工具,现在让我们深入探讨一下那些实现这些原因的功能和能力。
Tanzu Service Mesh 的功能和能力
以下是 Tanzu Service Mesh 提供的八个具体功能。这些功能使得实现我们在前一节中描述的目标成为可能:如何在多云或混合云环境中交付切实的成果:
- 
开箱即用的混合云和多云架构支持:只需通过几次点击 UI 或 API 调用,你就可以将多个不同的云和架构(Kubernetes、传统架构、无服务器架构)整合到一个虚拟空间中,在该空间内你可以快速且轻松地搭建任何行业标准的多云或混合云架构。 
- 
轻松在云之间迁移应用:你可以将应用部署到不同的 VPC、不同的平台(虚拟机与 Kubernetes)上,甚至是完全不同的云提供商,而不影响依赖的应用和服务。 
- 
自动高可用性:你可以将相同的服务部署到多个云平台,服务网格将自动在它们之间进行负载均衡。这包括当一个位置的服务发生故障时,自动从一个云切换到另一个云。 
- 
自动扩展的 SLO 跟踪:Tanzu Service Mesh 允许你定义服务级别目标(SLOs),跟踪你的错误预算相对于 SLO 的情况,甚至在 SLO 未达标时自动扩展服务。 
- 
端到端 mTLS:通过零操作员工作量,Tanzu Service Mesh 使用边车(sidecars)确保所有服务间的双向流量安全。这保证了客户端和服务器的身份,可以进一步用于加强服务安全。 
- 
安全策略与审计:通过双向 TLS,客户端和服务器 ID 在加密上得到了保证。这使得你能够创建严密的允许和拒绝策略,指定哪些服务可以相互通信。 
- 
完整工作负载可视化:Tanzu Service Mesh 实时可视化网格中的所有服务,并提供度量数据。 
- 
紧密控制部署:Tanzu Service Mesh 为你提供了 Istio 工具箱中的所有工具,以控制服务的发布:流量 shaping、金丝雀发布、A/B 测试等。 
通过这些功能,我希望你现在理解为什么要使用 Tanzu Service Mesh。接下来,让我们开始动手操作,正式开始使用它。
如何开始使用 Tanzu Service Mesh
Tanzu Service Mesh 由安装到 Kubernetes 集群中的控制器和一个中央 SaaS 全球控制平面组成。SaaS 控制平面执行以下任务:
- 
管理 Tanzu Service Mesh 组件在 Kubernetes 集群上的安装 
- 
根据需要自动更新这些组件 
- 
将全局配置发送到这些控制器(例如,其他集群上服务的位置) 
- 
管理和部署 Kubernetes 集群上的策略 
- 
收集度量数据以实现可视化和 SLO(服务级别目标) 
要开始使用 Tanzu Service Mesh,我们需要登录到 VMware Cloud Services 控制台,并从服务列表中选择Tanzu Service Mesh模块。
重要提示
Tanzu Service Mesh 是本书中唯一一个既不是免费使用也没有提供自助试用途径的产品。如果你目前没有 Tanzu Service Mesh 的许可证,你需要联系你的 VMware 客户经理来设置试用。如果这不可行,我们将在本节中涵盖的许多内容也可以在 VMware 为 Tanzu Service Mesh 提供的免费实践实验室中找到,网址如下:labs.hol.vmware.com/HOL/catalogs/lab/8509。
VMware Cloud Services 控制台位于这里:https://console.cloud.vmware.com/csp/gateway/portal/#/consumer/services/organization。
从下图所示的Tanzu Service Mesh模块中选择启动服务:

图 11.2 – 启动 Tanzu Service Mesh
一旦启动 Tanzu Service Mesh 应用程序,我们就可以开始将 Kubernetes 集群接入其中。
启动 Kubernetes 集群
这个示例需要两个独立的集群,并且能够创建LoadBalancer服务。你可以参考附录来探索搭建 Kubernetes 集群的选项。对于这个练习,我强烈建议使用公共云服务(EKS、AKS、GKE 或公共云上的 TKG),因为它们非常方便创建LoadBalancer服务,而这是这个练习所必需的。
以下是加入集群的步骤:
- 
选择新工作流 | 加入新集群。 
- 
在对话框中,为你的集群命名(例如, cluster-1),然后点击生成安全令牌。这将生成一些凭据,供你的 Kubernetes 集群连接到 SaaS 控制平面使用。
- 
在终端中,确保你已经将 kubectl 指向第一个集群: ubuntu@ip-172-31-33-59 ~> kubectl config get-contextsCURRENT NAME CLUSTER AUTHINFO NAMESPACE* user@eks-tsm-1.us-west-2.eksctl.io eks-tsm-1.us-west-2.eksctl.io acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.iouser@eks-tsm-2.us-west-2.eksctl.io eks-tsm-2.us-west-2.eksctl.io acmedemo-tkg@eks-tsm-2.us-west-2.eksctl.io
- 
然后,将 UI 中的每个 kubectl 命令复制到你的终端中: ubuntu@ip-172-31-33-59 ~> kubectl apply -f 'https://prod-4.nsxservicemesh.vmware.com/tsm/v1alpha2/projects/default/clusters/onboarding-manifest?tenant=b011ef56-1670-4d99-9179-0000000000000'namespace/vmware-system-tsm createdcustomresourcedefinition.apiextensions.k8s.io/aspclusters.allspark.vmware.com createdcustomresourcedefinition.apiextensions.k8s.io/clusters.client.cluster.tsm.tanzu.vmware.com createdcustomresourcedefinition.apiextensions.k8s.io/tsmclusters.tsm.vmware.com createdcustomresourcedefinition.apiextensions.k8s.io/clusterhealths.client.cluster.tsm.tanzu.vmware.com createdconfigmap/tsm-agent-operator createdserviceaccount/tsm-agent-operator-deployer createdclusterrole.rbac.authorization.k8s.io/tsm-agent-operator-cluster-role createdrole.rbac.authorization.k8s.io/vmware-system-tsm-namespace-admin-role createdclusterrolebinding.rbac.authorization.k8s.io/tsm-agent-operator-crb createdrolebinding.rbac.authorization.k8s.io/tsm-agent-operator-rb createddeployment.apps/tsm-agent-operator createdjob.batch/update-scc-job createdubuntu@ip-172-31-33-59 ~> kubectl -n vmware-system-tsm create secret generic cluster-token --from-literal=token=eyJhb…secret/cluster-token created
第一个命令安装控制平面组件。这些组件将回过头来安装 Istio,并与全局 SaaS 控制平面进行检查以查看是否有更新。
第二个命令创建一个 Kubernetes 秘密,用于认证到全球 SaaS 控制平面。
- 
最后,点击绿色的安装 Tanzu Service Mesh按钮。这将指示在你的 Kubernetes 集群上运行的组件拉取并安装 Istio 数据平面组件。 
- 
对你的第二个 Kubernetes 集群重复整个过程。 
此时,你应该已经在两个集群上启动并运行 Tanzu Service Mesh,并且它们应该在 Tanzu Service Mesh UI 的集群面板中可见。你应该会看到类似以下截图的内容。你会注意到我们每个集群上有四个节点,但还没有服务:

图 11.3 – 两个集群已加入
接下来,我们需要在每个集群中创建一个命名空间,作为我们在 Tanzu Service Mesh 中的全局命名空间。
创建 Tanzu Service Mesh 全局命名空间
每个集群中都有一个acme。现在,集群 1 中acme命名空间中的所有服务可以看到集群 2 中acme命名空间中的所有服务,反之亦然。以下是如何在我们两个已加入的集群之间创建 GNS 的步骤:
- 
继续创建命名空间: ubuntu@ip-172-31-33-59 ~> kubectl config use-context acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.io # target the 1st clusterSwitched to context "acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.io".ubuntu@ip-172-31-33-59 ~> kubectl create ns acmenamespace/acme createdubuntu@ip-172-31-33-59 ~> kubectl config use-context acmedemo-tkg@eks-tsm-2.us-west-2.eksctl.io # target the 1st clusterSwitched to context "acmedemo-tkg@eks-tsm-2.us-west-2.eksctl.io".ubuntu@ip-172-31-33-59 ~> kubectl create ns acmenamespace/acme created
- 
接下来,我们必须在 Tanzu Service Mesh UI 中创建逻辑 GNS。以下是高层次的步骤: - 
选择 acme-gns。
- 
为 GNS 选择一个域名。这将是服务相互发现的方式,因此我建议避免使用可能需要通过 DNS 解析的域名(例如, acme.com,mygns.net)。相反,我选择了devsecops-acme.gns,这是一个不会与公共域名混淆的名称。为了确保后续步骤不需要额外的更改,我建议为你的 GNS 使用相同的域名。
- 
你应该会看到如下所示的内容: 
 
- 

图 11.4 – 命名和选择唯一的域
- 接下来,我们需要在每个集群的 命名空间映射 屏幕中将 acme命名空间映射到这个 GNS,如下截图所示:

图 11.5 – 全局命名空间映射
- 对于剩余的屏幕,你可以接受默认设置。最后,你应该在 UI 的 GNS 概览 标签页中看到你的 GNS:

图 11.6 – 新的 GNS
现在我们的 GNS 已经启动并运行,是时候将一些服务部署到我们的集群中,这些服务将通过 GNS 进行通信。
安装服务
以下步骤中的文件将安装一个名为 Acme Fitness 的简单基于微服务的应用程序。如果你选择了 devsecops-acme.gns 作为你的域名,你可以直接部署这些文件;否则,你需要更新内部引用以反映你的域名。清单文件可以在此处找到:github.com/PacktPublishing/DevSecOps-in-Practice-with-VMware-Tanzu/tree/main/chapter-12:
确保你指向的是第一个 Kubernetes 集群,并且部署的是 cluster-1 的 YAML 清单。请注意命令末尾的 -n acme,这非常重要。你需要明确声明这些服务将被部署到 acme 命名空间。这将安装一些东西:
- 
应用程序将使用的机密,用于与其数据服务进行通信。 
- 
若干数据服务(如 MongoDB、Redis 等)。 
- 
一些基于微服务的应用程序。 
- 
一个网关,类似于一个虚拟的 L7 负载均衡器,告诉 Tanzu 服务网格将某些传入请求路由到哪里。在我们的案例中,这是唯一一个面向外部的应用程序,运行在集群中,因此我们将所有从集群外部传入的请求路由到我们的前端服务,服务名称为 shopping。
然后,切换到 cluster-2 并部署该清单。以下是我用来将服务部署到我两个 Kubernetes 集群中的命令:
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl config use-context  acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.io # target the 1st cluster
Switched to context "acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.io".
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl get all -n acme
No resources found in acme namespace.
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl apply -f ./cluster1.yaml -n acme
secret/redis-pass created
secret/order-mongo-pass created
secret/users-mongo-pass created
gateway.networking.istio.io/acme-gateway created
virtualservice.networking.istio.io/acme created
service/cart-redis created
deployment.apps/cart-redis created
service/cart created
deployment.apps/cart created
service/shopping created
deployment.apps/shopping created
service/order-mongo created
deployment.apps/order-mongo created
service/order created
deployment.apps/order created
service/payment created
deployment.apps/payment created
configmap/users-initdb-config created
service/users-mongo created
deployment.apps/users-mongo created
service/users created
deployment.apps/users created
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl config use-context  acmedemo-tkg@eks-tsm-2.us-west-2.eksctl.io # target the 2nd cluster
Switched to context "acmedemo-tkg@eks-tsm-2.us-west-2.eksctl.io".
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl apply -f ./cluster2.yaml -n acme
secret/catalog-mongo-pass created
configmap/catalog-initdb-config created
service/catalog-mongo created
deployment.apps/catalog-mongo created
service/catalog created
deployment.apps/catalog created
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)>
访问应用
现在我们已经在两个集群中安装了服务,让我们来验证应用是否正常运行。将你的 kubectl 上下文切换回第一个集群,并获取 istio-ingressgateway 服务在 istio-system 命名空间中的详细信息。如果你在 EKS 上运行,可能会获得负载均衡器的主机名;否则,你可能会看到一个 IPv4 地址。获取主机名或外部 IP,并将其插入浏览器中,使用 http,而不是 https。
下面是我获得服务的过程。请注意,我指向的是第一个集群,并且我使用的是 EKS,因此我获得了一个负载均衡器的主机名作为我的外部 IP:
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl get svc -n istio-system istio-ingressgateway
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP                       PORT(S)                AGE
istio-ingressgateway   LoadBalancer   10.100.7.70   a075e7d12da464c16a17e0aa0435fdbe-2ff7515fc9cc6551.elb.us-west-2.amazonaws.com   15021:30588/TCP,80:31893/TCP,443:31157/TCP   22h
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)>
这是你在浏览器中预期看到的内容。如果瑜伽垫和水瓶的图像出现,那么你就知道一切正常。该页面本身托管在集群 1 中,而目录托管在集群 2 中!

图 11.7 – Acme Fitness 部署在两个集群上
接下来,我们需要生成一些服务间流量,以便 Tanzu Service Mesh UI 可以可视化所有连接。
生成应用流量
以下是一些你可以做的事情,以确保所有服务都能接收到流量:
- 
点击购物车旁边的登录按钮。 
- 
使用以下凭据登录——用户名: dwight,密码:vmware1!。
- 
点击屏幕顶部的 Catalog 链接。 
- 
浏览一个项目。 
- 
将其添加到购物车。 
- 
点击 Shopping Cart 按钮。 
- 
点击 Proceed to Checkout。 
- 
完成结账流程。任何 16 位数字都可以作为信用卡号码。 
现在,我们可以返回 Tanzu Service Mesh UI 中的 acme-gns 页面。你应该能看到所有服务分布在两个集群中的情况,如下图所示:

图 11.8 – Tanzu Service Mesh 服务可视化
到目前为止,你已经成功完成了以下操作:
- 
启动了一个新的 Service Mesh 
- 
已加入多个集群 
- 
将它们联合到一个 GNS 中 
- 
部署了分布式应用 
- 
验证了应用的功能和跨集群通信 
这是第一天的令人印象深刻的清单。现在,我们来看看在完成了第一天的任务清单后,你可能会考虑的一些操作。
如何在 Tanzu Service Mesh 上执行关键的 Day-2 操作
到目前为止,我们已经成功地在两个 Kubernetes 集群中运行了一个分布式应用。如果你在真实的生产环境中进行此操作,可能会遇到一些 Day-2 的问题需要解决。例如,目录服务可以运行在单独的集群上,但如果该集群出现故障怎么办?我们如何在多个集群的实例间进行负载均衡呢?
此外,我们正处在一个这样的世界中:服务的部署、维护、度量和监控通常是 站点可靠性工程师(SREs)的职责。如果你是 Acme Fitness 的 SRE,你应该已经识别出了 服务水平指标(SLIs)并为你的服务定义了 SLO。Tanzu Service Mesh 通过允许你在 Tanzu Service Mesh UI 中定义 SLIs 和 SLOs,并使用实时指标来衡量服务是否达到了这些 SLO,从而大大简化了这一过程。
启用服务高可用性
首先,我们来讨论如何让服务具备高可用性。在我们的示例应用中,大多数服务都运行在cluster-1上,而目录服务及其数据存储则位于cluster-2上。Tanzu Service Mesh 使我们能够在多个集群中部署服务的额外实例,并且会自动在所有实例上线时进行负载均衡。
对于我们的目的,假设我们只需将目录服务的另一个实例部署到 cluster-1 上。我们可以通过以下方式非常轻松地实现:定位到 cluster-1 并应用 cluster-2 的部署清单:
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl config use-context  acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.io # target cluster 1
Switched to context "acmedemo-tkg@eks-tsm-1.us-west-2.eksctl.io".
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)> kubectl apply -f ./cluster2.yaml -n acme # this will land the catalog service on cluster 1
secret/catalog-mongo-pass created
configmap/catalog-initdb-config created
service/catalog-mongo created
deployment.apps/catalog-mongo created
service/catalog created
deployment.apps/catalog created
ubuntu@ip-172-31-33-59 ~/c/D/chapter-12 (main)>
现在,如果我们回到应用并多次访问目录,我们应该能看到像下面截图中的可视化效果。请注意,Tanzu 服务网格会自动在两个目录实例之间进行负载均衡:一个在 cluster-1,另一个在 cluster-2:

图 11.9 – 跨多个集群的自动负载均衡
接下来,让我们追踪一些 SLO。
定义和衡量 SLO
对于这个任务,我们将展示期望的结果和我们为实现这个结果所遵循的步骤。我们将展示一些截图,方便我们检查工作是否正确。接下来,我们会讲解各个字段的含义。
期望的结果
假设我们是 Acme Fitness 的 SRE,并且我们有一个关于目录服务的 SLO,要求其 99.99% 的时间内保持正常运行,通常称为四个九的正常运行时间。在我们的案例中,我们定义健康为 90% 的请求在 100 毫秒内完成。
让我们进入 Tanzu 服务网格 UI,定义这个 SLO,以便让 Tanzu 服务网格准确衡量我们是否达到了这个 SLO。
站点可靠性工程
如果你不熟悉 SRE、SLO 和 SLI 的概念,我强烈推荐阅读《站点可靠性工程》一书。你可以从常见的渠道获取电子书或纸质书,或者从 Google SRE 网站上免费阅读:sre.google/。
实现 SLO
从 Tanzu 服务网格 UI 中,导航到 新建工作流 | 新建 SLO 策略 | 监控的 SLO。这将启动一个向导。你可以按照以下方式填写第一页的表单值:
- 
acme-catalog-health
- 
GNS策略,GNS=acme-gns
- 
服务水平指标:p90 延迟小于 100 毫秒 
- 
服务水平目标:服务应保持健康,99.99% 的时间内正常运行 
- 
点击 下一步 
在第二屏幕上,选择 catalog 服务并点击下一步。如果你愿意,你还可以选择将这个 SLO 应用到多个服务。
最后,你将看到像这样的摘要。注意,它会计算出你的服务可以在不健康范围内的月度预算时间。随着服务在一个月内变为不健康状态,预算会进行更新:

图 11.10 – SLO 详细信息
现在,你可以通过导航到 策略 | SLOs 并点击你的 SLO 名称,查看服务相对于其 SLO 的表现。这里是我之前设置的一个 SLO,它有一个不合理的延迟阈值为 5 毫秒。这样做是为了展示当没有达到错误预算时的情况:

图 11.11 – SLO 进入红区
这向我们展示了,在一个月内,系统处于不健康状态的错误预算为 4 分钟 19 秒,而我们已经超出了该预算超过 3 分钟。SLO 对 SRE 来说是非常强大的工具,且在 Tanzu 服务网格中设置和维护非常容易。接下来,让我们继续讨论一些可能感兴趣的其他第二天任务。
进一步研究的其他第二天操作
要全面涵盖 Tanzu 服务网格中的所有第二天功能,可能会使本书的篇幅增加一倍;因此,考虑到这一点,以下是一些可以进一步探索的项目及相关文档链接:
- 
可操作的 SLO:你可以配置你的 SLO,在 SLI 超出范围时执行自愈操作。例如,当延迟过高时,Tanzu 服务网格可以自动扩展服务,以更好地处理负载: docs.vmware.com/en/VMware-Tanzu-Service-Mesh/services/slos-with-tsm/GUID-1B9A2D61-D264-44FB-8A06-40277AD42A8E.html。
- 
接入一些外部服务:有些服务存在于 Kubernetes 之外,但需要参与服务网格: docs.vmware.com/en/VMware-Tanzu-Service-Mesh/services/using-tanzu-service-mesh-guide/GUID-F7DC3814-0C3B-42E8-94A1-64B4B182D783.html。
- 
创建公共服务:这是一个可以从互联网或服务网格范围之外的网络(例如本地企业网络)访问的服务: docs.vmware.com/en/VMware-Tanzu-Service-Mesh/services/using-tanzu-service-mesh-guide/GUID-58A3FA7C-4EFC-44B2-B37B-D2152CB16359.html。
现在,我们已经全面覆盖了一些第二天任务,接下来让我们深入探讨一个特别重要的任务——全球服务器负载均衡 (GSLB)。
与 NSX-T 高级负载均衡器和 Tanzu 服务网格结合使用的 GSLB
一个特别值得单独讨论的第二天任务是实现与 Tanzu 服务网格和 NSX 高级负载均衡器结合使用的 GSLB。
NSX 高级负载均衡器
NSX 高级负载均衡器 (NSX-ALB) 是一款产品,尽管它在技术上不属于 Tanzu 产品组合,但与 Tanzu 产品组合非常互补。你可以通过以下链接了解更多信息,尤其是关于 GSLB 的内容:avinetworks.com/docs/20.1/gslb-architecture-terminology-object-model/#gslbsites。
简而言之,NSX-ALB 是一款强大的软件负载均衡器,完全通过 API 驱动,允许与其他基于 API 的技术(如 Kubernetes 或 Tanzu 服务网格)紧密集成。除了启用企业负载均衡器的常规功能(如 VIP、流量策略和 WAF)外,它还提供强大的 DNS 实现,这使其在 GSLB 中尤其有用。以下是 Tanzu 服务网格和 NSX-ALB 如何与您的企业 DNS(或公共 DNS)协同工作,以提供跨数据中心、多个区域和不同云提供商访问服务的粗略示意图:

图 11.12 – NSX 高级负载均衡器和 Tanzu 服务网格
在我们完全理解 Tanzu 服务网格如何与 NSX-ALB 的 GSLB 配合工作之前,让我们快速描述一下 NSX-ALB 如何单独执行 GSLB。
绕道 – 没有 Tanzu 服务网格的 GSLB
NSX ALB 通过实现一个 DNS 来启用 GSLB,该 DNS 会返回服务的工作实例的 IP 地址。以下是事件的顺序:
- 
客户端向本地 DNS 服务器请求 shopping.gslb.acme.com的 IP 地址。
- 
本地 DNS 将请求转发到位于纽约数据中心的 gslb.acme.com的权威 DNS 服务器。
- 
权威 DNS 服务器根据 GSLB 负载均衡策略和服务实例的健康状况,将返回三个 IP 地址中的一个:纽约数据中心的实例、伦敦数据中心的实例或 AWS 俄勒冈的实例。假设返回的是 20.30.40.50,这是位于纽约数据中心的 NSX ALB 服务引擎的 IP 地址。
- 
客户端向 20.30.40.50发出 HTTPS 请求,并带有shopping.gslb.acme.com.的 SNI 头。
- 
NSX ALB 服务引擎知道,带有特定 SNI 的请求将路由到 Kubernetes 集群中位于数据中心本地的 acme命名空间下的shopping服务。
- 
客户端成功地订购了他的瑜伽垫。 
现在,让我们加入 Tanzu 服务网格。
带有 NSX-ALB 和 Tanzu 服务网格的 GSLB
之前部分中的内容仍然适用,但不同的是,操作员不再手动为 shopping 服务设置 GSLB,而是将其注册为服务网格中的 public 服务 (docs.vmware.com/en/VMware-Tanzu-Service-Mesh/services/using-tanzu-service-mesh-guide/GUID-58A3FA7C-4EFC-44B2-B37B-D2152CB16359.html)。
然后,她将 Tanzu Service Mesh 与她的 NSX ALB 实例进行了集成。最后,Tanzu Service Mesh 会自动开始配置 GSLB。无论shopping服务在哪里部署在 GNS 中,Tanzu Service Mesh 都会配置 GSLB DNS 解析器,使其指向包含该服务的集群。你可以在这里详细阅读这个过程:docs.vmware.com/en/VMware-Tanzu-Service-Mesh/services/using-tanzu-service-mesh-guide/GUID-896EA3FA-17EA-49E2-B981-5C9634E45512.html。
总结
在本章中,我们介绍了 Tanzu Service Mesh,部署了一个实际应用,讨论了第二天的运维工作,甚至涵盖了一个非常高级的主题——GSLB。在下一章中,我们将尝试将所有部分组合在一起,描绘出使用整个 Tanzu 产品组合时“优秀”表现的图景。希望你能继续跟进!
第十二章:将一切汇聚在一起
恭喜你走到这本书的最后一章!在之前的章节中,我们学习了 VMware Tanzu 产品组合中的不同产品如何利用 Tanzu 所概述的 DevSecOps 能力,解决现代应用程序开发、安全和运维的挑战。本书的目的是为读者提供 Tanzu 整体能力的介绍,以便他们能够理解如何利用这一整套产品。VMware 在 Tanzu 的愿景方面做得非常出色,提供了一站式解决方案,满足你对现代应用程序的所有需求。正如你所想象的,这个产品组合中有很多内容我们在本书中没有涉及。此外,我们仅仅触及了本书中许多产品的表面。我们的目的是提供足够的细节,让读者理解每个产品的位置,并帮助读者进行实验以学习。这本书可以成为你深入学习与现实应用场景相关的产品的第一块垫脚石。
根据大纲,我们将覆盖 Tanzu 的更广泛的图景以及其采用选项。我们还将尝试预测这个生态系统的未来,那么,让我们开始吧,尽快完成这本书。
在本章中,为了将所有内容汇聚在一起,我们将涵盖以下主要主题:
- 
Tanzu 采用选项 
- 
超越本书的 Tanzu 
- 
从端到端的视角 
- 
单一供应商解决方案的优缺点 
- 
Kubernetes 的未来 
- 
Tanzu 的下一步是什么? 
Tanzu 采用选项
在写作本书时,本书讨论的大多数产品是独立的,可以按需定价。然而,VMware 将它们打包在一起,提供简化且更具成本效益的采用体验。以下是目前可供企业选择的产品包列表。
Tanzu Standard
这是最小的商业化 Tanzu 产品包,提供部署多云 Kubernetes 平台所需的基本工具。它主要包括 Tanzu Kubernetes Grid 和 Tanzu Mission Control 的基本功能。Tanzu Standard 还包括适用于 vSphere 的另一种 Kubernetes 产品。在这里,Kubernetes 集成在 vSphere 中,使得虚拟基础设施管理员更容易理解 vSphere 生态系统,从而简化了其采用过程。
Tanzu 应用平台(TAP)
- 
我们在第八章中深入探讨了这个产品捆绑包,标题为“通过 Tanzu 应用平台提升开发者生产力”。这个捆绑包包括简化开发人员在 Kubernetes 平台上构建和部署应用程序的工作的一些产品。截至本书编写时,该产品捆绑包在 Tanzu Kubernetes Grid、Amazon 的弹性 Kubernetes 服务(EKS)、Azure Kubernetes 服务(AKS)和Google Kubernetes 引擎(GKE)上作为多云解决方案得到支持。虽然 TAP 包括多个开源和独立可用的 Tanzu 产品,以下是此捆绑包中的一些主要产品: 
- 
Tanzu 应用加速器 – 定义预先配置好的、具有良好默认设置和所需模板代码的即用型应用模板 
- 
Tanzu 构建服务 – 使用 Cloud Native Buildpacks 开源项目从源代码构建应用容器镜像 
- 
应用实时视图 – 使用 Backstage(一种开源项目)来监控已部署到 TAP 的应用程序,查看它们的进展中的软件供应链及其元数据 
- 
供应链编排器 – 基于开源项目 Cartographer 的工具,允许根据应用程序类型定义一个预批准的生产路径 
- 
Cloud Native Runtime – 基于开源项目 Knative 的无服务器容器平台,用于 Kubernetes 
图 13.1展示了作为更广泛 TAP 用户界面一部分的应用加速器模块:

图 12.1 – TAP GUI 中的应用模板
接下来是一个捆绑产品集合,专为端到端 Kubernetes 操作而设计——VMware Tanzu for Kubernetes Operations。让我们来看看它。
VMware Tanzu for Kubernetes Operations
这个产品捆绑包专为 Kubernetes 平台拥有者设计,提供了管理大型 Kubernetes 基础设施所需的所有能力。它包含了本书中已详细介绍的多个产品,如下所示:
- 
Tanzu Kubernetes Grid – 多云 Kubernetes 发行版 
- 
Tanzu 任务控制 – 用于控制和管理数百个 Kubernetes 集群的单一视图 
- 
VMware Aria 应用操作 – 完整栈的可观察性工具,提供基础设施到任何地方部署的应用程序的可视化 
- 
Tanzu 服务网格 – 用于安全应用间流量的跨集群网络工具 
- 
NSX 高级负载均衡器 – 可扩展的、基于软件的应用负载均衡器,用于入口流量控制,并具备 Web 应用防火墙的安全功能 
Tanzu 数据解决方案
Tanzu 包括一组可以在虚拟机上、作为 Cloud Foundry 托管服务或作为运行在 Kubernetes 上的容器部署的数据服务。这个捆绑包包括以下开源产品的企业支持版本:
- 
GemFire —— 一种可靠的分布式缓存,基于开源 Apache Geode 项目提供可靠的数据存储 
- 
RabbitMQ —— 一种基于其开源发行版的异步通信数据队列解决方案 
- 
Tanzu SQL —— 包括基于其开源发行版的 MySQL 和 PostgreSQL RDBMS 数据库产品 
- 
Greenplum —— 基于开源 PostgreSQL 数据库的数据分析平台 
本书没有涵盖这一产品集,因为它仅包括具有少量修改和企业支持的开源产品。
VMware Spring 运行时
我们在第二章《开发云原生应用》中简要介绍了这一产品服务。它包括为多个开源应用开发框架、运行时和工具提供的商业企业支持,如下所列:
- 
多个 Spring 框架项目,包括但不限于 Spring Boot、Spring Security 等 
- 
Spring Cloud 服务: - 
Spring API 服务器 
- 
配置服务器 
- 
Spring Cloud Kubernetes 
- 
Spring Cloud Stream 
- 
Spring Cloud Data Flow 
 
- 
- 
Open JDK —— 一种开源的 Java 运行时版本 
- 
Apache Tomcat 服务器 
除了这些 Tanzu 产品组合外,还有其他一些产品,我们在本书中未详细介绍。让我们在下一节中回顾它们。
本书之外的 Tanzu
本书的范围是涵盖那些在 Kubernetes 平台上构建、运行和管理现代容器化应用时扮演关键角色的 Tanzu 产品。然而,Tanzu 生态系统中还有一些我们尚未涵盖的产品,如以下小节所示。
Tanzu 实验室
Tanzu 实验室是 Tanzu 旗下的专业服务部门。它提供以成果为导向的服务,通常为期 6 到 12 周,具体取决于工作范围。这些服务包括来自各领域的高级架构师和工程师的咨询。每项服务通常由两名全职工程师或架构师以及一名产品经理组成。这些专业人员与客户团队成员合作,遵循极限编程的实践方式。这样,客户在短期合作结束后,能够拥有所需的、经过培训的成员来接管应用或平台的管理,而不需要再寻求额外帮助。Tanzu 实验室提供以下类别的服务:
- 
构建新应用 —— 一项从零开始构建关键业务应用的服务,以迈出正确的第一步 
- 
现代化现有应用 —— 一项旨在将现有遗留系统现代化,使其云原生的服务,通常是通过使用现代工具、技术和平台对其进行重新架构 
- 
构建平台 —— 一项使用多个 Tanzu 产品部署生产级平台的服务 
- 
数据转换 – 一个关于数据服务优化、架构和部署的项目,涵盖了 Tanzu 数据服务捆绑包中包含的数据产品 
- 
分析应用程序组合 – 一个项目,旨在分析组织中的数百个应用程序,为它们制定云迁移计划,并为它们定义重新托管、重新平台化、重新定位、重新架构、保留和淘汰策略之一 
在 VMware 收购 Pivotal 之前,Tanzu Labs 也被称为 Pivotal Labs。这样,Tanzu Labs 在为非常大型企业提供这些服务方面有着成功的经验记录。了解更多关于 Tanzu Labs 的信息,请访问这里:tanzu.vmware.com/labs。
Tanzu 应用服务
Tanzu 应用服务之前被称为 Pivotal Cloud Foundry,是开源 Cloud Foundry 平台的商业支持版本。与 Kubernetes 类似,Cloud Foundry 也是一个云无关的容器平台,大大提升了开发者的生产力。只需一个小命令 cf push,我们就可以从源代码将云原生应用部署到容器中,无需任何自定义自动化。Pivotal Cloud Foundry,以及因此而来的 Tanzu 应用服务,是经过实战考验的技术,在全球范围内运行着超过百万个容器,托管着关键的应用程序。尽管 Kubernetes 的崛起和普及使得这项技术黯然失色,但它仍然是一个非常成熟和可靠的容器平台,适合任何规模和大小的企业。了解更多关于 Tanzu 应用服务的信息,请访问这里:tanzu.vmware.com/application-service。
Azure Spring Apps
在微软和 VMware 的合作下,他们在 Azure 上推出了一个由 Spring Framework、Tanzu 和 AKS 提供支持的微服务平台。它还支持部署 .NET Core 和其他语言开发的应用程序。在幕后,这个提供使用了我们在 第八章**,通过 Tanzu 应用平台增强开发者生产力 中了解的 TAP 能力,建立在 AKS 之上。它为 Azure 原生客户提供了一个熟悉的用户界面,利用 Tanzu 的开发者生产力和 Azure 的可扩展基础设施来部署他们的云原生应用。了解更多关于 Azure Spring Apps 的信息,请访问这里:tanzu.vmware.com/azure-spring-apps。
Concourse
Concourse 是一个商业支持但非常成熟的开源轻量级持续集成/持续部署(CI/CD)自动化平台,隶属于 Tanzu。凭借其水平可扩展的设计以及以容器并行运行工作节点的能力,它在一些大企业的非常大规模的 CI/CD 自动化平台中得到了应用。图 13**.2 显示了 Concourse Web 控制台上的一个复杂管道。该平台完全通过基于 YAML 的声明性配置驱动,遵循 GitOps 模型,并使用其简洁的基于 Web 的 UI 进行监控,以检查配置的管道状态。了解更多关于 Concourse 的信息:tanzu.vmware.com/concourse。

图 12.2 – 一个复杂的 Concourse 管道
图 13**.2 显示了一个部署在 Concourse 上的复杂 CI/CD 管道。标签和不同管道阶段的文本不可读取,因为这里的目的是展示复杂管道在 Concourse GUI 中的外观。左侧框的黑色标签显示了输入到相应管道任务的数据和配置。右侧类似的标签显示了相应任务的输出,这些输出可以作为下一个任务的输入。框列显示了按从左到右的顺序执行的不同阶段。堆叠在同一列中的框表示可以在同一阶段并行执行的任务。红色框表示任务失败。带有黄色边框的框表示当前正在执行的任务。绿色框表示与当前执行任务相关的已完成或待处理的任务。
通过这些内容,我们覆盖了 Tanzu 产品组合中所有产品的一些细节。现在,让我们通过描述一个端到端的图示来更好地理解它,涵盖 Tanzu 大部分产品。
端到端图示
到目前为止,在本书中我们已覆盖 Tanzu 产品组合中 20 多种不同的产品,涵盖了不同的详细程度。现在是时候将其中的一些产品整合在同一页面上,以理解它们如何协同工作,为您的应用程序提供一个生产级的生态系统,满足不同层次的需求。图 13**.3 显示了 Tanzu 产品组合中的关键产品,它们共同提供一个全面的 Kubernetes 平台,帮助实施围绕现代应用程序的 DevSecOps 实践:

图 12.3 – Tanzu 的端到端图示
以下要点描述了图 13**.3:
- 
一个应用程序可能使用以下组件: - 
根据需要使用 VMware Spring Runtime for OpenJDK、Tomcat 和 Spring 框架 
- 
Tanzu 数据服务,用于所需的后端数据存储 
- 
VMware 应用程序目录,用于满足任何开源软件的需求 
 
- 
- 
应用程序可以托管在 TAP 上,它内部使用多个组件将应用程序从开发到生产的路径铺开 
- 
TAP 可以使用 Harbor 作为容器镜像仓库,从 Tanzu Build Service 中获取应用构建的镜像,并利用这些镜像来部署容器。 
- 
TAP 可以部署在以下四种 Kubernetes 发行版之一: - 
Tanzu Kubernetes Grid – 在 vSphere 上部署用于本地部署,在 AWS 或 Azure 上用于公共云部署。 
- 
EKS 
- 
AKS 
- 
GKE 
 
- 
- 
Tanzu Service Mesh 可以连接所需的 Kubernetes 集群,实现应用间的安全流量通信。 
- 
Tanzu Mission Control 可以管理整个 Kubernetes 环境,提供多种类型的策略控制、生命周期管理、备份/恢复和合规审计功能。 
- 
VMware Aria 操作系统用于应用程序可以收集来自所有来源的遥测数据,以提供集中位置的端到端可见性,监控所有组件的健康状况。 
除了这种部署选项外,还有其他可能的方法可以使用相关的 Tanzu 产品在容器中部署应用程序。其一是使用自定义的 CI/CD 工具,而不是 TAP,并将容器部署在 Tanzu Kubernetes Grid 部署的 Kubernetes 集群中。其他所有产品的关联性保持不变。此外,自定义 CI/CD 流程可以使用 Concourse 部署。
在了解了整体大致情况后,让我们深入理解从像 VMware 这样的单一供应商获取所有服务意味着什么。
单一供应商解决方案的优缺点
使用像 Tanzu 这样的端到端解决方案或单一公共云有许多优点,但也存在一些缺点。企业应仔细考虑这些点,并相应地制定技术平台的采用计划。以下是使用包含多个产品的单一供应商解决方案的优缺点。
优点
- 
在软件领域,越来越多的公司选择使用开源技术,以避免供应商锁定并获得社区协作的好处。然而,选择一个成熟且得到支持的开源技术往往是一个具有挑战性且耗时的过程。这时,一个全面的技术平台,例如 Tanzu,可能会发挥巨大作用,因为它在背后使用了许多精心挑选的开源工具。这将为企业节省大量精力,同时也能让企业更加自信地广泛使用开源技术。 
- 
当企业选择来自不同供应商或开源社区的不同软件解决方案时,很难使这些工具按预期一起工作。可能没有人在单一解决方案中尝试过并测试过它们,随着我们向前迈进,可能会遇到令人不快的惊喜。即使在某个时间点使它们一起工作,也不能保证来自异构来源的这些工具的未来版本将继续和谐工作。这就是像 Tanzu 这样的端到端解决方案有用的地方,因为组合中的所有产品都设计和确保能够一起工作。否则,将无法明确一个产品版本与另一个产品版本兼容的情况。 
- 
一个大型企业承诺从单一供应商购买多个产品可能会比从不同供应商购买不同产品获得巨大的许可成本折扣。 
- 
在发生重大生产中断时,企业拥有来自单一供应商的产品解决方案可能比拥有多个供应商或纯社区支持的开源产品更有帮助。使用来自单一供应商的产品可以确保所需的问责制,而不会引发潜在的产品兼容性问题。 
- 
使用像 Tanzu 这样的平台可以带来运营效率的提升,因为在使用不同工具时有相似的用户体验。共同的工具集和用户界面加快了学习曲线和围绕平台的自动化工作。最终,这将促进使用单一供应商解决方案的组织的敏捷性和现代化速度。 
缺点
- 
企业使用多个基于开源技术的供应商提供的不同产品,可以避免过度依赖单一供应商的成功。如果供应商不使用其他供应商也支持的开源工具,单一供应商解决方案可能导致潜在的供应商锁定问题。 
- 
将所有产品来自单一供应商就像把所有鸡蛋放在一个篮子里。如果篮子掉了,所有鸡蛋都会摔碎。为了避免这种情况,使用多个平台并具备移动应用的能力可能是一种有效的缓解策略。 
- 
拥有一个端到端的解决方案可能意味着拥有一组产品,缺少一些与市场上不同供应商的类似产品相比可用的功能。企业可能需要根据必需功能而不是好有的功能来权衡其选择。每个软件供应商都有比其他更闪亮和更成熟的产品,因此从同一供应商获取多个产品可能意味着错过组合中某些产品的一些优秀替代品。 
在软件解决方案架构中,没有一个“灵丹妙药”能解决所有问题。决策是基于企业最重要的需求,考虑一种方法的好处,以及如何应对该方法所带来的风险。使用像 Tanzu 这样的端到端平台,在这种情况下也不例外。
Kubernetes 的未来
虽然没有人能够准确预测未来,但根据目前的技术采用数据和该生态系统中正在进行的工作流程,我们可以对 Kubernetes 的未来做出一些预测。正如我们在第七章《使用 Tanzu Kubernetes Grid 跨云编排容器》中所学到的,Kubernetes 的采用在过去两年里达到了前所未有的高度。它已经成为大多数新开发应用程序以及许多遗留应用程序的家园。它是新的中间件,抽象了底层基础设施,提供了容器化应用程序出现之前无法实现的真正应用程序可移植性。容器化改变了我们构建架构和思考软件开发的方式。过去几年中,这项容器化技术跨越了多个平台,包括 Docker Swarm、Mesosphere、AWS 弹性容器服务、Cloud Foundry 和 Kubernetes。虽然它们都是成熟可靠的技术,但无疑 Kubernetes 是这个领域中最受欢迎的选择。随着将软件作为容器运行的兴起,大多数软件供应商将他们的产品打包为容器镜像,这些镜像可以在 Kubernetes 上运行。
然而,这一切只是当前的情景。考虑到目前的进展,我们可以尝试预测 Kubernetes 的未来,如下所述:
- 
随着虚拟基础设施层成为大多数应用程序的新默认基础设施底层,Kubernetes 可能会取而代之,成为未来应用程序的默认基础设施层。从某种程度上讲,Kubernetes 有可能变得无处不在。 
- 
在微服务和物联网(IoT)的时代,应用程序变得非常小巧,适合在容器中运行。同时,将它们部署到离使用点更近的位置被认为是更优的选择。随着需要在边缘位置(如商店、手机塔、船只、飞机、家庭和分支办公室)运行的应用程序激增,我们预计未来 Kubernetes 在边缘部署中的使用场景将会增加。这将需要像 Tanzu Kubernetes Grid 这样的能力来支持本地部署,Tanzu Mission Control 来集中管理数百个集群,以及 VMware Aria 应用程序操作来集中监控这些集群、运行在其上的应用程序以及底层基础设施。 
- 
随着 Kubernetes 的日益普及,像 TAP 这样的工具将成为主流,用于将 Kubernetes 集群隐藏为低价值的工作内容。很快,Kubernetes 集群管理将被视为一种开销。开发者将花更少的时间编写 Kubernetes 特定的配置来部署应用程序,而是更多地关注丰富应用功能。就像开发者在部署应用时不会考虑服务器操作系统的具体细节一样,他们也会在不久的将来停止考虑 Kubernetes 层。 
- 
在大约十年前公共云平台出现之前,虚拟服务器曾被视为宠物,拥有名字,得到关爱和照顾,并有较长的生命周期。然而,基于 API 的云基础设施即代码(Infrastructure-as-Code)使得创建新服务器变得如此简单且成为必需,虚拟服务器就像牲畜一样。Kubernetes 集群也是如此,今天它们被视为宠物。随着集群需求的增加,未来它们也可能会像牲畜一样被对待。 
- 
随着 Kubernetes 越来越受欢迎,并且它的社区合作不断加强,未来我们可能会看到 Kubernetes 添加许多新功能,解决今天我们需要依赖外部工具才能解决的许多问题。 
Kubernetes 会长期存在,但我们今天对它的关心方式可能会在明天发生变化——而且应该发生变化,因为没有任何企业仅凭运行健康的 Kubernetes 集群就能获得更多收入。Kubernetes 只是一个基础设施层,使我们的创收应用能够繁荣发展。
Tanzu 的未来是什么?
VMware 于 2020 年通过将内部开发的相关产品与从 Pivotal、Bitnami、Heptio 和 Wavefront 收购的产品整合,创建了一个新的现代应用程序业务部门。这是一个深思熟虑的产品组合,涵盖了在多云环境中构建、运行和管理现代应用程序的大部分主要领域。该产品组合中的所有产品都有良好的长期发展规划,能够增加更多功能并支持不同的云基础设施提供商。然而,随着博通公司(Broadcom Inc.)宣布收购 VMware,预计这些产品的分组方式会发生变化,此外还会涉及 VMware 和博通现有产品的整合。更多细节将在收购后的未来展开。不管怎样,我们相信这些产品为市场带来的价值不会改变,即使它们的包装或名称将来发生变化,因此我们也希望本书中获得的知识依然能帮助读者。
重要提示
以下列表中提到的任何内容都属于前瞻性声明,预测未来产品的路线图。某些或所有列出的项目可能会在没有通知的情况下从路线图中删除。
以下列表包括不同 Tanzu 产品的部分现有工作流:
- 
Tanzu Mission Control 和 Tanzu Service Mesh 除了现有的基于云的 软件即服务 (SaaS) 部署外,可能还会有本地部署变体,以支持隔离环境中的部署。 
- 
Tanzu Mission Control 可能会增加更多功能,支持在其管理的 Kubernetes 集群上安装和配置第三方软件。 
- 
VMware Aria Operations for Applications 也可能具有日志聚合功能,并结合指标、直方图和跨度日志,将所有内容集中在一个地方,以实现完整的栈式可观察性。 
- 
Tanzu Kubernetes Grid 和 TAP 可以支持更多底层云平台,包括 OpenShift、Google Cloud Platform 和 Oracle Cloud。 
- 
TAP 的 Application Live View 组件可以支持 Tanzu 客户开发的自定义模块,作为底层开源 Backstage 项目的插件。 
让我们用一个简短的总结来结束本章。
总结
在本书的结尾部分,我们介绍了当前市场上不同的商业套餐,这些套餐将本书中介绍的不同产品打包在一起。我们还了解了 Tanzu 旗下其他产品和套餐,包括针对不同类型后端数据存储需求的 Tanzu Data、为最佳利用 Azure 云平台运行 Spring 应用程序的 Azure Spring Runtime,以及作为 Cloud Foundry 和 Concourse(一个轻量级 CI/CD 自动化工具)商业化产品的 Tanzu Application Service。我们还了解了使用本书中涉及的关键产品部署 Tanzu 的端到端部署图景。我们还了解了选择单一供应商的多种产品意味着什么。虽然选择一站式商店满足许多需求有一定的缺点,但这样做也带来了显著的好处。最后,我们根据 Kubernetes 和 Tanzu 当前的状况预测了它们的未来。
这本书到此结束。感谢你与我们一起走过这段学习旅程!我们希望你按照预期了解了 Tanzu 产品组合。正如本书中提到的,我们仅仅触及了表面。欲获取更多学习资源,请参考本书的 附录 部分。
附录
本节包含了关于 Tanzu 的额外学习资源,以及创建 Kubernetes 集群的参考资料,用于本书中的实战部分。
VMware 提供的额外学习资源
以下是一些好的学习参考资源,帮助进一步探索 Tanzu:
- 
官方 VMware Tanzu 产品文档: docs.vmware.com/allproducts.html#section
- 
VMware 提供了按需培训课程,面向开发人员和运维人员: tanzu.vmware.com/education
- 
Tanzu 实战工作坊: tanzu.vmware.com/developer/workshops/
- 
与 Tanzu 和构建现代应用相关的动手实验和课程: modernapps.ninja/
- 
Kubernetes 课程: kube.academy/
- 
Tanzu YouTube 频道: www.youtube.com/c/VMwareTanzu
创建 Kubernetes 集群的不同方式
本书中的大多数章节都要求 Kubernetes 集群作为前提条件之一,以便按照每章的说明进行操作。在本书中,我们介绍了创建 Tanzu 集群的三种不同方法,如下所述,但也有多种其他方式可以让你轻松启动并运行 Kubernetes 集群。本节列出了创建 Kubernetes 集群的多种方法。
创建 Tanzu Kubernetes Grid 集群
以下列表包括创建 Tanzu Kubernetes Grid 集群的方式:
- 
Tanzu Kubernetes Grid: 在第七章**,使用 Tanzu Kubernetes Grid 跨云编排容器 中,我们描述了如何使用 Tanzu Kubernetes Grid 创建一个托管的企业级 Kubernetes 集群。 
- 
Tanzu Mission Control: Tanzu Mission Control 使得创建 Kubernetes 集群变得非常简单直接。我们在第九章中详细介绍了这一点,内容为使用 Tanzu Mission Control 管理和控制 Kubernetes 集群。 
- 
vSphere with Tanzu: 如果你已经拥有 vSphere 集群,可能可以使用已经集成到虚拟基础设施中的 Supervisor Cluster 创建集群。你可以在这里了解更多信息: docs.vmware.com/en/VMware-vSphere/7.0/vmware-vsphere-with-tanzu/GUID-3B2102E6-D9AA-4FE6-B3AA-60B450BE8491.html
创建非 Tanzu Kubernetes 集群
以下列表包括在公共云、本地桌面环境和 OpenShift 平台上创建非 Tanzu Kubernetes 集群的方式:
- 
使用 Docker Desktop 创建本地 Kubernetes 集群: docs.docker.com/desktop/kubernetes/
- 
创建本地 Minikube 集群: minikube.sigs.k8s.io/docs/start/
- 
创建 AWS 弹性 Kubernetes 服务(EKS)集群: docs.aws.amazon.com/eks/latest/userguide/create-cluster.html
- 
创建 Google Kubernetes 引擎(GKE)集群: cloud.google.com/kubernetes-engine/docs/how-to/creating-a-zonal-cluster
- 
创建 Azure Kubernetes 服务(AKS)集群: docs.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-portal?tabs=azure-cli
- 
在 IBM Cloud 上创建 Red Hat OpenShift 集群: cloud.ibm.com/docs/openshift?topic=openshift-clusters&interface=ui

 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号