O ModelMesh inclui runtimes integrados para frameworks de inferência comuns, mas algumas cargas de trabalho exigem lógica personalizada de pré/pós-processamento, frameworks não suportados ou controle refinado de recursos. Um ServingRuntime personalizado permite definir exatamente como carregar e servir modelos e registrar esse runtime para que o ModelMesh agende e escale modelos automaticamente.
Este guia descreve como criar um runtime personalizado baseado em Python no MLServer, empacotá-lo como imagem de contêiner, registrá-lo como ServingRuntime e implantar um modelo nesse ambiente.
Pré-requisitos
Antes de começar, verifique se você tem:
Um cluster do Container Service for Kubernetes (ACK) adicionado à sua instância do Service Mesh (ASM)
Uma instância do ASM versão 1.18.0.134 ou posterior
Runtimes integrados
Antes de criar um runtime personalizado, verifique se já existe um runtime integrado compatível com o formato do seu modelo.
|
Servidor de modelo |
Desenvolvedor |
Frameworks suportados |
Mais indicado para |
|
Triton Inference Server |
NVIDIA |
TensorFlow, PyTorch, TensorRT, ONNX |
Inferência de alto desempenho, escalável e de baixa latência com monitoramento integrado |
|
MLServer |
Seldon |
SKLearn, XGBoost, LightGBM |
API unificada entre vários frameworks de ML |
|
OpenVINO Model Server |
Intel |
OpenVINO, ONNX |
Aceleração de hardware Intel |
|
TorchServe |
PyTorch |
PyTorch (incluindo modo eager) |
Serviço nativo leve para PyTorch |
Se nenhum desses runtimes oferecer suporte ao seu framework ou se o pipeline de inferência exigir lógica personalizada, crie um runtime de serviço personalizado conforme descrito abaixo.
Como funciona
Um ServingRuntime (escopo de namespace) ou ClusterServingRuntime (escopo de cluster) define o modelo de pod para servir um ou mais formatos de modelo. Cada recurso especifica:
A imagem de contêiner que executa o servidor de inferência
Uma lista de formatos de modelo suportados
Variáveis de ambiente para configuração do runtime
O ServingRuntime é uma CustomResourceDefinition (CRD) do Kubernetes. Assim, é possível criar runtimes reutilizáveis sem modificar o controlador do ModelMesh ou quaisquer recursos no namespace do controlador.
Para frameworks baseados em Python, a maneira mais rápida é estender o MLServer. O MLServer fornece a interface de serviço, você fornece a lógica do modelo e o ModelMesh gerencia o agendamento e o dimensionamento.
O fluxo de trabalho consiste em três etapas:
Implemente a classe do modelo estendendo a classe
MLModeldo MLServer.Empacote a classe e suas dependências em uma imagem de contêiner.
Registre a imagem como um ServingRuntime no Kubernetes.
Etapa 1: Implementar a classe MLModel
Crie uma classe Python que herde da classe MLModel do MLServer. Implemente dois métodos:
load()-- Inicializa o modelo (carrega pesos, aquece caches).predict()-- Executa a inferência em uma solicitação recebida.
from typing import List
from mlserver import MLModel, types
from mlserver.utils import get_model_uri
# List the filenames your model uses so MLServer can locate them.
WELLKNOWN_MODEL_FILENAMES = ["model.json", "model.dat"]
class CustomMLModel(MLModel):
async def load(self) -> bool:
model_uri = await get_model_uri(
self._settings, wellknown_filenames=WELLKNOWN_MODEL_FILENAMES
)
# TODO: Load the model from model_uri and store it as an instance attribute.
# Example: self._model = joblib.load(model_uri)
self.ready = True
return self.ready
async def predict(
self, payload: types.InferenceRequest
) -> types.InferenceResponse:
payload = self._check_request(payload)
return types.InferenceResponse(
model_name=self.name,
model_version=self.version,
outputs=self._predict_outputs(payload),
)
def _check_request(self, payload):
# TODO: Validate the request -- check input tensor names, shapes, and types.
return payload
def _predict_outputs(self, payload) -> List[types.ResponseOutput]:
# TODO: Extract input data from payload.
# TODO: Run the data through your model's prediction logic.
# TODO: Construct and return a list of ResponseOutput objects.
outputs = []
return outputs
Para mais exemplos, consulte a documentação de runtime personalizado do MLServer.
Etapa 2: Empacotar o runtime em uma imagem de contêiner
Agrupe a classe CustomMLModel, o MLServer e todas as dependências em uma imagem de contêiner.
Opção A: Usar a CLI do MLServer (recomendado)
O MLServer oferece o comando mlserver build para gerar uma imagem automaticamente. Para obter detalhes, veja Criando uma imagem personalizada.
Opção B: Escrever um Dockerfile
# Use a Python base image that matches your dependency requirements.
FROM python:3.8-slim-buster
RUN pip install mlserver
# Place your MLModel implementation on the Python path.
COPY --chown=${USER} ./custom_model.py /opt/custom_model.py
ENV PYTHONPATH=/opt/
# Set environment variables for ModelMesh compatibility.
# These can also be set in the ServingRuntime YAML, but embedding them here
# ensures consistent behavior during local testing.
ENV MLSERVER_MODELS_DIR=/models/_mlserver_models \
MLSERVER_GRPC_PORT=8001 \
MLSERVER_HTTP_PORT=8002 \
MLSERVER_LOAD_MODELS_AT_STARTUP=false \
MLSERVER_MODEL_NAME=dummy-model
# Point MLServer to your class so the implementation field is optional
# in model settings.
ENV MLSERVER_MODEL_IMPLEMENTATION=custom_model.CustomMLModel
CMD ["mlserver", "start", "${MLSERVER_MODELS_DIR}"]
Compile e envie a imagem:
docker build -t <your-registry>/<your-image-name>:<tag> .
docker push <your-registry>/<your-image-name>:<tag>
Substitua os seguintes espaços reservados pelos valores reais:
|
Espaço reservado |
Descrição |
Exemplo |
|
|
Endereço do registro de contêineres |
registry.cn-hangzhou.aliyuncs.com/my-namespace |
|
|
Nome da imagem |
custom-mlserver |
|
|
Tag de versão da imagem |
v1.0 |
Etapa 3: Criar o ServingRuntime
Defina um recurso ServingRuntime que aponte para sua imagem de contêiner e declare os formatos de modelo suportados.
Preencha os espaços reservados com os valores adequados:
|
Espaço reservado |
Descrição |
Exemplo |
|
|
Um nome exclusivo para o runtime |
my-model-server-0.x |
|
|
O formato de modelo compatível com este runtime. O ModelMesh compara os modelos recebidos com este valor. |
my-model |
|
|
A imagem de contêiner da Etapa 2 |
registry.cn-hangzhou.aliyuncs.com/my-namespace/custom-mlserver:v1.0 |
Aplique o recurso:
kubectl apply -f <serving-runtime>.yaml
Após a criação do recurso, o runtime personalizado aparece na implantação do ModelMesh e fica pronto para servir modelos correspondentes ao formato declarado.
Etapa 4: Implantar um modelo
Crie um InferenceService para implantar um modelo no runtime personalizado. O InferenceService é o principal recurso que o KServe e o ModelMesh usam para gerenciar endpoints de modelo.
Campos principais:
|
Campo |
Finalidade |
|
|
Indica ao ModelMesh qual runtime usar. Deve corresponder a uma entrada |
|
|
(Opcional) Seleciona explicitamente um runtime pelo nome. Se omitido, o ModelMesh faz a seleção automática com base no |
|
|
Referencia um backend de armazenamento pré-configurado (por exemplo, |
|
|
Caminho para o artefato do modelo dentro do backend de armazenamento. |
Aplique o recurso:
kubectl apply -f <inference-service>.yaml
Verifique se o modelo está pronto:
kubectl get inferenceservice my-model-sample -n modelmesh-serving
Saída esperada:
NAME URL READY AGE
my-model-sample True 1m
A coluna READY exibe True após o ModelMesh concluir o carregamento do modelo no runtime personalizado.
Depuração
Se o runtime personalizado falhar ao carregar modelos ou retornar erros de inferência, ative o log de depuração adicionando estas variáveis de ambiente ao ServingRuntime:
env:
- name: MLSERVER_DEBUG
value: "true"
- name: MLSERVER_MODEL_PARALLEL_WORKERS
# Set to 0 to disable parallel workers, which simplifies log output.
value: "0"
Consulte os logs do pod do runtime para obter mensagens de erro detalhadas:
kubectl logs -n modelmesh-serving <pod-name> -c mlserver
Próximos passos
Saiba mais sobre runtimes personalizados do ModelMesh Serving na documentação upstream.
Explore os exemplos de runtime personalizado do MLServer para conhecer padrões adicionais.