EAS支援使用自訂鏡像的方式來部署模型服務。您可以使用docker鏡像來構建自己完整的運行環境,並通過服務儲存掛載將模型或代碼在運行時掛載至服務執行個體中。本文介紹使用自訂鏡像部署模型服務的詳細步驟。
背景資訊
在模型服務開發過程中,通常會有較為複雜的商務邏輯,無法通過簡單的模型部署的方式實現複雜的業務需求。同時自訂的推理代碼對於環境也有較為複雜的依賴,比如需要使用yum install/apt-get install
命令在系統目錄中安裝依賴包等,因此EAS推出了使用自訂鏡像的方式來部署模型服務。
您可以通過控制台或用戶端工具EASCMD(詳情請參見下載並認證用戶端)來進行模型服務的部署,本文會分別介紹如何通過這兩種方式使用自訂鏡像來部署模型服務。
在服務運行過程中,EAS的服務引擎會以Sidecar的方式注入到服務執行個體中,主要進行流量或系統監控資料的採集,以及對服務要求增加認證資訊等。鏡像部署支援在鏡像中以HTTP、WebSocket、gRPC(HTTP2)三種協議提供API服務。
鏡像中使用GRPC協議時需要在服務部署時指定額外參數:"metadata.enable_grpc": true。
鏡像倉庫選擇
EAS支援以下兩種形式的自訂鏡像倉庫:
鏡像服務ACR。關於如何建立ACR鏡像,請參見什麼是Container RegistryACR。
使用者自建鏡像倉庫:如果您在阿里雲VPC中使用Harbor自建的鏡像倉庫,地址僅支援在您的VPC中訪問,與ACR企業版類似,需要打通EAS到您的VPC網路,具體操作,請參見配置網路連通。
EAS預設不通公網,如需要通過公網拉取鏡像倉庫,則需要開通公網訪問,詳情請參見公網串連及白名單配置。
鏡像倉庫認證
使用私人鏡像倉庫部署時,您需要提供認證資訊才能夠在EAS中拉取鏡像,分如下兩種情況:
ACR鏡像倉庫:您在開通EAS中選擇授權給EAS之後,對於同帳號下的ACR個人版和企業版鏡像倉庫部署時,無需指定認證資訊,EAS可實現跨服務免密拉取。
自建私人鏡像倉庫:若自建倉庫需要使用者名稱密碼訪問,則在服務部署時需要在服務配置中通過dockerAuth來提供使用者名稱密碼資訊,詳情請參見部署模型服務章節的dockerAuth參數說明。
鏡像服務開發
如果您已經有一個開發好的鏡像,並能夠提供HTTP、WebSocket、gRPC協議的訪問,則可跳過該章節,直接進行服務部署。
您可以使用多種方式開發一個鏡像服務,例如使用Flask拉起一個Webserver來進行服務訪問,範例程式碼如下。
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)
您也可使用EAS提供的高效能服務架構allspark來進行鏡像服務的開發,詳情請參見:使用Python開發自訂Processor,範例程式碼如下。
# -*- coding: utf-8 -*-
import allspark
class MyProcessor(allspark.BaseProcessor):
def initialize(self):
"""
This function is only executed once when the service starts,
and traffic will not be imported until it is completed.
It can be used to load models and service initialization.
"""
pass
def process(self, data):
"""
Each time a request is received, this function is called.
The input parameter of the function is the request body of the HTTP request,
and the function returns two parameters:
1. the first parameter will be used as the HTTP response body,
2. the second parameter is the HTTP response status code.
"""
data = 'hello eas'
return bytes(data, encoding='utf8'), 200
if __name__ == '__main__':
runner = MyProcessor(endpoint='0.0.0.0:8000')
runner.run()
開發好的代碼可以直接通過docker build打包在待部署的鏡像中,也可儲存在Nas或Git倉庫中,通過儲存掛載的方式在運行時掛載進服務執行個體,詳情請參見進階配置:服務儲存掛載。
部署模型服務
準備工作
準備條件,自訂鏡像部署需要如下三要素:
鏡像倉庫地址,例如:
registry-vpc.cn-shanghai.aliyuncs.com/xxx/yyy:zzz
。鏡像的啟動執行命令,例如:
/data/eas/ENV/bin/python /data/eas/app.py
。鏡像中進程監聽的網路連接埠號碼,例如:8000 。
說明連接埠號碼在一些情境中為可選。例如使用者服務中不依賴由EAS網關匯入的流量,而是使用者在鏡像中自行通過訂閱訊息佇列的方式擷取訊息,則此情境中鏡像連接埠號碼可選填。
部署服務時需準備JSON格式的設定檔,檔案內容的樣本如下。
通過控制台互動式頁面部署時最終也會產生下面的設定檔,您也可以使用該檔案通過eascmd或openapi來進行服務部署。
{ "name": "image_test", "containers": [ { "image": "registry-vpc.cn-shanghai.aliyuncs.com/xxx/yyy:zzz", "env": [ { "name": "var_name", "value": "var_value" } ], "command": "/data/eas/ENV/bin/python /data/eas/app.py", "port": 8000 } ], "metadata": { "cpu": 1, "instance": 1 } }
JSON檔案內的參數解釋如下表所示。
參數
是否必選
描述
containers
image
是
用於部署模型服務的鏡像地址。
由於EAS不開放公網存取權限,因此您需要使用VPC內網Registry地址進行部署。例如,registry-vpc.cn-shanghai.aliyuncs.com。
env
name
是
鏡像執行時的環境變數名稱。
value
是
鏡像執行時的環境變數取值。
command
二者必選其一
鏡像的入口命令,只支援單一命令形式,不支援複雜指令碼,如:cd xxx && python app.py,這種形式請使用下面的script參數來指定,command欄位適應於鏡像中無/bin/sh命令的情境。
script
鏡像的入口執行的指令碼,可指定較為複雜的指令碼形式,多行以\n或分號分隔。
port
否
容器連接埠。
重要由於EAS引擎監聽固定的8080/9090連接埠,因此容器連接埠需要避開8080/9090連接埠。
該連接埠一定要和command中的xxx.py檔案配置的連接埠保持一致。
prepare
pythonRequirements
否
執行個體啟動前安裝的python requirements列表,要求鏡像中在系統路徑中存在python和pip命令,list格式,如:
"prepare": { "pythonRequirements": [ "numpy==1.16.4", "absl-py==0.11.0" ] }
pythonRequirementsPath
否
執行個體啟動前安裝的python requirements.txt檔案地址,要求鏡像中在系統路徑中存在Python和pip命令,requirements.txt可直接打在鏡像中,也可以由外部儲存掛載的方式掛載到服務執行個體中,如:
"prepare": { "pythonRequirementsPath": "/data_oss/requirements.txt" }
health_check
tcp_socket.port
否
使用TCP方式健全狀態檢查時,檢查的TCP連接埠號碼。
http_get.path
否
使用HTTP方式健全狀態檢查時,檢查的HTTP Server訪問地址。
http_get.port
否
使用HTTP方式健全狀態檢查時,檢查的HTTP Server連接埠號碼。
initial_delay_seconds
否
預設健全狀態檢查開始的延時時間,預設為3秒。
period_seconds
否
配置每次健全狀態檢查請求的間隔時間,預設為3秒。
timeout_seconds
否
配置每次健全狀態檢查請求的逾時時間,超過該時間請求為正確返回則判定為健全狀態檢查失敗,預設為1秒。
success_threshold
否
健全狀態檢查成功的閾值,如設定為2,則表示健全狀態檢查成功2次判定為執行個體健康,開始啟動流量匯入。
failure_threshold
否
健全狀態檢查失敗的閾值,如設定為4,則表示健全狀態檢查失敗4次後則判斷執行個體為不健康,開始停止流量匯入。
dockerAuth
否
如果使用私人倉庫中的鏡像,則需要通過該參數指定Docker Registry的認證資訊。目前,認證資訊僅支援
username:password
的Base 64編碼形式。例如,
username:password
取值為abcd:abcde12345
時,命令echo -n "abcd:abcde12345" | base64
返回YWJjZDphYmNkZTEy****
,即為dockerAuth的取值。metadata
否
服務的Meta資訊,詳細參數請參見命令使用說明。
name
是
服務名稱,必須在同一地區內唯一。
使用用戶端工具部署
通過用戶端工具的
create
命令部署模型服務。
eascmd create image.json
其中image.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表示服務描述檔案。
使用控制台部署
上圖的樣本中示範了使用使用者自建私人倉庫來部署的情境,同時配置了訪問倉庫的使用者名稱和密碼。模型和代碼均以OSS儲存掛載的方式掛載到服務執行個體中,產生的完整配置如下所示。
{
"metadata": {
"name": "image_test",
"instance": 1
},
"storage": [
{
"mount_path": "/models/",
"oss": {
"path": "oss://example-cn-beijing/models/",
"readOnly": true
}
},
{
"mount_path": "/root/code",
"oss": {
"path": "oss://example-cn-beijing/processors/",
"readOnly": true
}
}
],
"containers": [
{
"image": "myharbor.com/xxx/yyy:zzz",
"script": "python /root/code/app.py",
"port": 8000,
"prepare": {
"pythonRequirementsPath": "/root/code/requirements.txt"
},
"env": [
{
"name": "var_name",
"value": "var_value"
}
]
}
],
"dockerAuth": "YWJjOmJjZA=="
}
服務要求
模型服務部署後,可在控制台服務詳情頁面中擷取到服務的訪問地址,通過eascmd desc
命令也可以擷取到服務的訪問地址。假設為使用者使用如下Flask代碼在鏡像中構建了一個API服務。
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)
上述代碼中提供了一個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
。
關於服務要求的更多資訊,詳情請參見服務調用方式。
附錄:服務配置樣本
使用PythonRequirements
{
"name": "image_test",
"containers": [
{
"image": "registry-vpc.cn-shanghai.aliyuncs.com/xxx/yyy:zzz",
"prepare": {
"pythonRequirements": [
"numpy==1.16.4",
"absl-py==0.11.0"
]
},
"command": "python app.py",
"port": 8000
}
],
"metadata": {
"instance": 1
}
}
自訂健全狀態檢查
{
"name": "image_test",
"containers": [
{
"image": "registry-vpc.cn-shanghai.aliyuncs.com/xxx/yyy:zzz",
"command": "python app.py",
"port": 8000,
"health_check":{
"http_get": {
"path": "/",
"port": 8000
},
"initial_delay_seconds": 3,
"period_seconds": 3,
"timeout_seconds": 1,
"success_threshold": 2,
"failure_threshold": 4
}
}
],
"metadata": {
"instance": 1
}
}
使用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
}
}