使用自定义镜像部署模型服务

当官方镜像无法满足复杂的业务逻辑和环境需求时,可构建自定义镜像封装完整的运行环境。EAS支持使用自定义镜像来部署模型服务。

说明

在服务运行过程中,EAS的服务引擎会以Sidecar方式注入服务实例,主要进行流量或系统监控数据的采集,以及对服务请求增加认证信息等。镜像部署支持在镜像中以HTTP、WebSocket、gRPC(HTTP2)三种协议提供API服务。

镜像仓库使用说明

容器镜像服务ACR

  • 推荐使用VPC地址拉取镜像。

    重要

    公网拉取镜像存在安全风险,且速度会特别慢,不建议使用。同时EAS默认不可访问公网,如需通过公网拉取镜像仓库,请参见EAS服务访问公网

  • 使用同账号下的ACR镜像仓库部署时,无需填写用户名密码,EAS可实现跨服务免密拉取。

自建镜像仓库

  • 阿里云VPC中使用Harbor自建的镜像仓库,地址仅支持在VPC中访问,与ACR企业版类似,需要打通EAS到您的VPC网络,详情请参见EAS服务访问VPC内网资源

  • 若自建仓库需要用户名密码访问,则在服务部署时需提供用户名密码信息。注意JSON配置文件中需以Base64编码username:password,详情请参见部署模型服务章节的dockerAuth参数说明。

准备工作

说明

如果您已经有一个开发好的镜像,并能够提供HTTP、WebSocket、gRPC协议的访问,则可跳过该章节。

1. 准备代码与模型文件

以一个简单的Flask Web 服务为例,代码文件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)

此处省略了模型处理的逻辑,为了提高部署效率和灵活性,建议将体积较大的模型文件(通常大于1GB)存储在对象存储OSS(Object Storage Service)中,而不是直接打包进镜像。在EAS部署时,通过挂载OSS的方式将模型加载到服务中,参见服务存储挂载

例如:将模型 my_model.pth 存放在 oss://my-bucket/models/ 目录下,并将此目录挂载到容器目录/mnt/data。在代码中,您可以通过绝对路径 /mnt/data/my_model.pth 来直接访问它。

2. 构建镜像

说明

如果使用DSW开发,在DSW实例的操作列中单击制作镜像,系统将构建Docker镜像并保存到阿里云容器镜像服务ACR中,部署时选择自定义镜像即可下拉选择。详情请参见制作DSW实例镜像

下文介绍本地安装Docker并构建镜像。也可以使用如阿里云容器镜像服务ACR进行镜像构建。

  1. 编写Dockerfile文件。

    Dockerfile是一个包含了构建镜像需要的指令和说明的文本文件。在app.py文件同级创建Dockerfile文件,文件目录结构如下:

    flask_app
      ├── app.py
      └── Dockerfile    

    以下Dockerfile示例文件中,将代码文件app.py打包在待部署的镜像中,也可以保存在OSS、NASGit仓库中,通过存储挂载的方式在运行时挂载进服务实例。

    # 说明该镜像以哪个镜像为基础
    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"]
  2. 构建本地镜像。在命令行中,进入目录flask_app,执行以下命令构建一个名为flask-appDocker镜像。

    docker build -t flask-app . 

3. 推送镜像到仓库

  1. 执行命令docker images可以获取构建的镜像ID。

  2. 假设使用ACR个人版,地址为crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***

  3. 执行以下命令,将镜像推送到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

部署模型服务

将上述镜像进行部署,相关参数取值如下:

  • 镜像地址:crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app

  • 镜像的启动执行命令:python3 app.py

  • 镜像中进程监听的网络端口号:8000。

    说明

    端口号在一些场景中为可选。例如,在用户服务中不依赖由EAS网关导入的流量,而是用户在镜像中自行通过订阅消息队列的方式获取消息,则此场景中镜像端口号可选填。

使用控制台部署

关键参数配置如下:

  • 部署方式:选择镜像部署

  • 镜像配置:选择镜像地址,填写:crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app。示例使用ACR镜像仓库,不需要填写用户名密码。

  • 运行命令:python3 app.py

  • 端口号:8000。

使用客户端工具部署

  1. 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
            }
        ]
    }

    关于自定义镜像部署的关键参数说明如下表所示。更多参数说明,详情请参见JSON部署

    参数

    是否必选

    描述

    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:passwordBase 64编码形式。

    例如,username:password取值为abcd:abcde12345时,命令echo -n "abcd:abcde12345" | base64返回YWJjZDphYmNkZTEy****,即为dockerAuth的取值。

  2. 通过客户端工具的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
  3. 如果需要修改服务配置,则通过客户端工具的modify命令实现。

    修改上述服务的示例命令如下,关于modify命令的详情信息,请参见修改服务配置

    eascmd modify registry_test -s image.json

    其中:registry_test表示服务名称;image.json表示服务描述文件。

服务验证

当服务状态变为“运行中”时,表示服务已成功启动。上述flask-app镜像提供了一个Web服务,访问路径为/hello/model,故可通过如下命令进行调用测试:

curl <endpoint>/hello/model -H "Authorization: <token>"

其中:<endpoint><token>替换为服务的实际调用地址和Token,参见获取访问地址和Token

关于服务请求的更多信息,详情请参见服务调用方式

常见问题

镜像拉取失败等问题,请参见EAS常见问题

相关文档

  • 自定义镜像部署支持使用健康检查功能,详情请参见健康检查

  • 服务部署成功后,在业务负载出现显著的波峰波谷时,您可以开启水平自动扩缩容功能,详情请参见水平自动扩缩容功能