写点什么

Seldon 使用 (四):内置的推理服务 TFServing

用户头像
托内多
关注
发布于: 2021 年 07 月 25 日

Seldon 内置(Prepack)支持了一些推理服务类型,包括 Tensorflow serving(简称 TFServing),Triton inference server, MLflow, sklearn, xgboost。本文重点介绍 Tensorflow serving,由点带面地理解内置(Prepack)推理服务如何使用以及实现细节。

1 TFServing 服务简介

TFServing 是 Tensorflow 官方提供的模型在线推理服务,开箱即用,具备高性能,低延迟,灵活易扩展,可同时支持多模型多版本,支持 GRPC 和 HTTP。


TFServing 服务架构如下图所示,这里摘抄一段官方的处理流程介绍,一个典型的模型加载及调用过程

  • 当 Source 模块检测到新的模型权重(weights),它会创建一个 Loader(指向该模型数据)

  • Source 模块通知 DynamicManager,告诉它这有一个可用的模型版本(Aspired version)

  • DynamicManager 根据 VersionPolicy 配置,判断是否加载这个新版本

  • DynamicManager 调用 Loader 加载并初始化这个新的模型版本

  • 客户端(client)向 DynamicManager 请求该模型的 handle,DynamicManager 返回该模型的最新 handle

如需更详细的资料,可查看https://github.com/tensorflow/serving/blob/master/tensorflow_serving/g3doc/architecture.md

2 如何创建和部署 TFServing

定义 SeldonDeployment 文件 tfserving-sdep.yaml,如下:

apiVersion: machinelearning.seldon.io/v1alpha2kind: SeldonDeploymentmetadata:  name: tfservingspec:  name: mnist  predictors:  - graph:      children: []      implementation: TENSORFLOW_SERVER      modelUri: gs://seldon-models/tfserving/mnist-model      name: mnist-model      parameters:        - name: signature_name          type: STRING          value: predict_images        - name: model_name          type: STRING          value: mnist-model    name: default    replicas: 1
复制代码

说明:


部署该 sdep,执行如下命令

kubectl create -f tfserving-sdep.yaml
复制代码

创建完成后,可通过如下命令,查看到 pod 及 service 被创建

# kubectl get sdepNAME           AGEtfserving      1m
# kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEtfserving-default-mnist-model ClusterIP 10.254.1.2 <none> 9000/TCP 1m
# kubectl get podNAME READY STATUS RESTARTS AGEtfserving-default-0-mnist-model-2e8e-y1ae7 3/3 Running 0 1m
复制代码

2.1 如何调用推理服务

从上面的 service 和 pod 信息,我们可以使用 service 的 cluster IP 或者 pod 的 IP,调用这个 mnist 推理服务。

下面我们通过 seldon 的 API 接口,调用推理服务。我们可以构造如下请求:

import jsonimport randomimport sys
import requests
url = "http://%s:9000/api/v1.0/predictions" % sys.argv[1]data = [ [random.random() for i in range(784)]]# seldon protocolpayload = {"data":{"ndarray": data}}
resp = requests.post(url, json=payload)print(resp.content)
复制代码

返回结果如下:

{   "data":{     "names":["t:0","t:1","t:2","t:3","t:4","t:5","t:6","t:7","t:8","t:9"],      "ndarray":[[2.31042499e-20,4.70782478e-30,0.017343564,0.903749764,1.29772914e-33,0.0789065957,9.34007e-14,4.42152e-19,1.50050141e-07,9.49472516e-17]]    },    "meta":{}}
复制代码

3 Seldon 如何实现内置推理服务

seldon 的 manager 服务,即 seldon-controller-manager,这是一个 k8s 的 Operator 服务,负责管理所有 SeldonDeployment(简称 sdep)资源的生命周期,包括创建,修改及删除。每当新的 sdep 资源被创建时,manager 服务会为其创建相关的 deployment 及 service。

从上面的 pod 信息,我们可以看到,当 sdep 资源创建后,manager 服务为其创建了一个 pod。这个 pod 包含了四个 container,具体如下内容:

  containers:  - name: mnist-model    env:    - name: PREDICTIVE_UNIT_PARAMETERS      value: '[{"name":"signature_name","value":"predict_images","type":"STRING"},{"name":"model_name","value":"mnist-model","type":"STRING"},{"name":"rest_endpoint","value":"http://0.0.0.0:2001","type":"STRING"},{"name":"model_name","value":"mnist-model","type":"STRING"}]'    image: seldonio/tfserving-proxy_rest:1.2.1  - name: tfserving    args:    - /usr/bin/tensorflow_model_server    - --port=2000    - --rest_api_port=2001    - --model_name=mnist-model    - --model_base_path=/mnt/models    image: tensorflow-serving:2.1.0    volumeMounts:    - mountPath: /mnt/models      name: tfserving-provision-location  - name: seldon-container-engine    args:    - --sdep    - tfserving    - --namespace    - kubeflow    - --predictor    - default    - --port    - "8000"    - --protocol    - seldon    - --prometheus_path    - /prometheus    image: seldon/seldon-core-executor:1.2.1  initContainers:  - args:    - gs://seldon-models/tfserving/mnist-model    - /mnt/models    image: gcr.io/kfserving/storage-initializer:0.2.2    volumeMounts:    - mountPath: /mnt/models      name: tfserving-provision-location
复制代码

这四个 container 的作用和关系,分别如下:

  • init 容器:根据 sdep 的参数 modelUri,从 gs 获取模型文件,并保存到/mnt/models

  • tfserving 容器:从/mnt/models 加载模型,并通过 2000/2001 端口提供服务

  • mnist-model 容器:从其使用的 image 可知,这是一个 proxy 服务,主要实现协议转换,即 seldon 协议请求,转换成 tensorflow 协议请求

  • engine 容器:主要用于支持 sdep 资源的 graph 功能,即可以将多个模型服务分别进行打分及组合。将在后续文章继续展开介绍


最后,再从代码的角度看看,manager 服务处理 sdep 的主要过程。如下所示,如同其他的 operator 一样,manager 实现了 Reconcile()接口方法:

func (r *SeldonDeploymentReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {    // 获取sdep资源实例的信息    instance := &machinelearningv1.SeldonDeployment{}    err := r.Get(ctx, req.NamespacedName, instance)
// 设置默认值 instance.Default()
// 创建所需组件:主要是container components, err := r.createComponents(ctx, instance, podSecurityContext, log) // 创建服务网络:主要是service servicesReady, err := r.createServices(components, instance, false, log) // 创建deployment:即将container分配到deployment,并创建 deploymentsReady, err := r.createDeployments(components, instance, log)
if deploymentsReady { // 完成最后的创建 err := r.completeServiceCreation(instance, components, log) }}
复制代码

代码逻辑比较直观,就是分别创建相关的 k8s 资源。这里主要说一下 Default()和 createComponents()。在 sdep 的声明中,我们只需要配置 tensorflow 模型的名称和文件路径,但 manager 服务创建了上述四个容器,分别实现了不同的功能:

  • Default()方法,检查 sdep 的 componentSpecs(该示例未使用)是否有定义 mnist-model 容器,如果没有则创建一个,使用 tfserving-proxy 镜像。换句话讲,我们可以在 componentSpec 中自定义该 proxy 容器,而不使用默认的

  • createComponents()方法,调用 addTFServerContainer()分别创建 tfserving 容器和 init 容器(同样,我们可以在 componentSpecs 中自定义)。其中,init 容器会使用 sdep 的 modelUri 参数,用以下载模型文件。最后,调用 addEngineToDeployment()创建 engine 容器。(关于 engine 容器,将在后续文章介绍)

tfserving 容器监听端口 2001,proxy 容器实现协议转换将请求发送到该端口。上文的调用示例,访问的是 proxy 服务的端口,使用的是 seldon 协议。同样,可以直接访问 tfserving 端口,使用 tensorflow 协议。如下:

curl -s  -X POST http://$endpoint:2001/v1/models/mnist-model:predict  \  -H "Content-Type: application/json" \  -d '{"instances": [[0.7663934193992182, 0.0880671623857957, 0.0775122634595451,..., 0.4126315414418871, 0.42650235187504826]], "signature_name": "predict_images"}'
复制代码

返回结果如下:

{    "predictions": [[1.04614508e-17, 3.39505514e-32, 0.489694506, 0.476404935, 2.44480641e-25, 0.0338525251, 3.64945924e-15, 6.72624967e-15, 4.80203671e-05, 7.55260474e-16]    ]}
复制代码

4 总结

seldon 内置的 TFServing 服务,大大简化了模型推理服务的部署,用户只需要配置模型名称及文件路径即可,而不需要考虑模型文件如何下载,如何做协议转换等服务部署相关问题。通过使用默认配置简化用户输入,同时也提供了可自定义的方式(componentSpecs),以满足特定场景需求,这是很好地设计。


发布于: 2021 年 07 月 25 日阅读数: 279
用户头像

托内多

关注

享受coding,与时俱进 2017.10.24 加入

简单生活,砥砺前行

评论

发布
暂无评论
Seldon 使用 (四):内置的推理服务TFServing