EAS支持使用自定义镜像的方式来部署模型服务。您可以使用docker镜像来构建自己完整的运行环境,并通过服务存储挂载将模型或代码在运行时挂载至服务实例中。本文介绍使用自定义镜像部署模型服务的详细步骤。
背景信息
模型服务开发中,通常会有较为复杂的业务逻辑,无法通过简单的模型部署的方式实现。同时自定义的推理代码对于环境也有较为复杂的依赖,比如需要使用yum install/apt-get install
命令在系统目录中安装依赖包等,因此EAS推出了使用自定义镜像的方式来部署模型服务。
您可以通过控制台或客户端工具EASCMD(详情请参见下载并认证客户端)来进行模型服务的部署,本文会分别介绍如何通过这两种方式使用自定义镜像来部署模型服务。
在服务运行过程中,EAS的服务引擎会以Sidecar的方式注入到服务实例中,主要进行流量或系统监控数据的采集,以及对服务请求增加认证信息等。镜像部署支持在镜像中以HTTP、WebSocket、gRPC(HTTP2)三种协议提供API服务。
镜像中使用GRPC协议时需要在服务部署时指定额外参数:"metadata.enable_grpc": true。
自定义镜像准备
如果您已经有一个开发好的镜像,并能够提供HTTP、WebSocket、gRPC协议的访问,则可跳过该章节。
镜像服务开发
您可以使用多种方式开发一个镜像服务,例如使用Flask拉起一个Webserver来进行服务访问。如下示例是一个最简单的服务。代码文件为app.py。
from flask import Flask
app = Flask(__name__)
@app.route('/hello/model')
def hello_world():
return 'Hello World'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
镜像构建
如果您使用DSW开发,在DSW实例的操作列中单击制作镜像,系统将构建Docker镜像并保存到阿里云容器镜像服务ACR中,部署时选择自定义镜像即可下拉选择到。
下文介绍本地安装Docker构建镜像。您也可以使用如阿里云容器镜像服务ACR进行镜像构建。关于如何创建ACR镜像,请参见什么是容器镜像服务ACR。
编写Dockerfile文件。
Dockerfile是一个包含了构建镜像需要的指令和说明的文本文件。在
app.py
文件同级创建Dockerfile文件,文件目录结构如下:flask_app ├── app.py └── Dockerfile
以下Dockerfile示例文件中其将模型服务文件
app.py
打包在待部署的镜像中,您也可以保存在OSS、NAS或Git仓库中,通过存储挂载的方式在运行时挂载进服务实例,详情请参见服务存储挂载。# 说明该镜像以哪个镜像为基础 FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/python # 在容器内部执行的命令 RUN yum -y install python3-pip RUN pip3 install flask # 创建 app 文件夹 RUN mkdir -p /app # 进入 app 目录 RUN cd /app # 将 linux 系统当前目录下的app.py拷贝到容器的 /app 目录下 COPY app.py /app/ # 暴露 8000 端口 EXPOSE 8000 # 将 app 文件夹为工作目录 WORKDIR /app # 容器启动的时候执行的命令 flask run CMD ["flask", "run", "--host", "0.0.0.0"]
本地构建镜像。在命令行中,进入目录flask_app,执行以下命令构建一个名为flask-app的Docker镜像。
docker build -t flask-app .
镜像推送仓库
EAS从镜像仓库拉取镜像进行部署,下面将本地构建的镜像推送到镜像仓库。
执行命令
docker images
可以获取刚刚构建的镜像ID。假设使用ACR镜像仓库,仓库地址为
crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***
。不同的镜像仓库对EAS部署时网络配置有不同要求,详情请参见镜像仓库选择。执行以下命令,将镜像推送到ACR镜像仓库。
docker login --username=<用户名> crpi-***.cn-hangzhou.personal.cr.aliyuncs.com docker tag <镜像ID> crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***:flask-app docker push crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***:flask-app
则该镜像的镜像地址为:
crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***:flask-app
镜像仓库选择
EAS使用不同类型镜像仓库需进行不同的网络配置。
容器镜像服务ACR:
个人版: ACR个人版会在每个区域提供统一的内网地址,与ACR个人版实例同区域可使用镜像内网地址来部署,否则需通过镜像公网地址部署。
企业版:企业版镜像内网地址仅在用户VPC中可访问,因此EAS需要配置VPC专有网络。详情请参见配置VPC专有网络。
自建镜像仓库:
如果您在阿里云VPC中使用Harbor自建的镜像仓库,地址仅支持在您的VPC中访问,与ACR企业版类似,需要打通EAS到您的VPC网络,详情请参见配置VPC专有网络。
EAS默认不可访问公网,如需通过公网拉取镜像仓库,则需要开通公网访问,详情请参见配置公网连接。
镜像仓库认证
使用同账号下的ACR镜像仓库部署时,无需填写用户名密码,EAS可实现跨服务免密拉取。
若自建仓库需要用户名密码访问,则在服务部署时需要在服务配置中通过dockerAuth来提供用户名密码信息,详情请参见部署模型服务章节的dockerAuth参数说明。
部署模型服务
将上述镜像进行部署,相关参数取值如下:
镜像地址:
crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app
。镜像的启动执行命令:
python3 app.py
。镜像中进程监听的网络端口号:8000。
说明端口号在一些场景中为可选。例如,在用户服务中不依赖由EAS网关导入的流量,而是用户在镜像中自行通过订阅消息队列的方式获取消息,则此场景中镜像端口号可选填。
使用控制台部署
关键参数配置如下:
参数 | 示例 |
部署方式 | 选择镜像部署 |
镜像配置 | 选择镜像地址,填写: |
运行命令 |
|
端口号 | 8000 |
使用客户端工具部署
JSON配置文件如下:
{ "metadata": { "name": "flask_app_test", "instance": 1 }, "cloud": { "computing": { "instances": [ { "type": "ecs.c8y.large" } ] } }, "containers": [ { "image": "crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app", "script": "python3 app.py", "port": 8000 } ] }
关于自定义镜像部署的关键参数说明如下表所示。更多参数说明,详情请参见服务模型所有相关参数说明。
参数
是否必选
描述
containers
image
是
用于部署模型服务的镜像地址。
command
二者必选其一
镜像的入口命令,只支持单一命令形式,不支持复杂脚本,如:cd xxx && python app.py,这种形式请使用下面的script参数来指定,command字段适应于镜像中无/bin/sh命令的场景。
script
镜像的入口执行的脚本,可指定较为复杂的脚本形式,多行以\n或分号分隔。
port
否
容器端口。
重要由于EAS引擎监听固定的8080/9090端口,因此容器端口需要避开8080/9090端口。
该端口一定要和command中的xxx.py文件配置的端口保持一致。
dockerAuth
否
如果使用私有仓库中的镜像,则需要通过该参数指定Docker Registry的认证信息。目前,认证信息仅支持
username:password
的Base 64编码形式。例如,
username:password
取值为abcd:abcde12345
时,命令echo -n "abcd:abcde12345" | base64
返回YWJjZDphYmNkZTEy****
,即为dockerAuth的取值。通过客户端工具的
create
命令部署模型服务。eascmd create image.json
其中image.json表示上一步中创建的服务配置JSON文件。
系统返回如下类似结果,包括服务的访问地址和访问Token。
[RequestId]: BFFFE5F5-1F07-437E-B59A-AF1F2B66**** +-------------------+-----------------------------------------------------------------------------------+ | Internet Endpoint | http://182848887922***.cn-shanghai.pai-eas.aliyuncs.com/api/predict/image_test | | Intranet Endpoint | http://182848887922***.vpc.cn-shanghai.pai-eas.aliyuncs.com/api/predict/image_test| | Token | NjA4MzQxOWQ0MTY2M2Y4OGY0NjgwODkwZTZmYWJmZWU1ZmY0Njhk**** | +-------------------+-----------------------------------------------------------------------------------+ [OK] Service is now creating [OK] Waiting [Total: 2, Pending: 2, Running: 0] [OK] Running [Total: 2, Pending: 0, Running: 2] [OK] Service is running
如果需要修改服务配置,则通过客户端工具的
modify
命令实现。修改上述服务的示例命令如下,关于
modify
命令的详情信息,请参见修改服务配置。eascmd modify registry_test -s image.json
其中:registry_test表示服务名称;image.json表示服务描述文件。
服务请求
模型服务部署后,可在控制台服务详情页面中获取到服务的访问地址,通过eascmd desc
命令也可以获取到服务的访问地址。
上述flask-app镜像提供了一个Web服务,访问路径为/hello/model
,则对于同步服务在进行访问服务时,需要在该访问地址后加上镜像中的访问路径。
例如在服务调用页面获取到的服务的公网访问地址为:http://182848887922***.cn-shanghai.pai-eas.aliyuncs.com/api/predict/image_test
。
则对于上述的镜像服务要请求/hello/model
路径时,最终的访问地址为:
http://182848887922***.cn-shanghai.pai-eas.aliyuncs.com/api/predict/image_test/hello/model
。
关于服务请求的更多信息,详情请参见服务调用方式。
附录:服务配置示例
使用GRPC协议
{
"name": "image_test",
"containers": [
{
"image": "registry-vpc.cn-shanghai.aliyuncs.com/xxx/yyy:zzz",
"command": "python app.py",
"port": 8000
}
],
"metadata": {
"instance": 1,
"enable_grpc": true
}
}