01-kubeflow 介绍
Kubeflow 组件较多,容易搞不清每个组件是干什么的,本文先对 Kubeflow 进行一个系统的概括,让大家明白各个组件分别的用处,并对组件间的关系进行理顺,帮助大家合理快速的选择自己需要的组件,随后会对每个组件的底层架构和流程分别进行详细的介绍和剖析,供大家针对性的进一步学习。
什么是 Kubeflow
Kubeflow 在官方文档中被称为 Kubernetes 机器学习工具包
Kubeflow 项目是基于容器和 Kubernetes 构建,旨在为数据科学家、机器学习工程师、系统运维人员提供面向机器学习业务的敏捷部署、开发、训练、发布和管理平台。它利用了云原生技术的优势,让用户更快速、方便的部署、使用和管理当前最流行的机器学习软件。
Kubeflow 集成了很多领域的开源项目,比如 Jupyter、TF Serving、Katib、Fairing、Argo 等。可以针对机器学习的不同阶段:数据预处理、模型训练、模型预测、服务管理等进行管理。
只要安装了 Kubernetes,可以在本地、机房、云环境中部署。
Kubeflow 是运行在 Kubernetes 之上的一套技术栈,这套技术栈包含了很多组件,组件之间的关系比较松散,我们可以配合起来用,也可以单独用其中的一部分。下图是官网显示 Kubeflow 作为在 Kubernetes 上安排 ML 系统组件的平台:
我们先大体看一眼 Kubeflow 都有哪些组件,是不是很多?接下来我会带大家逐步了解每个组件都有哪些作用。
开发 ML 系统是一个反复的过程。我们需要评估 ML 工作流各个阶段的输出,并在必要时对模型和参数进行更改,以确保模型不断产生所需的结果。
开发和部署 ML 系统时,ML 工作流程通常包括几个阶段。为了便于理解,下图按顺序显示了工作流程阶段,并将 Kubeflow 添加到工作流中,显示在每个阶段都有哪些 Kubeflow 组件有用。工作流末尾的箭头指向流程,以表示流程的迭代性质:
在实验阶段,我们将基于初始假设来开发模型,并反复测试和更新模型以产生所需的结果:
- 确定要解决的问题。
- 收集和分析训练 ML 模型所需的数据。
- 选择一个 ML 框架和算法,并为模型的初始版本编码。
- 试验数据并训练模型。
- 调整模型超参数以确保最有效的处理和最准确的结果。
在生产阶段,我们将部署执行以下过程的系统:
- 将数据转换为训练系统所需的格式(为了确保我们的模型在训练和预测过程中行为始终一致,转换过程在实验阶段和生产阶段必须相同)。
- 训练 ML 模型。
- 服务模型以进行在线预测或以批处理模式运行。
- 监督模型的性能,并将结果输入到我们的程序中,以调整或重新训练模型。
由此可以看出,Kubeflow 的目标是基于 K8S,构建一整套统一的机器学习平台,覆盖最主要的机器学习流程(数据->特征->建模->服务→监控),同时兼顾机器学习的实验探索阶段和正式的生产环境。
Kubeflow 组件
Kubeflow 提供了一大堆组件,涵盖了机器学习的方方面面,先整体看一下 Kubeflow 都有哪些组件:
Central Dashboard:Kubeflow 的看板页面
Metadata:用于跟踪各数据集、作业与模型
Jupyter Notebooks:一个交互式业务 IDE 编码环境,Kubeflow 代码编辑器。
Frameworks for Training:支持的 ML 框架
- Chainer
- MPI
- MXNet
- PyTorch
- TensorFlow
Hyperparameter Tuning: Katib,超参数服务器
Argo: 基于 Kubernetes 的工作流引擎
Pipelines:一个基于 Argo 实现了面向机器学习场景的工作流项目,提供机器学习流程的创建、编排调度和管理,还提供了一个 Web UI
Tools for Serving:提供在 Kubernetes 上对机器学习模型的部署
- KFServing(发布部署服务)
- Seldon Core Serving(在 Kubernetes 上对机器学习模型的部署)
- TensorFlow Serving(TFJob):提供对 Tensorflow 模型的在线部署,支持版本控制及无需停止线上服务、切换模型等
- NVIDIA Triton Inference Server(Triton以前叫TensorRT)
- TensorFlow Batch Prediction
Multi-Tenancy in Kubeflow:Kubeflow 中的多租户
Fairing:一个将代码打包构建 image 的组件
Ambassador: 对外提供统一服务的网关(API Gateway)
Istio: 提供微服务的管理,Telemetry 收集
Ksonnet: Kubeflow 使用 ksonnet 来向 kubernetes 集群部署需要的 k8s 资源
Operator:针对不同的机器学习框架提供资源调度和分布式训练的能力(TF-Operator,PyTorch-Operator,Caffe2-Operator,MPI-Operator,MXNet-Operator)
Katib:基于各个Operator实现的超参数搜索和简单的模型结构搜索的系统,支持并行搜索和分布式训练等。超参优化在实际的工作中还没有被大规模的应用,所以这部分的技术还需要一些时间来成熟
Pachyderm:Pachyderm 版本控制数据,类似于 Git 对代码的处理。 您可以跟踪一段时间内的数据状态,对历史数据进行回溯测试,与队友共享数据,以及恢复到以前的数据状态
Kubeflow 中大多数组件的实现都是通过定义 CRD(Custom Resource Definition,Kubernetes 内置的资源类型,即自定义资源的定义,用于描述用户定义的资源是什么样子)来工作。目前 Kubeflow 主要的组件有:
- Operator 是针对不同的机器学习框架提供资源调度和分布式训练的能力(
TF-Operator
,PyTorch-Operator
,Caffe2-Operator
,MPI-Operator
,MXNet-Operator
); - Pipelines 是一个基于
Argo
实现了面向机器学习场景的流水线项目,提供机器学习流程的创建、编排调度和管理,还提供了一个Web UI
。 - Katib(调参) 是基于各个
Operator
实现的超参数搜索和简单的模型结构搜索的系统,支持并行搜索和分布式训练等。超参优化在实际的工作中还没有被大规模的应用,所以这部分的技术还需要一些时间来成熟; - Serving 支持部署各个框架训练好的模型的服务化部署和离线预测。Kubeflow 提供基于
TFServing
,KFServing
,Seldon
等好几种方案。由于机器学习框架很多,算法模型也各种各样。工业界一直缺少一种能真正统一的部署框架和方案。这方面 Kubeflow 也仅仅是把常见的都集成了进来,但是并没有做更多的抽象和统一。
以上,对 Kubeflow 组件进行了系统的概括,来帮助我们对各个组件有一个基本的了解和整体的把握。趁热打铁,接下来我们详细介绍每一个组件的架构和工作流程。
Jupyter Notebooks
Jupyter 本身包含很多组件。对于个人用户,使用 JupyterLab+Notebook
就足够了。但是如果把 Jupyter 当成一个公司级的平台来看待的话就远远不够了。这时候需要考虑的事情就比较多了,比如多用户、资源分配、数据持久化、数据隔离、高可用、权限控制等等。而这些问题恰恰是 Kubernetes 的特长。因此把 Jupyter 和 Kubernetes 结合起来使用就非常顺理成章。
JupyterHub 是一个多用户的 Jupyter 门户,在设计之初就把多用户创建、资源分配、数据持久化等功能做成了插件模式。其工作机制如下图所示:
既然 JupyterHub 是个框架,因此出现了各种各样的插件。比如可以单机部署利用 OS 用户实现多用户和数据隔离;也可以使用 OAuth 完成用户鉴权等。当然,将整个 JupyterHub 和 Kubernetes 结合起来,是最完美的姿势。 Kubeflow 中的 Multi-Tenancy in Kubeflow
多租户组件我还没看,后面可以对比研究一下是否是基于此实现的。
下面我们再来说说 Kubeflow ,因为缺乏隔离和资源限制,目前仅适用数据科学家的 solo 场景,无法支持数据科学家团队合作场景。
Kubeflow 将 default-editor ServiceAccount
分配给 Jupyter notebook Pod
。该服务帐户绑定到 kubeflow-edit ClusterRole
,它对许多 Kubernetes 资源具有命名空间范围的权限,其中包括:
Pod
Deployment
Service
Job
TFJob
PyTorchJob
因此,可以直接从 Kubeflow 中的 Jupyter notebook
创建上述 Kubernetes 资源。notebook 中已预装了 Kubernetes kubectl
命令行工具,可以说也是非常简单了。
将 Jupyter notebook
绑定在 Kubeflow 中时,可以使用 Fairing
库使用 TFJob
提交训练作业。训练作业可以运行在单个节点,也可以分布在同一个 Kubernetes 集群上,但不能在 notebook pod
内部运行。通过 Fairing
库提交作业可以使数据科学家清楚地了解 Docker 容器化和 pod 分配等流程。
总体而言,Kubeflow-hosted notebooks
可以更好地与其他组件集成,同时提供 notebook image
的可扩展性。
Pipelines
在 Kubeflow v0.1.3 之后,pipeline
已经成为 Kubeflow 的核心组件。Kubeflow 的目的主要是为了简化在 Kubernetes 上运行机器学习任务的流程,最终希望能够实现一套完整可用的流水线, 来实现机器学习从数据到模型的一整套端到端的过程。 而 pipeline
是一个工作流平台,能够编译部署机器学习的工作流。所以从这个层面来说,pipeline
能够成为 Kubeflow 的核心组件一点也不意外。
kubeflow/pipelines
实现了一个工作流模型。所谓工作流,或者称之为流水线(pipeline
),可以将其当做一个有向无环图(DAG
)。其中的每一个节点被称作组件(component
)。组件处理真正的逻辑,比如预处理,数据清洗,模型训练等。每一个组件负责的功能不同,但有一个共同点,即组件都是以 Docker 镜像的方式被打包,以容器的方式被运行的。
下图显示了 Kubeflow Pipelines UI 中管道的运行时执行图:
实验(experiment
)是一个工作空间,在其中可以针对流水线尝试不同的配置。用户在执行的过程中可以看到每一步的输出文件,以及日志。
步(step
)是组件的一次运行,输出工件(step output artifacts
)是在组件的一次运行结束后输出的,能被系统的前端理解并渲染可视化的文件。
Kubeflow Pipelines 平台包括:
- 用于管理和跟踪实验、作业和运行的用户界面 (UI)。
- 用于调度多个步骤 ML 工作流的引擎。
- 用于定义和操作管道和组件的 SDK。
- 使用 SDK 用于与系统交互的 Notebooks。
Pipelines 架构
下图是官方提供的 Kubeflow Pipelines
架构图:
可以将 pipeline 主要划分为八部分:
- Python SDK: 用于创建
kubeflow pipelines
组件的特定语言(DSL)。 - DSL compiler: 将 Python 代码转换成 YAML 静态配置文件(DSL编译器)。
- Pipeline Web Server:pipeline 的前端服务,它收集各种数据以显示相关视图:当前正在运行的 pipeline 列表,pipeline 执行的历史记录,有关各个 pipeline 运行的调试信息和执行状态等。
- Pipeline Service:pipeline 的后端服务,调用 kubernetes 服务从 YAML 创建 pipeline 运行。
- Kubernetes Resources:pipeline service 调用 Kubernetes api 服务器去创建用来运行 pipeline 所必须的 Kubernetes 资源kubernetes resources-CRDs。
- Machine Learning Metadata Service: 用于监视由
Pipeline Service
创建的 Kubernetes 资源,并将这些资源的状态持久化在ML元数据服务中(存储任务流容器之间的input
/output
数据交互)。 - Artifact Storage:
Kubeflow Pipelines
将元数据存储在 MySQL 数据库中,将工件存储在Minio服务器或Cloud Storage等工件存储中。
pods 存储两种类型的数据:- Metadata(元数据): 实验、任务、运行的管道还有单梯度的指标。pipeline 将这些元数据存放在 MySQL 数据库中。
- Artifacts(归档文件):pipeline 的包、视图以及大规模指标。大规模指标可以用来 debug 运行中的 pipeline 或者调查单个运行的 pipelien 的性能。pipeline 存放这些归档文件到 minio server 或者云存储上。
- Orchestration Controllers:一组用来编排运行 pipeline 所需要执行的容器的控制器。这些容器运行在 Kubernetes 的 pod 中。任务编排,比如 Argo Workflow 控制器,它可以协调任务驱动的工作流。
Pipelines 工作原理
流水线的定义可以分为两步,
第一步是定义组件,组件可以从镜像开始完全自定义。自定义的方式:
- 首先需要打包一个 Docker 镜像,这个镜像是组件的依赖,每一个组件的运行,就是一个 Docker 容器。
- 其次需要为其定义一个 Python 函数,描述组件的输入输出等信息,这一定义是为了能够让流水线理解组件在流水线中的结构,有几个输入节点,几个输出节点等。
- 接下来组件的使用就与普通的组件并无二致了。
第二步是根据定义好的组件组成流水线,在流水线中,由输入输出关系会确定图上的边以及方向。在定义好流水线后,可以通过 Python 中实现好的流水线客户端提交到系统中运行。
虽然 kubeflow/pipelines
的使用略显复杂,但它的实现其实并不麻烦。整个的架构可以分为五个部分,分别是 ScheduledWorkflow CRD
以及其 operator 流水线前端
,流水线后端
,Python SDK
和 persistence agent
。
ScheduledWorkflow CRD
扩展了argoproj/argo
的Workflow
定义。这也是流水线项目中的核心部分,它负责真正地在 Kubernetes 上按照拓扑序创建出对应的容器完成流水线的逻辑。Python SDK
负责构造出流水线,并且根据流水线构造出ScheduledWorkflow
的YAML
定义,随后将其作为参数传递给流水线系统的后端服务。- 后端服务依赖关系存储数据库(如 MySQL)和对象存储(如 S3),处理所有流水线中的
CRUD
请求。 - 前端负责可视化整个流水线的过程,以及获取日志,发起新的运行等。
Persistence agent
负责把数据从Kubernetes Master
的etcd
中sync
到后端服务的关系型数据库中,其实现的方式与CRD operator
类似,通过informer
来监听Kubernetes apiserver
对应资源实现。
Pipelines 提供机器学习流程的创建、编排调度和管理,还提供了一个 Web UI
。这部分主要基于 Argo Workflow
。
Fairing
Kubeflow Fairing
是一个 Python 软件包,可轻松在 Kubeflow 上训练和部署 ML 模型。Fairing
还可以扩展为在其他平台上进行训练或部署。目前,Fairing
已扩展为可在Google AI Platform上进行训练。
Fairing
简化了在混合云环境中构建,训练和部署机器学习(ML)训练 job 的过程。通过使用 Fairing
并添加几行代码,可以直接从 Jupyter notebook
在本地或在云中使用 Python 代码运行ML训练作业。训练工作完成后,可以使用 Fairing
将训练后的模型部署为预测端点。
Katib
在了解 katib
的处理流程之前,先介绍下 katib
目前有哪些组件:
- Experiment Controller:提供对
Experiment CRD
的生命周期管理。 - Trial Controller:提供对
Trial CRD
的生命周期管理。 - Suggestions:以
Deployment
的方式部署,用Service
方式暴露服务,提供超参数搜索服务。目前有随机搜索,网格搜索,贝叶斯优化等。 - Katib Manager:一个
GRPC server
,提供了对Katib DB
的操作接口,同时充当Suggestion
与Experiment
之间的代理。 - Katib DB:数据库。其中会存储
Trial
和Experiment
,以及Trial
的训练指标。目前默认的数据库为 MySQL。
Katib 架构
Katib 工作原理
当一个 Experiment
被创建的时候,Experiment Controller
会先通过 Katib Manager
在 Katib DB
中创建一个 Experiment
对象,并且打上 Finalizer
表明这一对象使用了外部资源(数据库)。
随后,Experiment Controller
会根据自身的状态和关于并行的定义,通过 Katib Manager
提供的GRPC
接口,让 Manager
通过 Suggestion
提供的 GRPC
接口获取超参数取值,然后再转发给 Experiment Controller
。
在这个过程中,Katib Manager
是一个代理的角色,它代理了 Experiment Controller
对Suggestion
的请求。拿到超参数取值后,Experiment Controller
会根据 Trial Template
和超参数的取值,构造出 Trial
的定义,然后在集群中创建它。Trial
被创建后,与 Experiment Controller
的行为类似,Trial Controller
同样会通过 Katib Manager
在 Katib DB
中创建一个 Trial
对象。随后会构造出期望的 Job
(如batchv1 Job
,TFJob
,PyTorchJob
等)和 Metrics Collector Job
,然后在集群上创建出来。这些 Job
运行结束后,Trial Controller
会更新 Trial
的状态,进而 Experiment Controller
会更新 Experiment
的状态。
然后 Experiment
会继续下一轮的迭代。之前的 Trial
已经被训练完成,而且训练的指标已经被收集起来了。Experiment
会根据配置,判断是否要再创建新的 Trial
,如果需要则再重复之前的流程。
下图是从网络上(知乎@高策)找到的 Katib
竞品对比分析图,可供参考:
超参优化是一种 AutoML
的方法。 Kubeflow 把 Katib
集成进来作为超参优化的一种方案。超参优化在实际的工作中还没有被大规模的应用,所以这部分的技术还需要一些时间来成熟。
KFServing
对于深度学习的产品化来说,训练只是手段不是目的,目的是将通过训练产生的模型放到手机的程序里或者互联网的应用中,用于语音或者文字的识别等应用场景中。
模型的服务化部署和离线预测也是机器学习流程中非常重要的部分。Kubeflow 组件中可以看到,它提供基于TF Serving
,KFServing
,Seldon Core Serving
等好几种方案。由于机器学习框架很多,算法模型也各种各样。工业界一直缺少一种能真正统一的部署框架和方案。这方面 Kubeflow 也仅仅是把常见的都集成了进来,但是并没有做更多的抽象和统一。
Kubeflow 提供两个支持多框架的模型服务工具:KFServing
和 Seldon Core Serving
。或者,可以使用独立的模型服务系统,以便可以选择最能满足模型服务要求的框架。
对于 TensorFlow 模型,可以使用 TensorFlow Serving
将 TFJob
导出的模型进行实时预测。但是,如果打算使用多个框架,则应考虑如上所述使用 KFServing
或 Seldon Core Serving
。KFServing
是 Kubeflow 项目生态系统的一部分,Seldon Core Serving
是 Kubeflow 支持的外部项目。看起来 Kubeflow 社区更倾向 KFServing
这套方案。
KFServing
提供了 Kubernetes CRD,用于在任意框架上服务机器学习(ML)模型。它旨在通过为常见ML框架(Tensorflow
,XGBoost
,ScikitLearn
,PyTorch
和ONNX
等)提供高性能,高抽象的接口来解决模型服务用例。
NVIDIA Triton Inference Server
是一项 REST
和 GRPC
服务,用于对 TensorRT
,TensorFlow
,Pytorch
,ONNX
和 Caffe2
模型进行深度学习推理。该服务器经过优化,可以在GPU和CPU上大规模部署机器学习算法。Triton
推理服务器以前称为 TensorRT
推理服务器。
我们可以将 NVIDIA Triton Inference Server
用作独立系统,但如上所述,更应该考虑使用 KFServing
。KFServing
也包括对 NVIDIA Triton Inference Server
的支持。
赞!现在我们终于知道如何发布我们训练好的服务了!
虽然 Kubeflow 最开始只是基于 tf-operator
,但后来随着项目发展最后变成一个基于云原生构建的机器学习任务工具大集合。从数据采集,验证,到模型训练和服务发布,几乎所有步骤 Kubeflow 都提供解决方案的组件。