我正在探索Kubeflow作为部署和连接典型ML管道的各个组件的一种选择。我将Docker容器用作Kubeflow组件,到目前为止,我一直无法成功使用ContainerOp.file_outputs
对象在组件之间传递结果。
根据我对功能的了解,创建并保存到声明为组件file_outputs
之一的文件后,该文件将继续存在并可由以下组件读取。
这是我尝试在管道python代码中声明的方式:
import kfp.dsl as dsl
import kfp.gcp as gcp
@dsl.pipeline(name='kubeflow demo')
def pipeline(project_id='kubeflow-demo-254012'):
data_collector = dsl.ContainerOp(
name='data collector',
image='eu.gcr.io/kubeflow-demo-254012/data-collector',
arguments=[ "--project_id", project_id ],
file_outputs={ "output": '/output.txt' }
)
data_preprocessor = dsl.ContainerOp(
name='data preprocessor',
image='eu.gcr.io/kubeflow-demo-254012/data-preprocessor',
arguments=[ "--project_id", project_id ]
)
data_preprocessor.after(data_collector)
#TODO: add other components
if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(pipeline, __file__ + '.tar.gz')
在data-collector.py
组件的python代码中,我获取数据集,然后将其写入output.txt
。我可以从同一组件内的文件中读取文件,但不能在data-preprocessor.py
内的文件中读取文件。
使用FileNotFoundError
是否对基于容器的Kubeflow组件无效,还是我在代码中错误地使用了它?如果不是我的选择,是否可以在管道声明python代码内以编程方式创建Kubernetes卷并使用它们代替file_outputs
?
答案 0 :(得分:1)
在一个Kubeflow管道组件中创建的文件在容器本地。要在后续步骤中引用它,您需要将其传递为:
data_preprocessor = dsl.ContainerOp(
name='data preprocessor',
image='eu.gcr.io/kubeflow-demo-254012/data-preprocessor',
arguments=["--fetched_dataset", data_collector.outputs['output'],
"--project_id", project_id,
]
注意::data_collector.outputs['output']
将包含文件/output.txt
的实际字符串内容(不是文件的路径)。如果要使其包含文件的路径,则需要将数据集写入共享存储(例如s3或已安装的PVC卷),并将指向共享存储的路径/链接写入/output.txt
。 data_preprocessor
然后可以根据路径读取数据集。
答案 1 :(得分:0)
主要有三个步骤:
保存一个outputs.txt文件,其中将包含要传递给下一个组件的数据/参数/任何内容。 注意:它应该位于根级别,即/output.txt
将file_outputs = {'output':'/output.txt'}作为参数显示为示例。
在container_op内,您将在dsl.pipeline内部传递参数(传递给需要从较早组件输出的组件的相应参数)作为comp1.output(此处comp1是第一个产生输出并将其存储在/中的组件) output.txt)
import kfp
from kfp import dsl
def SendMsg(
send_msg: str = 'akash'
):
return dsl.ContainerOp(
name = 'Print msg',
image = 'docker.io/akashdesarda/comp1:latest',
command = ['python', 'msg.py'],
arguments=[
'--msg', send_msg
],
file_outputs={
'output': '/output.txt',
}
)
def GetMsg(
get_msg: str
):
return dsl.ContainerOp(
name = 'Read msg from 1st component',
image = 'docker.io/akashdesarda/comp2:latest',
command = ['python', 'msg.py'],
arguments=[
'--msg', get_msg
]
)
@dsl.pipeline(
name = 'Pass parameter',
description = 'Passing para')
def passing_parameter(send_msg):
comp1 = SendMsg(send_msg)
comp2 = GetMsg(comp1.output)
if __name__ == '__main__':
import kfp.compiler as compiler
compiler.Compiler().compile(passing_parameter, __file__ + '.tar.gz')