基于KServe快速部署一个推理服务

KServe是一个基于Kubernetes的机器学习模型服务框架,支持以Kubernetes CRD的形式将单个或多个经过训练的模型(例如TFServing、TorchServe、Triton等推理服务器)部署到模型服务运行时,使得模型的部署、更新和扩展变得更加简单快捷。本文介绍如何在Knative中基于 KServe 快速部署一个推理服务,帮助您高效地将机器学习模型应用于生产环境。

基于Knative使用InferenceService部署模型后,您将获得以下Serverless能力:

  • 缩容到0

  • 基于RPS、并发数、CPU/GPU指标自动弹性

  • 多版本管理

  • 流量管理

  • 安全认证

  • 开箱即用可观测性

展开查看KServe介绍

  • ModelServerMLServer

    KServe内置了ModelServerMLServer两种预定义模型服务运行时,它们能够提供开箱即用的模型服务。ModelServer使用预测v1协议在KServe本身中实现Python模型服务运行时,MLServer使用RESTgRPC实现预测v2协议。如果需要更复杂的用例,您也可以选择构建自己的自定义模型服务器。此外,KServe还提供基本API原语,可轻松构建自定义模型服务运行时。您也可以使用其他工具(例如BentoML)来构建您自己的自定义模型服务镜像。

  • KServe Controller

    KServe ControllerKServe的核心组件之一,它负责管理InferenceService自定义资源,并通过创建Knative服务部署实现自动化的扩缩容,即该服务部署能根据请求流量进行自动扩缩容,并在未收到流量时将服务的Pod缩容到0。这种自动化的扩缩容可以有效地管理模型服务的资源使用,并确保只有在需要时才会使用资源。

    image

前提条件

已在集群中部署Knative,请参见部署Knative

步骤一:部署KServe组件

  1. 登录容器服务管理控制台,在左侧导航栏选择集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > Knative

  3. 组件管理页签,找到KServe组件,然后单击部署,按照页面指引完成组件的安装。

    当组件状态显示为已部署,表明组件部署成功。

步骤二:部署InferenceService推理服务

首先,您需要部署一个带有预测能力的InferenceService推理服务,该推理服务将使用iris (鸢尾花)数据集训练的scikit-learn模型。该数据集具有三个输出类别:Iris Setosa(山鸢尾,索引:0)、Iris Versicolour(杂色鸢尾花,索引:1)和Iris Virginica(弗吉尼亚鸢尾,索引:2)。 然后您可以向部署的模型发送推理请求,以便预测对应的鸢尾植物类别。

说明

iris数据集是由三种鸢尾花,各50组数据构成的数据集。每个样本包含4个特征,分别为萼片(Sepals)的长和宽、花瓣(Petals)的长和宽。

  1. 执行以下命令,创建一个名为sklearn-irisInferenceService推理服务。

    kubectl apply -f - <<EOF
    apiVersion: "serving.kserve.io/v1beta1"
    kind: "InferenceService"
    metadata:
      name: "sklearn-iris"
    spec:
      predictor:
        model:
          modelFormat:
            name: sklearn
          storageUri: "gs://kfserving-examples/models/sklearn/1.0/model"
    EOF
  2. 执行以下命令,检查服务状态。

    kubectl get inferenceservices sklearn-iris

    预期输出:

    NAME           URL                                                         READY   PREV   LATEST   PREVROLLEDOUTREVISION   LATESTREADYREVISION                    AGE
    sklearn-iris   http://sklearn-iris-predictor-default.default.example.com   True           100                              sklearn-iris-predictor-default-00001   51s

步骤三:访问服务

不同服务网关的IP地址有所不同,访问方式也有所不同。请按需选择。

ALB

  1. 执行以下命令,获取ALB访问地址。

    kubectl get albconfig knative-internet                         

    预期输出:

    NAME               ALBID                    DNSNAME                                              PORT&PROTOCOL   CERTID   AGE
    knative-internet   alb-hvd8nngl0l*******   alb-hvd8nngl0l******.cn-<region>.alb.aliyuncs.com                               2
  2. 执行以下命令,将以下JSON内容写入 ./iris-input.json文件中,以准备推理输入请求。

    cat <<EOF > "./iris-input.json"
    {
      "instances": [
        [6.8,  2.8,  4.8,  1.4],
        [6.0,  3.4,  4.5,  1.6]
      ]
    }
    EOF
  3. 执行以下命令,访问服务。

    INGRESS_DOMAIN=$(kubectl get albconfig knative-internet -o jsonpath='{.status.loadBalancer.dnsname}')
    SERVICE_HOSTNAME=$(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d "/" -f 3)
    curl -v -H "Host: ${SERVICE_HOSTNAME}" "http://${INGRESS_DOMAIN}/v1/models/sklearn-iris:predict" -d @./iris-input.json

    预期输出:

    *   Trying 120.77.XX.XX...
    * TCP_NODELAY set
    * Connected to alb-hvd8nngl0l******.cn-<region>.alb.aliyuncs.com (120.77.XX.XX) port 80 (#0)
    > POST /v1/models/sklearn-iris:predict HTTP/1.1
    > Host: sklearn-iris-predictor-default.default.example.com
    > User-Agent: curl/7.58.0
    > Accept: */*
    > Content-Length: 76
    > Content-Type: application/x-www-form-urlencoded
    > 
    * upload completely sent off: 76 out of 76 bytes
    < HTTP/1.1 200 OK
    < Date: Thu, 13 Jul 2023 01:48:44 GMT
    < Content-Type: application/json
    < Content-Length: 21
    < Connection: keep-alive
    < 
    * Connection #0 to host alb-hvd8nngl0l******.cn-<region>.alb.aliyuncs.com left intact
    {"predictions":[1,1]}

    结果返回了两个预测 {"predictions": [1, 1]},该结果为推理发送的两组数据点对应于索引为1的花,模型预测这两种花都是Iris Versicolour(杂色鸢尾花)。

MSE

  1. 执行以下命令,获取MSE访问地址。

    kubectl -n knative-serving get ing stats-ingress

    预期输出:

    NAME            CLASS                  HOSTS   ADDRESS                         PORTS   AGE
    stats-ingress   knative-ingressclass   *       192.168.XX.XX,47.107.XX.XX      80      15d

    ADDRESS下方的47.107.XX.XXMSE网关公网地址,后续会使用该地址访问服务。MSE的公网和内网顺序不固定,有时公网排在内网后面,即ADDRESS47.107.XX.XX,192.168.XX.XX

  2. 执行以下命令,将以下JSON内容写入 ./iris-input.json文件中,以准备推理输入请求。

    cat <<EOF > "./iris-input.json"
    {
      "instances": [
        [6.8,  2.8,  4.8,  1.4],
        [6.0,  3.4,  4.5,  1.6]
      ]
    }
    EOF
  3. 执行以下命令,访问服务。

    # MSE的公网和内网顺序不固定,此处使用公网地址访问。ingress[1]代表公网排在第二位,ingress[0]代表公网排在第一位,请按照实际情况替换。
    INGRESS_HOST=$(kubectl -n knative-serving get ing stats-ingress -o jsonpath='{.status.loadBalancer.ingress[1].ip}')
    SERVICE_HOSTNAME=$(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d "/" -f 3)
    curl -v -H "Host: ${SERVICE_HOSTNAME}" "http://${INGRESS_HOST}/v1/models/sklearn-iris:predict" -d @./iris-input.json

    预期输出:

    *   Trying 47.107.XX.XX... # 47.107.XX.XXMSE网关的公网地址。
    * TCP_NODELAY set
    * Connected to 47.107.XX.XX (47.107.XX.XX) port 80 (#0)
    > POST /v1/models/sklearn-iris:predict HTTP/1.1
    > Host: sklearn-iris-predictor-default.default.example.com
    > User-Agent: curl/7.58.0
    > Accept: */*
    > Content-Length: 76
    > Content-Type: application/x-www-form-urlencoded
    > 
    * upload completely sent off: 76 out of 76 bytes
    < HTTP/1.1 200 OK
    < content-length: 21
    < content-type: application/json
    < date: Tue, 11 Jul 2023 09:56:00 GMT
    < server: istio-envoy
    < req-cost-time: 5
    < req-arrive-time: 1689069360639
    < resp-start-time: 1689069360645
    < x-envoy-upstream-service-time: 4
    < 
    * Connection #0 to host 47.107.XX.XX left intact
    {"predictions":[1,1]}

    结果返回了两个预测 {"predictions": [1, 1]},该结果为推理发送的两组数据点对应于索引为1的花,模型预测这两种花都是Iris Versicolour(杂色鸢尾花)。

Kourier

  1. 执行以下命令,获取Kourier服务访问地址。

    kubectl -n knative-serving get svc kourier

    预期输出:

    NAME      TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)                      AGE
    kourier   LoadBalancer   192.168.XX.XX   121.40.XX.XX  80:31158/TCP,443:32491/TCP   49m

    服务访问IP121.40.XX.XX,端口为80(HTTP)和443(HTTPS)。

  2. 执行以下命令,将以下JSON内容写入 ./iris-input.json文件中,以准备推理输入请求。

    cat <<EOF > "./iris-input.json"
    {
      "instances": [
        [6.8,  2.8,  4.8,  1.4],
        [6.0,  3.4,  4.5,  1.6]
      ]
    }
    EOF
  3. 执行以下命令,访问服务。

    INGRESS_HOST=$(kubectl -n knative-serving get service kourier -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    SERVICE_HOSTNAME=$(kubectl get inferenceservice sklearn-iris -o jsonpath='{.status.url}' | cut -d "/" -f 3)
    curl -v -H "Host: ${SERVICE_HOSTNAME}" "http://${INGRESS_HOST}/v1/models/sklearn-iris:predict" -d @./iris-input.json

    预期输出:

    *   Trying 121.40.XX.XX...
    * TCP_NODELAY set
    * Connected to 121.40.XX.XX (121.40.XX.XX) port 80 (#0)
    > POST /v1/models/sklearn-iris:predict HTTP/1.1
    > Host: sklearn-iris-predictor-default.default.example.com
    > User-Agent: curl/7.58.0
    > Accept: */*
    > Content-Length: 76
    > Content-Type: application/x-www-form-urlencoded
    > 
    * upload completely sent off: 76 out of 76 bytes
    < HTTP/1.1 200 OK
    < content-length: 21
    < content-type: application/json
    < date: Wed, 12 Jul 2023 08:23:13 GMT
    < server: envoy
    < x-envoy-upstream-service-time: 4
    < 
    * Connection #0 to host 121.40.XX.XX left intact
    {"predictions":[1,1]}

    结果返回了两个预测 {"predictions": [1, 1]},该结果为推理发送的两组数据点对应于索引为1的花,模型预测这两种花都是Iris Versicolour(杂色鸢尾花)。

相关文档