

基于OAM和kfserving实现通用化云原生模型应用部署
source link: https://my.oschina.net/Kanonpy/blog/4956258
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

kfserving 是 kubeflow 一个用于构建部署标准化的算法模型 serverless 组件,但其和 knative 深度绑定,对传输链路进行了隐藏,如封装istio,这样复杂的结构不利于生产环境直接使用,这里通过 kubevela 实现的 OAM 将 serverless 流程重新进行简单的标准化封装,以实现一个简单的算法模型 serverless。
如何为算法团队提供高效的工程化上云支持是云原生时代一个很重要的也很有意义的课题,现在开源社区比较完善的应该是 Kubeflow —— 一系列 ML 实验部署环境工具的集合,不过整体来看比较笨重,不适合小团队生产环境快速落地,这里基于 kubevela 和 kfserving 实现一个算法标准化模型的例子,供参考。
项目地址:https://github.com/shikanon/vela-example/tree/main/example/sklearnserver
通过 kubevela 提供了三种对象 mpserver, hpa, httproute。
- mpserver 主要负责生成 deployment 和 service 资源,是程序运行的主体
- httroute 主要负责生成对外暴露的端口,访问 url
- hpa 主要保证服务的可扩展性
部署前准备工作
由于使用到vela
,所以需要先下载vela
客户端
创建一个 sklearn 的服务
案例放在 exmaple/sklearnserver
下面。
- 本地镜像编译并运行:
# 编译
docker build -t swr.cn-north-4.myhuaweicloud.com/hw-zt-k8s-images/sklearnserver:demo-iris -f sklearn.Dockerfile .
- 上传到华为云镜像仓库
docker login swr.cn-north-4.myhuaweicloud.com
docker push swr.cn-north-4.myhuaweicloud.com/hw-zt-k8s-images/sklearnserver:demo-iris
- 创建一个
demo-iris-01.yaml
的应用文件
name: demo-iris-01
services:
demo-iris:
type: mpserver
image: swr.cn-north-4.myhuaweicloud.com/hw-zt-k8s-images/sklearnserver:demo-iris
ports: [8080]
cpu: "200m"
memory: "250Mi"
httproute:
gateways: ["external-gateway"]
hosts: ["demo-iris.rcmd.testing.mpengine"]
servernamespace: rcmd
serverport: 8080
hpa:
min: 1
max: 1
cpuPercent: 60
因为这里使用的是rcmd
命名空间,在创建的时候需要切换,可以通过vela dashboard 通过可视化界面创建一个 rcmd
命名空间的环境:
vela dashboard
成功后可以通过vela env
查看:
$ vela env ls
NAME CURRENT NAMESPACE EMAIL DOMAIN
default default
rcmd * rcmd
- 在云原生环境运行应用
$ vela up -f demo-iris-01.yaml
Parsing vela appfile ...
Load Template ...
Rendering configs for service (demo-iris)...
Writing deploy config to (.vela/deploy.yaml)
Applying application ...
Checking if app has been deployed...
App has not been deployed, creating a new deployment...
✅ App has been deployed 🚀🚀🚀
Port forward: vela port-forward demo-iris-01
SSH: vela exec demo-iris-01
Logging: vela logs demo-iris-01
App status: vela status demo-iris-01
Service status: vela status demo-iris-01 --svc demo-iris
部署好后可以测试:
$ curl -i -d '{"instances":[[5.1, 3.5, 1.4, 0.2]]}' -H "Content-Type: application/json" -X POST demo-iris.rcmd.testing.mpengine:8000/v1/models/model:predict
{"predictions": [0]}
kfserver 开发算法 server
kfserver 提供了多种常用框架的 server,比如 sklearn, lgb, xgb, pytorch 等多种服务的 server 框架, kfserver 基于 tornado 框架进行开发,其提供了 模型加载,接口健康检测,预测及 参考解释等多个抽象接口,详细见kfserving/kfserving/kfserver.py
:
...
def create_application(self):
return tornado.web.Application([
# Server Liveness API returns 200 if server is alive.
(r"/", LivenessHandler),
(r"/v2/health/live", LivenessHandler),
(r"/v1/models",
ListHandler, dict(models=self.registered_models)),
(r"/v2/models",
ListHandler, dict(models=self.registered_models)),
# Model Health API returns 200 if model is ready to serve.
(r"/v1/models/([a-zA-Z0-9_-]+)",
HealthHandler, dict(models=self.registered_models)),
(r"/v2/models/([a-zA-Z0-9_-]+)/status",
HealthHandler, dict(models=self.registered_models)),
(r"/v1/models/([a-zA-Z0-9_-]+):predict",
PredictHandler, dict(models=self.registered_models)),
(r"/v2/models/([a-zA-Z0-9_-]+)/infer",
PredictHandler, dict(models=self.registered_models)),
(r"/v1/models/([a-zA-Z0-9_-]+):explain",
ExplainHandler, dict(models=self.registered_models)),
(r"/v2/models/([a-zA-Z0-9_-]+)/explain",
ExplainHandler, dict(models=self.registered_models)),
(r"/v2/repository/models/([a-zA-Z0-9_-]+)/load",
LoadHandler, dict(models=self.registered_models)),
(r"/v2/repository/models/([a-zA-Z0-9_-]+)/unload",
UnloadHandler, dict(models=self.registered_models)),
])
...
这里我们使用的 sklearn server 的案例主要实现了 predict
接口:
import kfserving
import joblib
import numpy as np
import os
from typing import Dict
MODEL_BASENAME = "model"
MODEL_EXTENSIONS = [".joblib", ".pkl", ".pickle"]
class SKLearnModel(kfserving.KFModel): # pylint:disable=c-extension-no-member
def __init__(self, name: str, model_dir: str):
super().__init__(name)
self.name = name
self.model_dir = model_dir
self.ready = False
def load(self) -> bool:
model_path = kfserving.Storage.download(self.model_dir)
paths = [os.path.join(model_path, MODEL_BASENAME + model_extension)
for model_extension in MODEL_EXTENSIONS]
for path in paths:
if os.path.exists(path):
self._model = joblib.load(path)
self.ready = True
break
return self.ready
def predict(self, request: Dict) -> Dict:
instances = request["instances"]
try:
inputs = np.array(instances)
except Exception as e:
raise Exception(
"Failed to initialize NumPy array from inputs: %s, %s" % (e, instances))
try:
result = self._model.predict(inputs).tolist()
return {"predictions": result}
except Exception as e:
raise Exception("Failed to predict %s" % e)
Recommend
-
16
业务中台的价值主要体现在对通用化业务能力的沉淀、整合,通过对可复用业务流程和业务功能的设计,向不同业务方提供标准化且可扩展的服务能力。本文来聊一聊笔者工作过程中设计的通用化黑名单平台,通过将用户管控能力的下沉,为各业务团...
-
22
作者 | 匡大虎、阚俊宝 基于 Kubernetes 平台,我们可以轻松的搭建一些简单的无状态应用,比如对于一些常见的 web apps 或是移...
-
11
Bean是什么我们知道Bean是Spring最基础的核心构件,大多数逻辑代码都通过Bean进行管理。NestJS基于TypeScript和依赖注入也实现了类似于Spring Bean的机...
-
8
拥抱云原生,基于eBPF技术实现Serverless节点访问K8S ServiceServerless容器的服务发现2020年9月,UCloud上线了Serverless容器产品Cube,它具备了虚拟机级别的安全隔离、轻量化的系统占用、秒级的启动速度,高度自动化的弹性伸缩,以...
-
6
V2EX › JavaScript 有没有基于原生 JavaScript 实现的 admin 后台模板 manyfreebug · 12 小...
-
5
藏书馆App基于Rainbond实现云原生DevOps的实践> 我们需要的不是精通Kubernetes的工程师,我们需要一款小白都能用好的管理工具。 >...
-
9
-
6
1 微信小程序原生推拉流组件功能简介本文将介绍如何使用微信小程序原生推拉流组件 \ 进行推拉流,快速实现一个简单的实时音视频通话。由于微信小程序原生推拉流组件使用起来比较复杂,推荐开发者使用即构封装的音视频SDK \ 组件实现视频通话...
-
4
aspnetcore 原生 DI 实现基于 key 的服务获取 2023-02-21 2你可能想通过一个字符串或者其他的类型来获取一个具体的服务实现,那么在 aspnetcore 原生的 MSDI 中,如何实现呢?本文将介绍如何通过...
-
5
鸿蒙原生应用/元服务开发-Stage模型能力接口(九)上 精选 原创 鸿蒙时代
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK