WEB3DEV

Cover image for Entrega de ML na Borda com Snap, Microk8s e KServe no Ubuntu Core
Paulo Gio
Paulo Gio

Posted on

Entrega de ML na Borda com Snap, Microk8s e KServe no Ubuntu Core

Habilite a inferência segura de ML em sua frota de dispositivos IoT de borda com garantia de disponibilidade, protocolo de interface padronizado e capacidades de atualização automática.

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*UzqyJ1fJrYY618msps1gXA.jpeg

Foto por asharkyu no Shutterstock

Nos últimos anos, houve um aumento significativo na demanda por aplicações de Inteligência Artificial (IA) projetadas para operar em dispositivos de borda. Esse crescimento é atribuído às capacidades computacionais aprimoradas do hardware e à proliferação de redes de alta largura de banda, que levaram à geração de volumes substanciais de dados. Esses dados precisam ser processados rapidamente, idealmente em tempo real, à medida que buscamos realizações como veículos autônomos ou detecção rápida de anomalias supervisionadas por frotas de dispositivos IoT em instalações de produção. Consequentemente, a abordagem ideal é executar o processamento de dados no ponto de origem ou em proximidade a ele. Esta estratégia se alinha perfeitamente com o paradigma de ML (Machine Learning, ou Aprendizado de Máquina) na Borda, onde soluções de IA e de servidores de ML desempenham um papel fundamental na exploração do potencial de frotas de dispositivos IoT.

Olhando para a previsão da Fortune Business Insights: "O tamanho do mercado de IA de borda foi avaliado em 11,98 bilhões de dólares em 2021 e espera-se que atinja 107,47 bilhões de dólares até 2029, exibindo uma taxa de crescimento anual composta (CAGR) de 31,7% durante o período de previsão”. Em resumo, globalmente, quase todos os setores devem investir em aplicações de inteligência artificial de borda - o que significa que haverá um aumento massivo nos locais onde os dados serão gerados e espera-se que sejam processados por uma frota de dispositivos incorporando soluções de IA.

Hospedar modelos de aprendizado de máquina na borda introduz inúmeros desafios e riscos, sendo a segurança uma preocupação primordial. Uma estratégia aconselhável envolve servir seus modelos de aprendizado de máquina como serviços conteinerizados implantados em um orquestrador. Esta abordagem oferece vários benefícios, incluindo garantir a disponibilidade do modelo, facilitar a implantação de atualizações do modelo e, se necessário, permitir acesso controlado ao ponto de extremidade do modelo.

Em um artigo recente, você pode encontrar referências para mitigar riscos de segurança para modelos de Aprendizado de Máquina e um exemplo de implantação de ML de borda em dispositivos com uma boa conexão de rede.

https://medium.com/ubuntu-ai/ml-models-security-from-mlops-to-inference-685fb0d01a43?source=post_page-----33eb4ca5519d--------------------------------

Mas e se houver uma frota de dispositivos para gerenciar? E se for necessário implantar o mesmo modelo em dispositivos com arquiteturas ARM64 e AMD64?

Sem problemas! Vou cobrir tudo nesta publicação.

O código está disponível no repositório abaixo:

https://github.com/RafalSiwek/edge-ml-snap-kserve?source=post_page-----33eb4ca5519d--------------------------------

O sistema operacional de borda (edge OS)

Enquanto plataformas de orquestração de contêineres como Kubernetes protegem efetivamente o serviço de inferência de ML, é imperativo reconhecer que garantir a segurança da implantação também envolve executar a referida plataforma em um sistema operacional host configurado com segurança.

O Ubuntu Core é uma versão do sistema operacional Ubuntu projetada e desenvolvida para IoT e sistemas embarcados. Ele se atualiza automaticamente, bem como seus aplicativos. Pacotes Snap são usados exclusivamente para criar um sistema confinado e baseado em transações. Segurança e robustez são suas principais características, além de ser fácil de instalar, manter e atualizar.

Informações sobre o que está incluso e como implantar o Ubuntu Core em dispositivos de borda podem ser encontradas em:

https://ubuntu.com/core/docs/uc20/inside?source=post_page-----33eb4ca5519d--------------------------------

Para fins de teste, é possível lançar o Ubuntu Core em uma VM (Virtual Machine, ou Máquina Virtual) usando o Multipass.

Para este artigo, eu usei:

  • Ubuntu Core22 rodando em um Raspberry Pi 4B 8GB
  • VM Multipass em uma instância EC2 na arquitetura AMD64
  • Servidor Ubuntu em uma VM Multipass, em um MacBook Apple M1

Configuração do ambiente ML de borda

MicroK8s

Com o Ubuntu Core configurado, o primeiro passo é instalar o MicroK8s estritamente confinado para atender aos requisitos de segurança. O MicroK8s é um cluster leve do Kubernetes com pequenos requisitos de recursos. Ele é ideal para implantações de borda:

# A lista de versões disponíveis pode ser encontrada em:
# https://snapcraft.io/microk8s
snap install microk8s --channel=1.28-strict/stable
sudo usermod -a -G snap_microk8s $USER
mkdir -p ~/.kube
sudo chown -f -R $USER ~/.kube
newgrp snap_microk8s
# Crie um atalho para kubectl e helm:
sudo snap alias microk8s.kubectl kubectl
sudo snap alias microk8s.helm helm
# Microk8s não é iniciado por padrão após a instalação.
# Para iniciar o MicroK8s, execute:
sudo microk8s start
Enter fullscreen mode Exit fullscreen mode

Depois que o MicroK8s é iniciado, extensões necessárias devem ser habilitadas. Uma lista completa de complementos está disponível aqui: https://microk8s.io/docs/addons.

microk8s enable metallb:10.64.140.43-10.64.140.49
microk8s enable registry
Enter fullscreen mode Exit fullscreen mode

Antes de prosseguir para a próxima etapa, verifique se todos os plugins esperados estão habilitados e os Pods estão em execução. Aqui está o resultado esperado do status do MicroK8s:

$ microk8s status
microk8s is running
high-availability: no
 datastore master nodes: 127.0.0.1:19001
 datastore standby nodes: none
addons:
 enabled:
    cert-manager        # (core) Gerenciamento de certificados nativos da nuvem
    dns                 # (core) CoreDNS
    ha-cluster          # (core) Configurar alta disponibilidade no nó atual
    helm                # (core) Helm - gerenciador de pacotes para Kubernetes
    helm3               # (core) Helm 3 - gerenciador de pacotes para Kubernetes
    hostpath-storage    # (core) Classe de armazenamento; aloca armazenamento a partir do diretório host
    metallb             # (core) Balanceador de carga para seu cluster Kubernetes
    registry            # (core) Registro de imagem privado exposto em localhost:32000
    storage             # (core) Atalho para complemento hostpath-storage, obsoleto
  disabled:
    cis-hardening       # (core) Aplicar fortalecimento CIS K8s
    community           # (core) O repositório de complementos da comunidade
    dashboard           # (core) Painel Kubernetes
    host-access         # (core) Permitir que Pods se conectem a serviços do Host sem problemas
    ingress             # (core) Controlador de ingresso para acesso externo
    mayastor            # (core) OpenEBS MayaStor
    metrics-server      # (core) Servidor de métricas K8s para acesso API a métricas de serviço
    minio               # (core) Armazenamento de objetos MinIO
    observability       # (core) Uma pilha leve de observabilidade para logs, rastreios e métricas
    prometheus          # (core) Operador Prometheus para monitoramento e registro
    rbac                # (core) Controle de acesso baseado em função para autorização
    rook-ceph           # (core) Armazenamento Ceph distribuído usando Rook
Enter fullscreen mode Exit fullscreen mode

KServe

Com o MicroK8s instalado e as extensões configuradas, o KServe será a plataforma de inferência de modelos na qual os modelos de ML serão veiculados.

O KServe tem algumas semelhanças com o Seldon Core. O Seldon Core e seu uso foram descritos em um artigo separado.

https://medium.com/ubuntu-ai/deploy-ml-models-at-the-edge-with-microk8s-seldon-and-istio-5b97fe695578?source=post_page-----33eb4ca5519d--------------------------------

O Charmed KServe pode ser implantado usando o operador Juju na arquitetura AMD64 ou sem servidor ou diretamente da fonte para um aspecto mais leve e outras arquiteturas suportadas.

Neste caso, uma implantação de instalação rápida será realizada:

# Baixe o script quick_install do shell
curl -s "https://raw.githubusercontent.com/kserve/kserve/release-0.11/hack/quick_install.sh"
Enter fullscreen mode Exit fullscreen mode

Como o MicroK8s trabalha em confinamento estrito, o script de instalação rápida precisa ser executado com sudo, por isso temos que "injetar" a configuração do MicroK8s, provida pelo pacote Snap, no kubectl, que é executado dentro do script. Para fazer isso, abra o arquivo quick-install.sh e cole a variável fornecida:

# Edite o arquivo:
$ nano quick_install.sh

export ISTIO_VERSION=1.17.2
export KNATIVE_SERVING_VERSION=knative-v1.10.1
export KNATIVE_ISTIO_VERSION=knative-v1.10.0
export KSERVE_VERSION=v0.11.0
export CERT_MANAGER_VERSION=v1.3.0
# Adicione um ponteiro para o arquivo de configuração do MicroK8s snapped
export KUBECONFIG=/var/snap/microk8s/current/credentials/client.config
Enter fullscreen mode Exit fullscreen mode

Com o arquivo atualizado, o KServe pode ser instalado:

$ cat quick_install.sh | sudo bash
...
...
...
😀 Successfully installed KServe
Enter fullscreen mode Exit fullscreen mode

Verifique o status da implantação:

$ kubectl get pods --all-namespaces
NAMESPACE            NAME                                        READY   STATUS    RESTARTS   AGE
kube-system          calico-node-cxnms                           1/1     Running   0          7m16s
kube-system          coredns-864597b5fd-kfgq5                    1/1     Running   0          7m15s
kube-system          calico-kube-controllers-77bd7c5b-btfk4      1/1     Running   0          7m15s
kube-system          hostpath-provisioner-7df77bc496-7wdgq       1/1     Running   0          7m4s
metallb-system       controller-5c6b6c8447-jvjfg                 1/1     Running   0          7m2s
container-registry   registry-6c9fcc695f-5d6wp                   1/1     Running   0          7m4s
istio-system         istiod-57b55446f6-4vq54                     1/1     Running   0          6m25s
metallb-system       speaker-rq6wk                               1/1     Running   0          7m2s
istio-system         istio-ingressgateway-5b6899ddcc-w46xv       1/1     Running   0          6m15s
knative-serving      domain-mapping-5ffd4df948-mbw5b             1/1     Running   0          6m1s
cert-manager         cert-manager-cainjector-7c8bcfdd69-kmdkw    1/1     Running   0          5m57s
knative-serving      autoscaler-657cb48c96-sgxbt                 1/1     Running   0          6m2s
knative-serving      net-istio-webhook-55c8775bfd-xdttn          1/1     Running   0          6m
knative-serving      domainmapping-webhook-859df874cb-r6ml6      1/1     Running   0          6m1s
knative-serving      net-istio-controller-79dc5cdb78-hxxp5       1/1     Running   0          6m
knative-serving      controller-5649857ccc-q5ptg                 1/1     Running   0          6m1s
knative-serving      webhook-74b6f5cf75-mkj2h                    1/1     Running   0          6m1s
knative-serving      activator-7f86fb77f8-fjh8v                  1/1     Running   0          6m2s
cert-manager         cert-manager-5799666d46-9dvsz               1/1     Running   0          5m57s
cert-manager         cert-manager-webhook-6dd97d9768-szqgq       1/1     Running   0          5m57s
kserve               kserve-controller-manager-d754ccd4c-qllmw   2/2     Running   0          5m39s
Enter fullscreen mode Exit fullscreen mode

(Opcional) Para testar a implantação do KServe, siga as instruções vinculadas:

https://kserve.github.io/website/0.11/get_started/first_isvc/?source=post_page-----33eb4ca5519d--------------------------------#3-check-inferenceservice-status

O KServe, com seus ClusterServingRuntimes integrados, permite puxar modelos salvos de servidores hospedados, como o registro de modelo MLflow ou diretórios montados, e rodá-los em tempos de execução suportados. Ao gerenciar uma frota de dispositivos, essa abordagem introduz alguns problemas:

  • A implantação em dispositivos com conexões de rede instáveis causará interrupções e falhas na implantação.
  • A implantação precisa ser acionada manualmente ou requer uma implementação de um gancho com uma função de acionamento ao liberar o modelo no cluster.
  • Risco de incompatibilidade do modelo.

Uma melhor abordagem seria aproveitar os recursos de implantação do tempo de execução de serviço personalizado do KServe e implantar imagens de container de serviço do KServe pré-construídas e testadas com modelos injetados localmente. Dessa forma, devido ao teste, o risco de incompatibilidade do modelo será mitigado e, para a auto-implantação na alteração da imagem, ferramentas semelhantes ao Keel podem ser usadas:

https://keel.sh/docs/?source=post_page-----33eb4ca5519d--------------------------------#introduction

Pré-construção de imagens de container InferenceService

Construção de imagens de container InferenceService

Um arquivo de modelo treinado (exemplo SKlearn ElasticNet wine-rater) pode ser serializado usando o pacote Python Joblib e construído em uma imagem Docker usando a seguinte definição Dockerfile:

FROM kserve/sklearnserver

COPY model /tmp/model

CMD ["--model_dir", "/tmp/model", "--model_name", "wine-rater"]
Enter fullscreen mode Exit fullscreen mode

A imagem base e os argumentos CMD foram preenchidos de acordo com as especificações ClusterServingRuntime fornecidas disponíveis no repositório oficial do KServe:

https://github.com/kserve/kserve/tree/master/python?source=post_page-----33eb4ca5519d--------------------------------

Para construir a imagem nas arquiteturas necessárias e salvá-las como tarballs, pode-se usar o docker buildx build na máquina de compilação:

# Para o dispositivo alvo amd64
docker buildx build --output type=docker -t kserve-wine-rater-amd64 ml --platform linux/amd64
docker save kserve-wine-rater-amd64 -o images/kserve-wine-rater-amd64.tar

# Para o dispositivo alvo arm64
docker buildx build --output type=docker -t kserve-wine-rater-arm64 ml --platform linux/arm64
docker save kserve-wine-rater-arm64 -o images/kserve-wine-rater-arm64.tar
Enter fullscreen mode Exit fullscreen mode

As imagens podem ser executadas localmente da seguinte maneira:

# Carregue a imagem tarball exportada
docker load --input images/kserve-wine-rater-<sua-arquitetura>.tar

# Execute o container docker
docker run --rm -it -p 8080:8080 kserve-wine-rater-<sua-arquitetura>
Enter fullscreen mode Exit fullscreen mode

E testadas em um terminal separado com pedidos de exemplo:

$ curl -H "Content-Type: application/json" \
    -d '{"inputs": [{"name": "input1","shape": [1,11],"datatype": "FP32","data": [[5.6,0.31,0.37,1.4,0.074,12.0,96.0,0.9954,3.32,0.58,9.2]]}]}' \
  http://localhost:8080/v2/models/wine-rater/infer
{"model_name":"wine-rater","model_version":null,"id":"6e3a9120-8dba-4916-8bf6-cc8d3e85c0e5","parameters":null,"outputs":[{"name":"output-0","shape":[1],"datatype":"FP64","parameters":null,"data":[5.288068083678879]}]}%
Enter fullscreen mode Exit fullscreen mode

Entregando contêineres ML InferenceService para o dispositivo de borda

Para implantar as imagens do InferenceService nos dispositivos de borda, os tarballs de imagem devem ser carregados nos dispositivos e enviados para o registro interno do MicroK8s previamente habilitado.

Este processo pode ser feito manualmente carregando os tarballs de imagem no dispositivo e usando o docker para enviar as imagens para o registro:

# Instale o snap Docker de confinamento estrito
sudo snap install docker

# Carregue o tarball da imagem
sudo docker load --input kserve-wine-rater-<arquitetura do dispositivo>.tar

# Marque a imagem docker
docker tag kserve-wine-rater-<arquitetura do dispositivo> localhost:32000/kserve-wine-rater:<versão escolhida>

# Envie a imagem para o registro interno do MicroK8s
docker push localhost:32000/kserve-wine-rater:<versão escolhida>
Enter fullscreen mode Exit fullscreen mode

Isso não é adequado para lidar com uma frota de dispositivos com diferentes arquiteturas de dispositivo e estabilidade de rede. Imagine um caso em que uma atualização de modelo precisa ser implantada em 10.000 dispositivos!

Felizmente, a natureza do Ubuntu Core e dos Snaps vem ao resgate.

Usando o pacote Snap

Os Snaps são um formato seguro, confinado, livre de dependências e multiplataforma de empacotamento do Linux.

Os Snaps são autocontidos, o que significa que incluem tudo o que é necessário para executar ou usar componentes de outros snaps de maneira limitada e controlada. Eles são usados pelo Ubuntu Core para compor a imagem que é executada em um dispositivo e para entregar atualizações de software consistentes e confiáveis, muitas vezes para sistemas embarcados e IoT de baixo consumo, inacessíveis e administrados remotamente.

Mais informações sobre como gerenciar Snaps e construí-los com Snapcraft podem ser encontradas na documentação do Ubuntu Core e do Snapcraft.

A natureza dos Snaps permite que eles entreguem conteúdo estritamente confinado por uma loja de Snaps (Snap Store), que pode ser privada, intermediada ou até mesmo totalmente isolada. O daemon Snap (Snapd) gerencia as atualizações com segurança em segundo plano e permite baixar snaps mesmo com uma conexão lenta de rede. Porém, isso pode demorar um pouco.

O Snap de entrega do contêiner InferenceService pode ser definido com um arquivo snapcraft.yaml:

name: wine-rater
base: core22
version: "0.0.1"
summary: Inference carrier of sklearn container
description: |
 This snap delivers a KServe-compatible sklearn model inference container.
 Once installed or refreshed it pushes the inference container into a configured image registry available on localhost:32000

confinement: strict

architectures:
 - build-on: arm64
   build-for: amd64
 - build-on: arm64
   build-for: arm64

environment:

  # Defina a variável de host do registro, usada para enviar imagens para crane
  REGISTRY_HOST: localhost:32000

parts:
  copy-script:
    plugin: dump
    source: ./images
    stage:
      - kserve-wine-rater-${SNAPCRAFT_TARGET_ARCH}.tgz

  crane:
    plugin: dump
    source:
      - on arm64: "https://github.com/google/go-containerregistry/releases/download/v0.16.1/go-containerregistry_Linux_arm64.tar.gz"
      - on amd64: "https://github.com/google/go-containerregistry/releases/download/v0.16.1/go-containerregistry_Linux_x86_64.tar.gz"
    organize:
      crane: usr/bin/

plugs:
  network:
Enter fullscreen mode Exit fullscreen mode

Com a parte copy-script, o tarball de imagem para a arquitetura de compilação dada é carregado no Snap. Para evitar a configuração de uma interface do Docker super privilegiada para enviar as imagens para o registro, o crane será usado para interagir com o ponto de extremidade NodePort do registro interno do MicroK8S, disponível em localhost:32000. Como esse Snap só precisará acessar a rede, essa interface precisa ser definida.

Aproveitando os ganchos do Snapcraft, os contêineres InferenceService com atualizações de modelo podem ser entregues automaticamente e enviados para o registro na instalação ou atualização do snap. Para habilitar isso, instale (install) e crie scripts de pós-atualização (post-refresh) no diretório hooks/ com o conteúdo fornecido:

#!/bin/sh -e

crane push $SNAP/kserve-wine-rater-$SNAP_ARCH.tgz $REGISTRY_HOST/kserve-wine-rater:$SNAP_VERSION --insecure
Enter fullscreen mode Exit fullscreen mode

O layout do projeto, em efeito, parecerá com isso:

.
├── README.md
├── images
│   ├── kserve-wine-rater-amd64.tar
│   └── kserve-wine-rater-arm64.tar
└── snap
    ├── hooks
    │   ├── install
    │   └── post-refresh
    └── snapcraft.yaml
Enter fullscreen mode Exit fullscreen mode

Para construir os Snaps, o Snapcraft deve ser instalado no host de compilação e o que resta é executar o comando snapcraft:

$ snapcraft
Launching instance...
Executed: skip pull copy-script (already ran)
Executed: skip pull crane (already ran)
Executed: skip build copy-script (already ran)
Executed: skip build crane (already ran)
Executed: skip stage copy-script (already ran)
Executed: skip stage crane (already ran)
Executed: skip prime copy-script (already ran)
Executed: skip prime crane (already ran)
Executed parts lifecycle
Generated snap metadata
Created snap package wine-rater_0.0.1_amd64.snap
Launching instance...
Executed: skip pull copy-script (already ran)
Executed: skip pull crane (already ran)
Executed: skip build copy-script (already ran)
Executed: skip build crane (already ran)
Executed: skip stage copy-script (already ran)
Executed: skip stage crane (already ran)
Executed: skip prime copy-script (already ran)
Executed: skip prime crane (already ran)
Executed parts lifecycle
Generated snap metadata
Created snap package wine-rater_0.0.1_arm64.snap
Enter fullscreen mode Exit fullscreen mode

Com os metadados de configuração de arquiteturas e o uso de LXD como o provedor de compilação, arquivos .snap foram entregues para cada arquitetura.

Para carregar os snaps na loja, o Snapcraft precisa ser autenticado e o nome do snap precisa ser registrado:

# Faça login na Snap Store
snapcraft login

# Registre o nome do Snap como privado
snapcraft register --private wine-rater

# Lance os snaps
snapcraft upload --release=<sua versão> wine-rater_0.0.1_arm64.snap
snapcraft upload --release=<sua versão> wine-rater_0.0.1_amd64.snap
Enter fullscreen mode Exit fullscreen mode

Quando terminar, o https://snapcraft.io/wine-rater/releases deve estar preenchido com novas revisões disponíveis para serem promovidas:

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*MZrxUs2Iprm7IXifmPb6lA.png

Implantando contêineres ML InferenceService no dispositivo de borda

Para implantar as imagens InferenceService nos dispositivos de borda, os tarballs de imagem devem ser carregados nos dispositivos e enviados ao registro interno previamente habilitado do MicroK8s.

Os detalhes do serviço de registro podem ser encontrados executando:

$ kubectl get svc -n container-registry

NAME       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
registry   NodePort   10.152.183.90   <none>        5000:32000/TCP   7h29m
$ kubectl describe svc registry -n container-registry

Name:                     registry
Namespace:                container-registry
Labels:                   app=registry
Annotations:              <none>
Selector:                 app=registry
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.152.183.90
IPs:                      10.152.183.90
Port:                     registry  5000/TCP
TargetPort:               5000/TCP
NodePort:                 registry  32000/TCP
Endpoints:                10.1.11.6:5000
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
Enter fullscreen mode Exit fullscreen mode

Dependendo da configuração do cluster do MicroK8s, as implantações de contêiner com fonte de registro marcada como localhost:32000 podem resultar em erros ImagePullBack. Isso ocorre quando o pod não consegue resolver o localhost devido ao confinamento estrito ou como resultado de uma chamada https para o repositório inseguro, que responde com um erro de cliente HTTP de resposta do servidor ao ser chamado (server gave HTTP response to HTTPS client).

Para evitar esses erros, a implantação pode apontar para o ClusterIP do serviço de registro. Um ajuste foi proposto na documentação do registro privado do MicroK8s:

sudo mkdir -p /var/snap/microk8s/current/args/certs.d/<IP do serviço de registro>:5000 

sudo touch /var/snap/microk8s/current/args/certs.d/<IP do serviço de registro>:5000/hosts.toml
Enter fullscreen mode Exit fullscreen mode

Edite o arquivo /var/snap/microk8s/current/args/certs.d/&lt;ClusterIP do serviço de registro>:5000/hosts.toml:

# /var/snap/microk8s/current/args/certs.d/<IP do serviço de registro>:5000/hosts.toml
server = "http://<IP do serviço de registro>:5000"

[host."<ClusterIP do serviço de registro>:5000"] 
capabilities = ["pull", "resolve"]
Enter fullscreen mode Exit fullscreen mode

Reinicie o MicroK8s

sudo microk8s start 

sudo microk8s stop
Enter fullscreen mode Exit fullscreen mode

Para baixar o contêiner Snap ML InferenceService, o snapd deve ser autenticado na Snap Store com o modelo publicado:

# Login na Snap Store
sudo snap login

# Instale o contêiner Snap InferenceService wine-rater do canal dado
sudo snap install wine-rater --channel <canal necessário>
Enter fullscreen mode Exit fullscreen mode

Após baixar o Snap, os hooks de instalação enviarão a imagem automaticamente para o registro. O resultado pode ser testado consultando a API HTTP V2:

$ curl -X GET http://localhost:32000/v2/_catalog 
{"repositories":["kserve-wine-rater"]} 

$ curl -X GET http://localhost:32000/v2/kserve-wine-rater/tags/list 
{"name":"kserve-wine-rater","tags":["<versão escolhida>"]}
Enter fullscreen mode Exit fullscreen mode

Na configuração atual da rede, ao definir o arquivo de implantação KServe para permitir que ferramentas como o Keel verifiquem a versão da imagem e atualizem as implantações, o InferenceService pode ser implantado usando:

kubectl apply -f - <<EOF
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
 name: wine-rater
spec:
 predictor:
   containers:
     - name: kserve-container
       image: <registry svc ClusterIP>:5000/kserve-wine-rater:<the version>
EOF
Enter fullscreen mode Exit fullscreen mode

O resultado:

$ kubectl get inferenceservices
NAME         URL                                     READY   PREV   LATEST   PREVROLLEDOUTREVISION   LATESTREADYREVISION          AGE
wine-rater   http://wine-rater.default.example.com   True           100                              wine-rater-predictor-00001   47s
Enter fullscreen mode Exit fullscreen mode

Chamando o modelo:

export MODEL_NAME=wine-rater
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export SERVICE_HOSTNAME=$(kubectl get inferenceservice $MODEL_NAME -o jsonpath='{.status.url}' | cut -d "/" -f 3)

curl \
 -H "Host: ${SERVICE_HOSTNAME}" \
 -H "Content-Type: application/json" \
 -d '{"inputs": [{"name": "input1","shape": [1,11],"datatype": "FP32","data": [[5.6,0.31,0.37,1.4,0.074,12.0,96.0,0.9954,3.32,0.58,9.2]]}]}' \
 http://${INGRESS_HOST}:${INGRESS_PORT}/v2/models/${MODEL_NAME}/infer
Enter fullscreen mode Exit fullscreen mode

Resposta do modelo:

$ curl \
 -H "Host: ${SERVICE_HOSTNAME}" \
 -H "Content-Type: application/json" \
 -d '{"inputs": [{"name": "input1","shape": [1,11],"datatype": "FP32","data": [[5.6,0.31,0.37,1.4,0.074,12.0,96.0,0.9954,3.32,0.58,9.2]]}]}' \
 http://${INGRESS_HOST}:${INGRESS_PORT}/v2/models/${MODEL_NAME}/infer
{"model_name":"wine-rater","model_version":null,"id":"f00ad461-e7f6-48b2-a707-f3a3a7bc604b","parameters":null,"outputs":[{"name":"output-0","shape":[1],"datatype":"FP64","parameters":null,"data":[5.288068083678879]}]}
Enter fullscreen mode Exit fullscreen mode

Voilà!

https://miro.medium.com/v2/resize:fit:2000/format:webp/1*MdgYkgpDBGEtEXIzkFbUrw.png

Sistema de entrega ML na borda usando Snap Store

Resumo

Usando Snap, MicroK8s e KServe, construímos um sistema de entrega ML na borda totalmente funcional, seguro, escalável e autoatualizável rodando no Ubuntu Core. Os modelos implantados estão disponíveis para o host. Eles também podem ser configurados para estar disponíveis para o mundo externo usando o NodePort e todos têm uma estrutura de API padrão.

O site de borda pode ser estendido e personalizado com as seguintes ideias:

Continue experimentando com ferramentas de código aberto e compartilhe seus resultados!

Entre em contato comigo através das minhas redes sociais.

Artigo original publicado por Rafał Siwek. Traduzido por Paulinho Giovannini.

Top comments (0)