Kubernetes 上的机器学习(一)
本章中,我们定义了MLOps这一术语,并提出了一个协作型的 ML 项目生命周期,能够提供早期反馈。你已经了解到,通过这个项目生命周期,团队可以持续向业务提供价值。你还了解了为何基于开源软件构建平台是合理的,以及社区驱动软件的好处。本书的这一部分介绍了设置背景、学习为何需要平台以及探索平台预期解决的各种问题。下一章我们将探讨 Kubernetes 系统的一些基本概念,它是我们 ML 平台的核心。
原文:
annas-archive.org/md5/677f27c30764b3701bc2b6cf6de3a30e译者:飞龙
第一章:第二章:理解 MLOps
大多数软件工程背景的人都知道开发运维(DevOps)这个术语。对我们来说,DevOps 是关于在软件开发生命周期(SDLC)中跨不同团队之间进行协作和共享责任。这些团队不仅限于少数信息技术(IT)团队,而是涉及到项目中的所有利益相关者。不再区分软件构建(开发者的责任)和在生产环境中运行它(运维的责任)。相反,团队共同拥有产品。DevOps 之所以流行,是因为它帮助团队提高了正在开发的软件的速度和可靠性。
在本章中,我们将涵盖以下主题:
-
将机器学习(ML)与传统编程进行比较
-
探讨 DevOps 的好处
-
理解ML 运维(MLOps)
-
开源软件(OSS)在 ML 项目中的作用
-
在 Kubernetes 上运行 ML 项目
在我们可以将 DevOps 应用于 ML 项目之前,我们必须首先了解传统软件开发和 ML 开发过程之间的区别。
将 ML 与传统编程进行比较
与传统应用程序开发类似,ML 项目也是一个软件项目,但它们在交付方式上有根本性的区别。让我们了解一下 ML 项目与传统软件应用程序的不同之处。
在传统软件应用程序中,软件开发人员编写一个程序,其中包含一组明确定义的手工制作的规则。在运行时或预测时,构建的软件将这些明确定义的规则应用于给定的数据,程序的输出是基于编码规则计算得出的结果。
下图显示了传统软件应用程序的输入和输出(I/Os):
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_001.jpg
图 2.1 – 传统软件开发
在 ML 项目中,规则或模式并非完全已知,因此我们无法像在传统编程中那样在代码中明确描述规则。在 ML 中,有一个过程可以根据给定的数据样本对和其关联的预期结果提取规则。这个过程称为模型训练。在模型训练过程中,选择的 ML 算法根据给定的数据和验证的答案计算规则。这个过程的输出是ML 模型。生成的模型随后可用于在预测时推断答案。与传统软件开发不同的是,我们不使用明确编写的规则,而是使用生成的 ML 模型来获得结果。
下图显示了在训练时生成的 ML 模型,然后在预测时用于产生答案或结果:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_002.jpg
图 2.2 – ML 开发
尽管传统软件开发和机器学习在本质上是不同的,但这两种方法的工程过程之间存在一些协同效应。考虑到传统软件开发在当今时代非常成熟,我们可以将其中的经验教训应用到我们的机器学习项目中。当然,最主要的是,传统编程和机器学习都属于软件开发。我们在传统领域中应用于构建软件的所有流程——例如版本控制、将软件打包成容器、自动化部署等——也可以应用到机器学习项目中。然而,我们也必须考虑到机器学习中额外的过程,如模型训练。
那么,为什么我们在机器学习项目中真的需要 DevOps 呢?它能带来什么好处?我们将在下一节中探讨这个问题。
探索 DevOps 的好处
DevOps 不仅仅是关于工具集。假设你有一个可以为你运行单元测试的工具。然而,如果团队没有编写测试用例的文化,那么这个工具就不会有任何用处。DevOps 关注的是我们如何在跨团队的任务上协作。所以,DevOps 需要专注的三个主要领域是:
-
人员:来自多个学科的团队,旨在实现共同目标
-
过程:团队合作的方式
-
技术:促进不同团队间协作的工具
DevOps 基于敏捷开发实践,旨在简化软件开发过程。DevOps 团队是跨职能的,并且拥有通过持续集成/持续交付(CI/CD)来构建软件的自主权。DevOps 鼓励团队通过快速反馈回路进行协作,以提高开发软件的效率和质量。
下图展示了传统软件开发项目中完整的 DevOps 生命周期:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_003.jpg
图 2.3 – 展示 DevOps 过程的莫比乌斯环
通过 DevOps,团队可以拥有明确且简化的开发实践,用于构建、测试、部署和监控生产中的软件。所有这些都使得能够快速且可靠地将软件发布到生产环境中。以下是 DevOps 实践带来的一些好处:
-
CI/CD:CI 是一个阶段,软件在开发者将其推送到代码库时即进行合并和验证。CD 是一系列阶段,通过这些阶段,软件被构建、测试,并打包成准备部署的形式。持续部署(也称为 CD)是一个阶段,在这个阶段,准备部署的代码被选中并部署,以供最终用户使用。在 DevOps 中,所有这些流程都是自动化的。
-
基础设施即代码(IaC):IaC 是一种自动化 IT 基础设施配置和供应的方法。这一方面使得团队可以根据需求随时请求并配置基础设施。想象一下,团队中的数据科学家需要一个 图形处理单元(GPU)来进行模型训练。如果我们遵循 IaC 的配置和供应实践,那么系统可以自动完成对 GPU 的请求。接下来的章节中,你将看到这一能力的实际应用。
-
可观察性:可观察性与我们如何理解正在运行系统的状态有关。DevOps 通过联邦日志记录来自不同组件的日志、监控系统(例如 中央处理单元(CPU)、内存、响应时间等),并通过调用追踪提供一种将系统的各个部分关联起来的方式,从而使系统可观察。所有这些能力共同为理解系统状态提供基础,帮助调试任何问题,而不需要修改代码。
-
团队协作:DevOps 不仅仅是关于技术。事实上,团队的关键关注点是协作。协作是指来自不同团队的多个个体共同朝着一个共同目标努力。业务、开发和运维团队的合作是 DevOps 的核心。对于基于 ML 的项目,团队中除了上述角色外,还会有数据科学家和数据工程师。由于团队成员的多样性,沟通对于构建集体理解和对既定结果的共同责任感至关重要。
那么,我们如何将 DevOps 方法的优势带入到 ML 项目中呢?答案就是 MLOps。
理解 MLOps
MLOps 是一个新兴领域,它利用了现有软件开发流程的成熟性——换句话说,就是将 DevOps 与数据工程和 ML 学科结合起来。MLOps 可以简化为将 DevOps 应用于 ML 项目的工程实践。让我们更详细地了解这些学科如何构成 MLOps 的基础。
ML
ML 项目涉及一些传统编程中没有的活动。你在 图 2.3 中学习到,ML 项目中大部分的工作并不是模型开发,而是更多的数据收集与处理、数据分析、特征工程(FE)、过程管理、数据分析、模型服务等。实际上,根据 D. Sculley 等人的论文 Hidden Technical Debt in Machine Learning Systems,只有 5% 的工作是 ML 模型开发。因此,MLOps 不仅关注 ML 模型的开发任务,更多的是聚焦于大局——整个 ML 项目生命周期。
就像 DevOps 一样,MLOps 也关注人、流程和技术。但 MLOps 有一些复杂性是 DevOps 不需要处理的。我们在这里更详细地了解这些复杂性:
-
首先,与传统编程不同,你的输入不仅是代码,还包括数据。在 ML 中,模型开发阶段生成的 ML 模型高度依赖于数据。这意味着即使你没有改变代码,如果使用不同的数据集训练 ML 算法,生成的 ML 模型将不同,并且性能也会有所不同。在版本控制方面,这意味着不仅需要版本化促进模型训练的代码,还需要版本化数据。由于数据量巨大,数据版本控制相对较难。解决这个问题的一种方法是使用 Git 跟踪数据集版本,使用数据哈希存储实际数据在远程存储(如简单存储服务(S3)桶)中。一个名为数据版本控制(DVC)的开源工具可以做到这一点。
-
其次,在 ML 项目中涉及更多人物角色,需要更多的协作。你有数据科学家、ML 工程师和数据工程师与软件工程师、业务分析师和运营团队合作。有时,这些角色非常多样化。一个数据科学家可能完全不理解什么是真正的生产部署。另一方面,运营人员(有时甚至是软件工程师)不了解什么是 ML 模型。这使得在 ML 项目中进行协作比传统软件项目更加复杂。
-
第三,增加模型开发阶段为生命周期添加了更多的转折点。这使得整个过程变得更加复杂。与传统软件开发不同,你只需开发一组可工作的代码。在 ML 中,数据科学家或 ML 工程师可能会使用多个 ML 算法并生成多个 ML 模型,因为只有一个模型将被选中部署到生产环境中,这些模型将根据性能与其他模型属性进行比较。MLOps 适应了这种复杂的测试、比较和选择模型的工作流程。
传统编码生成可执行二进制文件通常需要几秒到几分钟。然而,训练 ML 算法生成 ML 模型可能需要几个小时或几天,有时甚至使用某些深度学习(DL)算法时可能需要几周。这使得建立敏捷的迭代时间限制节奏稍显复杂。MLOps 团队需要处理工作流中的这种延迟,一种方法是在等待其他模型完全训练完成时开始构建另一个模型。如果数据科学家或 ML 工程师在他们自己的笔记本电脑上训练他们的 ML 算法,这是非常难以实现的。这就是可扩展基础设施的用武之地。
- 最后,由于 ML 模型的性能依赖于训练过程中使用的数据,如果这些数据不再代表现实世界的情况,模型的准确性将会下降,从而导致预测性能变差。这被称为模型漂移,并且需要尽早检测。通常,这会作为 ML 项目生命周期监控过程的一部分进行。除了在生产中收集的传统指标外,使用 ML 模型时,你还需要监控模型漂移和异常值。然而,异常值检测的实现要困难得多,有时需要你训练并构建另一个 ML 模型。异常值检测是关于检测生产中进入的数据,这些数据与模型训练时使用的数据不相符:你不希望你的模型给出与这些无关问题的无关答案。另一个原因是,这可能是一次攻击或滥用系统的尝试。一旦你检测到模型漂移或异常值,你打算如何处理这些信息?这可能仅仅是触发警报,或者可能会触发其他自动化流程。
由于与传统编程相比,ML 增加了复杂性,因此必须解决这些复杂性,促使了 MLOps 的出现。
DevOps
在部署方面,想一想你在 ML 项目中编写的所有代码:执行数据处理的代码、促进模型训练和前端工程的代码、运行模型推理的代码以及执行模型漂移和异常值检测的代码。这些代码集需要构建、打包并部署以便大规模使用。一旦这些代码在生产环境中运行,它们还需要被监控和维护。这就是 DevOps 的 CI/CD 实践发挥作用的地方。自动化软件打包、测试、安全、部署和监控的实践源自 DevOps。
数据工程
每个 ML 项目都涉及到数据工程,而且 ML 项目处理的数据远比代码要多。因此,确保你的基础设施包括数据处理能力,并且能够与组织中现有的数据工程管道集成,是强制性的。
数据工程是一个庞大的主题—可以写一本书来讲述它。但我们在这里想强调的是,MLOps 与数据工程实践交叉,特别是在数据摄取、数据清洗、数据转换和大数据测试方面。事实上,你的 ML 项目可能只是一个小型的 ML 分类模型,它是一个更大数据工程或数据分析项目的子部分。MLOps 采纳了数据工程和分析中的最佳实践。
以下图表展示了 MLOps 的表示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_004.jpg
图 2.4 – MLOps 作为 ML、数据工程和 DevOps 的交集
用另一种方式来说,MLOps,如图 2.4所示,是ML、DevOps和数据工程学科的融合,专注于在生产环境中运行 ML。它还涉及将 ML 项目封装在一个高度可扩展、可靠且可观测的基础设施中。最后,它还涉及为团队建立可重复的流程,以执行成功交付 ML 项目所需的任务,如图 2.4所示,同时支持团队之间的协作。
有了对 MLOps 的基本理解后,让我们更深入地探讨 ML 项目生命周期。我们将从定义 ML 项目的一般阶段开始。
ML 项目生命周期
与 DevOps 类似,DevOps 提供了一系列活动,可以在 DevOps 周期中执行,你可以在图 2.5中看到一系列步骤,这些步骤可用于将你的 ML 项目从开始到结束。这些步骤或阶段将成为 ML 项目生命周期的一部分,并提供一种一致的方式将 ML 项目投入生产。你在本书中构建的 ML 平台是允许你实现这个流程的生态系统。在本书的后续章节中,你将使用这个流程作为平台的基础。ML 项目的各个阶段总结如下:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_005.jpg
图 2.5 - 一个 ML 项目生命周期
以下是前面图表中呈现的每个阶段的定义:
-
编码问题并定义成功指标:在这个阶段,团队评估给定的业务问题是否可以通过 ML 来解决。请注意这里的“团队”一词,团队至少包括数据科学家和业务领域专家(SME)。团队将定义一个成功标准,以评估模型的预测结果。
-
获取、清洗和标注数据:在这个阶段,团队评估是否有可用的数据来训练模型。团队将扮演额外的角色——数据工程师,帮助推动项目在这一阶段及其后的进展。团队将构建组件,从各种来源获取数据,清洗获取的数据,可能会标注数据并存储它。这些数据将构成 ML 活动的基础。
-
FE:FE 是指将原始数据转化为与给定问题更相关的特征。假设你正在构建一个模型,用来预测任何给定的泰坦尼克号乘客是否会生还。假设你得到的数据集包含了乘客的票号。你认为票号与乘客的生还有关系吗?一位业务领域专家(SME)可能会提到,票号可能能提供乘客所在舱位的信息,而头等舱的乘客可能更容易获得船上的救生艇。
-
模型构建和调优:在这个阶段,团队开始尝试不同的模型和不同的超参数。团队会将模型与给定的数据集进行测试,并比较每次迭代的结果。然后,团队会根据给定的成功指标确定最佳模型,并将该模型存储在模型注册表中。
-
模型验证:在这个阶段,团队使用一个在训练时无法获取的新数据集来验证模型。这个阶段至关重要,因为它决定了模型是否足够泛化以应对未见过的数据,或者模型只在训练数据上表现良好,而无法处理未见过的数据——换句话说,就是避免过拟合。模型验证还包括识别模型偏差。
-
模型部署:在这个阶段,团队从模型注册表中选取模型,将其打包并部署以供使用。传统的 DevOps 流程可以在这里使用,将模型作为服务提供。在本书中,我们将专注于模型即服务(MaaS),即将模型作为表现性状态转移(REST)服务提供。然而,在某些情况下,模型可以作为库打包,供其他应用程序使用。
-
监控和验证:在这个阶段,模型将持续监控响应时间、预测的准确性,以及输入数据是否与模型训练时的数据相似。我们简要介绍了异常值检测。在实践中,它的运作方式是这样的:假设你已经为公共交通系统的高峰时段空车率训练了一个模型,且模型训练时的数据是市民使用公共交通系统超过一年的数据。数据会存在周末、公共假期和其他事件的变化。现在,假设由于 COVID-19 封锁,所有人都不允许使用公共交通系统。现实世界与我们模型训练时的数据不同。自然地,我们的模型在这种变化的世界中并不是特别有用。我们需要检测这种异常并生成警报,以便在可能的情况下,我们能够使用新的数据集重新训练模型。
你刚刚了解了机器学习项目生命周期的各个阶段。尽管这些阶段看起来很简单,但在现实世界中,确实有一些很好的理由在某些情况下需要回到之前的阶段。
快速反馈循环
一个敏锐的观察者可能已经注意到,在第一章中我们展示的敏捷和跨职能团队的一个关键特征,在本章目前展示的阶段中并没有出现。现代 DevOps 的核心就是快速反馈循环,以便在项目生命周期的早期进行调整。这个概念将为机器学习项目带来更多的价值,因为机器学习项目比传统的软件应用程序更为复杂。
让我们看看在哪些阶段可以评估和衡量团队的进展。评估后,团队可以决定通过回到早期阶段进行调整,或继续推进到下一个阶段。
下图展示了带有各个阶段反馈检查点的机器学习项目生命周期,用绿色箭头表示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_006.jpg
图 2.6 – 带有反馈检查点的机器学习项目生命周期
让我们在这里更详细地看看:
-
数据摄取、清理和标注阶段的检查点:在完成第一阶段后,你已经开始按第二阶段的定义处理数据。你可能会发现实际数据不完整或不正确。你可以根据这些反馈改进对数据的理解,并可能需要重新定义项目的成功标准,或者在最坏的情况下,由于所需的数据不可用而停止项目。在许多场景中,团队会寻找额外的数据来源来填补第二阶段中识别的数据空白。
-
模型构建与调优阶段的检查点:在这个阶段,团队可能会发现用于训练模型的特征不足以获得预期的指标。此时,团队可能会决定花更多时间寻找新特征,或者重新审视原始数据,以确定是否需要更多数据。
-
模型验证阶段的检查点:在这个阶段,模型将针对一个模型从未见过的新数据集进行验证。此时指标较差可能会触发模型的调优,或者你也可以决定回去寻找更多特征,以提升模型的性能。
-
模型监控与验证阶段的检查点:一旦模型进入生产阶段,就必须持续监控,以验证模型是否仍然与现实世界和变化中的世界相关。你需要找出模型是否仍然有效,如果无效,如何使模型变得更有用。这个结果可能会触发生命周期中的其他任何阶段;正如在图 2.6中所看到的,你可能最终会使用新数据重新训练现有模型,或者完全换用不同的模型,甚至重新思考是否应该用机器学习来解决这个问题。没有确定的答案能告诉你最终会到哪个阶段,就像现实世界一样,它是不可预测的。然而,重要的是具备重新评估和重新审视的能力,并持续为业务创造价值。
你已经看到了机器学习项目生命周期的各个阶段以及从这些阶段获得的反馈检查点,决定是否继续推进到下一个阶段或返回上一个阶段。现在,让我们来看看每个阶段涉及的角色以及他们的合作点。
在项目生命周期中的协作
我们已经定义了构建模型的简化流程。让我们尝试定义一个多角色、多能力的团队如何协作完成这个模型。回顾上一章,构建模型需要不同团队成员的共同努力,每个团队成员拥有不同的能力。值得注意的是,在小型项目中,可能同一个人同时扮演不同的角色。例如,在一个小项目中,同一个人既可以是数据科学家,也可以是数据工程师。
以下图表展示了一个带有反馈点和角色重叠的 ML 项目生命周期图:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_007.jpg
图 2.7 – 一个包含反馈检查点和团队角色的 ML 项目生命周期
你们组织中的 ML 项目在第一阶段需要数据科学家与业务领域专家(SMEs)之间的协作。设想一下,团队希望根据一张图片预测某种皮肤病的概率。
-
在这个阶段,数据科学家和医生(在此案例中的业务领域专家)之间需要进行协作,以定义问题和性能指标。没有这种合作,项目将无法成功。
-
在第二阶段——数据摄取和清洗阶段——数据工程师需要与业务领域专家合作,了解哪些数据是可用的,并如何正确地清洗和标注数据。业务领域专家在这个阶段带来的知识至关重要,因为这将负责创建一个有用的数据集,以供后续阶段使用。
-
在第三阶段,数据科学家、数据工程师和业务领域专家将协作处理第二阶段的基础数据,提取有用的特征。数据科学家和业务领域专家将提供有关可以提取哪些数据的指导,数据工程师将编写处理逻辑来实现这一目标。
-
在第四和第五阶段,大部分工作将由数据科学家完成,以根据给定标准构建和调整模型。然而,根据模型是否达到了定义的指标,团队可能会决定返回到任何一个先前的阶段,以提高模型的性能。
一旦模型构建完成,DevOps 团队的专家可以对模型进行打包、版本管理,并将其部署到正确的环境中。
- 最后阶段至关重要:团队利用可观察性功能来监控模型在生产环境中的性能。在监控了模型在实际环境中的表现后,团队可以根据反馈决定是否返回任何前阶段,以使模型对业务更有价值。
现在你已经很好地理解了我们所提到的挑战,以及如何通过机器学习生命周期克服这些挑战,接下来的阶段是要有一个支持这一生命周期的平台,同时为大图中的每个组件提供解决方案(请参见第一章,机器学习中的挑战),并具备自服务和自动化能力。与开源社区合作,开始这段旅程,还有什么比这更好的方式呢?
开源软件在机器学习项目中的角色
现在你已经清楚地了解了机器学习平台需要解决的问题,接下来我们来看一下为什么开源是最好的起点。我们应该从一些定义开始,以便打好基础,对吧?
免费的开源软件(OSS)是指用户有自由运行、复制、分发、研究、修改和改进软件的地方。
开源软件
想了解更多关于开源软件的信息,请参阅以下链接:
www.gnu.org/philosophy/free-sw.html
开源无处不在。Linux 是最常见的操作系统,运行在数据中心并支持全球云计算。Apache Spark 和相关的开源技术是大数据革命的基础,帮助众多组织实现其目标。基于开源的人工智能(AI)技术,如 TensorFlow 和 MLflow,处于 AI 发展的前沿,并被成百上千的组织所使用。开源的容器编排平台 Kubernetes 已经成为容器平台的事实标准。
计算领域的顶级玩家——如亚马逊、苹果、Facebook、谷歌、微软和红帽等——已经为主要开源项目做出贡献并拥有这些项目,而且新的参与者也不断加入。全球各地的企业和政府每天都依赖开源软件来支持关键任务和高可扩展的系统。
云计算领域最成功的开源项目之一就是Kubernetes。Kubernetes 成立于 2014 年中期,2015 年中期发布了它的 1.0 版本。自那时以来,它已成为容器编排的事实标准。
此外,云原生计算基金会(CNCF)是由Linux 基金会创建的,使命是让云计算无处不在。CNCF 通过汇集世界顶级工程师、开发者、终端用户和供应商来实现这一目标。它们还举办世界上最大的开源会议。基金会的创建使用了Kubernetes作为种子项目。正是通过这个项目,Kubernetes 设定了云原生的标准定义。截至本文撰写时,基金会已经有 741 个会员组织,130 个认证的 Kubernetes 发行版和平台,并且已经毕业了 16 个非常成功的开源项目。当然,其中包括Kubernetes,还有Operator Framework,你将在下一章了解更多关于它的内容。
在大数据和云计算爆炸式发展的之前,机器学习(ML)项目主要是学术性质的。它们很少走出高校的范围,但这并不意味着人工智能(AI)、机器学习(ML)和数据科学没有向前发展。学术界实际上已经创造了数百个开源的 Python 库,用于数学、科学和统计计算。这些库已经成为现代机器学习框架的基础。目前最流行的机器学习框架——TensorFlow、PyTorch、scikit-learn 和 Spark ML——都是开源的。如今最流行的数据科学和机器学习开发环境——Jupyter Notebook、JupyterLab、JupyterHub、Anaconda 等——同样都是开源的。
机器学习是一个不断发展的领域,它需要超越任何单一组织的大型社区的愿景。社区合作模式的工作流程能够促进机器学习项目所需的合作与创造力,而开源正是机器学习快速发展的重要原因之一。
现在你已经对开源软件(OSS)在人工智能和机器学习领域的重要性有了基本了解。接下来,让我们更详细地看看为什么你应该在 Kubernetes 上运行机器学习项目。
在 Kubernetes 上运行机器学习项目
为了构建可靠且可扩展的机器学习系统,你需要一个稳固的基础。Kubernetes为构建可扩展且可靠的分布式系统提供了基础,并提供了平台所需的自助服务功能。Kubernetes 能够将硬件基础设施抽象为一个单一的单元进行消费,这对于我们的平台具有巨大的益处。
另一个关键因素是基于 Kubernetes 的软件能够在任何地方运行,从小型本地数据中心到大型超大规模云平台(Amazon Web Services(AWS)、Google Cloud Platform(GCP)、Azure)。这个能力将为你提供在任何你想要的地方运行机器学习平台的可移植性。它带给平台使用者的统一性非常出色,因为团队可以在云上以极低的初始成本进行实验,然后根据企业的更广泛需求定制平台。
选择 Kubernetes 的第三个也是最后一个理由是其能够运行不同类型的工作负载。你可能还记得在前一章中提到的,成功的机器学习项目不仅需要机器学习,还需要基础设施自动化、数据生命周期管理、有状态组件等。Kubernetes 提供了一个一致的基础,可以运行各种类型的软件组件,从而为业务用例创建一个端到端(E2E)的解决方案。
以下截图展示了一个 ML 平台的各个层次。Kubernetes 提供了一个扩展和抽象层,ML 平台就是在这个层次上构建的。Kubernetes 提供了抽象底层基础设施的自由。正因如此,我们可以在各种云服务商和本地解决方案上运行。你将在本书中构建的 ML 平台支持 ML 项目三个更广泛领域的运营化和自助服务——前端(FE)、模型开发和 DevOps:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_02_008.jpg
图 2.8 – 基于开源软件的 ML 平台
就这样:你的 ML 平台将基于开源软件,并使用 Kubernetes 作为托管基础。开源 Kubernetes 社区的力量将帮助你使用最好的技术,而这些技术会随着领域的不断成熟而不断发展。
总结
本章中,我们定义了 MLOps 这一术语,并提出了一个协作型的 ML 项目生命周期,能够提供早期反馈。你已经了解到,通过这个项目生命周期,团队可以持续向业务提供价值。你还了解了为何基于开源软件构建平台是合理的,以及社区驱动软件的好处。
本书的这一部分介绍了设置背景、学习为何需要平台以及探索平台预期解决的各种问题。下一章我们将探讨 Kubernetes 系统的一些基本概念,它是我们 ML 平台的核心。
进一步阅读
有关本章所涵盖主题的更多信息,请查阅以下资源:
- DevOps:打破开发与运维的壁垒
www.atlassian.com/devops
第二章:第三章: 探索 Kubernetes
现在你已经看到,Kubernetes 将成为你在本地计算机或云端的 minikube 实例的基础。这个是一个单节点的 Kubernetes 集群,你将使用它作为构建和运行 ML 平台的基础设施。
我们将按以下顺序覆盖以下主题:
-
探索 Kubernetes 的主要组件
-
通过 Kubernetes 实现云中立性
-
理解操作符(Operators)
-
设置本地 Kubernetes 环境
-
(可选)在谷歌云平台(GCP)上配置虚拟机(VM)
技术要求
本章包括一些动手操作。你将设置一个 Kubernetes 集群,为此,你需要一台符合以下硬件规格的机器:
-
至少四个核心的中央处理单元(CPU);推荐八个核心
-
至少 16 吉字节(GB)的内存;推荐 32 GB
-
至少 60 GB 可用空间的磁盘
这可以是物理机器,如笔记本电脑、服务器,或者是支持嵌套虚拟化的云端虚拟机(VM)。
探索 Kubernetes 主要组件
网络上有许多 Kubernetes 的定义。我们假设,作为 Kubernetes 用户,你已经有了自己偏好的定义。因此,在本节中,你将看到一些基本概念来刷新你对 Kubernetes 的知识。本节绝不是 Kubernetes 系统的参考资料或教程。
从第二章,《理解 MLOps》中,你已经看到 Kubernetes 为你的 ML 平台提供了以下能力:
-
提供声明式的软件组件运行方式:这一能力将帮助你的团队实现自主性。
-
提供硬件资源的抽象层:通过这个能力,你可以在各种硬件上运行 ML 平台,并提供按需的资源调度。
-
提供应用程序接口(API)以进行交互:这将使你能够将自动化引入到运行不同组件的 ML 平台中。
让我们从定义 Kubernetes 平台的主要组件开始:控制平面和工作节点。
控制平面
控制平面是一组组件,构成了 Kubernetes 的大脑。它由 API 服务器、键值数据库、调度器和一组控制器组成。让我们分别定义这些组件:
-
API 服务器:该组件提供了一组表征状态传输(REST)API,用于与 Kubernetes 系统交互。每个人都通过这个 API 与 Kubernetes 进行交互。作为开发人员或运维工程师,你使用 API,而 Kubernetes 内部组件通过 API 服务器进行通信,执行不同的活动。
-
etcd。Kubernetes 系统的其他组件不会直接与这个值存储交互——它只能通过 API 服务器访问。 -
调度器:调度器组件决定应用实例将在哪个节点上运行。调度器根据 Kubernetes 管理员定义的策略选择最合适的工作节点。
-
控制器:控制平面中运行着多个控制器。每个控制器都有一项特定任务;例如,节点控制器负责监控节点的状态。
以下图表显示了多个控制平面组件之间的交互:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_001.jpg
图 3.1 – Kubernetes 控制平面组件
控制平面协调对象的创建、更新和删除。它监控并保持 Kubernetes 集群的健康状态。控制平面运行着保持集群运行的工作负载。那么,应用程序工作负载呢?
工作节点
正如其名称所示,工作节点是一组承载应用软件的节点。例如,所有 ML 平台组件将在工作节点上执行。然而,工作节点还运行一些 Kubernetes 组件,这些组件在控制平面与工作节点之间建立通信通道,并管理在工作节点上运行的应用程序。除应用程序外,这些是运行在工作节点上的关键组件:
-
Kube proxy:其主要作用是管理运行在节点上的应用程序的网络通信规则。
-
Kubelet:可以将 Kubelet 软件组件看作是运行在每个节点上的代理。这个代理的主要作用是与控制平面 API 服务器通信,并管理运行在节点上的应用程序。该代理还会捕获并通过 API 将节点和应用程序的状态反馈给控制平面。
-
容器运行时:容器运行时组件负责按照 Kubelet 的指示运行承载应用程序的容器。Docker 就是其中的一个例子;然而,Kubernetes 定义了容器运行时接口(CRI)。CRI 定义了 Kubernetes 使用的接口,Kubernetes 管理员可以选择与 CRI 兼容的任何容器运行时。
以下图表显示了多个工作节点组件之间的交互:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_002.jpg
图 3.2 – Kubernetes 工作组件
工作节点,也称为计算节点,负责在集群中实际运行应用程序工作负载。运行应用程序工作负载需要你使用 Kubernetes 对象或资源与控制平面进行交互。
运行应用程序所需的 Kubernetes 对象
现在,让我们定义一组在 Kubernetes 系统上运行应用程序时常用的对象。当你为你的 ML 平台构建组件时,你将使用这些 Kubernetes 对象在 Kubernetes 上运行应用程序。以下是这些对象的列表:
-
命名空间:一个 Kubernetes 集群由多个团队和项目共享。命名空间提供了一种隔离 Kubernetes 资源的方式。通过这种隔离,不同的团队、不同的环境,甚至不同的应用程序可以共享同一个集群,同时保持不同的配置、网络策略、资源配额和访问控制。这就像在同一个 Kubernetes 集群内拥有一个逻辑上的子集群。
-
容器镜像:当你想在 Kubernetes 上运行一个应用程序时,你需要将应用程序打包成标准格式。这个打包格式包含了你的应用程序及其所有依赖项,称为容器镜像,而这个镜像的运行实例称为容器。它将你的应用程序及所有依赖项,包括操作系统资源和应用程序所需的资源,打包成一个共同的单元。
-
部署:这个 Kubernetes 对象代表了集群中应用程序的期望状态。一个部署对象包含了诸如你希望运行的容器镜像以及你需要多少个容器实例或副本等信息。Kubernetes 会定期将当前集群状态与部署对象中定义的期望状态进行对比。当 Kubernetes 发现当前状态与期望状态不符时,它会应用必要的更新来使集群达到期望状态。这些更新包括根据部署对象中定义的容器镜像启动新的容器、停止容器以及配置部署对象所需的网络和其他资源。
-
Pod:Pod 是 Kubernetes 中运行应用程序的基本单元。它也是最小的可调度部署单元。Pod 可以包含一个或多个容器。Pod 内的容器共享网络和磁盘资源。运行在同一个 Pod 中的容器会一起调度到同一个节点,并且能够彼此进行本地通信。
-
服务:Pod 之间是如何通信的呢?Pod 通过集群网络进行通信,每个 Pod 都有自己的互联网协议(IP)地址。然而,Pod 是可能会变动的。Kubernetes 可能会因为节点健康状况或调度变化而重启一个 Pod,当这种情况发生时,Pod 的 IP 地址会发生变化。此外,如果部署对象配置为运行多个相同 Pod 的副本,这意味着每个副本都会有自己的 IP 地址。
在 Kubernetes 中,服务将一组 Pod 暴露为一个抽象的网络服务。它提供一个一致的 IP 地址和域名系统(DNS)名称,可以对 Pod 进行流量路由并执行负载均衡。可以把服务看作是一个负载均衡的反向代理,指向你正在运行的 Pod。
- 配置映射和密钥:我们将应用程序打包成容器镜像并作为 pod 运行。相同的 pod 将在多个环境中部署,例如开发环境、测试环境和生产环境。然而,每个环境将有不同的配置,比如数据库位置等。将这种配置硬编码到容器镜像中不是正确的做法。一个原因是容器镜像可能会在多个环境中部署,而这些环境的设置是不同的。必须有一种方法可以在容器镜像之外定义配置,并在运行时将该配置注入到容器中!
配置映射和密钥提供了一种在 Kubernetes 中存储配置信息的方式。一旦定义了这些对象,它们可以作为文件或一组环境变量注入到运行中的 pod 中。
配置映射(ConfigMap)用于存储和访问配置信息。然而,对于敏感的配置,如密码和私钥,Kubernetes 提供了一种特殊的对象来处理这些内容,称为密钥(Secret)。与配置映射类似,密钥也可以作为文件或环境变量挂载到 pod 中。
下图展示了部署、pod、配置映射和服务之间的逻辑关系。部署对象提供了一个容器化应用程序的抽象,它隐藏了运行副本控制器和 pod 的复杂性。部署帮助你将应用程序作为单个 pod 或 pod 组运行,配置映射为你的 pod 提供环境特定的配置,而服务将部署中的 pod 作为一个单一的网络服务暴露出来:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_003.jpg
图 3.3 – Kubernetes 中的存储配置
- 存储(持久卷和持久卷声明(PV 和 PVC)):Pod 是短暂的。一旦它们被销毁,所有本地资源都会丧失。通常,作为 pod 部署的应用程序可能需要访问存储,以读取和写入能够超越 pod 存活周期的持久数据。
Kubernetes 承诺成为许多硬件供应商和云提供商之上的基础设施抽象层。然而,不同云提供商和本地系统请求存储资源或配置磁盘的方式是不同的。这要求在不同的硬件供应商和云提供商之间以一致的方式请求存储资源。
Kubernetes 的解决方案是将存储资源分为两个 Kubernetes 对象。持久卷(PV)是定义物理存储卷的对象。它包含底层存储基础设施的详细信息。而持久卷声明(PVC)则是一个抽象的指针,指向一个 PV。PVC 表明所有者对特定 PV 的占用权。pod 的存储资源与 PVC 相关联,而不是直接与 PV 相关联;通过这种方式,底层存储定义从应用程序中抽象出来。
下图显示了 pod、PVC 和 PV 之间的关系。Pod 将 PVC 作为卷挂载;PVC 作为一个抽象层,用于为 pod 请求与 pod 关联的物理卷;PVC 绑定到提供磁盘具体信息的 PV:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_004.jpg
图 3.4 - Kubernetes 中的存储供给(续)
- Ingress:服务允许从 Kubernetes 集群内访问 pod。对于需要从 Kubernetes 集群外部访问 pod 的场景,Ingress 是答案。Ingress 提供了一种方式,使您可以将特定服务暴露给从集群外部访问的方式。这使您可以映射指向服务的基于 HTTP 的 URL。Ingress 还可以在暴露的 URL 上使用 SSL,并可以配置终止集群内部流量的 SSL。这样,传输层将在整个到达 Ingress 的过程中加密,同时将流量转发到 pod 中的明文 HTTP。值得注意的是,如果需要,Kubernetes 还允许流量加密一直到 pod。
下图显示了 Ingress 如何使 pod 可以从 Kubernetes 集群外部访问:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_005.jpg
图 3.5 - Kubernetes 集群中的 Ingress 对象
现在您已经刷新了对 Kubernetes 的理解,让我们看看 Kubernetes 如何让您在任何地方运行您的平台。
通过 Kubernetes 实现云无关性
我们正在构建的 ML 平台的一个关键方面是,它使组织能够在任何云或数据中心上运行。然而,每个云都有自己专有的 API 来管理资源和部署应用程序。例如,亚马逊网络服务(AWS)API 在提供服务器时使用 弹性计算云(EC2)实例(即服务器),而谷歌云的 API 则使用 Google 计算引擎(GCE)虚拟机(即服务器)。甚至资源的名称也不同!这就是 Kubernetes 发挥关键作用的地方。
Kubernetes 的广泛采用迫使主要云供应商提供与 Kubernetes 紧密集成的解决方案。这使任何人都可以在几分钟内在 AWS、GCP 或 Azure 上创建一个 Kubernetes 集群。
Kubernetes API 允许您管理云资源。使用标准 Kubernetes API,您可以在任何主要云提供商上部署应用程序,而无需了解云提供商的 API。Kubernetes API 已经成为在云中管理工作负载的抽象层。本书中将构建的 ML 平台将完全使用 Kubernetes API 来部署和运行应用程序。这包括构成 ML 平台的软件组件。
下图展示了 Kubernetes 如何帮助你实现云无关性。你通过 Kubernetes API 与 Kubernetes 交互,从而避免或减少直接与云提供商 API 的交互。换句话说,Kubernetes 提供了一种一致的方式来与环境交互,无论它运行在哪个云平台或数据中心:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_006.jpg
图 3.6 – Kubernetes 作为云提供商 API 的适配层
另一个 Kubernetes 社区推出的重要概念是 操作员。你将使用 Kubernetes 操作员来部署大多数机器学习平台的组件。我们来深入了解一下。
了解操作员
在传统的信息技术(IT) 组织中,需要专门的团队来维护应用程序和其他软件组件,如数据库、缓存和消息组件。这些团队不断监控软件生态系统,并执行特定任务,例如备份数据库、升级和修补软件组件的新版本等。
操作员就像系统管理员或工程师一样,持续监控 Kubernetes 环境中运行的应用程序,并执行与特定组件相关的运维任务。换句话说,操作员是一个自动化的软件管理器,负责管理 Kubernetes 上应用程序的安装和生命周期。
简而言之,操作员负责基于你提供的配置来创建和更新 Kubernetes 对象(如部署、入口等),而不是你自己来执行这些任务。指示操作员执行特定任务的配置叫做 自定义资源 (CR),而 CR 的结构或模式由一个叫做 CR 定义 (CRD) 的对象来定义。
下图展示了操作员如何自动化应用程序的运维活动。在传统的方法中,开发人员构建和开发应用程序,然后由应用运维团队提供支持以运行该应用程序。Kubernetes 操作员的目标之一是自动化运维人员执行的任务:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_007.jpg
图 3.7 – 操作员是一种自动化运维团队任务的软件
Kubernetes 操作员可能很复杂。有些操作员管理数据库实例,而有些则管理协同工作的 Pod 集群。一些操作员只拥有 1 或 2 个 CRD,而另一些则可能拥有超过 10 个 CRD。操作员生命周期管理器 (OLM) 简化了 Kubernetes 操作员的安装和管理。我们来更深入地了解一下。
在 OLM 中,安装 Operator 需要多个步骤:为 Operator 创建部署对象,配置运行 Operator 所需的权限(因为它需要观察 Kubernetes 集群中的变化),以及创建 CRD。为了减少安装 Operator 的复杂性,可能需要一个管理层来帮助完成这些任务。OLM 就是完成这个角色的工具。
OLM 标准化了与 Operators 的交互。它要求所有与 Operator 的交互都通过 Kubernetes API 完成。OLM 使得通过单一标准接口——Kubernetes API 来管理多个 Operator 的生命周期变得更加简单。我们的 ML 平台将使用几个 Operators,因此了解 OLM 和与之相关的对象是很有用的。让我们在这里更详细地了解它们:
-
ClusterServiceVersion:此对象定义了有关 Operator 的元数据。它包括 Operator 的名称和版本,以及安装信息和所需权限。它还描述了 Operator 所拥有和所需的 CRD。 -
Subscription:Subscription对象允许用户安装和更新 Operator。OLM 使用此对象来安装和配置 Operators、CRDs 以及相关的访问控制对象。 -
OperatorGroup:OperatorGroup提供了一种将您的 Operator 与特定命名空间集合关联的方法。OperatorGroup定义了一组命名空间,关联的 Operator 将对这些命名空间作出反应。如果我们在OperatorGroup定义中没有定义命名空间集合,那么 Operator 将在所有命名空间中全局运行。
在接下来的章节中,您将安装和配置本地的 Kubernetes 环境,并在 Kubernetes 集群上安装 OLM。
设置本地 Kubernetes 环境
现在,我们已经回顾了一些基础的 Kubernetes 概念,是时候开始实际操作了。在这一章节中,我们将准备并验证我们的本地 Kubernetes 集群。我们在这里设置的集群将用于在后续章节中托管 ML 平台。
安装 kubectl
kubectl 是一个命令行工具,帮助您在 Kubernetes 集群中运行命令。您可以通过这个工具创建 Kubernetes 对象、查看日志并监控操作进展。以下步骤将帮助您在机器上安装 kubectl。
在 Linux 上安装 kubectl
首先,让我们看看在运行 Linux 的机器上安装 kubectl 的过程。请按照以下步骤操作:
-
创建或 安全外壳(SSH)到您 Linux 计算机的终端会话。
-
下载
kubectl。本书中使用的 Kubernetes 版本为1.22.4。以下两行代码是一条命令:curl -LO https://dl.k8s.io/release/v1.22.4/bin/linux/amd64/kubectl -
通过运行以下命令安装
kubectlCLI:sudo install kubectl /usr/local/bin/kubectl -
通过运行以下命令验证它是否已安装:
kubectl version --client
您应该看到以下对 version 命令的响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_008.jpg
图 3.8 – 在 Linux 中运行 kubectl version 命令的输出
现在你应该能够在 Linux 机器上运行 kubectl。
在 macOS 上安装 kubectl
首先,让我们了解在运行 macOS 的机器上安装 kubectl 的过程。请按照以下步骤操作:
-
在你的 Mac 电脑上创建或
SSH到一个终端会话。 -
下载
kubectlKubernetes CLI。本书中将使用 1.22.4 版本。
对于 Intel Mac,运行以下命令:
curl -LO https://dl.k8s.io/release/v1.22.4/bin/darwin/amd64/kubectl
对于 Apple M1 Mac,运行以下命令:
curl -LO https://dl.k8s.io/release/v1.22.4/bin/darwin/aa64/kubectl
-
运行以下命令安装
kubectlCLI:sudo install kubectl /usr/local/bin/kubectl -
通过运行以下命令验证是否已安装:
kubectl version --client
你应该看到以下对 version 命令的响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_009.jpg
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_009.jpg)
图 3.9 – macOS 中 kubectl version 命令的输出
现在你应该能够在 macOS 上运行 kubectl。
在 Windows 上安装 kubectl
接下来,让我们了解 Windows 系统上的步骤:
-
以 管理员 身份运行 PowerShell。
-
通过运行以下命令下载
kubectlKubernetes CLI 二进制文件。本书中将使用 1.22.4 版本:curl.exe -LO https://dl.k8s.io/release/v1.22.4/bin/windows/amd64/kubectl.exe -
通过运行以下命令,将
kubectl.exe文件复制到c:\kubectl:mkdir c:\kubectl copy kubectl.exe c:\kubectl -
通过运行以下命令将
c:\kubectl添加到PATH环境变量中,然后重新启动 PowerShell 终端:setx $ENV:PATH "$ENV:PATH;C:\kubectl" /M -
通过运行以下命令验证是否已安装:
kubectl version –client
你应该看到以下对 version 命令的响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_010.jpg
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_010.jpg)
图 3.10 – Windows 中 kubectl version 命令的输出
你刚刚安装了 kubectl Kubernetes CLI。下一步是安装 minikube,一个本地单节点 Kubernetes 集群。
安装 minikube
minikube 提供了一种轻松运行本地 Kubernetes 集群的方法。这是一个最小化的集群,旨在仅用于本地开发或实验。将 Kubernetes 用于生产环境超出了本书的范围。
与kubectl类似,接下来让我们了解如何在不同类型的操作系统上进行安装。
在 Linux 上安装 minikube
按照以下步骤在 Linux 上安装 minikube:
-
创建一个终端会话或通过
SSH连接到你的 Linux 计算机。 -
使用以下代码为
minikube安装podman:sudo dnf install podman -y -
从此位置下载
minikube。我们使用的是minikube的1.24.0版本:curl -LO https://storage.googleapis.com/minikube/releases/v1.24.0/minikube-linux-amd64 -
按照以下步骤安装
minikube工具:sudo install minikube-linux-amd64 /usr/local/bin/minikube -
验证
minikube版本,如下所示:minikube version
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_011.jpg
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_011.jpg)
图 3.11 – Linux 上 minikube version 命令的输出
你刚刚在 Linux 上安装了 kubectl 和 minikube。这两个命令行工具将帮助你设置一个本地 Kubernetes 集群。
在 macOS 上安装 minikube
虽然本书的首选操作系统是 Linux,但我们也提供了如何在 macOS 上安装 minikube 的步骤。很多开发者使用 macOS 系统,因此提供 Apple 操作系统的详细步骤也会很有帮助。接下来的步骤如下:
-
从 Docker 官网下载并安装 Docker Desktop,或者通过访问以下网页进行下载:
www.docker.com/products/docker-desktop。 -
一旦 Docker 安装完成,确保通过运行以下命令来验证其是否正确安装。运行此命令前,请确保 Docker 已经启动:
docker version
你应该看到以下响应。如果收到错误信息,请确保 Docker 已经启动:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_012.jpg
图 3.12 – macOS 上执行 docker version 命令的输出
-
在 macOS 计算机上打开一个终端。
-
通过运行以下命令之一来下载
minikube。你将使用版本 1.24.0 的 Minikube:-
如果你使用的是 Intel Mac,请运行以下命令:
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v1.24.0/minikube-darwin-amd64 -
如果你有 M1 Mac(Apple Silicon),请运行以下命令:
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v1.24.0/minikube-darwin-arm64
-
-
将下载的文件移动到
/usr/local/bin文件夹,并通过以下命令将下载的文件设为可执行文件:sudo mv minikube /usr/local/bin sudo chmod +x /usr/local/bin/minikube -
验证
minikube版本,方法如下:minikube version
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_013.jpg
图 3.13 – minikube version 命令的输出
你刚刚在 macOS 上安装了 kubectl 和 minikube。这两个命令行工具将帮助你设置本地 Kubernetes 集群。
在 Windows 上安装 minikube
和 macOS 一样,许多开发者也使用 Windows。为 Microsoft 的强大操作系统 Windows 提供操作步骤是公平的。我们来探讨一下如何在 Windows 上使用 Hyper-V,Microsoft 的虚拟化层,来运行 minikube。请注意,Hyper-V 在除 Windows Home 外的所有 Windows 版本中均可用。按照以下步骤操作:
-
以 管理员 身份运行 PowerShell。
-
在 PowerShell 控制台中,运行以下命令以启用
Hyper-V:Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V --All
如果 Hyper-V 未启用,你应该看到以下响应。如果已经启用,该命令将仅打印状态。按 Y 继续:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_014.jpg
图 3.14 – Windows 上启用 Hyper-V 命令的输出
如有需要,请重启计算机。
-
通过在浏览器中打开以下链接来下载
minikube安装程序:github.com/kubernetes/minikube/releases/download/v1.24.0/minikube-installer.exe。 -
运行已下载的安装程序,你应该会看到语言设置界面,如下图所示。点击 OK:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_015.jpg
图 3.15 – minikube 安装程序的语言选择对话框
- 安装程序将显示以下欢迎界面。点击下一步 >,如下面的截图所示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_016.jpg
图 3.16 – minikube 安装程序向导
- 安装程序将显示以下许可协议界面。点击我同意:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_017.jpg
图 3.17 – minikube 安装程序的许可协议界面
- 在此界面中,选择你希望安装
minikube的位置,然后点击安装,如下面的截图所示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_018.jpg
图 3.18 – minikube 安装程序的安装位置界面
- 安装可能需要几分钟时间。一旦安装成功,你应该看到以下界面。点击下一步 >:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_019.jpg
图 3.19 – minikube 安装程序的成功安装界面
- 这是你
minikube设置过程中的最后一个界面。点击完成以结束设置:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_020.jpg
图 3.20 – minikube 安装程序的最终界面
-
最后,在 PowerShell 控制台中,将
minikube的虚拟化驱动程序设置为hyperv。你可以通过运行以下命令来完成:minikube config set driver hyperv
你应该会看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_021.jpg
图 3.21 – minikube 配置命令的输出
恭喜你——你已经在 Windows 机器上成功设置了minikube程序!
在前面的章节中,你已经安装了kubectl和minikube工具以设置 Kubernetes 集群。在接下来的章节中,你将设置一个 Kubernetes 集群。
设置本地 Kubernetes 集群
现在,我们将在你的本地机器上设置 Kubernetes 集群。如技术要求中所述,我们需要至少 4 个 CPU 核心或虚拟 CPU(vCPUs)、60GB 的可用磁盘空间,并且至少需要分配 16GB 内存给 Kubernetes 集群。我们推荐的配置是 8 个 CPU 和 64GB 内存,并配备 60GB 磁盘空间。如果你本地没有这些资源,你可以在云中提供一个 Linux 主机。我们将在下一节中描述如何在 Google Cloud 上提供主机。请按以下步骤继续:
-
通过以下命令设置
minikube的 CPU、磁盘和内存配置:minikube config set cpus 8 minikube config set memory 32GB minikube config set disk-size 60GB -
通过以下命令验证配置是否正确设置:
minikube config view
你应该会看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_022.jpg
图 3.22 – minikube 配置命令的输出
-
现在,通过运行以下命令启动 Kubernetes 集群:
minikube start --kubernetes-version=1.22.4
你应该会看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_023.jpg
图 3.23 – minikube start 命令的部分输出
一旦启动过程完成,Kubernetes 平台可用后,你应该看到类似于以下的成功消息:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_024.jpg
图 3.24 – minikube 启动成功后的输出
-
通过在 Linux 或 macOS 上运行以下命令验证所有 pods 是否处于 运行中 状态。请注意,pods 可能需要几分钟才能处于 运行中 状态:
watch kubectl get pods --all-namespaces
或者,在 Windows PowerShell 中运行以下命令:
while (1) {kubectl get pods --all-namespaces; sleep 5}
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_025.jpg
图 3.25 – 验证 Kubernetes pods 已成功启动
恭喜!你刚刚成功安装并验证了新的 Kubernetes 集群。接下来的步骤是安装可以在新 Kubernetes 集群上运行的组件。
安装 OLM
在验证所有 pods 已在本地 Kubernetes 集群中运行后,你将安装 OLM。在 Kubernetes 中安装 OLM 或任何其他应用程序的过程对于所有操作系统类型都是相同的。按照以下步骤进行:
-
运行以下命令安装 OLM 的 CRD:
kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.19.1/crds.yaml
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_026.jpg
图 3.26 – 验证 OLM CR 已成功创建
-
运行以下命令在 Kubernetes 上安装 OLM:
kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.19.1/olm.yaml
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_027.jpg
图 3.27 – 在 Kubernetes 中创建 OLM 对象
-
通过在 Linux 或 macOS 上运行以下命令验证所有 OLM pods 是否处于 运行中 状态:
watch kubectl get pods -n olm
或者,在 Windows PowerShell 中运行以下命令:
while (1) {kubectl get pods -n olm; sleep 5}
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_028.jpg
图 3.28 – 验证 OLM 的资源已成功创建
-
通过发出以下命令验证
catalogsource是否可用:kubectl get catalogsource -n olm
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_029.jpg
图 3.29 – 验证 Operator 目录已安装
恭喜!你现在已经在本地运行了一个 Kubernetes 集群,并在其中安装了 OLM。你的集群现在准备好安装 Kubernetes Operators。一些人可能没有访问到满足 ML 平台运行所需最低硬件要求的机器,但不用担心——我们会为你提供帮助。接下来的部分将帮助你在 Google Cloud 中配置所需的虚拟机。
在 GCP 上配置虚拟机
最好能有一个本地环境,以便你能在其中进行本书的练习。然而,我们理解并非每个人的本地机器都具备所需的计算资源。那么,来使用云吧!你可以在云中按需配置适合本书练习的机器,而且是免费的。例如,Google Cloud 会为新账户提供 300 美元(USD)的信用额度。其他云服务提供商,如 AWS 和 Azure,也提供类似的免费套餐,具体选择哪个云服务商由你决定。然而,关于本书中所需的虚拟机配置,我们将使用 Google Cloud。
一旦你整理好账户信息,按照以下步骤在你的账户中配置虚拟机。只需记住,在完成会话后停止虚拟机实例,以避免在不使用机器时仍然被收费。
以下步骤将指导你通过 Google Cloud 配置虚拟机的过程:
-
首先,在
cloud.google.com注册一个新账户。 -
按照
cloud.google.com/sdk/docs/install上的步骤安装gcloud软件开发工具包(SDK)。 -
使用以下命令登录 Google Cloud。该命令将打开一个浏览器实例,在其中输入你的 Google Cloud 账户登录凭据:
gcloud auth login
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_030.jpg
图 3.30 – 登录命令的输出
- 然后,它会带你到浏览器,你需要在浏览器中进行身份验证。浏览器完成身份验证后,你将在命令行看到以下输出:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_031.jpg
图 3.31 – 成功登录 gcloud 账户后的输出
-
在 Google Cloud 中创建一个新项目,如下所示。你的虚拟机将属于此项目。请注意,项目名称在 GCP 中必须是全局唯一的,因此请根据个人喜好修改项目名称:
gcloud projects create mlops-kube --name="MLOps on Kubernetes"
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_032.jpg
图 3.32 – 创建项目命令在 Google Cloud 中的输出
GCP 中的项目
项目 mlops-kube。为使该命令生效,请选择你自己的项目名称。你还需要在后续的命令中使用你选择的项目名称,而不是 mlops-kube 项目名称。
-
通过执行以下命令,确保你在正确的项目中:
gcloud config set project mlops-kube
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_033.jpg
图 3.33 – 设置当前项目上下文命令的输出
-
根据你的所在位置设置正确的区域和可用区。你可以通过
gcloud compute zones list命令获取所有可用区的列表,如下所示:gcloud config set compute/region australia-southeast1
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_034.jpg
图 3.34 – 设置 gcloud 区域后的输出
运行以下命令:
gcloud config set compute/zone australia-southeast1-a
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_035.jpg
图 3.35 – 设置 gcloud 区域后的输出
-
启用计算引擎 API,如下所示。此步骤是通过 API 提供 Linux 虚拟机所必需的:
gcloud services enable compute.googleapis.com -
禁用 OS 登录,因为你只通过 SSH 连接,如下所示:
gcloud compute project-info add-metadata --metadata enable-oslogin=FALSE -
现在,通过运行以下命令在此项目中创建一个虚拟机(VM):
gcloud compute instances create mlopskube-cluster --project=mlops-kube --zone=australia-southeast1-a --machine-type=c2-standard-8 --network-interface=network-tier=PREMIUM,subnet=default --maintenance-policy=MIGRATE --service-account=702800110954-compute@developer.gserviceaccount.com --scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append --create-disk=auto-delete=yes,boot=yes,device-name=instance-1,image=projects/centos-cloud/global/images/centos-8-v20211105,mode=rw,size=80,type=projects/mlops-kube/zones/australia-southeast1-b/diskTypes/pd-balanced --no-shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring --reservation-affinity=any
命令的输出应该显示机器的详细信息,如下所示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_036.jpg
图 3.36 – 在 Google Cloud 上创建 VM 命令的输出
-
添加防火墙规则,允许通过端口
22进行 SSH 访问实例,如下所示。这是一个宽松的规则,不应在生产环境中使用:gcloud compute --project=mlops-kube firewall-rules create allow22 --direction=INGRESS --priority=1000 --network=default --action=ALLOW --rules=tcp:22 --source-ranges=0.0.0.0/0
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_037.jpg
图 3.37 – 防火墙规则命令的输出
-
使用
gcloudSSH 功能连接到机器,如下所示。这将给你命令行,你可以执行前面章节中提到的 Kubernetes 命令:gcloud beta compute ssh --zone "australia-southeast1-a" "mlopskube-cluster" --project "mlops-kube" -
完成会话后,请删除实例,如下所示:
gcloud compute instances delete --zone "australia-southeast1-a" "mlopskube-cluster" --project "mlops-kube"
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_03_038.jpg
图 3.38 – 在 Google Cloud 上删除机器
此时,你可以使用这个 gcloud 虚拟机作为 Kubernetes 集群的主机。按照之前的章节,你现在应该知道如何安装 kubectl 和 minikube,以及如何在这个虚拟机上设置本地 Kubernetes 集群。
总结
在本章中,你回顾了一些基础的 Kubernetes 概念,并了解了 Kubernetes 生态系统中的 Operator。如果你想深入了解 Kubernetes,*Packt 出版社的《Kubernetes Workshop》*是一个不错的起点。
你已经安装了设置本地 Kubernetes 集群所需的工具。你已经看过在其他环境(如 Linux、macOS 和 Windows)中进行设置的说明。你已经在 Google Cloud 上设置了一个虚拟机(VM),以防你不想使用本地计算机进行练习。你已配置 OLM 来管理 Kubernetes 集群上的操作员(Operators)。这些技术将构成我们机器学习平台的基础设施,接下来的章节你将开始构建这个平台。
第二部分:MLOps 平台的构建模块以及如何在 Kubernetes 上构建一个
本部分深入定义了 MLOps 解决方案的不同组件。各章节详细介绍了每个组件及其所服务的目的。本节还提供了一个 OSS 解决方案,可以在 MLOps 平台中扮演每个组件的角色。
本部分包括以下章节:
-
第四章*,机器学习平台的构成*
-
第五章*,数据工程*
-
第六章*,机器学习工程*
-
第七章*,模型部署与自动化*
第三章:第四章:机器学习平台的构成
在这一章及接下来的几章中,你将学习并安装构建在 Kubernetes 上的机器学习(ML)平台的各个组件。一个 ML 平台应当能够提供运行 ML 项目全生命周期所需的工具,如第二章《理解 MLOps》中所描述的那样。本章首先从技术无关的角度定义了 ML 平台的不同组件。在后续部分,你将看到一组开源软件,能够满足每个组件的要求。我们选择这种方式,是为了不将你束缚于特定的技术栈;相反,你可以根据自己的环境需要替换组件。
你将在本书中构建的解决方案将基于开源技术,并托管在你在第三章《探索 Kubernetes》中构建的 Kubernetes 平台上。
在本章中,你将学习以下主题:
-
定义自助平台
-
探索数据工程组件
-
探索 ML 模型生命周期组件
-
解决安全性、监控和自动化问题
-
探索 Open Data Hub
技术要求
本章包括一些实践设置。你将需要一个配置了操作符生命周期管理器(OLM)的运行中 Kubernetes 集群。如何构建这样的 Kubernetes 环境已在第三章《探索 Kubernetes》中介绍。在尝试本章的技术练习之前,请确保你有一个正在工作的 Kubernetes 集群。你可以选择使用与第三章《探索 Kubernetes》中描述的不同版本的 Kubernetes,只要该集群安装了 OLM。
定义自助服务平台
自助服务被定义为平台的一种能力,允许平台终端用户按需提供资源而无需其他人工干预。例如,数据科学家用户可能需要一个 Jupyter notebook 服务器实例,运行在一个具有 8 个 CPU 的主机容器上,以执行他的/她的工作。一个自助式的 ML 平台应当允许数据科学家通过一个终端用户友好的界面,提供容器并运行 Jupyter notebook 服务器实例。另一个自助服务的例子是,数据工程师请求提供一个新的 Apache Spark 集群实例,以运行他的/她的数据管道。最后一个例子是数据科学家希望将其 ML 模型打包并作为 REST 服务进行部署,以便应用程序可以使用该模型。
自助服务平台的一个好处是,它允许跨职能团队以最小的依赖关系共同工作。这种独立性带来了更好的团队动态、更少的摩擦和更高的团队速度。
然而,自服务模型需要治理。试想,每个数据科学家都请求 GPU,或者数据工程师请求数十 TB 的存储!自服务功能非常好,但如果没有适当的治理,也可能带来问题。为了避免此类问题,平台必须由平台团队进行管理,团队可以控制或限制最终用户的操作。资源配额就是这种限制的一个例子。团队和/或个人用户可以分配配额,并负责在分配的配额范围内管理自己的资源。幸运的是,Kubernetes 具有这种能力,我们的机器学习平台可以利用此能力为团队的资源应用限制。
作为治理的一部分,平台必须具备基于角色的访问控制。这是为了确保只有具有适当角色的用户才能访问他们管理的资源。例如,平台团队可以更改资源配额,而数据工程师只能启动新的 Spark 集群并运行数据管道。
自服务平台的另一个方面是工作负载的隔离。许多团队将共享同一个平台,尽管配额将使团队保持在预定义的边界内,但至关重要的是,平台必须具备隔离工作负载的能力,以确保在同一平台上运行的多个不相关的项目不会重叠。
探索数据工程组件
在本书的上下文中,数据工程是指从源系统中摄取原始数据,并生成可用于分析、业务报告和机器学习等场景的可靠数据的过程。数据工程师是构建软件来收集和处理原始数据,从而为数据分析师和数据科学家生成干净且有意义的数据集的人。这些数据集将成为组织机器学习计划的基础。
图 4.1 展示了典型的机器学习项目中数据工程阶段的各个步骤:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_001.jpg
图 4.1 – 机器学习中的数据工程阶段
数据工程通常与特征工程有交集。虽然数据科学家决定哪些特征对机器学习用例更有用,但他或她可能会与数据工程师合作,以获取当前特征集中没有的数据点。这是数据工程师与数据科学家之间的主要合作点。数据工程师在数据工程阶段创建的数据集将成为机器学习阶段中的特征集。
一个支持团队进行特征工程的机器学习平台将包含以下组件和过程。
- 数据摄取:数据摄取是团队理解数据源并构建和部署收集来自一个或多个数据源的数据的软件的过程。数据工程师理解从源系统读取数据的影响。例如,在从源读取数据时,源系统的性能可能会受到影响。因此,机器学习平台必须具备工作流调度功能,以便在源系统不太活跃的时间安排数据收集。
一个机器学习平台使团队能够以多种方式从各种来源摄取数据。例如,某些数据源允许拉取数据,而其他数据源可能允许推送数据。数据可能来自关系型数据库、数据仓库、数据湖、数据池、数据流、API 调用,甚至是原始文件系统。平台还应具备理解不同协议的能力,例如,一个消息系统可能有多种协议,如高级消息队列协议(AMQP)、消息队列遥测传输(MQTT)和 Kafka。换句话说,机器学习平台应该具备从不同类型的数据源以各种方式收集不同形状和大小的数据的能力。图 4.2展示了平台应该能够摄取的各种数据来源:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_002.jpg
图 4.2 – 数据摄取集成
-
数据转换:一旦数据从各种来源摄取,它需要从原始形式转化为对机器学习模型训练和其他应用场景更有用的形式。根据福布斯的一项调查,80%的数据科学家工作都与为模型训练准备数据相关;这通常是数据科学团队中被认为最枯燥的阶段。然而,如果数据没有转换为合适的形式,它将导致不那么有用和/或低效的机器学习模型。一个机器学习平台使团队能够轻松编写、构建和部署数据转换管道和作业。该平台抽象了运行和管理数据转换组件(如 Apache Spark 作业)的复杂性。平台不仅管理这些过程的执行,还管理运行这些组件所需的计算资源(如 CPU、内存和网络)的供应和清理。
-
存储:在特征工程过程中,您将在各个阶段读取和写入数据。您可能会创建数据集的临时表示以进行进一步处理,或者您可能会写入新数据集以供机器学习过程使用。在这些情况下,您将需要可以轻松访问并根据需要扩展的存储资源。一个机器学习平台提供按需存储,确保您的数据集能够以可靠的方式存储。
现在,让我们看看数据工程师将如何在他们的工作流中使用这些组件。
数据工程师工作流
前一节中提到的所有功能都由机器学习平台以自服务的方式提供。数据工程师在使用平台时通常会执行的工作流如下:
-
登录平台:在此步骤中,数据工程师进行平台身份验证。
-
配置开发环境:在此步骤中,数据工程师向平台请求开发环境所需的资源(如 CPU 数量、内存大小和特定的软件库)。平台随后会自动配置所请求的资源。
-
构建数据管道:在此步骤中,数据工程师编写用于数据摄取和数据转换的代码。然后,数据工程师将在隔离环境中运行代码,验证其有效性,并进行必要的重构和调优。
-
运行数据管道:在此步骤中,数据工程师按需安排代码运行。可以根据使用场景选择定期运行(如每小时或每日)或一次性运行。
从前面的步骤中可以看到,除了编写代码,其他所有步骤都是声明性的。数据工程师的重点将放在构建用于摄取和转换数据的代码上。流程的其他方面将由机器学习平台负责。这将提高团队的效率和工作速度。平台的声明式功能将帮助团队在整个组织内标准化流程,从而减少定制工具链的数量,并提升整体流程的安全性。
数据工程流程的主要输出是一个可用的、已转换并部分清理的数据集,可以用来开始构建和训练模型。
探索模型开发组件
一旦清理后的数据可用,数据科学家将对问题进行分析,尝试确定哪些模式对于该情况有帮助。关键是数据科学家的主要职责是从数据中找出模式。机器学习平台的模型开发组件会探索数据模式、构建和训练机器学习模型,并试验多种配置,找到最佳的配置和算法,以实现模型所需的性能。
在模型开发过程中,数据科学家或机器学习工程师基于多个算法构建多个模型。这些模型将使用数据工程流程中收集和准备的数据进行训练。数据科学家接着会调整几个超参数,通过模型测试得到不同的结果。然后,这些训练和测试的结果将与其他模型进行比较。这些实验过程将重复多次,直到达到预期的结果。
实验阶段将导致选择最合适的算法和配置。选定的模型将被标记以便打包和部署。
图 4.3 显示了机器学习项目中模型开发的各个阶段:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_003.jpg
图 4.3 – 机器学习数据工程阶段
一个能够支持团队进行模型开发的机器学习平台将包含以下组件:
-
数据探索:我们人类在数据可视化时比仅仅查看原始数据集时更擅长发现模式。机器学习平台使你能够可视化数据。作为数据科学家,你需要与领域专家(SMEs)合作,后者拥有专业知识。假设你正在分析一组冠状病毒患者的数据集。如果你不是病毒学或医学领域的专家,你将需要与一个能够提供关于数据集、特征关系以及数据质量的见解的领域专家合作。机器学习平台允许你将自己创建的可视化图表分享给更广泛的团队,以便获得更好的反馈。平台还允许非技术人员以更图形化的方式查看数据,这有助于他们更好地理解数据。
-
实验:作为数据科学家,你将把数据分为训练集和测试集,然后开始为给定的指标构建模型。接下来,你将尝试多种机器学习算法,如决策树、XGBoost 和深度学习,并为每个算法应用不同的参数调优,例如深度学习模型中的层数或神经元数量。这就是我们所说的实验,平台使团队能够以自主的方式进行实验。请记住,对于每个实验,你可能需要不同的计算资源,如 GPU。因此,平台的自助服务配置能力至关重要。
-
跟踪:在进行多个实验时,你需要跟踪每个实验使用的参数以及它所取得的指标。一些算法可能需要不同的特征集,这意味着你还需要跟踪在训练中使用的数据集版本。这样做有两个原因。第一个原因是,你将需要保留实验历史,以便进行比较并挑选最佳组合。第二个原因是,你可能需要将结果与其他数据科学家共享。机器学习平台使你能够记录实验结果并无缝共享。
-
模型构建与调优:在实验阶段,你已经找到了最佳的算法和最佳参数。你已比较了模型的结果和相关指标,并选择了用于模型的算法和参数。在这个阶段,你将使用这些参数训练你的模型,并将其注册到模型注册表中:
- 模型注册表:作为数据科学家,当你对模型感到满意时,你将与团队一起部署它。然而,现实世界会发生变化,你需要为新数据集、不同指标或仅仅为了提高指标而更新模型。新版本的模型不断出现,ML 平台使你能够追踪模型版本。模型版本控制功能将帮助团队比较新旧模型版本的效率,并在需要时允许团队将生产中的新模型回滚至以前的版本。
-
存储:存储不仅在数据工程阶段重要,在模型开发过程中同样至关重要。在模型开发过程中,你会在多个阶段读取和写入数据。你将数据集分成测试集和训练集,你可能选择只写入一次数据,这样你可以在相同数据集上进行不同模型参数的实验。实验追踪模块和模型注册表都需要存储。ML 平台为你的数据集提供按需存储,确保数据可靠存储。
现在,让我们看看数据科学家如何在他们的工作流程中使用这些组件。
理解数据科学家的工作流程
上一节中提到的所有功能都由 ML 平台以自助方式提供。数据科学家的典型工作流程如下:
-
登录平台:数据科学家对平台进行身份验证。
-
开发环境的配置:在这一步骤中,数据科学家向平台请求开发环境的资源要求,如 CPU 数量、内存大小和特定的软件库。平台会自动为你配置所需资源。
-
探索性数据分析:在这个阶段,数据科学家进行多种数据转换和可视化技术,以理解数据中隐藏的模式。
-
尝试不同的算法:在这个阶段,数据科学家将完整数据集拆分为训练集和测试集。然后,数据科学家应用不同的 ML 算法和超参数,以实现所需的指标。数据科学家接着比较每次训练运行的参数,选择最适合给定用例的参数。
-
模型训练:数据科学家根据前一阶段找到的最优化参数训练模型,并将模型注册到模型注册表中。
-
运行模型部署管道:在此步骤中,数据科学家将模型打包以作为服务消费,并构建自动化部署流程。根据用例,它可以定期调度或一次性运行。
您可以在前面的步骤中看到,除了编写便于模型构建和训练的代码之外,所有其他步骤都是声明性的。数据科学家的重点将放在构建更多的数据科学和 ML 工程任务上。流程的所有其他方面将由 ML 平台处理。这将提高团队的效率和速度,更不用说数据科学家的幸福感了。平台的声明能力还将允许团队在整个组织中标准化流程,从而减少使用定制工具链,提高一致性并改善整个流程的安全性。
在接下来的部分中,您将探讨 ML 平台的常见服务。这些服务对于使平台达到生产就绪状态并在企业环境中更易于采用至关重要。
安全性、监控和自动化
在本节中,您将看到适用于我们到目前为止讨论的所有组件和阶段的 ML 平台的一些常见组件。这些组件帮助您在组织中实现平台的操作化:
-
数据管道执行:数据工程的结果是一个数据管道,用于摄取、清理和处理数据。您已经用缩减版数据构建了这个管道以供开发目的使用。现在,您需要用生产数据运行这些代码,或者您希望定期运行新数据,比如每周。ML 平台允许您获取代码并在不同环境中自动执行它。这是一大进步,因为平台不仅允许您运行代码,还将管理代码的所有依赖项的打包,使其可以在任何地方运行。如果您构建的代码使用 Apache Spark,平台应允许您自动化提供 Spark 集群和运行数据管道所需的所有其他组件的过程。
-
模型部署:一旦模型准备好供使用,它应该可以作为服务供消费。如果没有 ML 平台的自动化模型打包和部署能力,将模型打包并将其托管为服务的过程需要一些软件工程工作。这项工作需要与软件工程师和运维团队紧密合作,并可能需要花费数天甚至数周的时间才能完成。ML 平台自动化了这个过程,通常只需几秒到几分钟的时间。这个过程的结果是在环境中部署的 ML 模型,并可以作为服务访问,通常以 REST API 的形式提供。
模型的部署是一个方面;随着时间的推移,你可能还需要用新数据集重新训练模型。该平台还使团队能够使用第一次训练模型时所编写的相同训练代码来自动化重新训练过程。重新训练的模型将自动重新部署。这项功能大大提高了团队的效率,允许更高效地利用时间,如处理新的挑战,同时为业务提供价值。
-
监控:监控不仅仅是指拥有观察生产环境中组件动态的能力,例如监控模型响应时间,它还使团队能够在问题发生之前响应事件。一个好的监控平台在整个机器学习项目生命周期中提供可观测性,而不仅仅是生产环境中的监控。当你编写代码处理数据时,你可能需要调整来自多个系统的数据集之间的连接表达式。这是你在开发过程中需要的信息之一。该平台允许你在开发过程中深入了解细节。平台还提供监控底层 IT 基础设施的能力。例如,在模型训练阶段运行代码时,平台提供硬件资源利用率的度量。
-
安全性和治理:你正在构建的平台使团队能够独立工作。团队可以随时使用平台中的工具进行工作。然而,谁可以访问什么资源、谁可以使用哪些工具,成为许多组织面临的挑战。为此,平台必须具备访问控制功能,只允许授权用户访问。平台的安全组件通过标准协议,如OAuth2或OpenID Connect,对用户进行认证和授权。你将使用开源组件将认证功能引入平台。平台还使用 Kubernetes 命名空间功能,在共享相同集群的不同团队之间提供工作负载隔离。Kubernetes 还提供将硬件资源使用限制分配给各个团队的能力。这些功能将使团队能够在组织内的多个单位之间共享平台,同时提供明确的隔离边界和硬件资源配额。
-
源代码管理:当你构建数据管道或训练模型时,你会编写代码。该平台提供与源代码管理解决方案的集成功能。Git是集成平台的默认源代码管理解决方案。
现在,让我们继续介绍开放数据中心(ODH)。
引入 ODH
ODH 是一个开源项目,提供了构建我们 ML 平台所需的大部分组件。它包括一个 Kubernetes 操作符和一套精心挑选的开源软件组件,这些组件构成了 ML 平台的大部分。在本书中,我们将主要使用 ODH 操作符。平台中还有其他一些组件,它们并非 ODH 原生提供的。ODH 操作符的一个优点是,您可以根据实际需求,随时将默认组件替换为其他组件。
为了构建平台,您将使用以下组件。在接下来的几章中,您将学习每个组件的详细信息及其使用方法。目前,您只需了解这些组件的高层次用途:
-
ODH 操作符:一个 Kubernetes 操作符,用于管理 ML 平台中不同组件的生命周期。它控制并管理 ML 平台中使用的软件组件的安装和维护。
-
JupyterHub:管理 Jupyter Notebook 服务器实例及其相关资源。
-
Jupyter notebooks:一个集成开发环境(IDE),是平台中主要的数据工程和数据科学工作区。数据科学家和工程师将使用这些工作区编写和调试数据工程及 ML 工作流的代码。
-
Apache Spark:一个分布式并行数据处理引擎和框架,用于处理大规模数据集。它提供了广泛的数据摄取连接器,能够从各种数据源中获取数据。
-
Apache Airflow:一个工作流引擎,用于自动化执行和调度数据管道和模型部署。Airflow 协调数据管道中的不同组件。
-
Seldon Core:一个将 ML 模型打包并部署为 REST 服务的库。它还具有监控已部署模型的功能。它支持流行的 ML 框架,能够将使用 TensorFlow、scikit-learn、XGBoost 和 PyTorch 等框架构建的 ML 模型包装成 REST 服务。
-
Prometheus 和 Grafana:这两个组件为我们的平台提供监控功能。Prometheus 提供度量数据库,用于记录平台组件提供的遥测数据,而 Grafana 提供图形用户界面(GUI)来可视化捕获的度量数据。
-
Minio:一个与 Amazon S3 API 兼容的对象存储提供者。Minio 组件并非 ODH 工具链的一部分,但我们将扩展并配置 ODH 操作符以管理平台上的 Minio 组件。
-
MLFlow:一个用于追踪不同模型实验的组件,同时也作为平台的模型注册中心。MLFlow 组件并非 ODH 工具链的一部分,但我们将扩展 ODH 操作符以管理 MLFlow 组件。
您还将安装一个开源身份提供者组件。该组件的目标是为所有平台组件提供一个通用的单点登录功能。我们将使用 Keycloak 作为身份管理系统,但在您的情况下,可以使用基于 OAuth2 的系统来替换 Keycloak。Keycloak 不是 ODH 的一部分,我们将展示如何将其作为独立组件安装到您的 Kubernetes 集群中。
图 4.4 显示了作为 ML 平台主要组件的主要开源软件。ODH 可扩展性模型允许您根据需求添加或选择使用的产品。您可以用其他开源产品替换任何组件。不过,在本书的练习中,我们将使用此处列出的产品:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_004.jpg
图 4.4 – ML 平台的主要组件
在下一节中,您将部署 ODH 运算符和 Keycloak 服务器到您的 Kubernetes 集群中。您还将安装并配置入口控制器,以接受来自集群外部的流量。
在 Kubernetes 上安装 ODH 运算符
在本节中,您将把 ODH 运算符安装到 Kubernetes 集群中。此时,您还不会启用平台的任何组件。要安装运算符,您首先需要注册运算符的目录源,然后才能安装它。
首先,让我们注册 ODH 运算符的目录。目录源包含元数据,通过这些元数据,OLM 可以发现运算符及其依赖项。ODH 运算符不在默认的 OLM 目录中,因此我们需要注册一个包含 ODH 元数据的新目录,以供 OLM 使用:
-
如果您使用的是
minikube,请验证您的 Kubernetes 集群是否正在运行:minikube status
您应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_005.jpg
图 4.5 – 验证 Kubernetes 是否通过 minikube 正在运行
如果您的 Kubernetes 集群没有运行,请参考第三章,探索 Kubernetes,了解如何配置和启动 Kubernetes 集群。
-
通过执行以下命令来验证 OLM 是否已安装并正在运行:
kubectl get pods -n olm
您应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_006.jpg
图 4.6 – 命令输出显示 OLM Pod 正在运行
确保所有 OLM Pod 都在运行。如果您遇到这种情况,请参考第三章,探索 Kubernetes,在 如何在集群中安装 OLM 部分。
- 克隆 Git 仓库并导航到仓库的根目录。该仓库包含你在本书范围内构建平台所需的所有源文件、脚本和清单: https://github.com/PacktPublishing/Machine-Learning-on-Kubernetes.git cd Machine-Learning-on-Kubernetes。
使用本书源代码中提供的 YAML 文件注册一个新的 catalog source 操作员:
kubectl create -f chapter4/catalog-source.yaml
-
几分钟后,验证操作员在你的集群中是否可用:
kubectl get packagemanifests -o wide -n olm | grep -I opendatahub
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_007.jpg
图 4.7 – 验证 ODH 操作员是否可用
在 Windows PowerShell 上,你可能需要将 grep 命令替换为 findstr。
-
现在,创建 ODH 操作员的订阅。回想一下第三章,订阅对象通过 OLM 触发操作员的安装:
kubectl create -f chapter4/odh-subscription.yaml
你应该看到一个响应消息,显示订阅已创建。
-
在创建订阅后,OLM 会自动安装操作员及其所有组件。通过执行以下命令验证 ODH pod 是否在运行。可能需要几秒钟才能看到 pod 出现。如果 pod 未列出,等待几秒钟并重新运行相同的命令:
kubectl get pods -n operators
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_008.jpg
图 4.8 – 验证 ODH pod 是否已启动并运行
你刚刚在 Kubernetes 集群上安装了 ODH 操作员。请注意,你并没有使用像 Deployments 这样的通用 Kubernetes 对象来运行你的操作员。OLM 允许你通过 Subscription 对象轻松管理操作员的安装。
在下一节中,你将安装 ingress 控制器,以允许流量进入 Kubernetes 集群。
在 Kubernetes 集群上启用 ingress 控制器
回想一下 第三章,探索 Kubernetes 中提到的,ingress 提供了一种方式,让你可以暴露特定的服务,使其可以从集群外部访问。Kubernetes 上有许多 ingress 提供商,我们将它留给你选择合适的 ingress 提供商来为你的集群提供服务。
如果你正在使用 minikube,需要按照以下步骤启用默认的 ingress:
-
通过执行以下命令,为你的集群启用基于 NGINX 的 ingress 控制器:
minikube addons enable ingress
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_009.jpg
图 4.9 – 启用 minikube ingress 插件的输出
-
验证你的集群中是否有 ingress pod 在运行:
kubectl get pods -n ingress-nginx
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_010.jpg
图 4.10 – 验证 Nginx ingress pod 是否处于运行状态
现在您已将外部流量启用到您的集群,下一步是为您的 ML 平台安装开源身份验证和授权组件。
在 Kubernetes 上安装 Keycloak
我们将使用 Keycloak (www.keycloak.org) 作为我们的身份提供者,并为您的平台添加身份验证和访问管理功能。Keycloak 支持行业标准的安全机制,如OAuth2和OpenID Connect。在本节中,您将在 Kubernetes 集群上安装 Keycloak 服务器,并登录到 Keycloak UI 以验证安装:
-
通过为
keycloak应用程序创建一个新命名空间开始:kubectl create ns keycloak
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_011.jpg
图 4.11 – 为 Keycloak 创建新命名空间的输出
-
使用提供的 YAML 文件创建 Keycloak 清单:
kubectl create -f chapter4/keycloak.yaml --namespace keycloak -
验证
keycloakpod 是否正在运行。请注意,--namespace和-n标志在kubectl中是可以互换的:kubectl get pods -n keycloak
启动可能需要一些时间,因为它会从互联网上拉取容器镜像。第一次运行命令时,您可能会看到 Keycloak pod 正在运行,您应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_012.jpg
图 4.12 – 验证 Keycloak pod 是否处于运行状态
在接下来的几个步骤中,您将定义并配置 Keycloak pod 的 ingress,使其能够从集群外部访问。
-
通过运行以下命令获取
minikube机器的 IP 地址:minikube ip
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_013.jpg
图 4.13 – 您的 minikube 实例的 IP 地址
- 打开
chapter4/keycloak-ingress.yaml文件,并将KEYCLOAK_HOST字符串替换为keycloak.<YOUR_MINIKUBE_IP_ADDRESS>.nip.io字符串。所以,如果您的minikube的 IP 地址是192.168.61.72,那么字符串值将是keycloak.192.168.61.72.nip.io。
文件中有两个地方需要放入这个新字符串。文件将呈现 图 4.14 的样式。不要忘记保存此文件中的更改。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_014.jpg
图 4.14 – 您的 minikube 实例的 IP 地址在 keycloak-ingress 文件中已更改
将修改后的文件应用到 Kubernetes 集群。这个 ingress 对象将为您创建所需的配置,使您能够从集群外部访问 Keycloak 服务器。运行以下命令以创建 ingress 对象:
kubectl create -f chapter4/keycloak-ingress.yaml --namespace keycloak
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_015.jpg
图 4.15 – 修改后的 ingress 已应用
-
通过运行以下命令验证
ingress对象是否可用:kubectl get ingress --namespace keycloak
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_016.jpg
图 4.16 – Ingress 对象已创建
- 现在你已经验证 Keycloak 正在运行,并通过
ingress对象暴露,打开你机器上的浏览器(minikube运行的地方),并访问以下网址。你需要根据步骤 5 中的说明替换正确的 IP 地址:https://keycloak.192.168.61.72.nip.io/auth/。
你会收到一个警告,提示 证书无效。这是因为 Keycloak 服务器默认使用自签名证书。你只需要点击浏览器显示的 高级 按钮,然后选择继续访问该网站。
你应该看到以下页面;点击 管理控制台 链接继续操作:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_017.jpg
图 4.17 – Keycloak 登录页
- 在以下页面中使用凭据 admin/admin 登录。输入凭据后,点击 登录:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_018.jpg
图 4.18 – Keycloak 登录页面
- 验证 Keycloak 的主管理页面是否如以下所示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_04_019.jpg
图 4.19 – Keycloak 管理页面
恭喜你!你已成功将 ODH 操作员和 Keycloak 安装到你的 Kubernetes 集群中。
总结
在本章中,你已经了解了 ML 平台的主要组件,以及开源社区项目如何为这些组件提供软件产品。使用开源软件不仅使大量用户可以免费使用软件,同时也促进了对组件的持续改进,并为软件不断发展与新增功能做出贡献。
你已经安装了设置 ML 平台所需的操作员,并且已安装 ingress 控制器以允许流量进入你的集群,同时也安装了 Keycloak,为你的平台提供身份与访问管理功能。
基础已经搭建好,我们可以深入探讨 ML 生命周期中的每个组件。在下一章中,你将学习如何在你的平台上设置 Spark 和 JupyterHub,这将使数据工程师能够构建和部署数据管道。
进一步阅读
- 数据准备是数据科学中最不令人愉快的任务:
www.forbes.com/sites/gilpress/2016/03/23/data-preparation-most-time-consuming-least-enjoyable-data-science-task-survey-says/?sh=1e5986216f63
第四章:第五章:数据工程
数据工程通常是指在组织中管理和组织数据及数据流的过程。它涉及数据收集、处理、版本控制、数据治理和分析。这是一个庞大的主题,围绕数据处理平台、数据湖、数据集市、数据仓库和数据流的开发与维护展开。数据工程是一个重要的实践,它为大数据和机器学习(ML)项目的成功做出了贡献。本章将介绍数据工程在机器学习中的具体应用。
许多机器学习教程/书籍从一个干净的数据集和 CSV 文件开始,构建您的模型。现实世界则不同。数据呈现出多种形态和规模,因此您需要有一个明确的策略来收集、处理并大规模准备数据。本章将讨论开源工具,这些工具可以为机器学习项目中的数据工程奠定基础。您将学习如何在 Kubernetes 平台上安装这些开源工具集,以及这些工具如何帮助您和您的团队提高效率和灵活性。
在本章中,您将学习以下内容:
-
配置 Keycloak 进行身份验证
-
配置 Open Data Hub 组件
-
理解并使用 JupyterHub IDE
-
理解 Apache Spark 的基础知识
-
理解 Open Data Hub 如何按需提供 Apache Spark 集群
-
从 Jupyter Notebook 编写并运行 Spark 应用程序
技术要求
本章包括一些动手设置和练习。您将需要一个已配置好操作生命周期管理器(Operator Lifecycle Manager)的 Kubernetes 集群。如何构建这样的 Kubernetes 环境已在第三章《探索 Kubernetes》中介绍。在进行本章的技术练习之前,请确保您已经在 Kubernetes 集群上搭建了运行中的 Kubernetes 集群,并安装了Open Data Hub(ODH)。ODH 的安装可参考第四章《机器学习平台的构成》。您可以在github.com/PacktPublishing/Machine-Learning-on-Kubernetes找到本书的所有相关代码。
配置 Keycloak 进行身份验证
在开始使用平台的任何组件之前,您需要配置与平台组件相关联的身份验证系统。如在第四章《机器学习平台的构成》中所述,您将使用 Keycloak,这是一款开源软件,用于提供身份验证服务。
首先,从 chapter5/realm-export.json 导入配置,该文件可在本书关联的代码库中找到。此文件包含将 OAuth2 功能关联到平台组件所需的配置。
虽然本书不是 Keycloak 的指南,但我们会提供一些基本定义,以帮助你理解 Keycloak 服务器的高级分类:
-
Realm:Keycloak 领域是一个管理属于同一域的用户、角色、组和客户端应用程序的对象。一个 Keycloak 服务器可以有多个领域,因此你可以有多个配置集,例如一个领域用于内部应用程序,另一个用于外部应用程序。
-
Clients:客户端是可以请求用户认证的实体。一个 Keycloak 客户端对象与一个领域相关联。我们平台中所有需要单点登录(SSO)的应用程序都将作为客户端注册到 Keycloak 服务器中。
-
用户和组:这两个术语不言而喻,在接下来的步骤中,你将创建一个新用户,并使用它登录到平台的不同软件中。
下一步是配置 Keycloak,为我们的 ML 平台组件提供 OAuth 功能。
导入 Keycloak 配置以供 ODH 组件使用
在本节中,你将把客户端和组配置导入到运行在 Kubernetes 集群上的 Keycloak 服务器中。以下步骤将把所有配置导入到 Keycloak 服务器的主领域:
- 使用用户名
admin和密码admin登录到你的 Keycloak 服务器。在左侧边栏的管理标题下点击导入链接:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_001.jpg
图 5.1 – Keycloak 主领域
- 点击屏幕上的选择文件按钮,如下所示:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_002.jpg
图 5.2 – Keycloak 导入配置页面
- 从弹出窗口中选择
chapter5/realm-export.json文件。之后,选择跳过,在如果资源已存在下拉选项中,然后点击导入:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_003.jpg
图 5.3 – Keycloak 导入配置页面
- 验证记录是否已成功导入到你的 Keycloak 服务器:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_004.jpg
图 5.4 – Keycloak 导入配置结果页面
- 验证是否已创建四个客户端,方法是点击左侧菜单中的Clients项。应该存在以下客户端 ID:aflow、mflow、grafana和jhub。aflow客户端用于平台的工作流引擎,是Apache Airflow的一个实例。mflow客户端用于模型注册和训练跟踪工具,是MLflow的一个实例。grafana客户端用于监控 UI,是Grafana的一个实例。最后,jhub客户端用于JupyterHub服务器实例。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_005.jpg
图 5.5 – Keycloak 客户端页面
- 验证是否已创建名为 ml-group 的组,方法是在左侧面板点击 Groups 链接:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_006.jpg
图 5.6 – Keycloak 组页面
你将使用该用户组来创建平台用户。
很棒!你刚刚为 ML 平台配置了多个 Keycloak 客户端。下一步是在 Keycloak 中创建一个用户,你将使用该用户进行本书余下部分的操作。需要注意的是,Keycloak 可以与企业目录或任何其他数据库集成,并将其用作用户源。请记住,我们在这里使用的领域配置非常基础,不建议用于生产环境。
创建 Keycloak 用户
在本节中,你将创建一个新用户,并将新创建的用户与前一节中导入的组关联。将用户与组关联将授予不同 ODH 软件所需的角色:
- 在 Keycloak 页面左侧,点击 Users 链接进入该页面。要添加新用户,点击右侧的 Add user 按钮:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_007.jpg
图 5.7 – Keycloak 用户列表
- 添加用户名
mluser,确保 User Enabled 和 Email Verified 切换按钮设置为 ON。在 Groups 中,选择 ml-group 组,并填写 Email、First Name 和 Last Name 字段,如 图 5.8 所示,然后点击 Save 按钮:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_008.jpg
图 5.8 – Keycloak 添加用户页面
- 点击 Credentials 标签页为你的用户设置密码:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_009.jpg
图 5.9 – Keycloak 凭证页面
- 输入你选择的密码,然后禁用 Temporary 标志,点击 Set Password 按钮。
你刚刚在 Keycloak 中创建并配置了一个用户。现在你的 Keycloak 服务器已经可以被 ML 平台组件使用。下一步是探索平台中为所有角色提供主要编码环境的组件。
配置 ODH 组件
在第四章《机器学习平台的构成》中,你已经安装了 ODH 操作符。使用 ODH 操作符,你将配置一个 ODH 实例,该实例将自动安装 ML 平台的组件。ODH 执行 Kustomize 脚本来安装 ML 平台的组件。作为本书代码的一部分,我们提供了模板来安装和配置运行平台所需的所有组件。
你还可以通过 manifests 文件配置 ODH 操作员为你安装哪些组件。你可以将特定的配置传递给清单文件,并选择所需的组件。一本书的代码仓库中有一个这样的清单,路径为 manifests/kfdef/ml-platform.yaml。这个 YAML 文件为 ODH 操作员配置了所需的安装软件,使其成为平台的一部分。你需要对这个文件进行一些修改,接下来你将看到具体操作。
该文件定义了平台的组件以及这些组件获取设置的位置:
-
名称:定义组件的名称。
-
path属性定义了配置此组件所需文件的相对路径位置。 -
KEYCLOAK_URL和JUPYTERHUB_HOST需要根据你的配置进行更改。 -
manifests/jupytherhub/overlays文件夹在代码仓库中。 -
Repos:此配置部分特定于每个清单文件,并适用于清单中的所有组件。它定义了包含所有被清单文件引用文件的 Git 仓库的位置和版本。如果你希望清单引用你自己的安装文件,需在此处指定正确的 Git 仓库(包含你文件的仓库)。
图 5.10 展示了清单文件中定义 JupyterHub 组件的部分:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_010.jpg
图 5.10 – ODH 清单文件中的组件
你将使用提供的清单文件来创建 ML 平台的实例。你也可以根据需要修改此文件,通过调整配置或添加、移除平台组件来进行个性化设置。但是,在书中的练习中,我们不建议你进行更改,除非有特别指示。
现在你已经看到了 ODH 清单文件,是时候充分利用它来创建你的第一个 Kubernetes 上的 ML 平台了。
安装 ODH
在我们安装平台的数据工程组件之前,我们首先需要创建一个 ODH 实例。ODH 实例是一个经过精心策划的相关工具集的集合,作为 ML 平台的组件。尽管 ML 平台可能包含 ODH 提供之外的组件,但可以公平地说,ODH 实例就是 ML 平台的一个实例。你也可以在同一个 Kubernetes 集群上运行多个 ODH 实例,只要它们运行在各自隔离的 Kubernetes 命名空间中。这在组织中的多个团队或部门共享单一 Kubernetes 集群时非常有用。
以下是你需要按照的步骤,以在 Kubernetes 集群上创建 ODH 实例:
-
使用以下命令在 Kubernetes 集群中创建一个新命名空间:
kubectl create ns ml-workshop
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_011.jpg
图 5.11 – 你的 Kubernetes 集群中的新命名空间
-
确保 ODH 操作符正在运行,执行以下命令:
kubectl get pods -n operators
你应该看到以下响应。确保状态显示为Running:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_012.jpg
图 5.12 – ODH 操作符的状态
-
获取你
minikube环境的 IP 地址。这个 IP 地址将用于为平台的不同组件创建入口,就像我们为 Keycloak 所做的那样。请注意,依据你的底层基础设施,每个minikube实例的 IP 可能会不同:minikube ip
这个命令应该会给出你minikube集群的 IP 地址。
-
打开
manifests/kfdef/ml-platform.yaml文件,并将以下参数的值更改为你minikube实例的 NIP(nip.io)域名。只需要替换域名中的 IP 地址部分。例如,KEYCLOAK_URL keycloak.<IP Address>.nip.io应该改为keycloak.192.168.61.72.nip.io。注意,这些参数在文件中可能会被多次引用。在完整的 Kubernetes 环境中,<IP Address>应该是你的 Kubernetes 集群的域名:-
KEYCLOAK_URL -
JUPYTERHUB_HOST -
AIRFLOW_HOST -
MINIO_HOST -
MLFLOW_HOST -
GRAFANA_HOST
-
-
使用以下命令将清单文件应用到你的 Kubernetes 集群:
kubectl create -f manifests/kfdef/ml-platform.yaml -n ml-workshop
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_013.jpg
图 5.13 – 应用 ODH 组件清单后的结果
-
使用以下命令开始监控在
ml-workshop命名空间中创建的 Pods。安装所有组件需要一些时间。几分钟后,所有 Pods 将进入运行状态。在 Pods 创建过程中,你可能会看到一些 Pods 抛出错误。这是正常现象,因为某些 Pods 依赖于其他 Pods。耐心等待,所有组件最终会安装完毕,Pods 将进入运行状态:watch kubectl get pods -n ml-workshop
当所有 Pods 都在运行时,你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_014.jpg
图 5.14 – CLI 响应,展示 ODH 组件在 Kubernetes 集群上运行的情况
那么,这个命令是做什么的呢?kfdef ml-workshop命名空间:
kubectl get all -n ml-workshop
你应该看到 ODH 操作符在ml-workshop命名空间中创建的所有对象。
恭喜!你刚刚创建了一个新的 ODH 实例。现在你已经看过了从清单文件创建 ML 平台实例的过程,是时候看看数据工程师将用来开展工作的平台各个组件了。
使用 Podman 驱动的 Minikube
请注意,对于某些使用 podman 驱动程序的 minikube 设置(在 Linux 上),由于线程数的限制,Spark 操作符可能会失败。为了解决这个问题,你需要在 minikube 配置中使用 kvm2 驱动程序。你可以通过在 minikube start 命令中添加 --driver=kvm2 参数来实现。
理解和使用 JupyterHub
Jupyter Notebook 已成为编写机器学习项目代码的极受欢迎的工具。JupyterHub 是一款软件,它便于自助提供计算环境,包括启动预配置的 Jupyter Notebook 服务器并在 Kubernetes 平台上提供相关的计算资源。数据工程师和数据科学家等按需终端用户可以为自己提供专用的 Jupyter Notebook 实例。如果请求的用户已经有了自己运行的 Jupyter Notebook 实例,Hub 将直接将用户引导到现有实例,从而避免重复的环境。对终端用户而言,整个过程是无缝的。你将在本章的下一部分看到这一点。
当用户请求 JupyterHub 中的一个环境时,他们还可以选择预配置的硬件资源(如 CPU、内存和存储)大小。这为开发者、数据工程师和数据科学家提供了一种灵活的方式,使他们能够为特定任务分配合适的计算资源。这种资源的动态分配是通过底层的 Kubernetes 平台来实现的。
不同的用户可能需要不同的框架、库和编程环境的版本。一些数据科学家可能想使用 TensorFlow,而其他人可能想使用 scikit-learn 或 PyTorch。一些数据工程师可能更喜欢使用 pandas,而其他人可能需要在 PySpark 中运行数据管道。在 JupyterHub 中,他们可以为这些场景配置多个预定义的环境。用户在请求新环境时,可以选择一个预定义的配置。这些预定义的环境实际上是容器镜像。这意味着平台操作员或管理员可以准备多个预定义的容器镜像,作为终端用户的计算环境。此功能还支持环境的标准化。你有多少次在不同开发者计算机上处理不同版本库的情况?环境的标准化可以减少与库版本不一致相关的问题,并通常减少 它在我的机器上能运行 的问题。
图 5.15 展示了为 JupyterHub 环境配置的新环境的三步流程:
![图 5.15 – 创建 JupyterHub 新环境的工作流程]
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_015.jpg)
图 5.15 – 创建 JupyterHub 新环境的工作流程
现在你知道了 JupyterHub 能做什么,我们来看看它是如何运作的。
验证 JupyterHub 安装
团队中的每个数据工程师都遵循一个简单而标准的环境配置工作流。不再需要手动安装和调试工作站配置。这对于自主团队来说非常好,肯定能提高团队的效率。
ODH 运维人员已经为你在之前的部分安装了 JupyterHub。现在,你将以数据工程师身份启动一个新的 Jupyter Notebook 环境,并编写数据管道:
-
使用以下命令获取在 Kubernetes 环境中创建的 ingress 对象。我们运行此命令以查找 JupyterHub 的 URL:
kubectl get ingress -n ml-workshop
你应该看到以下示例响应。请注意在 HOSTS 列中显示的 JupyterHub URL:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_016.jpg
图 5.16 – 集群中的所有 ingress
- 从与 minikube 运行在同一台机器上的浏览器中,访问 JupyterHub URL。该 URL 看起来像是 https://jupyterhub..nip.io。此 URL 会将你带到 Keycloak 登录页面进行 SSO 认证。确保在这个 URL 中将 IP 地址替换为你 minikube 的 IP 地址:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_017.jpg
图 5.17 – JupyterHub 的 SSO 挑战
- 输入
mluser作为用户名,然后输入你为该用户设置的密码,点击 Sign In。
你将看到 JupyterHub 服务器的登录页面,允许你选择你想使用的 notebook 容器镜像,以及你所需的预定义计算资源大小。
notebook 镜像部分包含了你通过 ODH 清单文件从代码库中的 manifests/jupyterhub-images 文件夹中配置的标准 notebooks。
容器大小下拉菜单允许你选择适合你需求的环境大小。此配置也通过 manifests/jupyterhub/jupyterhub/overlays/mlops/jupyterhub-singleuser-profiles-sizes-configmap.yaml 清单文件进行控制。
我们鼓励你查看这些文件,了解你可以为每个清单配置哪些设置。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_018.jpg
图 5.18 – JupyterHub 登录页面
选择 Base Elyra Notebook Image 和 Default 容器大小,然后点击 Start server。
-
通过执行以下命令验证是否为你的用户创建了一个新的 Pod。Jupyter Notebook 实例的名称以
jupyter-nb-开头,并以用户名作为后缀。这使得每个用户的 notebook pod 拥有独特的名称:kubectl get pods -n ml-workshop | grep mluser
你应该看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_019.jpg
图 5.19 – JupyterHub 创建的 Jupyter Notebook pod
- 恭喜!你现在正在 Kubernetes 平台上运行自己的自供给 Jupyter Notebook 服务器。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_020.jpg
图 5.20 – Jupyter Notebook 登录页面
- 现在,让我们停止 notebook 服务器。点击 File > Hub Control Panel 菜单选项,进入以下所示的 Hub 控制面板 页面:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_021.jpg
图 5.21 – 查看 Hub 控制面板的菜单选项
- 点击 Stop My Server 按钮。这是停止你 Jupyter Notebook 实例的方式。你可能稍后想要重新启动它以继续下一步。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_022.jpg
图 5.22 – Hub 控制面板
-
通过发出以下命令验证新 pod 是否已为你的用户销毁:
kubectl get pods -n ml-workshop | grep mluser
此命令应该没有输出,因为 Jupyter Notebook pod 已被 JupyterHub 销毁。
我们将留给你自己探索在你环境中 notebook 的不同配置。你将在本章和接下来的几章中使用这个 Jupyter notebook 编写代码,所以如果你只是想继续阅读,你不会错过任何重要内容。
运行你的第一个 Jupyter notebook
现在你的 Jupyter notebook 已经运行,是时候编写 Hello World! 程序了。在本书的代码仓库中,我们提供了这样的一个程序,在接下来的步骤中,你将使用 Git 检出代码并运行该程序。在开始这些步骤之前,请确保你可以通过浏览器访问你的 Jupyter notebook,如前一节所述:
- 点击 Jupyter notebook 左侧菜单中的 Git 图标。该图标是从顶部数起的第三个。它会显示三个不同操作的按钮。点击 Clone a Repository 按钮:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_024.jpg
图 5.23 – Jupyter notebook 中的 Git 操作
- 在 Clone a repo 弹出框中,输入本书的代码仓库位置,
github.com/PacktPublishing/Machine-Learning-on-Kubernetes.git,然后点击 CLONE。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_025.jpg
图 5.24 – 在 Jupyter notebook 中克隆 Git 仓库
- 你会看到代码仓库已被克隆到 Jupyter notebook 的文件系统中。如 图 5.25 所示,导航到
chapter5/helloworld.ipynb文件并在 notebook 中打开它。点击顶部栏上的小播放图标运行该单元:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_026.jpg
图 5.25 – 在你的 Jupyter 环境中的 notebook
-
Voilà!你刚刚在自己配置的 Kubernetes 上运行的 Jupyter Notebook 服务器中执行了 Python 代码。
-
通过选择 文件 > Hub 控制面板 菜单选项关闭你的笔记本。点击 停止我的服务器 按钮来关闭你的环境。请注意,ODH 会保存你的磁盘,下次启动笔记本时,所有保存的文件都会可用。
恭喜!现在,你可以在平台上运行你的代码。接下来,我们将回顾一下 Apache Spark 引擎的一些基础知识。
理解 Apache Spark 的基础知识
Apache Spark 是一个开源的数据处理引擎,旨在分布式大规模数据处理。这意味着,如果你处理的是较小的数据集,比如 10s 或者几百 GB,经过优化的传统数据库可能会提供更快的处理时间。Apache Spark 的主要特点是其能够在内存中进行中间计算,这使得 Apache Spark 比 Hadoop MapReduce 更加高效。
Apache Spark 的设计目标是速度、灵活性和易用性。Apache Spark 提供了超过 70 个高级数据处理操作符,使数据工程师可以轻松构建数据应用程序,因此使用 Apache Spark API 编写数据处理逻辑变得非常简单。灵活性意味着 Spark 作为一个统一的数据处理引擎,可以处理多种数据工作负载,如批处理应用程序、流处理应用程序、交互式查询,甚至是机器学习算法。
图 5.26 显示了 Apache Spark 组件:
![图 5.26 – Apache Spark 组件]
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_027.jpg)
图 5.26 – Apache Spark 组件
理解 Apache Spark 作业执行
现在大多数数据工程师都知道 Apache Spark 是一个大规模并行数据处理引擎。它是 Apache 软件基金会最成功的项目之一。Spark 通常运行在多个 虚拟机(VMs)或裸金属服务器的集群上。然而,随着容器和 Kubernetes 的流行,Spark 增加了对在 Kubernetes 上运行 Spark 集群的支持。
在 Kubernetes 上运行 Spark 的两种最常见方式如下。第一种,也是原生方式,是通过 Kubernetes 引擎本身来协调 Kubernetes 工作节点。在这种方法中,Spark 集群实例始终运行,Spark 应用程序被提交到 Kubernetes API,然后 Kubernetes API 调度提交的应用程序。我们不会深入探讨这部分实现。第二种方法是通过 Kubernetes 运维工具(operators)。运维工具利用 Kubernetes CRD 来在 Kubernetes 中本地创建 Spark 对象。在这种方法中,Spark 集群是通过 Spark 运维工具动态创建的。与其将 Spark 应用程序提交到现有的集群,不如通过运维工具按需启动 Spark 集群。
Spark 集群采用管理/工作架构。Spark 集群管理器知道工作节点的位置,以及工作节点可用的资源。Spark 集群管理着将运行应用程序的工作节点集群的资源。每个工作节点都有一个或多个执行进程,通过执行进程运行分配的任务。
Spark 应用程序有两部分:驱动程序组件和数据处理逻辑。驱动程序组件负责执行数据处理操作的流程。驱动程序首先与集群管理器交互,找出哪些工作节点将运行应用程序逻辑。驱动程序将所有应用操作转换为任务,调度它们,并将任务直接分配给工作节点上的执行进程。一个执行进程可以运行多个与相同 Spark 上下文相关的任务。
如果你的应用程序需要收集计算结果并进行合并,驱动程序将负责此项工作。作为数据工程师,这一切操作都通过 SparkSession 对象进行了抽象,你只需要编写数据处理逻辑。我们提到过 Apache Spark 旨在简化操作吗?
图 5.27 显示了 Spark 驱动程序、Spark 集群管理器和 Spark 工作节点之间的关系:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_028.jpg
图 5.27 – Apache Spark 组件关系
了解 ODH 如何按需提供 Apache Spark 集群
我们已经讨论了 ODH 如何帮助你创建一个动态灵活的开发环境,使用 Jupyter Notebook 编写代码,如数据管道。我们注意到,数据开发人员需要与 IT 部门互动,以便获得数据处理集群(如 Apache Spark)上的时间。这些互动降低了团队的敏捷性,而这是 ML 平台解决的一个问题。为了符合这一场景,ODH 提供了以下组件:
-
一个 Spark 操作符,用于启动 Apache Spark 集群。本书中,我们基于 ODH 和 radanalytics 提供的原始 Spark 操作符进行了分支,以适应 Kubernetes API 的最新变化。
-
JupyterHub 中的一项功能,当用户创建特定的笔记本环境时,向 Spark 操作符发出请求,要求创建一个新的 Spark 集群。
作为数据工程师,当你使用某些笔记本镜像启动新的笔记本环境时,JupyterHub 不仅会启动一个新的笔记本服务器,还会通过 Spark 操作符为你创建一个专用的 Apache Spark 集群。
创建 Spark 集群
让我们首先看看 Spark 操作符在 Kubernetes 集群中的工作方式。ODH 创建了 Spark 控制器。你可以在 chapter5/ml-platform.yaml 文件中查看配置,文件名为 radanalyticsio-spark-cluster,如 图 5.28 所示。你可以看到,这是另一组 Kubernetes YAML 文件,定义了本书代码库中的 manifests/radanalyticsio 文件夹。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_029.jpg
图 5.28 – 安装 Spark 操作符的清单部分代码片段
当你需要启动一个 Apache Spark 集群时,可以通过创建一个名为SparkCluster的 Kubernetes 自定义资源来实现。收到请求后,Spark 操作符将根据所需的配置来配置一个新的 Spark 集群。以下步骤将向你展示如何在你的平台上配置 Spark 集群:
-
验证 Spark 操作符 Pod 是否正在运行:
kubectl get pods -n ml-workshop | grep spark-operator
你应该看到如下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_030.jpg
图 5.29 – Spark 操作符 Pod
- 使用
chapter5/simple-spark-cluster.yaml文件创建一个包含一个工作节点的简单 Spark 集群。你可以看到该文件请求一个包含一个主节点和一个工作节点的 Spark 集群。通过这个自定义资源,你可以设置多个 Spark 配置,正如我们将在下一节中看到的那样:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_031.jpg
图 5.30 – Spark 自定义资源
在你的 Kubernetes 集群中通过运行以下命令创建这个 Spark 集群自定义资源。Spark 操作符会不断扫描 Kubernetes 平台上的此资源,并为每个指定的 Spark 集群自定义资源自动创建一个新的 Apache Spark 集群实例:
kubectl create -f chapter5/simple-spark-cluster.yaml -n ml-workshop
你应该看到如下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_032.jpg
图 5.31 – 创建 Spark 集群后的响应
-
验证 Spark 集群的 Pod 是否在你的集群中运行:
kubectl get pods -n ml-workshop | grep simple-spark
你应该看到如下响应。Spark 操作符已创建两个 Pod,一个用于 Spark 主节点,另一个用于工作节点。工作节点的 Pod 数量取决于SparkCluster资源中的instances参数值。首次启动时,Pod 可能需要一些时间才能进入运行状态:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_033.jpg
图 5.32 – 正在运行的 Spark 集群 Pod 列表
现在,你已经了解了 Spark 操作符在 Kubernetes 集群中的工作原理。下一步是查看 JupyterHub 是如何配置以动态请求集群,并在为你配置新笔记本时提供 Spark 集群的。
了解 JupyterHub 如何创建 Spark 集群
简而言之,JupyterHub 执行了你在前一节中所做的操作。JupyterHub 在 Kubernetes 中创建一个SparkCluster资源,以便 Spark 操作符可以为你配置 Apache Spark 集群。这个SparkCluster资源配置是一个 Kubernetes ConfigMap文件,位于manifests/jupyterhub/jupyterhub/base/jupyterhub-spark-operator-configmap.yaml。请查找文件中的sparkClusterTemplate,如图 5.33所示。你可以看到它看起来与前一节中你创建的文件相似:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_034.jpg
图 5.33 – JupyterHub 用于 Spark 资源的模板
你们中的一些人可能已经注意到这是一个模板,它需要填写模板中提到的特定变量的值。诸如{{ user }}和{{ worker_nodes }}等变量。回想一下,我们提到过 JupyterHub 在为你的笔记本配置容器时,会创建SparkCluster请求。JupyterHub 使用这个文件作为模板,并在创建笔记本时填充相应的值。JupyterHub 是如何决定创建 Spark 集群的呢?这个配置文件在manifests/jupyterhub/jupyterhub/overlays/spark3/jupyterhub-singleuser-profiles-configmap.yaml中,称为ConfigMap文件。它看起来像图 5.33所示的文件。
你可以看到,image字段指定了该配置文件将触发的容器镜像名称。因此,作为数据工程师,当你从 JupyterHub 登录页选择该笔记本镜像时,JupyterHub 将应用此配置文件。配置文件中的第二部分是env部分,它指定了将被推送到笔记本容器实例的环境变量。configuration对象定义了将应用于在resources键中提到的模板的值:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_035.jpg
图 5.34 – JupyterHub 针对 Spark 资源的配置文件
正如你可能已经感受到的那样,在后台有很多工作在进行,旨在为你和你的团队提供一个流畅的体验,并且从开源的真正意义上讲,你可以配置所有内容,甚至如果你有任何修改或新功能,也可以回馈项目。
在下一节中,你将看到如何在运行这些组件的平台上编写和运行 Spark 应用程序是多么容易。
从 Jupyter Notebook 编写和运行 Spark 应用程序
在执行以下步骤之前,请确保你理解了我们在本章前面部分介绍的组件及其相互关系:
-
通过运行以下命令,验证 Spark 操作员 Pod 是否正在运行:
kubectl get pods -n ml-workshop | grep spark-operator
你应该会看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_036.jpg
图 5.35 – Spark 操作员 Pod
-
通过运行以下命令,验证 JupyterHub Pod 是否正在运行:
kubectl get pods -n ml-workshop | grep jupyterhub
你应该会看到以下响应:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_037.jpg
图 5.36 – JupyterHub Pod
-
在启动笔记本之前,让我们通过运行以下命令删除你在前面部分创建的 Spark 集群。这样可以演示 JupyterHub 将自动为你创建一个新的 Spark 集群实例:
kubectl delete sparkcluster simple-spark-cluster -n ml-workshop -
登录到你的 JupyterHub 服务器。参考本章前面提到的验证 JupyterHub 配置部分。你将看到服务器的登录页面。选择
manifests/jupyterhub/jupyterhub/overlays/spark3/jupyterhub-singleuser-profiles-configmap.yaml文件。 -
点击 启动服务器:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_039.jpg
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_038.jpg)
图 5.37 – 显示 Elyra Notebook 图像与 Spark 的 JupyterHub 登录页面
你刚刚启动的笔记本也会触发为你创建一个专用的 Spark 集群。启动笔记本可能需要一些时间,因为它需要等待 Spark 集群准备好。
此外,你可能已经注意到,在 jupyterhub-singleuser-profiles-configmap.yaml 文件中配置的镜像是 quay.io/ml-aml-workshop/elyra-spark:0.0.4,而我们选择的文件名称是 manifests/jupyterhub-images/elyra-notebook-spark3-imagestream.yaml。你会发现显示在 JupyterHub 登录页面上的描述性文本来自该文件的 annotations 部分。如果你想添加包含特定库的自定义镜像,只需在这里添加另一个文件,它就会对你的团队可用。JupyterHub 的这一功能使笔记本容器镜像的标准化成为可能,从而使团队中的每个人都能拥有相同的环境配置和相同的库集。
-
启动笔记本后,验证 Spark 集群是否已经为你配置好。请注意,这是为该笔记本用户专用的 Spark 集群,仅限于该用户使用:
kubectl get pods -n ml-workshop | grep mluser
你应该看到以下响应。该响应包含一个笔记本 Pod 和两个 Spark Pod;其中带有 -m 字符的是主节点,另一个是工作节点。注意,你的用户名(mluser)是如何与 Pod 名称关联的:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_038.jpg
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_039.jpg)
图 5.38 – Jupyter Notebook 和 Spark 集群 Pod
现在,你团队中的每个人都会获得自己的开发环境,并配备专用的 Spark 实例来编写和测试数据处理代码。
- Apache Spark 提供了一个用户界面,通过该界面你可以监控应用程序和数据处理作业。ODH 提供的 Spark 集群提供了这个图形用户界面,并且它可以通过
https://spark-cluster-mluser.192.168.61.72.nip.io访问。确保将 IP 地址更改为你自己的 minikube IP 地址。你可能还会注意到,登录 JupyterHub 使用的用户名mluser是 URL 的一部分。如果你使用了不同的用户名,可能需要相应地调整 URL。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_039.jpg
](https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_040.jpg)
图 5.39 – Spark 用户界面
前面的用户界面提到你在集群中有一个工作节点,你可以点击该工作节点查看在其中运行的执行器。如果你想刷新你对 Spark 集群的了解,请参考本章前面的 理解 Apache Spark 基础知识 部分。
- 打开 notebook 中的
chapter5/hellospark.ipynb文件。这是一个非常简单的作业,计算给定数组的平方。记住,Spark 会自动调度作业并将其分发给执行器。这里的 notebook 是 Spark 驱动程序,它与 Spark 集群进行通信,所有这一切都通过SparkSession对象进行抽象。
在此 notebook 的第二个代码单元格中,你正在创建一个 SparkSession 对象。getOrCreateSparkSession 实用函数将连接到平台为你配置的 Spark 集群。
最后一格单元格是你数据处理逻辑所在的位置。在这个例子中,逻辑是获取数据并计算数组中每个元素的平方。一旦数据处理完成,collect方法会将响应带回到你 notebook 中运行的 Spark 应用程序的驱动程序。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_041.jpg
图 5.40 – 一个包含简单 Spark 应用程序的 notebook
点击运行 > 运行所有单元格菜单选项,notebook 将连接到 Spark 集群,提交并执行你的作业。
- 在作业进行时,打开 Spark UI,网址是
spark-cluster-mluser.192.168.61.72.nip.io。记得根据你的设置调整 IP 地址,并点击页面中运行中的应用程序标题下的应用程序 ID表格。
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_042.jpg
图 5.41 – Apache Spark UI
- 进入 Spark 应用程序的详情页。请注意,应用程序标题Hello from ODH已在你的 notebook 中设置。点击应用程序详情 UI链接:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_043.jpg
图 5.42 – Spark UI 显示已提交的 Spark 作业
你应该看到一个页面,显示你刚刚在 Spark 集群上通过 Jupyter notebook 执行的作业的详细指标:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_044.jpg
图 5.43 – Spark UI 显示已提交的作业详情
- 完成工作后,转到文件 > Hub 控制面板菜单选项,并点击停止我的服务器按钮:
https://github.com/OpenDocCN/freelearn-devops-pt6-zh/raw/master/docs/ml-k8s/img/B18332_05_045.jpg
图 5.44 – Jupyter Notebook 控制面板
-
通过执行以下命令来验证 Spark 集群是否已被终止:
kubectl get pods -n ml-workshop | grep mluser
你不应该看到响应,因为这些 pods 已被集群中的 Spark 操作员终止。
你终于在一个按需的、运行在 Kubernetes 上的临时 Spark 集群中运行了一个基本的数据处理作业。请注意,你是通过在 Kubernetes 上运行的 Jupyter notebook 完成了这一切。
通过平台的这一功能,数据工程师可以直接从浏览器执行大规模的数据处理任务。这一功能还使他们能够轻松地协作,提供转换、清洗过的高质量数据,以支持你的 ML 项目。
总结
在这一章节中,你刚刚创建了你的第一个 ML 平台。你通过 ODH Kubernetes 操作员配置了 ODH 组件。你已经看到,数据工程师如何使用 JupyterHub 来配置 Jupyter notebook 和 Apache Spark 集群实例,同时平台自动提供环境的配置。你还看到,平台如何通过容器镜像实现操作环境的标准化,确保一致性和安全性。你也看到了,数据工程师如何从 Jupyter notebook 中运行 Apache Spark 作业。
所有这些功能使得数据工程师能够自主工作,并以自服务的方式操作。你已经看到,所有这些组件都是自主且按需提供的。平台的弹性和自服务特性将使团队在应对数据和 ML 领域不断变化的需求时更加高效和敏捷。
在下一章节中,你将看到数据科学家如何从平台中受益并提高效率。
更多推荐


所有评论(0)