添加部署推理服务模板

This commit is contained in:
pengluan 2022-05-31 14:15:48 +08:00
parent 01b0cda021
commit 73e2f3c81e
4 changed files with 388 additions and 0 deletions

View File

@ -0,0 +1,33 @@
FROM ubuntu:18.04
# 安装运维工具
RUN apt-get update && apt install -y --force-yes --no-install-recommends vim apt-transport-https gnupg2 ca-certificates-java rsync jq wget git dnsutils iputils-ping net-tools curl locales zip
# 安装python
RUN apt install -y python3.6-dev python3-pip libsasl2-dev libpq-dev \
&& ln -s /usr/bin/python3 /usr/bin/python \
&& ln -s /usr/bin/pip3 /usr/bin/pip
# 安装中文
RUN apt install -y --force-yes --no-install-recommends locales ttf-wqy-microhei ttf-wqy-zenhei xfonts-wqy && locale-gen zh_CN && locale-gen zh_CN.utf8
ENV LANG zh_CN.UTF-8
ENV LC_ALL zh_CN.UTF-8
ENV LANGUAGE zh_CN.UTF-8
# 便捷操作
RUN echo "alias ll='ls -alF'" >> /root/.bashrc && \
echo "alias la='ls -A'" >> /root/.bashrc && \
echo "alias vi='vim'" >> /root/.bashrc && \
/bin/bash -c "source /root/.bashrc"
RUN pip install kubernetes==12.0.1 pysnooper psutil
COPY job/deploy-service/* /app/
#COPY job/pkgs/config/ubuntu-sources.list /etc/apt/sources.list
#COPY job/pkgs/config/pip.conf /root/.pip/pip.conf
COPY job/pkgs /app/job/pkgs
WORKDIR /app
ENV PYTHONPATH=/app:$PYTHONPATH
ENTRYPOINT ["python3", "launcher.py"]

View File

@ -0,0 +1,192 @@
# deploy-service 模板
镜像ai.tencentmusic.com/tme-public/deploy-service:20211001
启动参数:
```bash
{
"shell": {
"--project_name": {
"type": "str",
"item_type": "str",
"label": "部署项目名",
"require": 1,
"choice": [],
"range": "",
"default": "public",
"placeholder": "",
"describe": "部署项目名",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--service_type": {
"type": "str",
"item_type": "str",
"label": "推理服务类型",
"require": 0,
"choice": ['service','tfserving','torch-server','onnxruntime','triton-server'],
"range": "",
"default": "service",
"placeholder": "",
"describe": "推理服务类型",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--label": {
"type": "str",
"item_type": "str",
"label": "推理服务描述",
"require": 0,
"choice": [],
"range": "",
"default": "demo推理服务",
"placeholder": "",
"describe": "推理服务描述",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--model_name": {
"type": "str",
"item_type": "str",
"label": "模型名",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "模型名",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--model_version": {
"type": "str",
"item_type": "str",
"label": "模型版本号",
"require": 0,
"choice": [],
"range": "",
"default": "v2022.10.01.1",
"placeholder": "",
"describe": "模型版本号",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--model_path": {
"type": "str",
"item_type": "str",
"label": "模型地址",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "模型地址",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--images": {
"type": "str",
"item_type": "str",
"label": "推理服务镜像",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "推理服务镜像",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--replicas": {
"type": "str",
"item_type": "str",
"label": "pod副本数",
"require": 0,
"choice": [],
"range": "",
"default": "1",
"placeholder": "",
"describe": "pod副本数",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--working_dir": {
"type": "str",
"item_type": "str",
"label": "推理容器工作目录",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "推理容器工作目录",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--command": {
"type": "str",
"item_type": "str",
"label": "推理容器启动命令",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "推理容器启动命令",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--args": {
"type": "str",
"item_type": "str",
"label": "推理容器启动参数",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "推理容器启动参数",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--env": {
"type": "text",
"item_type": "str",
"label": "推理容器环境变量",
"require": 0,
"choice": [],
"range": "",
"default": "",
"placeholder": "",
"describe": "推理容器环境变量",
"editable": 1,
"condition": "",
"sub_args": {}
},
"--ports": {
"type": "str",
"item_type": "str",
"label": "推理容器暴露端口",
"require": 0,
"choice": [],
"range": "",
"default": "80",
"placeholder": "",
"describe": "推理容器暴露端口",
"editable": 1,
"condition": "",
"sub_args": {}
},
}
}
```

View File

@ -0,0 +1,9 @@
#!/bin/bash
set -ex
docker build -t ai.tencentmusic.com/tme-public/deploy-service:20211001 -f job/deploy-service/Dockerfile .
docker push ai.tencentmusic.com/tme-public/deploy-service:20211001

View File

@ -0,0 +1,154 @@
import os,sys
base_dir = os.path.split(os.path.realpath(__file__))[0]
sys.path.append(base_dir)
import argparse
import datetime
import json
import time
import uuid
import os
import pysnooper
import os,sys
import re
import requests
import psutil
import copy
KFJ_CREATOR = os.getenv('KFJ_CREATOR', 'admin')
host = 'http://kubeflow-dashboard.infra'
# host = 'http://127.0.0.1:80'
# host = 'http://9.135.92.226'
@pysnooper.snoop()
def deploy(**kwargs):
# print(kwargs)
headers = {
'Content-Type': 'application/json',
'Authorization': KFJ_CREATOR
}
# 获取项目组
url = host + "/project_modelview/api/?form_data=" + json.dumps({
"filters": [
{
"col": "name",
"opr": "eq",
"value": kwargs['project_name']
}
]
})
res = requests.get(url, headers=headers)
exist_project = res.json().get('result', {}).get('data', [])
if not exist_project:
print('不存在项目组')
return
exist_project = exist_project[0]
# 查询同名是否存在,创建者是不是指定用户
url = host+"/inferenceservice_modelview/api/?form_data="+json.dumps({
"filters":[
{
"col": "model_name",
"opr": "eq",
"value": kwargs['model_name']
},
{
"col": "model_version",
"opr": "eq",
"value": kwargs['model_version']
}
]
})
# print(url)
res = requests.get(url,headers=headers)
# print(res.content)
if res.status_code==200:
payload = {
'model_name': kwargs['model_name'],
'model_version': kwargs['model_version'],
'model_path':kwargs['model_path'],
'label': kwargs['label'],
'project': exist_project['id'],
'images': kwargs['images'],
'working_dir': kwargs['working_dir'],
'command': kwargs['command'],
'args': kwargs['args'],
'env': kwargs['env'],
'resource_memory': kwargs['resource_memory'],
'resource_cpu': kwargs['resource_cpu'],
'resource_gpu': kwargs['resource_gpu'],
'min_replicas': kwargs['replicas'],
'max_replicas': kwargs['replicas'],
'ports': kwargs['ports'],
'volume_mount': kwargs['volume_mount'],
'host': kwargs['host'],
'hpa': kwargs['hpa'],
'service_type':kwargs['service_type']
}
exist_services = res.json().get('result',{}).get('data',[])
new_service=None
# 不存在就创建新的服务
if not exist_services:
url = host + "/inferenceservice_modelview/api/"
res = requests.post(url, headers=headers,json=payload)
if res.status_code==200:
new_service = res.json().get('result', {})
# print(res)
else:
exist_service=exist_services[0]
# 更新服务
url = host + "/inferenceservice_modelview/api/%s"%exist_service['id']
res = requests.put(url, headers=headers, json=payload)
if res.status_code==200:
new_service = res.json().get('result',{})
# print(res)
if new_service:
print(new_service)
url = host + "/inferenceservice_modelview/deploy/prod/%s"%new_service['id']
res = requests.post(url,headers=headers)
if res.status_code==302 or res.status_code==200:
print('部署成功')
else:
print('部署失败')
if __name__ == "__main__":
arg_parser = argparse.ArgumentParser("deploy service launcher")
arg_parser.add_argument('--project_name', type=str, help="所属项目组", default='public')
arg_parser.add_argument('--service_type', type=str, help="服务类型", default='service')
arg_parser.add_argument('--label', type=str, help="服务中文名", default='演示服务')
arg_parser.add_argument('--model_name', type=str, help="模型名", default='demo')
arg_parser.add_argument('--model_version', type=str, help="模型版本号", default=datetime.datetime.now().strftime('v%Y.%m.%d.1'))
arg_parser.add_argument('--model_path', type=str, help="模型地址", default='')
arg_parser.add_argument('--images', type=str, help="镜像", default='nginx')
arg_parser.add_argument('--resource_memory', type=str, help="内存", default='2G')
arg_parser.add_argument('--resource_cpu', type=str, help="cpu", default='2')
arg_parser.add_argument('--resource_gpu', type=str, help="gpu", default='0')
arg_parser.add_argument('--replicas', type=str, help="副本数", default='1')
arg_parser.add_argument('--host', type=str, help="域名", default='')
arg_parser.add_argument('--command', type=str, help="启动命令", default='')
arg_parser.add_argument('--args', type=str, help="启动参数", default='')
arg_parser.add_argument('--working_dir', type=str, help="工作目录", default='')
arg_parser.add_argument('--env', type=str, help="环境变量", default='')
arg_parser.add_argument('--hpa', type=str, help="弹性伸缩", default='')
arg_parser.add_argument('--ports', type=str, help="端口号", default='80')
arg_parser.add_argument('--volume_mount', type=str, help="挂载", default='')
args = arg_parser.parse_args()
# print("{} args: {}".format(__file__, args))
deploy(**args.__dict__)